refactor(ui): improve slider style
This commit is contained in:
parent
337373ff75
commit
0b4d5b3acd
|
@ -3,6 +3,7 @@ import { ref, computed, onMounted } from 'vue'
|
|||
|
||||
import Layout from "~/components/ui/Layout.vue"
|
||||
import Spacer from "~/components/ui/Spacer.vue"
|
||||
import Markdown from "~/components/ui/Markdown.vue"
|
||||
|
||||
const props = defineProps<{
|
||||
label?: string,
|
||||
|
@ -48,7 +49,7 @@ onMounted(() => {
|
|||
{{ label }}
|
||||
</label>
|
||||
|
||||
<!-- Model indicator -->
|
||||
<!-- List of options -->
|
||||
|
||||
<Layout flex no-gap>
|
||||
<button v-for="key in keys" :class="[$style.key, {[$style.current]: key===model}]"
|
||||
|
@ -62,19 +63,23 @@ onMounted(() => {
|
|||
|
||||
<!-- Slider -->
|
||||
|
||||
<input ref="input" type="range"
|
||||
style="width: var(--slider-width);"
|
||||
:max="keys.length - 1"
|
||||
v-model="index"
|
||||
/>
|
||||
<span style="position: relative;">
|
||||
<input ref="input" type="range"
|
||||
style="width: var(--slider-width); opacity: .001;"
|
||||
:max="keys.length - 1"
|
||||
v-model="index" />
|
||||
<div :class="$style.range" />
|
||||
<div :class="$style.pin" />
|
||||
</span>
|
||||
<Spacer size-8/>
|
||||
|
||||
<!-- Description of current option -->
|
||||
|
||||
<span style="position: relative;">
|
||||
<span style="display: inline-flex; margin-right: -100%; width: 100%; visibility: hidden;" >
|
||||
<span v-for="key in keys" :class="$style.description" :style="`margin-right: -20%; --current-step: 0; color: magenta;`">{{ options[key] }}</span>
|
||||
</span>
|
||||
<span style="position: absolute;" :class="$style.description">{{ options[model] }}</span>
|
||||
<span style="display: inline-flex; margin-right: -100%; width: 100%; visibility: hidden;" >
|
||||
<span v-for="key in keys" :class="$style.description" :style="`margin-right: -20%; --current-step: 0; color: magenta;`"><Markdown :md="options[key]" /></span>
|
||||
</span>
|
||||
<span style="position: absolute;" :class="$style.description"><Markdown :md="options[model]" /></span>
|
||||
</span>
|
||||
</Layout>
|
||||
</template>
|
||||
|
@ -103,5 +108,37 @@ onMounted(() => {
|
|||
--inset: calc(var(--step-size) * var(--current-step));
|
||||
margin-left: var(--inset);
|
||||
margin-right: calc(0px - var(--inset));
|
||||
p {
|
||||
margin: 0;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
}
|
||||
// Fake slider
|
||||
.range {
|
||||
width: calc(var(--step-size) * var(--current-step));
|
||||
border-bottom: 2px solid currentcolor;
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
transition: all .1s;
|
||||
pointer-events: none;
|
||||
}
|
||||
input:focus~.range {
|
||||
// focused style
|
||||
}
|
||||
.pin {
|
||||
border-radius: 8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
left: calc(var(--step-size) * var(--current-step));
|
||||
background: currentcolor;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
transition: all .1s;
|
||||
pointer-events: none;
|
||||
}
|
||||
input:focus~.pin {
|
||||
background-color: var(--focus-ring-color);
|
||||
outline: 2px solid currentcolor;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
import Spacer from "~/components/ui/Spacer.vue"
|
||||
import Slider from '~/components/ui/Slider.vue'
|
||||
|
||||
const options = {
|
||||
|
@ -9,7 +10,7 @@ const options = {
|
|||
everyone: "Everyone can find and edit this"
|
||||
} as const
|
||||
|
||||
const option = ref<keyof typeof options>('me')
|
||||
const option = ref<keyof typeof options>('pod')
|
||||
</script>
|
||||
|
||||
```ts
|
||||
|
@ -18,9 +19,10 @@ import Slider from "~/components/ui/Slider.vue";
|
|||
|
||||
# Slider
|
||||
|
||||
Let a user select a value along a gradient.
|
||||
Let a user select a value along a line.
|
||||
|
||||
The model (required) is the current value.
|
||||
For each option, provide a description. Markdown is supported.
|
||||
Select a key from the `options` by setting `v-model`
|
||||
|
||||
```ts
|
||||
const options = {
|
||||
|
@ -33,10 +35,21 @@ const option = ref<keyof typeof options>("me");
|
|||
```
|
||||
|
||||
```vue-html
|
||||
<Slider :options="options" v-model="option" label="Privacy" />
|
||||
<Slider :options="options" v-model="option" label="Privacy level" />
|
||||
```
|
||||
|
||||
<Slider :options="options" v-model="option" label="Privacy" />
|
||||
<Spacer />
|
||||
<Slider :options="options" v-model="option" label="Privacy level" />
|
||||
|
||||
## Add a label
|
||||
|
||||
You can either specify the `label` prop or add custom Html into the `#label` slot.
|
||||
|
||||
## Autofocus
|
||||
|
||||
Add the prop `autofocus` to focus the slider as soon as it renders. Make sure to only autofocus one element per page.
|
||||
|
||||
---
|
||||
|
||||
Functionality:
|
||||
|
||||
|
@ -55,5 +68,6 @@ Design:
|
|||
- A pin (same as in the toggle component)
|
||||
- a range (very faint)
|
||||
- Ticks
|
||||
- Constant dimensions, fitting the largest text box
|
||||
|
||||
- Not to be confused with a pearls navigation patterns (list of dots; indicates temporal range)
|
||||
|
|
Loading…
Reference in New Issue