ソースを参照

Massively upgraded shadow control, added sorting by specificity in themes3, added/fixed disabled inputs

Henry Jameson 2 ヶ月 前
コミット
a044dc377e

+ 21 - 11
src/components/checkbox/checkbox.vue

@@ -3,6 +3,13 @@
     class="checkbox"
     :class="{ disabled, indeterminate, 'indeterminate-fix': indeterminateTransitionFix }"
   >
+    <span
+      v-if="!!$slots.before"
+      class="label -before"
+      :class="{ faint: disabled }"
+    >
+      <slot name="before"/>
+    </span>
     <input
       type="checkbox"
       class="visible-for-screenreader-only"
@@ -14,11 +21,13 @@
     <i
       class="input -checkbox checkbox-indicator"
       :aria-hidden="true"
+      :class="{ disabled }"
       @transitionend.capture="onTransitionEnd"
     />
     <span
       v-if="!!$slots.default"
-      class="label"
+      class="label -after"
+      :class="{ faint: disabled }"
     >
       <slot />
     </span>
@@ -93,14 +102,9 @@ export default {
     box-sizing: border-box;
   }
 
-  &.disabled {
-    .checkbox-indicator::before,
-    .label {
-      opacity: 0.5;
-    }
-
-    .label {
-      color: var(--text);
+  .disabled {
+    .checkbox-indicator::before {
+      background-color: var(--background);
     }
   }
 
@@ -121,8 +125,14 @@ export default {
     }
   }
 
-  & > span {
-    margin-left: 0.5em;
+  & > .label {
+    &.-after {
+      margin-left: 0.5em;
+    }
+
+    &.-before {
+      margin-right: 0.5em;
+    }
   }
 }
 </style>

+ 18 - 6
src/components/color_input/color_input.scss

@@ -1,12 +1,15 @@
 .color-input {
   display: inline-flex;
 
+  .label {
+    flex: 1 1 auto;
+  }
+
   &-field.input {
     display: inline-flex;
     flex: 0 0 0;
     max-width: 9em;
     align-items: stretch;
-    padding: 0.2em 8px;
 
     input {
       color: var(--text);
@@ -25,6 +28,7 @@
     .nativeColor {
       cursor: pointer;
       flex: 0 0 auto;
+      padding: 0;
 
       input {
         appearance: none;
@@ -41,10 +45,10 @@
     .invalidIndicator,
     .transparentIndicator {
       flex: 0 0 2em;
-      margin: 0 0.5em;
+      margin: 0.2em 0.5em;
       min-width: 2em;
       align-self: stretch;
-      min-height: 1.5em;
+      min-height: 1.1em;
       border-radius: var(--roundness);
     }
 
@@ -81,9 +85,17 @@
         border-bottom-right-radius: var(--roundness);
       }
     }
-  }
 
-  .label {
-    flex: 1 1 auto;
+    &.disabled,
+    &:disabled {
+      .nativeColor input,
+      .computedIndicator,
+      .validIndicator,
+      .invalidIndicator,
+      .transparentIndicator {
+        /* stylelint-disable-next-line declaration-no-important */
+        opacity: 0.25 !important;
+      }
+    }
   }
 }

+ 7 - 1
src/components/color_input/color_input.vue

@@ -6,6 +6,7 @@
     <label
       :for="name"
       class="label"
+      :class="{ faint: !present || disabled }"
     >
       {{ label }}
     </label>
@@ -16,10 +17,14 @@
       class="opt"
       @update:modelValue="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
     />
-    <div class="input color-input-field">
+    <div
+      class="input color-input-field"
+      :class="{ disabled: !present || disabled }"
+      >
       <input
         :id="name + '-t'"
         class="textColor unstyled"
+        :class="{ disabled: !present || disabled }"
         type="text"
         :value="modelValue || fallback"
         :disabled="!present || disabled"
@@ -51,6 +56,7 @@
           type="color"
           :value="modelValue || fallback"
           :disabled="!present || disabled"
+          :class="{ disabled: !present || disabled }"
           @input="$emit('update:modelValue', $event.target.value)"
         >
       </label>

+ 1 - 1
src/components/input.style.js

@@ -60,7 +60,7 @@ export default {
     {
       state: ['disabled'],
       directives: {
-        background: '$blend(--inheritedBackground, 0.25, --parent)'
+        background: '--parent'
       }
     },
     {

+ 2 - 0
src/components/opacity_input/opacity_input.vue

@@ -6,6 +6,7 @@
     <label
       :for="name"
       class="label"
+      :class="{ faint: !present || disabled }"
     >
       {{ $t('settings.style.common.opacity') }}
     </label>
@@ -22,6 +23,7 @@
       type="number"
       :value="modelValue || fallback"
       :disabled="!present || disabled"
+      :class="{ disabled: !present || disabled }"
       max="1"
       min="0"
       step=".05"

+ 22 - 1
src/components/select/select.vue

@@ -6,13 +6,14 @@
     <select
       :disabled="disabled"
       :value="modelValue"
-      v-bind="attrs"
+      v-bind="$attrs"
       @change="$emit('update:modelValue', $event.target.value)"
     >
       <slot />
     </select>
     {{ ' ' }}
     <FAIcon
+      v-if="!$attrs.size && !$attrs.multiple"
       class="select-down-icon"
       icon="chevron-down"
     />
@@ -26,6 +27,11 @@
 label.Select {
   padding: 0;
 
+  &.disabled,
+  &:disabled {
+    background-color: var(--background);
+  }
+
   select {
     appearance: none;
     background: transparent;
@@ -39,6 +45,21 @@ label.Select {
     z-index: 1;
     height: 2em;
     line-height: 16px;
+
+    &[multiple],
+    &[size] {
+      height: 100%;
+      padding: 0.2em;
+
+      option {
+        background: transparent;
+
+        &.-active {
+          color: var(--selectionText);
+          background-color: var(--selectionBackground);
+        }
+      }
+    }
   }
 
   .select-down-icon {

+ 8 - 7
src/components/settings_modal/tabs/theme_tab/theme_tab.scss

@@ -25,7 +25,9 @@
     margin-bottom: 5px;
 
     .label {
+      margin-right: 1em;
       flex: 1;
+      line-height: 2;
     }
 
     .opt {
@@ -48,15 +50,14 @@
 
       &[type="range"] {
         flex: 1;
-        min-width: 3em;
-        align-self: flex-start;
+        min-width: 2em;
+        align-self: center;
+        margin: 0 0.5em;
       }
-    }
 
-    &.disabled {
-      input,
-      select {
-        opacity: 0.5;
+      &[type="checkbox"] + i {
+        height: 1.1em;
+        align-self: center;
       }
     }
   }

+ 4 - 1
src/components/shadow_control/shadow_control.js

@@ -1,6 +1,7 @@
 import ColorInput from '../color_input/color_input.vue'
 import OpacityInput from '../opacity_input/opacity_input.vue'
 import Select from '../select/select.vue'
+import Checkbox from '../checkbox/checkbox.vue'
 import { getCssShadow } from '../../services/theme_data/theme_data.service.js'
 import { hex2rgb } from '../../services/color_convert/color_convert.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
@@ -40,6 +41,7 @@ export default {
   emits: ['update:modelValue'],
   data () {
     return {
+      lightGrid: false,
       selectedId: 0,
       // TODO there are some bugs regarding display of array (it's not getting updated when deleting for some reason)
       cValue: (this.modelValue || this.fallback || []).map(toModel)
@@ -48,7 +50,8 @@ export default {
   components: {
     ColorInput,
     OpacityInput,
-    Select
+    Select,
+    Checkbox
   },
   methods: {
     add () {

+ 178 - 0
src/components/shadow_control/shadow_control.scss

@@ -0,0 +1,178 @@
+.settings-modal .settings-modal-panel .shadow-control {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: stretch;
+  grid-gap: 0.25em;
+  margin-bottom: 1em;
+
+  .shadow-switcher {
+    order: 1;
+    flex: 1 0 6em;
+    min-width: 6em;
+    margin-right: 0.125em;
+    display: flex;
+    flex-direction: column;
+
+    .shadow-list {
+      flex: 1 0 auto;
+    }
+
+    .arrange-buttons {
+      flex: 0 0 auto;
+      display: grid;
+      grid-auto-columns: 1fr;
+      grid-auto-flow: column;
+      grid-gap: 0.125em;
+      margin-top: 0.25em;
+
+      .button-default {
+        margin: 0;
+        padding: 0;
+      }
+    }
+  }
+
+  .shadow-tweak {
+    order: 3;
+    flex: 2 0 10em;
+    min-width: 10em;
+    margin-left: 0.125em;
+    margin-right: 0.125em;
+
+    /* hack */
+    .input-boolean {
+      flex: 1;
+      display: flex;
+
+      .label {
+        flex: 1;
+      }
+    }
+
+    .input-string {
+      flex: 1 0 5em;
+    }
+
+    .id-control {
+      align-items: stretch;
+
+      .shadow-switcher,
+      .btn {
+        min-width: 1px;
+        margin-right: 5px;
+      }
+
+      .btn {
+        padding: 0 0.4em;
+        margin: 0 0.1em;
+      }
+    }
+  }
+
+  .shadow-preview {
+    order: 2;
+    flex: 3 3 15em;
+    min-width: 10em;
+    display: grid;
+    margin-left: 0.125em;
+    align-self: start;
+    grid-template-columns: 3em 1fr 3em;
+    grid-template-rows: 2em 1fr 2em;
+    grid-template-areas:
+      ".       header  y-num  "
+      ".       preview y-slide"
+      "x-num   x-slide .      "
+      "options options options";
+    grid-gap: 0.5em;
+
+    .header {
+      grid-area: header;
+      justify-self: center;
+      align-self: baseline;
+      line-height: 2;
+    }
+
+    .input-light-grid {
+      grid-area: options;
+      justify-self: end;
+    }
+
+    .input-number {
+      min-width: 2em;
+    }
+
+    .x-shift-number {
+      grid-area: x-num;
+    }
+
+    .x-shift-slider {
+      grid-area: x-slide;
+      height: auto;
+      align-self: start;
+      min-width: 10em;
+    }
+
+    .y-shift-number {
+      grid-area: y-num;
+    }
+
+    .y-shift-slider {
+      grid-area: y-slide;
+      writing-mode: vertical-lr;
+      justify-self: left;
+      min-height: 10em;
+    }
+
+    .x-shift-slider,
+    .y-shift-slider {
+      padding: 0;
+    }
+
+    .preview-window {
+      --__grid-color1: rgb(102 102 102);
+      --__grid-color2: rgb(153 153 153);
+      --__grid-color1-disabled: rgba(102 102 102 / 20%);
+      --__grid-color2-disabled: rgba(153 153 153 / 20%);
+
+      &.-light-grid {
+        --__grid-color1: rgb(205 205 205);
+        --__grid-color2: rgb(255 255 255);
+        --__grid-color1-disabled: rgba(205 205 205 / 20%);
+        --__grid-color2-disabled: rgba(255 255 255 / 20%);
+      }
+
+      grid-area: preview;
+      aspect-ratio: 1;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      min-width: 10em;
+      min-height: 10em;
+      background-color: var(--__grid-color2);
+      background-image:
+        linear-gradient(45deg, var(--__grid-color1) 25%, transparent 25%),
+        linear-gradient(-45deg, var(--__grid-color1) 25%, transparent 25%),
+        linear-gradient(45deg, transparent 75%, var(--__grid-color1) 75%),
+        linear-gradient(-45deg, transparent 75%, var(--__grid-color1) 75%);
+      background-size: 20px 20px;
+      background-position: 0 0, 0 10px, 10px -10px, -10px 0;
+      border-radius: var(--roundness);
+
+      &.disabled {
+        background-color: var(--__grid-color2-disabled);
+        background-image:
+          linear-gradient(45deg, var(--__grid-color1-disabled) 25%, transparent 25%),
+          linear-gradient(-45deg, var(--__grid-color1-disabled) 25%, transparent 25%),
+          linear-gradient(45deg, transparent 75%, var(--__grid-color1-disabled) 75%),
+          linear-gradient(-45deg, transparent 75%, var(--__grid-color1-disabled) 75%);
+      }
+
+      .preview-block {
+        width: 33%;
+        height: 33%;
+        border-radius: var(--roundness);
+        background: var(--background);
+      }
+    }
+  }
+}

+ 106 - 175
src/components/shadow_control/shadow_control.vue

@@ -1,81 +1,92 @@
 <template>
   <div
-    class="shadow-control"
+    class="label shadow-control"
     :class="{ disabled: !present }"
   >
-    <div class="shadow-preview-container">
-      <div
+    <div class="shadow-preview">
+      <label
+        class="header"
+        :class="{ faint: !present }"
+      >
+        {{ $t('settings.style.shadows.offset') }}
+      </label>
+      <input
+        v-model="selected.y"
         :disabled="!present"
-        class="y-shift-control"
+        :class="{ disabled: !present }"
+        class="input input-number y-shift-number"
+        type="number"
+      >
+      <input
+        v-model="selected.y"
+        :disabled="!present"
+        :class="{ disabled: !present }"
+        class="input input-range y-shift-slider"
+        type="range"
+        max="20"
+        min="-20"
+      >
+      <div
+        class="preview-window"
+        :class="{ disabled: !present, '-light-grid': lightGrid }"
       >
-        <input
-          v-model="selected.y"
-          :disabled="!present"
-          class="input input-number"
-          type="number"
-        >
-        <div class="wrap">
-          <input
-            v-model="selected.y"
-            :disabled="!present"
-            class="input input-range"
-            type="range"
-            max="20"
-            min="-20"
-          >
-        </div>
-      </div>
-      <div class="preview-window">
         <div
           class="preview-block"
           :style="style"
         />
       </div>
-      <div
+      <input
+        v-model="selected.x"
         :disabled="!present"
-        class="x-shift-control"
+        :class="{ disabled: !present }"
+        class="input input-number x-shift-number"
+        type="number"
       >
-        <input
-          v-model="selected.x"
-          :disabled="!present"
-          class="input input-number"
-          type="number"
-        >
-        <div class="wrap">
-          <input
-            v-model="selected.x"
-            :disabled="!present"
-            class="input input-range"
-            type="range"
-            max="20"
-            min="-20"
-          >
-        </div>
-      </div>
-    </div>
+      <input
+        v-model="selected.x"
+        :disabled="!present"
+        :class="{ disabled: !present }"
+        class="input input-range x-shift-slider"
+        type="range"
+        max="20"
+        min="-20"
+      >
+      <Checkbox
+        id="inset"
+        v-model="lightGrid"
+        :disabled="!present"
+        name="lightGrid"
+        class="input-light-grid"
+      >
+        {{ $t('settings.style.shadows.light_grid') }}
+      </Checkbox>
 
-    <div class="shadow-tweak">
+    </div>
+    <div class="shadow-switcher">
+      <Select
+        class="shadow-list"
+        id="shadow-list"
+        v-model="selectedId"
+        size="10"
+        :disabled="!ready || usingFallback"
+      >
+        <option
+          v-for="(shadow, index) in cValue"
+          :value="index"
+          :class="{ '-active': index === Number(selectedId) }"
+          :key="index"
+        >
+          {{ shadow.name ?? $t('settings.style.shadows.shadow_id', { value: index }) }}
+        </option>
+      </Select>
       <div
         :disabled="usingFallback"
-        class="id-control style-control"
+        class="id-control arrange-buttons"
       >
-        <Select
-          id="shadow-switcher"
-          v-model="selectedId"
-          class="shadow-switcher"
-          :disabled="!ready || usingFallback"
-        >
-          <option
-            v-for="(shadow, index) in cValue"
-            :key="index"
-            :value="index"
-          >
-            {{ $t('settings.style.shadows.shadow_id', { value: index }) }}
-          </option>
-        </Select>
         <button
           class="btn button-default"
           :disabled="!ready || !present"
+          :class="{ disabled: !present }"
           @click="del"
         >
           <FAIcon
@@ -86,6 +97,7 @@
         <button
           class="btn button-default"
           :disabled="!moveUpValid"
+          :class="{ disabled: !present }"
           @click="moveUp"
         >
           <FAIcon
@@ -105,7 +117,7 @@
         </button>
         <button
           class="btn button-default"
-          :disabled="usingFallback"
+          :disabled="usingFallback || !present"
           @click="add"
         >
           <FAIcon
@@ -114,37 +126,54 @@
           />
         </button>
       </div>
+    </div>
+    <div class="shadow-tweak">
       <div
         :disabled="!present"
-        class="inset-control style-control"
+        :class="{ disabled: !present }"
+        class="name-control style-control"
       >
         <label
-          for="inset"
+          for="spread"
           class="label"
+          :class="{ faint: !present }"
         >
-          {{ $t('settings.style.shadows.inset') }}
+          {{ $t('settings.style.shadows.name') }}
         </label>
         <input
+          id="name"
+          v-model="selected.name"
+          :disabled="!present"
+          :class="{ disabled: !present }"
+          name="name"
+          class="input input-string"
+        >
+      </div>
+      <div
+        :disabled="!present"
+        class="inset-control style-control"
+      >
+        <Checkbox
           id="inset"
           v-model="selected.inset"
           :disabled="!present"
           name="inset"
-          class="input -checkbox input-inset visible-for-screenreader-only"
-          type="checkbox"
+          class="input-inset input-boolean"
         >
-        <label
-          class="checkbox-label"
-          for="inset"
-          :aria-hidden="true"
-        />
+          <template #before>
+            {{ $t('settings.style.shadows.inset') }}
+          </template>
+        </Checkbox>
       </div>
       <div
         :disabled="!present"
+        :class="{ disabled: !present }"
         class="blur-control style-control"
       >
         <label
           for="spread"
           class="label"
+          :class="{ faint: !present }"
         >
           {{ $t('settings.style.shadows.blur') }}
         </label>
@@ -152,6 +181,7 @@
           id="blur"
           v-model="selected.blur"
           :disabled="!present"
+          :class="{ disabled: !present }"
           name="blur"
           class="input input-range"
           type="range"
@@ -161,6 +191,7 @@
         <input
           v-model="selected.blur"
           :disabled="!present"
+          :class="{ disabled: !present }"
           class="input input-number"
           type="number"
           min="0"
@@ -169,10 +200,12 @@
       <div
         :disabled="!present"
         class="spread-control style-control"
+        :class="{ disabled: !present }"
       >
         <label
           for="spread"
           class="label"
+          :class="{ faint: !present }"
         >
           {{ $t('settings.style.shadows.spread') }}
         </label>
@@ -180,6 +213,7 @@
           id="spread"
           v-model="selected.spread"
           :disabled="!present"
+          :class="{ disabled: !present }"
           name="spread"
           class="input input-range"
           type="range"
@@ -189,6 +223,7 @@
         <input
           v-model="selected.spread"
           :disabled="!present"
+          :class="{ disabled: !present }"
           class="input input-number"
           type="number"
         >
@@ -208,6 +243,7 @@
       <i18n-t
         scope="global"
         keypath="settings.style.shadows.hintV3"
+        :class="{ faint: !present }"
         tag="p"
       >
         <code>--variable,mod</code>
@@ -218,109 +254,4 @@
 
 <script src="./shadow_control.js"></script>
 
-<style lang="scss">
-.shadow-control {
-  display: flex;
-  flex-wrap: wrap;
-  justify-content: center;
-  margin-bottom: 1em;
-
-  .shadow-preview-container,
-  .shadow-tweak {
-    margin: 5px 6px 0 0;
-  }
-
-  .shadow-preview-container {
-    flex: 0;
-    display: flex;
-    flex-wrap: wrap;
-
-    input[type="number"] {
-      width: 5em;
-      min-width: 2em;
-    }
-
-    .x-shift-control,
-    .y-shift-control {
-      display: flex;
-      flex: 0;
-
-      &[disabled="disabled"] * {
-        opacity: 0.5;
-      }
-    }
-
-    .x-shift-control {
-      align-items: flex-start;
-    }
-
-    .x-shift-control .wrap,
-    input[type="range"] {
-      margin: 0;
-      width: 15em;
-      height: 2em;
-    }
-
-    .y-shift-control {
-      flex-direction: column;
-      align-items: flex-end;
-
-      .wrap {
-        width: 2em;
-        height: 15em;
-      }
-
-      input[type="range"] {
-        transform-origin: 1em 1em;
-        transform: rotate(90deg);
-      }
-    }
-
-    .preview-window {
-      flex: 1;
-      background-color: #999;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      background-image:
-        linear-gradient(45deg, #666 25%, transparent 25%),
-        linear-gradient(-45deg, #666 25%, transparent 25%),
-        linear-gradient(45deg, transparent 75%, #666 75%),
-        linear-gradient(-45deg, transparent 75%, #666 75%);
-      background-size: 20px 20px;
-      background-position: 0 0, 0 10px, 10px -10px, -10px 0;
-      border-radius: var(--roundness);
-
-      .preview-block {
-        width: 33%;
-        height: 33%;
-        border-radius: var(--roundness);
-      }
-    }
-  }
-
-  .shadow-tweak {
-    flex: 1;
-    min-width: 280px;
-
-    .id-control {
-      align-items: stretch;
-
-      .shadow-switcher {
-        flex: 1;
-      }
-
-      .shadow-switcher,
-      .btn {
-        min-width: 1px;
-        margin-right: 5px;
-      }
-
-      .btn {
-        padding: 0 0.4em;
-        margin: 0 0.1em;
-      }
-    }
-  }
-}
-</style>
+<style src="./shadow_control.scss" lang="scss"></style>

+ 3 - 0
src/i18n/en.json

@@ -870,6 +870,9 @@
         "component": "Component",
         "override": "Override",
         "shadow_id": "Shadow #{value}",
+        "offset": "Shadow offset",
+        "light_grid": "Use light checkerboard",
+        "name": "Name",
         "blur": "Blur",
         "spread": "Spread",
         "inset": "Inset",