From 03c4d56a91bc410aaea2a2481a34c135fdd4702b Mon Sep 17 00:00:00 2001 From: JimmFly Date: Thu, 22 Aug 2024 04:24:36 +0000 Subject: [PATCH] feat(component): add slider ui component (#7879) ![CleanShot 2024-08-15 at 14 27 07@2x](https://github.com/user-attachments/assets/50299f44-6446-4ec8-a097-7d456ff67f46) --- packages/frontend/component/package.json | 1 + packages/frontend/component/src/index.ts | 1 + .../component/src/ui/slider/index.css.ts | 57 ++++++++++++++ .../frontend/component/src/ui/slider/index.ts | 1 + .../src/ui/slider/slider.stories.tsx | 24 ++++++ .../component/src/ui/slider/slider.tsx | 75 +++++++++++++++++++ yarn.lock | 1 + 7 files changed, 160 insertions(+) create mode 100644 packages/frontend/component/src/ui/slider/index.css.ts create mode 100644 packages/frontend/component/src/ui/slider/index.ts create mode 100644 packages/frontend/component/src/ui/slider/slider.stories.tsx create mode 100644 packages/frontend/component/src/ui/slider/slider.tsx diff --git a/packages/frontend/component/package.json b/packages/frontend/component/package.json index cfb9c11c3f..97b5f714a9 100644 --- a/packages/frontend/component/package.json +++ b/packages/frontend/component/package.json @@ -43,6 +43,7 @@ "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-scroll-area": "^1.0.5", + "@radix-ui/react-slider": "^1.2.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-toast": "^1.1.5", diff --git a/packages/frontend/component/src/index.ts b/packages/frontend/component/src/index.ts index f93554d6f5..13b2b77e33 100644 --- a/packages/frontend/component/src/index.ts +++ b/packages/frontend/component/src/index.ts @@ -22,6 +22,7 @@ export * from './ui/popover'; export * from './ui/radio'; export * from './ui/scrollbar'; export * from './ui/skeleton'; +export * from './ui/slider'; export * from './ui/switch'; export * from './ui/table'; export * from './ui/tabs'; diff --git a/packages/frontend/component/src/ui/slider/index.css.ts b/packages/frontend/component/src/ui/slider/index.css.ts new file mode 100644 index 0000000000..4d2811098e --- /dev/null +++ b/packages/frontend/component/src/ui/slider/index.css.ts @@ -0,0 +1,57 @@ +import { cssVarV2 } from '@toeverything/theme/v2'; +import { style } from '@vanilla-extract/css'; + +export const trackStyle = style({ + width: '100%', + height: '1px', + position: 'relative', + display: 'flex', + alignItems: 'center', + padding: '12px 0', + cursor: 'pointer', +}); +export const fakeTrackStyle = style({ + width: '100%', + height: '1px', + backgroundColor: cssVarV2('layer/insideBorder/border'), + position: 'relative', + display: 'flex', + justifyContent: 'space-between', +}); + +export const filledTrackStyle = style({ + height: '100%', + backgroundColor: cssVarV2('icon/primary'), + borderRadius: '1px', + position: 'absolute', + top: '0', + left: '0', +}); + +export const thumbStyle = style({ + width: '8px', + height: '8px', + backgroundColor: cssVarV2('icon/primary'), + borderRadius: '50%', + position: 'absolute', + top: '50%', + transform: 'translate(-50%, -50%)', + cursor: 'pointer', +}); + +export const nodeStyle = style({ + width: '4px', + height: '4px', + border: '2px solid transparent', + backgroundColor: cssVarV2('layer/insideBorder/border'), + borderRadius: '50%', + position: 'absolute', + top: '50%', + cursor: 'pointer', + transform: 'translate(-50%, -50%)', + selectors: { + '&[data-active="true"]': { + backgroundColor: cssVarV2('icon/primary'), + }, + }, +}); diff --git a/packages/frontend/component/src/ui/slider/index.ts b/packages/frontend/component/src/ui/slider/index.ts new file mode 100644 index 0000000000..eb0742f801 --- /dev/null +++ b/packages/frontend/component/src/ui/slider/index.ts @@ -0,0 +1 @@ +export * from './slider'; diff --git a/packages/frontend/component/src/ui/slider/slider.stories.tsx b/packages/frontend/component/src/ui/slider/slider.stories.tsx new file mode 100644 index 0000000000..900dc4e26c --- /dev/null +++ b/packages/frontend/component/src/ui/slider/slider.stories.tsx @@ -0,0 +1,24 @@ +import type { Meta, StoryFn } from '@storybook/react'; +import { useState } from 'react'; + +import type { SliderProps } from './index'; +import { Slider } from './index'; + +export default { + title: 'UI/Slider', + component: Slider, +} satisfies Meta; + +const Template: StoryFn = args => { + const [value, setValue] = useState([0]); + return ; +}; + +export const Default: StoryFn = Template.bind(undefined); +Default.args = { + min: 0, + max: 10, + width: 500, + step: 1, + nodes: [0, 5, 10], +}; diff --git a/packages/frontend/component/src/ui/slider/slider.tsx b/packages/frontend/component/src/ui/slider/slider.tsx new file mode 100644 index 0000000000..cba5734ce5 --- /dev/null +++ b/packages/frontend/component/src/ui/slider/slider.tsx @@ -0,0 +1,75 @@ +import * as Sliders from '@radix-ui/react-slider'; +import { useRef } from 'react'; + +import * as styles from './index.css'; + +export interface SliderProps extends Sliders.SliderProps { + width?: number; + containerStyle?: React.CSSProperties; + rootStyle?: React.CSSProperties; + trackStyle?: React.CSSProperties; + rangeStyle?: React.CSSProperties; + thumbStyle?: React.CSSProperties; + noteStyle?: React.CSSProperties; + nodes?: number[]; // The values where the nodes should be placed +} + +export const Slider = ({ + value, + min = 0, + max = 10, + step, + width = 250, + nodes, + containerStyle, + rootStyle, + trackStyle, + rangeStyle, + thumbStyle, + noteStyle, + ...props +}: SliderProps) => { + const sliderRef = useRef(null); + + return ( +
+ + +
+ +
+ + {!!nodes && + nodes.map((nodeValue, index) => ( +
= nodeValue} + style={{ + left: `${((nodeValue - (min !== undefined ? min : 0)) / (max !== undefined ? max - (min !== undefined ? min : 0) : 1)) * 100}%`, + transform: + index === 0 + ? 'translateY(-50%)' + : index === nodes.length - 1 + ? 'translateY(-50%) translateX(-100%)' + : undefined, + ...noteStyle, + }} + /> + ))} + + + +
+ ); +}; diff --git a/yarn.lock b/yarn.lock index 86bf7480f0..2cf86d61b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -310,6 +310,7 @@ __metadata: "@radix-ui/react-popover": "npm:^1.0.7" "@radix-ui/react-radio-group": "npm:^1.1.3" "@radix-ui/react-scroll-area": "npm:^1.0.5" + "@radix-ui/react-slider": "npm:^1.2.0" "@radix-ui/react-slot": "npm:^1.1.0" "@radix-ui/react-tabs": "npm:^1.1.0" "@radix-ui/react-toast": "npm:^1.1.5"