tharaday 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitignore +30 -0
- package/.prettierrc.json +10 -0
- package/.storybook/main.ts +8 -0
- package/.storybook/preview.ts +50 -0
- package/.versionrc.json +6 -0
- package/README.md +73 -0
- package/dist/components/Accordion/Accordion.d.ts +2 -0
- package/dist/components/Accordion/Accordion.stories.d.ts +14 -0
- package/dist/components/Accordion/Accordion.types.d.ts +18 -0
- package/dist/components/Avatar/Avatar.d.ts +2 -0
- package/dist/components/Avatar/Avatar.stories.d.ts +14 -0
- package/dist/components/Avatar/Avatar.types.d.ts +10 -0
- package/dist/components/Badge/Badge.d.ts +2 -0
- package/dist/components/Badge/Badge.stories.d.ts +33 -0
- package/dist/components/Badge/Badge.types.d.ts +9 -0
- package/dist/components/Box/Box.d.ts +2 -0
- package/dist/components/Box/Box.stories.d.ts +38 -0
- package/dist/components/Box/Box.types.d.ts +49 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +3 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.stories.d.ts +13 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.types.d.ts +11 -0
- package/dist/components/Button/Button.d.ts +2 -0
- package/dist/components/Button/Button.stories.d.ts +22 -0
- package/dist/components/Button/Button.types.d.ts +12 -0
- package/dist/components/Card/Card.d.ts +5 -0
- package/dist/components/Card/Card.stories.d.ts +27 -0
- package/dist/components/Card/Card.types.d.ts +15 -0
- package/dist/components/Checkbox/Checkbox.d.ts +2 -0
- package/dist/components/Checkbox/Checkbox.stories.d.ts +17 -0
- package/dist/components/Checkbox/Checkbox.types.d.ts +6 -0
- package/dist/components/Dropdown/Dropdown.d.ts +2 -0
- package/dist/components/Dropdown/Dropdown.stories.d.ts +12 -0
- package/dist/components/Dropdown/Dropdown.types.d.ts +24 -0
- package/dist/components/Header/Header.d.ts +2 -0
- package/dist/components/Header/Header.stories.d.ts +18 -0
- package/dist/components/Header/Header.types.d.ts +14 -0
- package/dist/components/Input/Input.d.ts +2 -0
- package/dist/components/Input/Input.stories.d.ts +29 -0
- package/dist/components/Input/Input.types.d.ts +8 -0
- package/dist/components/Loader/Loader.d.ts +2 -0
- package/dist/components/Loader/Loader.stories.d.ts +25 -0
- package/dist/components/Loader/Loader.types.d.ts +8 -0
- package/dist/components/Modal/Modal.d.ts +2 -0
- package/dist/components/Modal/Modal.stories.d.ts +22 -0
- package/dist/components/Modal/Modal.types.d.ts +12 -0
- package/dist/components/NavBar/NavBar.d.ts +6 -0
- package/dist/components/NavBar/NavBar.stories.d.ts +8 -0
- package/dist/components/NavBar/NavBar.types.d.ts +34 -0
- package/dist/components/Notification/Notification.d.ts +2 -0
- package/dist/components/Notification/Notification.stories.d.ts +26 -0
- package/dist/components/Notification/Notification.types.d.ts +8 -0
- package/dist/components/Pagination/Pagination.d.ts +2 -0
- package/dist/components/Pagination/Pagination.stories.d.ts +21 -0
- package/dist/components/Pagination/Pagination.types.d.ts +34 -0
- package/dist/components/ProgressBar/ProgressBar.d.ts +2 -0
- package/dist/components/ProgressBar/ProgressBar.stories.d.ts +32 -0
- package/dist/components/ProgressBar/ProgressBar.types.d.ts +12 -0
- package/dist/components/RadioButton/RadioButton.d.ts +2 -0
- package/dist/components/RadioButton/RadioButton.stories.d.ts +30 -0
- package/dist/components/RadioButton/RadioButton.types.d.ts +8 -0
- package/dist/components/Select/Select.d.ts +2 -0
- package/dist/components/Select/Select.stories.d.ts +29 -0
- package/dist/components/Select/Select.types.d.ts +15 -0
- package/dist/components/Skeleton/Skeleton.d.ts +2 -0
- package/dist/components/Skeleton/Skeleton.stories.d.ts +15 -0
- package/dist/components/Skeleton/Skeleton.types.d.ts +8 -0
- package/dist/components/Stepper/Step.d.ts +2 -0
- package/dist/components/Stepper/Step.types.d.ts +17 -0
- package/dist/components/Stepper/Stepper.d.ts +2 -0
- package/dist/components/Stepper/Stepper.stories.d.ts +15 -0
- package/dist/components/Stepper/Stepper.types.d.ts +13 -0
- package/dist/components/Stepper/stepper.utils.d.ts +3 -0
- package/dist/components/Switch/Switch.d.ts +2 -0
- package/dist/components/Switch/Switch.stories.d.ts +16 -0
- package/dist/components/Switch/Switch.types.d.ts +5 -0
- package/dist/components/Table/Table.d.ts +8 -0
- package/dist/components/Table/Table.stories.d.ts +27 -0
- package/dist/components/Table/Table.types.d.ts +17 -0
- package/dist/components/Tabs/Tabs.d.ts +2 -0
- package/dist/components/Tabs/Tabs.stories.d.ts +14 -0
- package/dist/components/Tabs/Tabs.types.d.ts +16 -0
- package/dist/components/Text/Text.d.ts +2 -0
- package/dist/components/Text/Text.stories.d.ts +35 -0
- package/dist/components/Text/Text.types.d.ts +21 -0
- package/dist/components/Textarea/Textarea.d.ts +2 -0
- package/dist/components/Textarea/Textarea.stories.d.ts +29 -0
- package/dist/components/Textarea/Textarea.types.d.ts +9 -0
- package/dist/components/Tooltip/Tooltip.d.ts +2 -0
- package/dist/components/Tooltip/Tooltip.stories.d.ts +10 -0
- package/dist/components/Tooltip/Tooltip.types.d.ts +12 -0
- package/dist/ds.css +1 -0
- package/dist/ds.js +1930 -0
- package/dist/ds.umd.cjs +1 -0
- package/dist/index.d.ts +63 -0
- package/dist/layouts/AppLayout/AppLayout.d.ts +8 -0
- package/dist/layouts/AppLayout/AppLayout.stories.d.ts +19 -0
- package/dist/layouts/AppLayout/AppLayout.types.d.ts +50 -0
- package/dist/layouts/AuthLayout/AuthLayout.d.ts +2 -0
- package/dist/layouts/AuthLayout/AuthLayout.stories.d.ts +12 -0
- package/dist/layouts/AuthLayout/AuthLayout.types.d.ts +7 -0
- package/dist/layouts/DashboardLayout/DashboardLayout.d.ts +2 -0
- package/dist/layouts/DashboardLayout/DashboardLayout.stories.d.ts +17 -0
- package/dist/layouts/DashboardLayout/DashboardLayout.types.d.ts +15 -0
- package/dist/layouts/SettingsLayout/SettingsLayout.d.ts +2 -0
- package/dist/layouts/SettingsLayout/SettingsLayout.stories.d.ts +17 -0
- package/dist/layouts/SettingsLayout/SettingsLayout.types.d.ts +14 -0
- package/eslint.config.js +45 -0
- package/package.json +100 -0
- package/src/components/Accordion/Accordion.module.css +158 -0
- package/src/components/Accordion/Accordion.stories.tsx +133 -0
- package/src/components/Accordion/Accordion.tsx +68 -0
- package/src/components/Accordion/Accordion.types.ts +21 -0
- package/src/components/Avatar/Avatar.module.css +58 -0
- package/src/components/Avatar/Avatar.stories.tsx +41 -0
- package/src/components/Avatar/Avatar.tsx +64 -0
- package/src/components/Avatar/Avatar.types.ts +12 -0
- package/src/components/Badge/Badge.module.css +98 -0
- package/src/components/Badge/Badge.stories.tsx +108 -0
- package/src/components/Badge/Badge.tsx +22 -0
- package/src/components/Badge/Badge.types.ts +11 -0
- package/src/components/Box/Box.module.css +638 -0
- package/src/components/Box/Box.stories.tsx +109 -0
- package/src/components/Box/Box.tsx +95 -0
- package/src/components/Box/Box.types.ts +65 -0
- package/src/components/Breadcrumbs/Breadcrumbs.module.css +41 -0
- package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +40 -0
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +54 -0
- package/src/components/Breadcrumbs/Breadcrumbs.types.ts +13 -0
- package/src/components/Button/Button.module.css +247 -0
- package/src/components/Button/Button.stories.tsx +93 -0
- package/src/components/Button/Button.tsx +31 -0
- package/src/components/Button/Button.types.ts +14 -0
- package/src/components/Card/Card.module.css +112 -0
- package/src/components/Card/Card.stories.tsx +86 -0
- package/src/components/Card/Card.tsx +70 -0
- package/src/components/Card/Card.types.ts +20 -0
- package/src/components/Checkbox/Checkbox.module.css +88 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +65 -0
- package/src/components/Checkbox/Checkbox.tsx +57 -0
- package/src/components/Checkbox/Checkbox.types.ts +7 -0
- package/src/components/Dropdown/Dropdown.module.css +140 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +86 -0
- package/src/components/Dropdown/Dropdown.tsx +251 -0
- package/src/components/Dropdown/Dropdown.types.ts +27 -0
- package/src/components/Header/Header.module.css +38 -0
- package/src/components/Header/Header.stories.tsx +53 -0
- package/src/components/Header/Header.tsx +49 -0
- package/src/components/Header/Header.types.ts +15 -0
- package/src/components/Input/Input.module.css +87 -0
- package/src/components/Input/Input.stories.tsx +101 -0
- package/src/components/Input/Input.tsx +41 -0
- package/src/components/Input/Input.types.ts +10 -0
- package/src/components/Loader/Loader.module.css +49 -0
- package/src/components/Loader/Loader.stories.tsx +75 -0
- package/src/components/Loader/Loader.tsx +15 -0
- package/src/components/Loader/Loader.types.ts +9 -0
- package/src/components/Modal/Modal.module.css +88 -0
- package/src/components/Modal/Modal.stories.tsx +94 -0
- package/src/components/Modal/Modal.tsx +115 -0
- package/src/components/Modal/Modal.types.ts +13 -0
- package/src/components/NavBar/NavBar.module.css +77 -0
- package/src/components/NavBar/NavBar.stories.tsx +55 -0
- package/src/components/NavBar/NavBar.tsx +50 -0
- package/src/components/NavBar/NavBar.types.ts +36 -0
- package/src/components/Notification/Notification.module.css +72 -0
- package/src/components/Notification/Notification.stories.tsx +81 -0
- package/src/components/Notification/Notification.tsx +34 -0
- package/src/components/Notification/Notification.types.ts +10 -0
- package/src/components/Pagination/Pagination.module.css +31 -0
- package/src/components/Pagination/Pagination.stories.tsx +128 -0
- package/src/components/Pagination/Pagination.tsx +245 -0
- package/src/components/Pagination/Pagination.types.ts +37 -0
- package/src/components/ProgressBar/ProgressBar.module.css +67 -0
- package/src/components/ProgressBar/ProgressBar.stories.tsx +91 -0
- package/src/components/ProgressBar/ProgressBar.tsx +49 -0
- package/src/components/ProgressBar/ProgressBar.types.ts +13 -0
- package/src/components/RadioButton/RadioButton.module.css +162 -0
- package/src/components/RadioButton/RadioButton.stories.tsx +114 -0
- package/src/components/RadioButton/RadioButton.tsx +43 -0
- package/src/components/RadioButton/RadioButton.types.ts +10 -0
- package/src/components/Select/Select.module.css +88 -0
- package/src/components/Select/Select.stories.tsx +99 -0
- package/src/components/Select/Select.tsx +51 -0
- package/src/components/Select/Select.types.ts +18 -0
- package/src/components/Skeleton/Skeleton.module.css +71 -0
- package/src/components/Skeleton/Skeleton.stories.tsx +54 -0
- package/src/components/Skeleton/Skeleton.tsx +32 -0
- package/src/components/Skeleton/Skeleton.types.ts +10 -0
- package/src/components/Stepper/Step.module.css +162 -0
- package/src/components/Stepper/Step.tsx +62 -0
- package/src/components/Stepper/Step.types.ts +19 -0
- package/src/components/Stepper/Stepper.module.css +39 -0
- package/src/components/Stepper/Stepper.stories.tsx +88 -0
- package/src/components/Stepper/Stepper.tsx +47 -0
- package/src/components/Stepper/Stepper.types.ts +16 -0
- package/src/components/Stepper/stepper.utils.ts +41 -0
- package/src/components/Switch/Switch.module.css +74 -0
- package/src/components/Switch/Switch.stories.tsx +56 -0
- package/src/components/Switch/Switch.tsx +36 -0
- package/src/components/Switch/Switch.types.ts +6 -0
- package/src/components/Table/Table.module.css +78 -0
- package/src/components/Table/Table.stories.tsx +124 -0
- package/src/components/Table/Table.tsx +75 -0
- package/src/components/Table/Table.types.ts +29 -0
- package/src/components/Tabs/Tabs.module.css +74 -0
- package/src/components/Tabs/Tabs.stories.tsx +48 -0
- package/src/components/Tabs/Tabs.tsx +113 -0
- package/src/components/Tabs/Tabs.types.ts +18 -0
- package/src/components/Text/Text.module.css +126 -0
- package/src/components/Text/Text.stories.tsx +128 -0
- package/src/components/Text/Text.tsx +50 -0
- package/src/components/Text/Text.types.ts +43 -0
- package/src/components/Textarea/Textarea.module.css +82 -0
- package/src/components/Textarea/Textarea.stories.tsx +99 -0
- package/src/components/Textarea/Textarea.tsx +43 -0
- package/src/components/Textarea/Textarea.types.ts +11 -0
- package/src/components/Tooltip/Tooltip.module.css +125 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +68 -0
- package/src/components/Tooltip/Tooltip.tsx +87 -0
- package/src/components/Tooltip/Tooltip.types.ts +14 -0
- package/src/index.ts +132 -0
- package/src/layouts/AppLayout/AppLayout.module.css +17 -0
- package/src/layouts/AppLayout/AppLayout.stories.tsx +124 -0
- package/src/layouts/AppLayout/AppLayout.tsx +46 -0
- package/src/layouts/AppLayout/AppLayout.types.ts +50 -0
- package/src/layouts/AuthLayout/AuthLayout.module.css +49 -0
- package/src/layouts/AuthLayout/AuthLayout.stories.tsx +109 -0
- package/src/layouts/AuthLayout/AuthLayout.tsx +27 -0
- package/src/layouts/AuthLayout/AuthLayout.types.tsx +8 -0
- package/src/layouts/DashboardLayout/DashboardLayout.module.css +37 -0
- package/src/layouts/DashboardLayout/DashboardLayout.stories.tsx +144 -0
- package/src/layouts/DashboardLayout/DashboardLayout.tsx +41 -0
- package/src/layouts/DashboardLayout/DashboardLayout.types.tsx +14 -0
- package/src/layouts/SettingsLayout/SettingsLayout.module.css +39 -0
- package/src/layouts/SettingsLayout/SettingsLayout.stories.tsx +103 -0
- package/src/layouts/SettingsLayout/SettingsLayout.tsx +37 -0
- package/src/layouts/SettingsLayout/SettingsLayout.types.tsx +13 -0
- package/src/styles/ds.css +12 -0
- package/src/styles/semantic.css +56 -0
- package/src/styles/themes/dark.css +58 -0
- package/src/styles/themes/light.css +58 -0
- package/src/styles/themes/retro.css +58 -0
- package/src/styles/tokens.css +138 -0
- package/tsconfig.app.json +28 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +26 -0
- package/vite.config.ts +33 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { useId } from 'react';
|
|
3
|
+
|
|
4
|
+
import { Step } from './Step.tsx';
|
|
5
|
+
import styles from './Stepper.module.css';
|
|
6
|
+
import type { StepperProps } from './Stepper.types.ts';
|
|
7
|
+
import { getStepStatus, resolveCurrentIndex } from './stepper.utils.ts';
|
|
8
|
+
|
|
9
|
+
export const Stepper = ({
|
|
10
|
+
steps,
|
|
11
|
+
currentStep,
|
|
12
|
+
orientation = 'horizontal',
|
|
13
|
+
size = 'md',
|
|
14
|
+
onStepClick,
|
|
15
|
+
ariaLabel,
|
|
16
|
+
className,
|
|
17
|
+
id,
|
|
18
|
+
...props
|
|
19
|
+
}: StepperProps) => {
|
|
20
|
+
const baseId = useId();
|
|
21
|
+
const componentId = id ?? `ds-stepper-${baseId}`;
|
|
22
|
+
const currentIndex = resolveCurrentIndex(currentStep, steps);
|
|
23
|
+
const listLabel = ariaLabel ?? 'Progress';
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<ol
|
|
27
|
+
id={componentId}
|
|
28
|
+
className={clsx(styles.root, styles[orientation], styles[size], className)}
|
|
29
|
+
aria-label={listLabel}
|
|
30
|
+
data-orientation={orientation}
|
|
31
|
+
{...props}
|
|
32
|
+
>
|
|
33
|
+
{steps.map((step, index) => (
|
|
34
|
+
<Step
|
|
35
|
+
key={step.id}
|
|
36
|
+
id={`${componentId}-step-${step.id}`}
|
|
37
|
+
step={step}
|
|
38
|
+
index={index}
|
|
39
|
+
status={getStepStatus(index, currentIndex, step.status)}
|
|
40
|
+
isInteractive={Boolean(onStepClick)}
|
|
41
|
+
onStepClick={onStepClick}
|
|
42
|
+
isLast={index === steps.length - 1}
|
|
43
|
+
/>
|
|
44
|
+
))}
|
|
45
|
+
</ol>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { StepOptions } from './Step.types.ts';
|
|
4
|
+
|
|
5
|
+
export type StepperOrientation = 'horizontal' | 'vertical';
|
|
6
|
+
export type StepperSize = 'sm' | 'md' | 'lg';
|
|
7
|
+
|
|
8
|
+
export interface StepperProps extends HTMLAttributes<HTMLOListElement> {
|
|
9
|
+
steps: StepOptions[];
|
|
10
|
+
currentStep?: number | string;
|
|
11
|
+
orientation?: StepperOrientation;
|
|
12
|
+
size?: StepperSize;
|
|
13
|
+
onStepClick?: (step: StepOptions, index: number) => void;
|
|
14
|
+
ariaLabel?: string;
|
|
15
|
+
id?: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { StepperStatus, StepOptions } from './Step.types.ts';
|
|
2
|
+
|
|
3
|
+
const clampIndex = (index: number, length: number) => {
|
|
4
|
+
if (Number.isNaN(index) || length <= 0) {
|
|
5
|
+
return -1;
|
|
6
|
+
}
|
|
7
|
+
return Math.min(Math.max(index, 0), length - 1);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const resolveCurrentIndex = (
|
|
11
|
+
currentStep: number | string | undefined,
|
|
12
|
+
steps: StepOptions[]
|
|
13
|
+
) => {
|
|
14
|
+
if (typeof currentStep === 'number') {
|
|
15
|
+
return clampIndex(currentStep, steps.length);
|
|
16
|
+
}
|
|
17
|
+
if (typeof currentStep === 'string') {
|
|
18
|
+
return steps.findIndex((step) => step.id === currentStep);
|
|
19
|
+
}
|
|
20
|
+
return steps.findIndex((step) => step.status === 'current');
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const getStepStatus = (
|
|
24
|
+
index: number,
|
|
25
|
+
currentIndex: number,
|
|
26
|
+
stepStatus?: StepperStatus
|
|
27
|
+
): StepperStatus => {
|
|
28
|
+
if (stepStatus) {
|
|
29
|
+
return stepStatus;
|
|
30
|
+
}
|
|
31
|
+
if (currentIndex === -1) {
|
|
32
|
+
return 'upcoming';
|
|
33
|
+
}
|
|
34
|
+
if (index < currentIndex) {
|
|
35
|
+
return 'completed';
|
|
36
|
+
}
|
|
37
|
+
if (index === currentIndex) {
|
|
38
|
+
return 'current';
|
|
39
|
+
}
|
|
40
|
+
return 'upcoming';
|
|
41
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: var(--ds-space-1);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.container {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
gap: var(--ds-space-3);
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
user-select: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.container.disabled {
|
|
16
|
+
cursor: not-allowed;
|
|
17
|
+
opacity: 0.5;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.input {
|
|
21
|
+
position: absolute;
|
|
22
|
+
opacity: 0;
|
|
23
|
+
width: 0;
|
|
24
|
+
height: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.track {
|
|
28
|
+
position: relative;
|
|
29
|
+
width: 2.5rem;
|
|
30
|
+
height: 1.25rem;
|
|
31
|
+
background-color: var(--ds-border-1);
|
|
32
|
+
border-radius: var(--ds-radius-full);
|
|
33
|
+
transition: background-color var(--ds-transition-fast);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.input:checked ~ .track {
|
|
37
|
+
background-color: var(--ds-info);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.input:focus-visible ~ .track {
|
|
41
|
+
box-shadow:
|
|
42
|
+
0 0 0 2px var(--ds-ring-offset),
|
|
43
|
+
0 0 0 4px var(--ds-ring);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.thumb {
|
|
47
|
+
position: absolute;
|
|
48
|
+
top: 0.125rem;
|
|
49
|
+
left: 0.125rem;
|
|
50
|
+
width: 1rem;
|
|
51
|
+
height: 1rem;
|
|
52
|
+
background-color: white;
|
|
53
|
+
border-radius: var(--ds-radius-full);
|
|
54
|
+
transition: transform var(--ds-transition-fast);
|
|
55
|
+
box-shadow: var(--ds-shadow-sm);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.input:checked ~ .track .thumb {
|
|
59
|
+
transform: translateX(1.25rem);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.label {
|
|
63
|
+
font-family: var(--ds-font-family-base);
|
|
64
|
+
font-size: var(--ds-font-size-sm);
|
|
65
|
+
color: var(--ds-text-1);
|
|
66
|
+
font-weight: var(--ds-font-weight-medium);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.helperText {
|
|
70
|
+
font-family: var(--ds-font-family-base);
|
|
71
|
+
font-size: var(--ds-font-size-xs);
|
|
72
|
+
color: var(--ds-text-2);
|
|
73
|
+
margin-left: calc(2.5rem + var(--ds-space-3));
|
|
74
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { Switch } from './Switch.tsx';
|
|
4
|
+
import { Box } from '../Box/Box.tsx';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/Switch',
|
|
8
|
+
component: Switch,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: 'centered',
|
|
12
|
+
},
|
|
13
|
+
} satisfies Meta<typeof Switch>;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof meta>;
|
|
17
|
+
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
label: 'Dark Mode',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const Checked: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
label: 'Enable push notifications',
|
|
27
|
+
defaultChecked: true,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const WithHelperText: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
label: 'Public Profile',
|
|
34
|
+
helperText: 'Making your profile public allows others to find you.',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Disabled: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
label: 'Disabled setting',
|
|
41
|
+
disabled: true,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const All: Story = {
|
|
46
|
+
name: 'Gallery',
|
|
47
|
+
render: () => (
|
|
48
|
+
<Box display="flex" flexDirection="column" gap={6}>
|
|
49
|
+
<Switch label="Default" />
|
|
50
|
+
<Switch label="Checked" defaultChecked />
|
|
51
|
+
<Switch label="With Helper Text" helperText="Additional information here" />
|
|
52
|
+
<Switch label="Disabled" disabled />
|
|
53
|
+
<Switch label="Disabled Checked" disabled defaultChecked />
|
|
54
|
+
</Box>
|
|
55
|
+
),
|
|
56
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { useId } from 'react';
|
|
3
|
+
|
|
4
|
+
import styles from './Switch.module.css';
|
|
5
|
+
import type { SwitchProps } from './Switch.types.ts';
|
|
6
|
+
|
|
7
|
+
export const Switch = ({ label, helperText, className, disabled, id, ...props }: SwitchProps) => {
|
|
8
|
+
const baseId = useId();
|
|
9
|
+
const componentId = id ?? `ds-switch-${baseId}`;
|
|
10
|
+
const helperId = helperText ? `${componentId}-help` : undefined;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div className={clsx(styles.wrapper, className)}>
|
|
14
|
+
<label htmlFor={componentId} className={clsx(styles.container, disabled && styles.disabled)}>
|
|
15
|
+
<input
|
|
16
|
+
type="checkbox"
|
|
17
|
+
id={componentId}
|
|
18
|
+
role="switch"
|
|
19
|
+
disabled={disabled}
|
|
20
|
+
className={styles.input}
|
|
21
|
+
aria-describedby={helperId}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
<span className={styles.track}>
|
|
25
|
+
<span className={styles.thumb} />
|
|
26
|
+
</span>
|
|
27
|
+
{label && <span className={styles.label}>{label}</span>}
|
|
28
|
+
</label>
|
|
29
|
+
{helperText && (
|
|
30
|
+
<span id={helperId} className={styles.helperText}>
|
|
31
|
+
{helperText}
|
|
32
|
+
</span>
|
|
33
|
+
)}
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
width: 100%;
|
|
3
|
+
overflow-x: auto;
|
|
4
|
+
border: 1px solid var(--ds-border-1);
|
|
5
|
+
border-radius: var(--ds-radius-md);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.table {
|
|
9
|
+
width: 100%;
|
|
10
|
+
border-collapse: collapse;
|
|
11
|
+
font-family: var(--ds-font-family-base);
|
|
12
|
+
font-size: var(--ds-font-size-sm);
|
|
13
|
+
color: var(--ds-text-1);
|
|
14
|
+
background-color: var(--ds-surface-0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.thead {
|
|
18
|
+
background-color: var(--ds-surface-1);
|
|
19
|
+
border-bottom: 0.125rem solid var(--ds-border-1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.tbody .tr {
|
|
23
|
+
border-bottom: 1px solid var(--ds-border-1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.tbody .tr:last-child {
|
|
27
|
+
border-bottom: none;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.th {
|
|
31
|
+
padding: var(--ds-space-3) var(--ds-space-4);
|
|
32
|
+
font-weight: var(--ds-font-weight-bold);
|
|
33
|
+
text-align: left;
|
|
34
|
+
color: var(--ds-text-2);
|
|
35
|
+
text-transform: uppercase;
|
|
36
|
+
font-size: var(--ds-font-size-xs);
|
|
37
|
+
letter-spacing: 0.05em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.td {
|
|
41
|
+
padding: var(--ds-space-4);
|
|
42
|
+
vertical-align: middle;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Modifiers */
|
|
46
|
+
.striped .tbody .tr:nth-child(even) {
|
|
47
|
+
background-color: var(--ds-surface-1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.hoverable .tbody .tr:hover {
|
|
51
|
+
background-color: var(--ds-surface-1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.dense .th {
|
|
55
|
+
padding: var(--ds-space-2) var(--ds-space-4);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.dense .td {
|
|
59
|
+
padding: var(--ds-space-2) var(--ds-space-4);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.align-left {
|
|
63
|
+
text-align: left;
|
|
64
|
+
}
|
|
65
|
+
.align-center {
|
|
66
|
+
text-align: center;
|
|
67
|
+
}
|
|
68
|
+
.align-right {
|
|
69
|
+
text-align: right;
|
|
70
|
+
}
|
|
71
|
+
.align-justify {
|
|
72
|
+
text-align: justify;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.loading {
|
|
76
|
+
opacity: 0.7;
|
|
77
|
+
pointer-events: none;
|
|
78
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from './Table.tsx';
|
|
4
|
+
import { Badge } from '../Badge/Badge.tsx';
|
|
5
|
+
import { Button } from '../Button/Button.tsx';
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'Components/Table',
|
|
9
|
+
component: Table,
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: 'padded',
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
striped: { control: 'boolean' },
|
|
16
|
+
hoverable: { control: 'boolean' },
|
|
17
|
+
dense: { control: 'boolean' },
|
|
18
|
+
},
|
|
19
|
+
} satisfies Meta<typeof Table>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
type Story = StoryObj<typeof meta>;
|
|
23
|
+
|
|
24
|
+
const data = [
|
|
25
|
+
{ id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin', status: 'Active' },
|
|
26
|
+
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'Editor', status: 'Active' },
|
|
27
|
+
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Viewer', status: 'Inactive' },
|
|
28
|
+
{ id: 4, name: 'Alice Williams', email: 'alice@example.com', role: 'Admin', status: 'Active' },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export const Default: Story = {
|
|
32
|
+
render: (args) => (
|
|
33
|
+
<Table {...args}>
|
|
34
|
+
<TableHeader>
|
|
35
|
+
<TableRow>
|
|
36
|
+
<TableHead>Name</TableHead>
|
|
37
|
+
<TableHead>Email</TableHead>
|
|
38
|
+
<TableHead>Role</TableHead>
|
|
39
|
+
<TableHead>Status</TableHead>
|
|
40
|
+
<TableHead align="right">Actions</TableHead>
|
|
41
|
+
</TableRow>
|
|
42
|
+
</TableHeader>
|
|
43
|
+
<TableBody>
|
|
44
|
+
{data.map((row) => (
|
|
45
|
+
<TableRow key={row.id}>
|
|
46
|
+
<TableCell>{row.name}</TableCell>
|
|
47
|
+
<TableCell>{row.email}</TableCell>
|
|
48
|
+
<TableCell>{row.role}</TableCell>
|
|
49
|
+
<TableCell>
|
|
50
|
+
<Badge
|
|
51
|
+
intent={row.status === 'Active' ? 'success' : 'neutral'}
|
|
52
|
+
variant="subtle"
|
|
53
|
+
size="sm"
|
|
54
|
+
>
|
|
55
|
+
{row.status}
|
|
56
|
+
</Badge>
|
|
57
|
+
</TableCell>
|
|
58
|
+
<TableCell align="right">
|
|
59
|
+
<Button variant="subtle" size="xs">
|
|
60
|
+
Edit
|
|
61
|
+
</Button>
|
|
62
|
+
</TableCell>
|
|
63
|
+
</TableRow>
|
|
64
|
+
))}
|
|
65
|
+
</TableBody>
|
|
66
|
+
</Table>
|
|
67
|
+
),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const Striped: Story = {
|
|
71
|
+
...Default,
|
|
72
|
+
args: {
|
|
73
|
+
striped: true,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const Hoverable: Story = {
|
|
78
|
+
...Default,
|
|
79
|
+
args: {
|
|
80
|
+
hoverable: true,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const Dense: Story = {
|
|
85
|
+
...Default,
|
|
86
|
+
args: {
|
|
87
|
+
dense: true,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const TanStackTableExample: Story = {
|
|
92
|
+
parameters: {
|
|
93
|
+
docs: {
|
|
94
|
+
description: {
|
|
95
|
+
story:
|
|
96
|
+
'This example shows how you could wrap TanStack Table using our Table components. (Simulated integration)',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
render: (args) => {
|
|
101
|
+
// This is a simplified example of how TanStack table would render.
|
|
102
|
+
// In a real scenario, you'd use flexRender, getHeaderGroups, getRowModel, etc.
|
|
103
|
+
return (
|
|
104
|
+
<Table {...args}>
|
|
105
|
+
<TableHeader>
|
|
106
|
+
<TableRow>
|
|
107
|
+
<TableHead>Column A</TableHead>
|
|
108
|
+
<TableHead>Column B</TableHead>
|
|
109
|
+
</TableRow>
|
|
110
|
+
</TableHeader>
|
|
111
|
+
<TableBody>
|
|
112
|
+
<TableRow>
|
|
113
|
+
<TableCell>Data A1</TableCell>
|
|
114
|
+
<TableCell>Data B1</TableCell>
|
|
115
|
+
</TableRow>
|
|
116
|
+
<TableRow>
|
|
117
|
+
<TableCell>Data A2</TableCell>
|
|
118
|
+
<TableCell>Data B2</TableCell>
|
|
119
|
+
</TableRow>
|
|
120
|
+
</TableBody>
|
|
121
|
+
</Table>
|
|
122
|
+
);
|
|
123
|
+
},
|
|
124
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
|
|
3
|
+
import styles from './Table.module.css';
|
|
4
|
+
import type {
|
|
5
|
+
TableProps,
|
|
6
|
+
TableHeaderProps,
|
|
7
|
+
TableBodyProps,
|
|
8
|
+
TableFooterProps,
|
|
9
|
+
TableRowProps,
|
|
10
|
+
TableHeadProps,
|
|
11
|
+
TableCellProps,
|
|
12
|
+
} from './Table.types.ts';
|
|
13
|
+
|
|
14
|
+
export const Table = ({
|
|
15
|
+
children,
|
|
16
|
+
className,
|
|
17
|
+
striped,
|
|
18
|
+
hoverable,
|
|
19
|
+
dense,
|
|
20
|
+
isLoading,
|
|
21
|
+
...props
|
|
22
|
+
}: TableProps) => {
|
|
23
|
+
return (
|
|
24
|
+
<div className={clsx(styles.wrapper, isLoading && styles.loading, className)}>
|
|
25
|
+
<table
|
|
26
|
+
className={clsx(
|
|
27
|
+
styles.table,
|
|
28
|
+
striped && styles.striped,
|
|
29
|
+
hoverable && styles.hoverable,
|
|
30
|
+
dense && styles.dense
|
|
31
|
+
)}
|
|
32
|
+
aria-busy={isLoading || undefined}
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</table>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const TableHeader = ({ children, className, ...props }: TableHeaderProps) => (
|
|
42
|
+
<thead className={clsx(styles.thead, className)} {...props}>
|
|
43
|
+
{children}
|
|
44
|
+
</thead>
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export const TableBody = ({ children, className, ...props }: TableBodyProps) => (
|
|
48
|
+
<tbody className={clsx(styles.tbody, className)} {...props}>
|
|
49
|
+
{children}
|
|
50
|
+
</tbody>
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
export const TableFooter = ({ children, className, ...props }: TableFooterProps) => (
|
|
54
|
+
<tfoot className={clsx(styles.tfoot, className)} {...props}>
|
|
55
|
+
{children}
|
|
56
|
+
</tfoot>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export const TableRow = ({ children, className, ...props }: TableRowProps) => (
|
|
60
|
+
<tr className={clsx(styles.tr, className)} {...props}>
|
|
61
|
+
{children}
|
|
62
|
+
</tr>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
export const TableHead = ({ children, className, align, ...props }: TableHeadProps) => (
|
|
66
|
+
<th className={clsx(styles.th, align && styles[`align-${align}`], className)} {...props}>
|
|
67
|
+
{children}
|
|
68
|
+
</th>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
export const TableCell = ({ children, className, align, ...props }: TableCellProps) => (
|
|
72
|
+
<td className={clsx(styles.td, align && styles[`align-${align}`], className)} {...props}>
|
|
73
|
+
{children}
|
|
74
|
+
</td>
|
|
75
|
+
);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
HTMLAttributes,
|
|
3
|
+
TableHTMLAttributes,
|
|
4
|
+
TdHTMLAttributes,
|
|
5
|
+
ThHTMLAttributes,
|
|
6
|
+
} from 'react';
|
|
7
|
+
|
|
8
|
+
export interface TableProps extends TableHTMLAttributes<HTMLTableElement> {
|
|
9
|
+
striped?: boolean;
|
|
10
|
+
hoverable?: boolean;
|
|
11
|
+
dense?: boolean;
|
|
12
|
+
isLoading?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type TableHeaderProps = HTMLAttributes<HTMLTableSectionElement>;
|
|
16
|
+
|
|
17
|
+
export type TableBodyProps = HTMLAttributes<HTMLTableSectionElement>;
|
|
18
|
+
|
|
19
|
+
export type TableFooterProps = HTMLAttributes<HTMLTableSectionElement>;
|
|
20
|
+
|
|
21
|
+
export type TableRowProps = HTMLAttributes<HTMLTableRowElement>;
|
|
22
|
+
|
|
23
|
+
export interface TableHeadProps extends ThHTMLAttributes<HTMLTableCellElement> {
|
|
24
|
+
align?: 'left' | 'center' | 'right' | 'justify' | 'char';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface TableCellProps extends TdHTMLAttributes<HTMLTableCellElement> {
|
|
28
|
+
align?: 'left' | 'center' | 'right' | 'justify' | 'char';
|
|
29
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
width: 100%;
|
|
5
|
+
font-family: var(--ds-font-family-base);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.tabList {
|
|
9
|
+
display: flex;
|
|
10
|
+
gap: var(--ds-space-4);
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
list-style: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.tabItem {
|
|
17
|
+
all: unset;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
padding: var(--ds-space-2) var(--ds-space-1);
|
|
20
|
+
font-size: var(--ds-font-size-sm);
|
|
21
|
+
font-weight: var(--ds-font-weight-medium);
|
|
22
|
+
color: var(--ds-text-2);
|
|
23
|
+
transition: all var(--ds-transition-fast);
|
|
24
|
+
border-bottom: 0.125rem solid transparent;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.tabItem:hover:not(.disabled):not(.active) {
|
|
28
|
+
color: var(--ds-text-1);
|
|
29
|
+
border-bottom-color: var(--ds-border-1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.tabItem:focus-visible {
|
|
33
|
+
outline: none;
|
|
34
|
+
box-shadow:
|
|
35
|
+
0 0 0 2px var(--ds-ring-offset),
|
|
36
|
+
0 0 0 4px var(--ds-ring);
|
|
37
|
+
border-radius: var(--ds-radius-sm);
|
|
38
|
+
z-index: 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.tabItem.active {
|
|
42
|
+
color: var(--ds-info);
|
|
43
|
+
border-bottom-color: var(--ds-info);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.tabItem.disabled {
|
|
47
|
+
cursor: not-allowed;
|
|
48
|
+
opacity: 0.5;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* Pill variant */
|
|
52
|
+
.pillList {
|
|
53
|
+
gap: var(--ds-space-2);
|
|
54
|
+
background-color: var(--ds-surface-1);
|
|
55
|
+
padding: var(--ds-space-1);
|
|
56
|
+
border-radius: var(--ds-radius-md);
|
|
57
|
+
width: fit-content;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.pillItem {
|
|
61
|
+
padding: var(--ds-space-1) var(--ds-space-4);
|
|
62
|
+
border-radius: var(--ds-radius-sm);
|
|
63
|
+
border-bottom: none;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.pillItem.active {
|
|
67
|
+
background-color: var(--ds-surface-0);
|
|
68
|
+
color: var(--ds-text-1);
|
|
69
|
+
box-shadow: var(--ds-shadow-sm);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.tabPanel {
|
|
73
|
+
padding-top: var(--ds-space-4);
|
|
74
|
+
}
|