Skip to content

Commit

Permalink
fixes #175 proof of concept for Slider component from daisyUI
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Smith committed Jun 14, 2023
1 parent a274a0c commit 7d86f39
Show file tree
Hide file tree
Showing 6 changed files with 346 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ dist
.DS_Store
.history
.vercel
.idea
7 changes: 7 additions & 0 deletions docs/components/content/examples/SliderExample.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script setup>
const value = ref(50)
</script>

<template>
<USlider v-model="value" />
</template>
83 changes: 83 additions & 0 deletions docs/content/3.forms/9.slider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
github: true
description: Display a slider field
navigation:
badge: "Edge"
---

## Usage

Use a `v-model` to make the Input reactive.

::component-example
#default
:slider-example

#code

```vue
<script setup>
const value = ref("");
</script>
<template>
<USlider v-model="value" />
</template>
```

::

### Style

Use the `color` prop to change the visual style of the Slider.

## ::component-card

baseProps:
name: 'slider'
placeholder: 'Search...'
props:
color: 'lime'

---

::

### Size

Use the `size` prop to change the size of the Input.

## ::component-card

baseProps:
name: 'slider'
props:
size: 'sm'

---

::

### Disabled

Use the `disabled` prop to disable the Input.

## ::component-card

baseProps:
name: 'input'
placeholder: 'Search...'
props:
disabled: true

---

::

## Props

:component-props

## Preset

