diff --git a/app/globals.css b/app/globals.css index b7c18bb..0c0cc65 100644 --- a/app/globals.css +++ b/app/globals.css @@ -76,14 +76,66 @@ } @layer components { -} + .slider { + --handle-size: 16px; + --handle-radius: 1000px; + --track-size: 3px; + --bg: white; + --track-color: #d1d5db; + --handle-color: hsl(250deg 100% 50%); + --track-active-color: hsl(0deg 0% 50% / 0.125); + --handle-active-color: hsl(250deg 100% 70%); + + display: block; + width: 100%; + background: transparent; + appearance: none; + outline-offset: 6px; + cursor: pointer; + } -@layer utilities { - .clip-path-none { - clip-path: none; + .slider::-webkit-slider-thumb { + appearance: none; + height: var(--handle-size); + width: var(--handle-size); + border-radius: var(--handle-radius); + background: var(--handle-color); + cursor: grab; + transform: translateY(calc(-50% + var(--track-size) / 2)); + outline: 2px solid var(--bg); + } + + .slider::-moz-range-thumb { + background: var(--handle-color); + border: 2px solid var(--bg); + border-radius: var(--handle-radius); + height: var(--handle-size); + width: var(--handle-size); + } + + .slider:active::-webkit-slider-thumb, + .slider:active::-moz-range-thumb { + cursor: grabbing; + background: var(--handle-active-color); } - .clip-path-halfCircle { - clip-path: polygon(50% 0, 100% 0, 100% 100%, 50% 100%); + .slider::-webkit-slider-runnable-track { + width: calc(100% - var(--handle-size)); + height: var(--track-size); + background: var(--track-color); + border-radius: var(--track-size) / 2; + margin: calc(var(--handle-size) / 2) 0; } + + .slider::-moz-range-track { + background: var(--track-color); + } + + .slider:active::-webkit-slider-runnable-track, + .slider:active::-moz-range-track { + background: var(--track-active-color); + } +} + +@layer utilities { } diff --git a/components/Slider/Slider.stories.tsx b/components/Slider/Slider.stories.tsx new file mode 100644 index 0000000..20d74af --- /dev/null +++ b/components/Slider/Slider.stories.tsx @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import Slider from './Slider'; + +const meta: Meta = { + title: 'Components/Slider', + component: Slider, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + decorators: [ + Story => ( +
+ +
+ ), + ], +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + label: 'Volume', + min: 0, + max: 100, + }, +}; diff --git a/components/Slider/Slider.tsx b/components/Slider/Slider.tsx new file mode 100644 index 0000000..59f1a9f --- /dev/null +++ b/components/Slider/Slider.tsx @@ -0,0 +1,49 @@ +import React from 'react'; + +type SliderProps = { + /** + * label description for the slider + */ + label: string; + /** + * the minimum value for the slider + */ + min: number; + /** + * the maximum value for the slider + */ + max: number; + /** + * the current value of the slider + */ + value: number; + /** + * handler for the slider value change + */ + onChange: (event: React.ChangeEvent) => void; +}; + +const Slider = (props: SliderProps) => { + const { label, min, max, value, onChange } = props; + + const id = React.useId(); + + return ( +
+ + +
+ ); +}; + +export default Slider; diff --git a/components/Slider/index.tsx b/components/Slider/index.tsx new file mode 100644 index 0000000..9898d6a --- /dev/null +++ b/components/Slider/index.tsx @@ -0,0 +1 @@ +export { default } from './Slider';