diff --git a/front/src/components/ui/Slider.vue b/front/src/components/ui/Slider.vue index 8a3b882d5..a1340267e 100644 --- a/front/src/components/ui/Slider.vue +++ b/front/src/components/ui/Slider.vue @@ -13,14 +13,18 @@ const props = defineProps<{ const keys = computed(() => Object.keys(props.options) as T[]) -const model = defineModel({ required: true }) +const model = defineModel({ required: true }) const index = computed({ get () { - return keys.value.indexOf(model.value) + return model.value + ? keys.value.indexOf(model.value) + : undefined }, set (newIndex) { - model.value = keys.value[newIndex] + model.value = newIndex + ? keys.value[newIndex] + : undefined } }) @@ -38,7 +42,8 @@ onMounted(() => { :style="` --step-size: calc(100% / ${keys.length + 2}); --slider-width: calc(var(--step-size) * ${keys.length - 1} + 16px); - --current-step: ${index}; + --slider-opacity: ${ index === undefined ? .5 : 1 }; + --current-step: ${ index === undefined ? keys.length - 1 : index }; `" > @@ -65,8 +70,8 @@ onMounted(() => { - @@ -83,12 +87,15 @@ onMounted(() => { ref="input" v-model="index" type="range" - style="width: var(--slider-width); opacity: .001;" + style="width: var(--slider-width); opacity: .001; cursor: pointer;" :max="keys.length - 1" :autofocus="autofocus || undefined" >
-
+
@@ -104,6 +111,7 @@ onMounted(() => { > @@ -147,6 +155,7 @@ onMounted(() => { top: 11px; transition: all .1s; pointer-events: none; + opacity: var(--slider-opacity); } input:focus~.range { // focused style diff --git a/front/ui-docs/components/ui/slider.md b/front/ui-docs/components/ui/slider.md index 89e741f21..07cdc96ac 100644 --- a/front/ui-docs/components/ui/slider.md +++ b/front/ui-docs/components/ui/slider.md @@ -11,6 +11,8 @@ const options = { } as const const option = ref('pod') + +const optionWithUndefined = ref(undefined) ```ts @@ -49,25 +51,50 @@ You can either specify the `label` prop or add custom Html into the `#label` slo Add the prop `autofocus` to focus the slider as soon as it renders. Make sure to only autofocus one element per page. +## Undefined state + +If you want to aggregate potentially mixed states, or start with no initial selection, +you can set v-model to `undefined`. + +```ts +const optionWithUndefined = ref(undefined) +``` + +```vue-html + +``` + + + + + --- -Functionality: +**Functionality** -- Define a list of `[value:string, description:markdown]` pairs (props) -- Select one value as active (model) +- Define a possible values +- Select zero or one values as active (`v-model`) -User interaction: +**User interaction** - It mimics the functionality of a single `range` input: - to be operated with arrow keys or mouse - focus is indicated - ticks are indicated -Design: +**Design** - A pin (same as in the toggle component) - a range (very faint) -- Ticks +- Ticks? - Constant dimensions, fitting the largest text box - Not to be confused with a pearls navigation patterns (list of dots; indicates temporal range)