:component-preset
1 change: 1 addition & 0 deletions src/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export const generateSafelist = (colors: string[]) => {

return [
...safelist,
...colors.map(color => `[&::-webkit-slider-thumb]:shadow-${color}-500`),
// Gray safelist for Avatar & Notification
'bg-gray-500',
'dark:bg-gray-400',
Expand Down
10 changes: 10 additions & 0 deletions src/runtime/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,15 @@ const toggle = {
}
}

const slider = {
base: 'h-6 w-full cursor-pointer bg-transparent rounded-full overflow-hidden',
thumb : '[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:top-[50%] [&::-webkit-slider-thumb]:shadow-range [&::-webkit-slider-thumb]:inset-box-shadow [&::-webkit-slider-thumb]:relative [&::-webkit-slider-thumb]:h-6 [&::-webkit-slider-thumb]:w-6 [&::-webkit-slider-thumb]:border-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:shadow-{color}-500 [&::-webkit-slider-thumb]:-translate-y-1/2',
default: {
size: 'sm',
color: 'primary',
}
}

// Layout

const card = {
Expand Down Expand Up @@ -864,6 +873,7 @@ export default {
dropdown,
kbd,
input,
slider,
formGroup,
textarea,
select,
Expand Down
244 changes: 244 additions & 0 deletions src/runtime/components/forms/Slider.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
<template>
<div :class="ui.wrapper">
<input
:id="name"
ref="input"
:name="name"
:value="modelValue"
:disabled="disabled"
type="range"
:class="inputClass"
v-bind="$attrs"
@input="onInput"
@focus="$emit('focus', $event)"
@blur="$emit('blur', $event)"
>
<slot />
</div>
</template>

<script lang="ts">
import { ref, computed, onMounted, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { defu } from 'defu'
import { classNames } from '../../utils'
import { useAppConfig } from '#imports'
// TODO: Remove
// @ts-expect-error
import appConfig from '#build/app.config'
export default defineComponent({
props: {
modelValue: {
type: [String, Number],
default: ''
},
name: {
type: String,
default: null
},
disabled: {
type: Boolean,
default: false
},
autofocus: {
type: Boolean,
default: false
},
padded: {
type: Boolean,
default: true
},
size: {
type: String,
default: () => appConfig.ui.input.default.size,
validator(value: string) {
return Object.keys(appConfig.ui.input.size).includes(value)
}
},
color: {
type: String,
default: () => appConfig.ui.slider.default.color,
validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(appConfig.ui.input.color)].includes(value)
}
},
ui: {
type: Object as PropType<Partial<typeof appConfig.ui.slider>>,
default: () => appConfig.ui.slider
}
},
emits: ['update:modelValue', 'focus', 'blur'],
setup(props, { emit, slots }) {
// TODO: Remove
const appConfig = useAppConfig()
console.log(props.ui)
const ui = computed<Partial<typeof appConfig.ui.slider>>(() => defu({}, props.ui, appConfig.ui.slider))
const onInput = (event: InputEvent) => {
emit('update:modelValue', (event.target as any).value)
}
console.log(ui.value)
const inputClass = computed(() => {
return classNames(
ui.value.base,
ui.value.thumb.replaceAll('{color}', props.color),
"range",
/* ui.value.rounded,
ui.value.placeholder,
ui.value.size[props.size],
props.padded ? ui.value.padding[props.size] : 'p-0',*/
)
})
// eslint-disable-next-line vue/no-dupe-keys
return { ui, onInput, inputClass }
}
})
</script>

<style scoped>
:root {
--bc: var(--color-primary-500);
}
.range {
&-xs {
@apply h-4;
&::-webkit-slider-runnable-track {
@apply h-1;
}
&::-moz-range-track {
@apply h-1;
}
&::-webkit-slider-thumb {
@apply h-4 w-4;
--filler-offset: 0.4rem;
}
&::-moz-range-thumb {
@apply h-4 w-4;
--filler-offset: 0.4rem;
}
}
&-sm {
@apply h-5;
&::-webkit-slider-runnable-track {
@apply h-1;
}
&::-moz-range-track {
@apply h-1;
}
&::-webkit-slider-thumb {
@apply h-5 w-5;
--filler-offset: 0.5rem;
}
&::-moz-range-thumb {
@apply h-5 w-5;
--filler-offset: 0.5rem;
}
}
&-md {
@apply h-6;
&::-webkit-slider-runnable-track {
@apply h-2;
}
&::-moz-range-track {
@apply h-2;
}
&::-webkit-slider-thumb {
@apply h-6 w-6;
--filler-offset: 0.6rem;
}
&::-moz-range-thumb {
@apply h-6 w-6;
--filler-offset: 0.6rem;
}
}
&-lg {
@apply h-8;
&::-webkit-slider-runnable-track {
@apply h-4;
}
&::-moz-range-track {
@apply h-4;
}
&::-webkit-slider-thumb {
@apply h-8 w-8;
--filler-offset: 1rem;
}
&::-moz-range-thumb {
@apply h-8 w-8;
--filler-offset: 1rem;
}
}
}
.range {
appearance: none;
-webkit-appearance: none;
--range-shdw: var(--bc);
&:focus {
outline: none;
}
&::-webkit-slider-runnable-track {
@apply h-2 w-full rounded-full bg-gray-200;
}
&::-moz-range-track {
@apply h-2 w-full rounded-full bg-gray-200;
}
&::-webkit-slider-thumb {
color: var(--tw-shadow-color);
--filler-size: 100rem;
--filler-offset: 0.6rem;
box-shadow: 0 0 0 3px var(--tw-shadow-color) inset, var(--focus-shadow, 0 0), calc(var(--filler-size) * -1 - var(--filler-offset)) 0 0 var(--filler-size);
}
&::-moz-range-thumb {
@apply relative h-6 w-6 border-none rounded-full bg-white;
top: 50%;
color: var(--tw-shadow-color);
--filler-size: 100rem;
--filler-offset: 0.5rem;
box-shadow: 0 0 0 3px hsl(var(--range-shdw)) inset, var(--focus-shadow, 0 0),
calc(var(--filler-size) * -1 - var(--filler-offset)) 0 0 var(--filler-size);
}
}
.range:focus-visible::-webkit-slider-thumb {
--focus-shadow: 0 0 0 6px white inset, 0 0 0 2rem var(--tw-shadow-color) inset
}
.range:focus-visible::-moz-range-thumb {
--focus-shadow: 0 0 0 6px var(--tw-shadow-color) inset, 0 0 0 2rem var(--tw-shadow-color) inset
}
</style>

0 comments on commit 7d86f39

Please sign in to comment.