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 Layout from "~/components/ui/Layout.vue"
|
||||||
import Spacer from "~/components/ui/Spacer.vue"
|
import Spacer from "~/components/ui/Spacer.vue"
|
||||||
|
import Markdown from "~/components/ui/Markdown.vue"
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
label?: string,
|
label?: string,
|
||||||
|
@ -48,7 +49,7 @@ onMounted(() => {
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<!-- Model indicator -->
|
<!-- List of options -->
|
||||||
|
|
||||||
<Layout flex no-gap>
|
<Layout flex no-gap>
|
||||||
<button v-for="key in keys" :class="[$style.key, {[$style.current]: key===model}]"
|
<button v-for="key in keys" :class="[$style.key, {[$style.current]: key===model}]"
|
||||||
|
@ -62,19 +63,23 @@ onMounted(() => {
|
||||||
|
|
||||||
<!-- Slider -->
|
<!-- Slider -->
|
||||||
|
|
||||||
|
<span style="position: relative;">
|
||||||
<input ref="input" type="range"
|
<input ref="input" type="range"
|
||||||
style="width: var(--slider-width);"
|
style="width: var(--slider-width); opacity: .001;"
|
||||||
:max="keys.length - 1"
|
:max="keys.length - 1"
|
||||||
v-model="index"
|
v-model="index" />
|
||||||
/>
|
<div :class="$style.range" />
|
||||||
|
<div :class="$style.pin" />
|
||||||
|
</span>
|
||||||
<Spacer size-8/>
|
<Spacer size-8/>
|
||||||
|
|
||||||
<!-- Description of current option -->
|
<!-- Description of current option -->
|
||||||
|
|
||||||
<span style="position: relative;">
|
<span style="position: relative;">
|
||||||
<span style="display: inline-flex; margin-right: -100%; width: 100%; visibility: hidden;" >
|
<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 v-for="key in keys" :class="$style.description" :style="`margin-right: -20%; --current-step: 0; color: magenta;`"><Markdown :md="options[key]" /></span>
|
||||||
</span>
|
</span>
|
||||||
<span style="position: absolute;" :class="$style.description">{{ options[model] }}</span>
|
<span style="position: absolute;" :class="$style.description"><Markdown :md="options[model]" /></span>
|
||||||
</span>
|
</span>
|
||||||
</Layout>
|
</Layout>
|
||||||
</template>
|
</template>
|
||||||
|
@ -103,5 +108,37 @@ onMounted(() => {
|
||||||
--inset: calc(var(--step-size) * var(--current-step));
|
--inset: calc(var(--step-size) * var(--current-step));
|
||||||
margin-left: var(--inset);
|
margin-left: var(--inset);
|
||||||
margin-right: calc(0px - 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>
|
</style>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
import Spacer from "~/components/ui/Spacer.vue"
|
||||||
import Slider from '~/components/ui/Slider.vue'
|
import Slider from '~/components/ui/Slider.vue'
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
@ -9,7 +10,7 @@ const options = {
|
||||||
everyone: "Everyone can find and edit this"
|
everyone: "Everyone can find and edit this"
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
const option = ref<keyof typeof options>('me')
|
const option = ref<keyof typeof options>('pod')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
|
@ -18,9 +19,10 @@ import Slider from "~/components/ui/Slider.vue";
|
||||||
|
|
||||||
# Slider
|
# 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
|
```ts
|
||||||
const options = {
|
const options = {
|
||||||
|
@ -33,10 +35,21 @@ const option = ref<keyof typeof options>("me");
|
||||||
```
|
```
|
||||||
|
|
||||||
```vue-html
|
```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:
|
Functionality:
|
||||||
|
|
||||||
|
@ -55,5 +68,6 @@ Design:
|
||||||
- A pin (same as in the toggle component)
|
- A pin (same as in the toggle component)
|
||||||
- a range (very faint)
|
- 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)
|
- Not to be confused with a pearls navigation patterns (list of dots; indicates temporal range)
|
||||||
|
|
Loading…
Reference in New Issue