Skip to content

Commit 95978e0

Browse files
committed
feat: add slider component
1 parent d20966d commit 95978e0

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import React from "react";
3+
import { Slider } from "./Slider";
4+
5+
const meta: Meta<typeof Slider> = {
6+
title: "components/Slider",
7+
component: Slider,
8+
args: {},
9+
argTypes: {
10+
value: {
11+
control: "number",
12+
description: "The controlled value of the slider",
13+
},
14+
defaultValue: {
15+
control: "number",
16+
description: "The default value when initially rendered",
17+
},
18+
disabled: {
19+
control: "boolean",
20+
description:
21+
"When true, prevents the user from interacting with the slider",
22+
},
23+
},
24+
};
25+
26+
export default meta;
27+
type Story = StoryObj<typeof Slider>;
28+
29+
export const Default: Story = {};
30+
31+
export const Controlled: Story = {
32+
render: (args) => {
33+
const [value, setValue] = React.useState(50);
34+
return (
35+
<Slider {...args} value={[value]} onValueChange={([v]) => setValue(v)} />
36+
);
37+
},
38+
args: { value: [50], min: 0, max: 100, step: 1 },
39+
};
40+
41+
export const Uncontrolled: Story = {
42+
args: { defaultValue: [30], min: 0, max: 100, step: 1 },
43+
};
44+
45+
export const Disabled: Story = {
46+
args: { defaultValue: [40], disabled: true },
47+
};
48+
49+
export const MultipleThumbs: Story = {
50+
args: {
51+
defaultValue: [20, 80],
52+
min: 0,
53+
max: 100,
54+
step: 5,
55+
minStepsBetweenThumbs: 1,
56+
},
57+
};

site/src/components/Slider/Slider.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Copied from shadc/ui on 04/16/2025
3+
* @see {@link https://ui.shadcn.com/docs/components/slider}
4+
*/
5+
import * as SliderPrimitive from "@radix-ui/react-slider";
6+
import * as React from "react";
7+
8+
import { cn } from "utils/cn";
9+
10+
export const Slider = React.forwardRef<
11+
React.ElementRef<typeof SliderPrimitive.Root>,
12+
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
13+
>(({ className, ...props }, ref) => (
14+
<SliderPrimitive.Root
15+
ref={ref}
16+
className={cn(
17+
"relative flex w-full touch-none select-none items-center h-1.5",
18+
className,
19+
)}
20+
{...props}
21+
>
22+
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-surface-secondary data-[disabled]:opacity-40">
23+
<SliderPrimitive.Range className="absolute h-full bg-content-primary" />
24+
</SliderPrimitive.Track>
25+
<SliderPrimitive.Thumb
26+
className="block h-4 w-4 rounded-full border border-solid border-surface-invert-secondary bg-surface-primary shadow transition-colors
27+
focus-visible:outline-none hover:border-content-primary
28+
focus-visible:ring-0 focus-visible:ring-content-primary focus-visible:ring-offset-surface-primary
29+
disabled:pointer-events-none data-[disabled]:opacity-100 data-[disabled]:border-border"
30+
/>
31+
<SliderPrimitive.Thumb
32+
className="block h-4 w-4 rounded-full border border-solid border-surface-invert-secondary bg-surface-primary shadow transition-colors
33+
focus-visible:outline-none hover:border-content-primary
34+
focus-visible:ring-0 focus-visible:ring-content-primary focus-visible:ring-offset-surface-primary
35+
disabled:pointer-events-none data-[disabled]:opacity-100 data-[disabled]:border-border"
36+
/>
37+
</SliderPrimitive.Root>
38+
));

0 commit comments

Comments
 (0)