@lateralus-ai/shipping-ui 2.0.0-dev.0 → 2.0.0-dev.10
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/dist/components/EmptyState.d.ts +1 -1
- package/dist/components/Entry.d.ts +27 -7
- package/dist/components/Modal.d.ts +36 -0
- package/dist/components/Tabs.d.ts +23 -8
- package/dist/components/index.d.ts +3 -2
- package/dist/index.cjs +32 -32
- package/dist/index.d.ts +2 -2
- package/dist/index.esm.js +4406 -3917
- package/dist/patterns/Search/ResultRow.d.ts +16 -7
- package/dist/patterns/Search/SearchModal.d.ts +84 -2
- package/dist/patterns/Search/index.d.ts +2 -2
- package/dist/primitives/Badge.d.ts +7 -4
- package/dist/primitives/Button.d.ts +17 -8
- package/dist/primitives/button-styles.d.ts +4 -0
- package/dist/primitives/index.d.ts +4 -2
- package/dist/style.css +1 -1
- package/dist/tailwind-theme.d.ts +4 -4
- package/dist/theme-entry-BUK3MJUJ.mjs +261 -0
- package/dist/theme-entry-ygTpGaNC.js +1 -0
- package/dist/theme-entry.d.ts +2 -0
- package/dist/theme.cjs +1 -0
- package/dist/theme.d.ts +2 -0
- package/dist/theme.esm.js +5 -0
- package/package.json +10 -3
- package/src/components/EmptyState.tsx +2 -2
- package/src/components/Entry.tsx +119 -45
- package/src/components/Modal.tsx +141 -0
- package/src/components/Tabs.tsx +146 -48
- package/src/components/index.ts +43 -13
- package/src/icons/arrow-paths.ts +8 -8
- package/src/icons/chevron-paths.ts +17 -17
- package/src/icons/icons-data.ts +656 -656
- package/src/index.ts +76 -50
- package/src/patterns/Search/ResultRow.tsx +44 -52
- package/src/patterns/Search/SearchModal.tsx +310 -88
- package/src/patterns/Search/index.ts +31 -5
- package/src/patterns/Sidebar/assets/logo-compliance-mark.png +5 -5
- package/src/patterns/Sidebar/assets/logo-compliance-mask.png +13 -13
- package/src/patterns/Sidebar/assets/logo-compliance.svg +17 -17
- package/src/patterns/Sidebar/assets/logo-technical-avatar.svg +17 -17
- package/src/patterns/Sidebar/assets/logo-technical-mark.png +5 -5
- package/src/patterns/Sidebar/assets/logo-technical.svg +16 -16
- package/src/patterns/Skeleton/Skeleton.tsx +56 -57
- package/src/primitives/Badge.tsx +20 -10
- package/src/primitives/Button.tsx +201 -37
- package/src/primitives/button-styles.ts +92 -0
- package/src/primitives/index.ts +7 -2
- package/src/stories/canvases/ButtonsCanvas.tsx +94 -44
- package/src/stories/canvases/ButtonsMatrixCanvas.tsx +8 -7
- package/src/stories/canvases/ContentCanvas.tsx +157 -88
- package/src/stories/canvases/SearchCanvas.tsx +150 -65
- package/src/stories/canvases/figma-buttons-layout.ts +83 -0
- package/src/stories/canvases/helpers.tsx +26 -43
- package/src/stories/components/Buttons.stories.tsx +11 -11
- package/src/stories/components/Chat.stories.tsx +11 -11
- package/src/stories/components/Content.stories.tsx +11 -11
- package/src/stories/components/Core.stories.tsx +11 -11
- package/src/stories/components/DomainForms.stories.tsx +11 -11
- package/src/stories/components/Filters.stories.tsx +11 -11
- package/src/stories/components/Forms.stories.tsx +11 -11
- package/src/stories/components/Icons.stories.tsx +11 -11
- package/src/stories/components/Illustrations.stories.tsx +11 -11
- package/src/stories/components/Library.stories.tsx +11 -11
- package/src/stories/components/Modals.stories.tsx +11 -11
- package/src/stories/components/Report.stories.tsx +11 -11
- package/src/stories/components/ReportLayout.stories.tsx +11 -11
- package/src/stories/components/Search.stories.tsx +11 -11
- package/src/stories/components/Settings.stories.tsx +11 -11
- package/src/stories/components/Ships.stories.tsx +11 -11
- package/src/stories/components/SidebarLayouts.stories.tsx +11 -11
- package/src/stories/components/Skeletons.stories.tsx +11 -11
- package/src/stories/components/Workflows.stories.tsx +11 -11
- package/src/stories/style-guide/Buttons.stories.tsx +11 -11
- package/src/stories/style-guide/ColorTokens.stories.tsx +11 -11
- package/src/stories/style-guide/Colors.stories.tsx +11 -11
- package/src/stories/style-guide/RaiseLevels.stories.tsx +11 -11
- package/src/stories/style-guide/Typography.stories.tsx +11 -11
- package/src/tailwind-theme.ts +4 -4
- package/src/theme-entry.ts +2 -0
- package/tailwind.config.ts +12 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<g id="Mask" clip-path="url(#clip0_0_4)">
|
|
3
|
-
<g id="icon-compliance.svg">
|
|
4
|
-
<path id="Vector" d="M8.30333 5.84667L5.18333 14.2917H6.33833V14.2883C6.34 14.2883 6.34167 14.29 6.34167 14.29L8.90667 11.7267H9.06667L11.6283 14.2917H12.8233L9.71667 5.84667H8.305H8.30333ZM9.215 10.4433H8.75667L7.15167 12.0483L8.89 7.25167H9.10167L10.825 12.055L9.21667 10.4433H9.215Z" fill="var(--fill-0, #232323)"/>
|
|
5
|
-
<path id="Vector_2" d="M8.98833 4.85833C9.87167 4.85833 10.6817 5.23 11.3117 5.84667H12.7967C11.925 4.54667 10.5433 3.70667 8.98833 3.70667C7.43333 3.70667 6.05167 4.54667 5.18 5.84667H6.665C7.29333 5.23 8.105 4.85833 8.98833 4.85833Z" fill="var(--fill-0, #232323)"/>
|
|
6
|
-
</g>
|
|
7
|
-
</g>
|
|
8
|
-
<defs>
|
|
9
|
-
<clipPath id="clip0_0_4">
|
|
10
|
-
<rect width="18" height="18" fill="white"/>
|
|
11
|
-
</clipPath>
|
|
12
|
-
</defs>
|
|
13
|
-
</svg>
|
|
1
|
+
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g id="Mask" clip-path="url(#clip0_0_4)">
|
|
3
|
+
<g id="icon-compliance.svg">
|
|
4
|
+
<path id="Vector" d="M8.30333 5.84667L5.18333 14.2917H6.33833V14.2883C6.34 14.2883 6.34167 14.29 6.34167 14.29L8.90667 11.7267H9.06667L11.6283 14.2917H12.8233L9.71667 5.84667H8.305H8.30333ZM9.215 10.4433H8.75667L7.15167 12.0483L8.89 7.25167H9.10167L10.825 12.055L9.21667 10.4433H9.215Z" fill="var(--fill-0, #232323)"/>
|
|
5
|
+
<path id="Vector_2" d="M8.98833 4.85833C9.87167 4.85833 10.6817 5.23 11.3117 5.84667H12.7967C11.925 4.54667 10.5433 3.70667 8.98833 3.70667C7.43333 3.70667 6.05167 4.54667 5.18 5.84667H6.665C7.29333 5.23 8.105 4.85833 8.98833 4.85833Z" fill="var(--fill-0, #232323)"/>
|
|
6
|
+
</g>
|
|
7
|
+
</g>
|
|
8
|
+
<defs>
|
|
9
|
+
<clipPath id="clip0_0_4">
|
|
10
|
+
<rect width="18" height="18" fill="white"/>
|
|
11
|
+
</clipPath>
|
|
12
|
+
</defs>
|
|
13
|
+
</svg>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<rect width="18" height="18" fill="#F5F5F5"/>
|
|
3
|
-
<g id="Core">
|
|
4
|
-
<path d="M-330 -683C-330 -694.046 -321.046 -703 -310 -703H382C393.046 -703 402 -694.046 402 -683V927C402 938.046 393.046 947 382 947H-310C-321.046 947 -330 938.046 -330 927V-683Z" fill="#FDFDFC"/>
|
|
5
|
-
<g id="Content">
|
|
6
|
-
<g id="Avatar">
|
|
7
|
-
<rect x="-273.5" y="-30.5" width="619" height="79" rx="4.5" stroke="#9747FF" stroke-dasharray="10 5"/>
|
|
8
|
-
<g id="Chief=Technical, Size=18">
|
|
9
|
-
<path d="M0 9C0 4.02944 4.02944 0 9 0C13.9706 0 18 4.02944 18 9C18 13.9706 13.9706 18 9 18C4.02944 18 0 13.9706 0 9Z" fill="#FDFDFC"/>
|
|
10
|
-
<g id="Logo">
|
|
11
|
-
<path id="Glyph" d="M9.89258 5.62793L13.2041 14.625H11.9316L9.20117 11.8926H9.03223L6.29785 14.623C6.29785 14.623 6.29573 14.6211 6.29395 14.6211V14.625H5.0625L8.38867 5.62793H9.89258ZM9.01172 7.12305L7.16016 12.2334L8.87109 10.5234H9.36133L11.0762 12.2402L9.23828 7.12305H9.01172ZM12.6904 3.375V4.64355H5.61328V3.375H12.6904Z" fill="#262420"/>
|
|
12
|
-
</g>
|
|
13
|
-
</g>
|
|
14
|
-
</g>
|
|
15
|
-
</g>
|
|
16
|
-
</g>
|
|
17
|
-
</svg>
|
|
1
|
+
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="18" height="18" fill="#F5F5F5"/>
|
|
3
|
+
<g id="Core">
|
|
4
|
+
<path d="M-330 -683C-330 -694.046 -321.046 -703 -310 -703H382C393.046 -703 402 -694.046 402 -683V927C402 938.046 393.046 947 382 947H-310C-321.046 947 -330 938.046 -330 927V-683Z" fill="#FDFDFC"/>
|
|
5
|
+
<g id="Content">
|
|
6
|
+
<g id="Avatar">
|
|
7
|
+
<rect x="-273.5" y="-30.5" width="619" height="79" rx="4.5" stroke="#9747FF" stroke-dasharray="10 5"/>
|
|
8
|
+
<g id="Chief=Technical, Size=18">
|
|
9
|
+
<path d="M0 9C0 4.02944 4.02944 0 9 0C13.9706 0 18 4.02944 18 9C18 13.9706 13.9706 18 9 18C4.02944 18 0 13.9706 0 9Z" fill="#FDFDFC"/>
|
|
10
|
+
<g id="Logo">
|
|
11
|
+
<path id="Glyph" d="M9.89258 5.62793L13.2041 14.625H11.9316L9.20117 11.8926H9.03223L6.29785 14.623C6.29785 14.623 6.29573 14.6211 6.29395 14.6211V14.625H5.0625L8.38867 5.62793H9.89258ZM9.01172 7.12305L7.16016 12.2334L8.87109 10.5234H9.36133L11.0762 12.2402L9.23828 7.12305H9.01172ZM12.6904 3.375V4.64355H5.61328V3.375H12.6904Z" fill="#262420"/>
|
|
12
|
+
</g>
|
|
13
|
+
</g>
|
|
14
|
+
</g>
|
|
15
|
+
</g>
|
|
16
|
+
</g>
|
|
17
|
+
</svg>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<rect width="18" height="18" fill="#F5F5F5"/>
|
|
3
|
-
<g id="Core">
|
|
4
|
-
<path d="M-330 -683C-330 -694.046 -321.046 -703 -310 -703H382C393.046 -703 402 -694.046 402 -683V927C402 938.046 393.046 947 382 947H-310C-321.046 947 -330 938.046 -330 927V-683Z" fill="#FDFDFC"/>
|
|
5
|
-
<g id="Content">
|
|
6
|
-
<g id="Avatar">
|
|
7
|
-
<rect x="-273.5" y="-30.5" width="619" height="79" rx="4.5" stroke="#9747FF" stroke-dasharray="10 5"/>
|
|
8
|
-
<g id="Chief=Technical, Size=18">
|
|
9
|
-
<path d="M0 9C0 4.02944 4.02944 0 9 0C13.9706 0 18 4.02944 18 9C18 13.9706 13.9706 18 9 18C4.02944 18 0 13.9706 0 9Z" fill="#FDFDFC"/>
|
|
10
|
-
<g id="Logo">
|
|
11
|
-
<path id="Glyph" d="M9.89258 5.62793L13.2041 14.625H11.9316L9.20117 11.8926H9.03223L6.29785 14.623C6.29785 14.623 6.29573 14.6211 6.29395 14.6211V14.625H5.0625L8.38867 5.62793H9.89258ZM9.01172 7.12305L7.16016 12.2334L8.87109 10.5234H9.36133L11.0762 12.2402L9.23828 7.12305H9.01172ZM12.6904 3.375V4.64355H5.61328V3.375H12.6904Z" fill="#262420"/>
|
|
12
|
-
</g>
|
|
13
|
-
</g>
|
|
14
|
-
</g>
|
|
15
|
-
</g>
|
|
16
|
-
</g>
|
|
17
|
-
</svg>
|
|
1
|
+
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="18" height="18" fill="#F5F5F5"/>
|
|
3
|
+
<g id="Core">
|
|
4
|
+
<path d="M-330 -683C-330 -694.046 -321.046 -703 -310 -703H382C393.046 -703 402 -694.046 402 -683V927C402 938.046 393.046 947 382 947H-310C-321.046 947 -330 938.046 -330 927V-683Z" fill="#FDFDFC"/>
|
|
5
|
+
<g id="Content">
|
|
6
|
+
<g id="Avatar">
|
|
7
|
+
<rect x="-273.5" y="-30.5" width="619" height="79" rx="4.5" stroke="#9747FF" stroke-dasharray="10 5"/>
|
|
8
|
+
<g id="Chief=Technical, Size=18">
|
|
9
|
+
<path d="M0 9C0 4.02944 4.02944 0 9 0C13.9706 0 18 4.02944 18 9C18 13.9706 13.9706 18 9 18C4.02944 18 0 13.9706 0 9Z" fill="#FDFDFC"/>
|
|
10
|
+
<g id="Logo">
|
|
11
|
+
<path id="Glyph" d="M9.89258 5.62793L13.2041 14.625H11.9316L9.20117 11.8926H9.03223L6.29785 14.623C6.29785 14.623 6.29573 14.6211 6.29395 14.6211V14.625H5.0625L8.38867 5.62793H9.89258ZM9.01172 7.12305L7.16016 12.2334L8.87109 10.5234H9.36133L11.0762 12.2402L9.23828 7.12305H9.01172ZM12.6904 3.375V4.64355H5.61328V3.375H12.6904Z" fill="#262420"/>
|
|
12
|
+
</g>
|
|
13
|
+
</g>
|
|
14
|
+
</g>
|
|
15
|
+
</g>
|
|
16
|
+
</g>
|
|
17
|
+
</svg>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<g id="Logo">
|
|
3
|
-
<path id="Glyph" d="M9.89258 5.62793L13.2041 14.625H11.9316L9.20117 11.8926H9.03223L6.29785 14.623C6.29785 14.623 6.29573 14.6211 6.29395 14.6211V14.625H5.0625L8.38867 5.62793H9.89258ZM9.01172 7.12305L7.16016 12.2334L8.87109 10.5234H9.36133L11.0762 12.2402L9.23828 7.12305H9.01172ZM12.6904 3.375V4.64355H5.61328V3.375H12.6904Z" fill="var(--fill-0, #262420)"/>
|
|
4
|
-
</g>
|
|
5
|
-
</svg>
|
|
1
|
+
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g id="Logo">
|
|
3
|
+
<path id="Glyph" d="M9.89258 5.62793L13.2041 14.625H11.9316L9.20117 11.8926H9.03223L6.29785 14.623C6.29785 14.623 6.29573 14.6211 6.29395 14.6211V14.625H5.0625L8.38867 5.62793H9.89258ZM9.01172 7.12305L7.16016 12.2334L8.87109 10.5234H9.36133L11.0762 12.2402L9.23828 7.12305H9.01172ZM12.6904 3.375V4.64355H5.61328V3.375H12.6904Z" fill="var(--fill-0, #262420)"/>
|
|
4
|
+
</g>
|
|
5
|
+
</svg>
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<rect width="18" height="18" fill="#F5F5F5"/>
|
|
3
|
-
<g id="Core">
|
|
4
|
-
<path d="M-330 -683C-330 -694.046 -321.046 -703 -310 -703H382C393.046 -703 402 -694.046 402 -683V927C402 938.046 393.046 947 382 947H-310C-321.046 947 -330 938.046 -330 927V-683Z" fill="white"/>
|
|
5
|
-
<g id="Content">
|
|
6
|
-
<g id="Avatar">
|
|
7
|
-
<rect x="-273.5" y="-30.5" width="619" height="79" rx="4.5" stroke="#9747FF" stroke-dasharray="10 5"/>
|
|
8
|
-
<g id="Chief=Technical, Size=18">
|
|
9
|
-
<g id="Logo">
|
|
10
|
-
<path id="Glyph" d="M9.89258 5.62793L13.2041 14.625H11.9316L9.20117 11.8926H9.03223L6.29785 14.623C6.29785 14.623 6.29573 14.6211 6.29395 14.6211V14.625H5.0625L8.38867 5.62793H9.89258ZM9.01172 7.12305L7.16016 12.2334L8.87109 10.5234H9.36133L11.0762 12.2402L9.23828 7.12305H9.01172ZM12.6904 3.375V4.64355H5.61328V3.375H12.6904Z" fill="#262420"/>
|
|
11
|
-
</g>
|
|
12
|
-
</g>
|
|
13
|
-
</g>
|
|
14
|
-
</g>
|
|
15
|
-
</g>
|
|
16
|
-
</svg>
|
|
1
|
+
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="18" height="18" fill="#F5F5F5"/>
|
|
3
|
+
<g id="Core">
|
|
4
|
+
<path d="M-330 -683C-330 -694.046 -321.046 -703 -310 -703H382C393.046 -703 402 -694.046 402 -683V927C402 938.046 393.046 947 382 947H-310C-321.046 947 -330 938.046 -330 927V-683Z" fill="white"/>
|
|
5
|
+
<g id="Content">
|
|
6
|
+
<g id="Avatar">
|
|
7
|
+
<rect x="-273.5" y="-30.5" width="619" height="79" rx="4.5" stroke="#9747FF" stroke-dasharray="10 5"/>
|
|
8
|
+
<g id="Chief=Technical, Size=18">
|
|
9
|
+
<g id="Logo">
|
|
10
|
+
<path id="Glyph" d="M9.89258 5.62793L13.2041 14.625H11.9316L9.20117 11.8926H9.03223L6.29785 14.623C6.29785 14.623 6.29573 14.6211 6.29395 14.6211V14.625H5.0625L8.38867 5.62793H9.89258ZM9.01172 7.12305L7.16016 12.2334L8.87109 10.5234H9.36133L11.0762 12.2402L9.23828 7.12305H9.01172ZM12.6904 3.375V4.64355H5.61328V3.375H12.6904Z" fill="#262420"/>
|
|
11
|
+
</g>
|
|
12
|
+
</g>
|
|
13
|
+
</g>
|
|
14
|
+
</g>
|
|
15
|
+
</g>
|
|
16
|
+
</svg>
|
|
@@ -1,57 +1,56 @@
|
|
|
1
|
-
import { cn } from "../../utils/cn";
|
|
2
|
-
|
|
3
|
-
export type SkeletonVariant = "content" | "search";
|
|
4
|
-
|
|
5
|
-
export type SkeletonProps = {
|
|
6
|
-
variant?: SkeletonVariant;
|
|
7
|
-
className?: string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const ContentSkeleton = () => (
|
|
11
|
-
<div className="flex flex-col gap-4 p-4" aria-hidden>
|
|
12
|
-
<div className="flex items-center gap-3">
|
|
13
|
-
<div className="size-8 animate-pulse rounded-full bg-grey-200" />
|
|
14
|
-
<div className="flex flex-1 flex-col gap-2">
|
|
15
|
-
<div className="h-4 w-1/3 animate-pulse rounded bg-grey-200" />
|
|
16
|
-
<div className="h-3 w-1/4 animate-pulse rounded bg-grey-100" />
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
19
|
-
<div className="flex flex-col gap-2">
|
|
20
|
-
<div className="h-4 w-full animate-pulse rounded bg-grey-200" />
|
|
21
|
-
<div className="h-4 w-5/6 animate-pulse rounded bg-grey-200" />
|
|
22
|
-
<div className="h-4 w-2/3 animate-pulse rounded bg-grey-100" />
|
|
23
|
-
</div>
|
|
24
|
-
<div className="h-24 animate-pulse rounded-control bg-grey-100" />
|
|
25
|
-
</div>
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
);
|
|
1
|
+
import { cn } from "../../utils/cn";
|
|
2
|
+
|
|
3
|
+
export type SkeletonVariant = "content" | "search";
|
|
4
|
+
|
|
5
|
+
export type SkeletonProps = {
|
|
6
|
+
variant?: SkeletonVariant;
|
|
7
|
+
className?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const ContentSkeleton = () => (
|
|
11
|
+
<div className="flex flex-col gap-4 p-4" aria-hidden>
|
|
12
|
+
<div className="flex items-center gap-3">
|
|
13
|
+
<div className="size-8 animate-pulse rounded-full bg-grey-200" />
|
|
14
|
+
<div className="flex flex-1 flex-col gap-2">
|
|
15
|
+
<div className="h-4 w-1/3 animate-pulse rounded bg-grey-200" />
|
|
16
|
+
<div className="h-3 w-1/4 animate-pulse rounded bg-grey-100" />
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<div className="flex flex-col gap-2">
|
|
20
|
+
<div className="h-4 w-full animate-pulse rounded bg-grey-200" />
|
|
21
|
+
<div className="h-4 w-5/6 animate-pulse rounded bg-grey-200" />
|
|
22
|
+
<div className="h-4 w-2/3 animate-pulse rounded bg-grey-100" />
|
|
23
|
+
</div>
|
|
24
|
+
<div className="h-24 animate-pulse rounded-control bg-grey-100" />
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
/** Figma Search loading — 8 rows of icon + bar (no input/pills). */
|
|
29
|
+
const SearchSkeleton = () => {
|
|
30
|
+
const widths = [250, 300, 220, 255, 250, 300, 220, 255];
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div className="flex flex-col gap-1.5 p-4" aria-hidden>
|
|
34
|
+
{widths.map((width, index) => (
|
|
35
|
+
<div key={index} className="flex items-start gap-2 py-2">
|
|
36
|
+
<div className="size-3 shrink-0 animate-pulse rounded-md bg-grey-200" />
|
|
37
|
+
<div
|
|
38
|
+
className="h-3 animate-pulse rounded-md bg-grey-200"
|
|
39
|
+
style={{ width }}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
))}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Skeleton = ({ variant = "content", className }: SkeletonProps) => (
|
|
48
|
+
<div
|
|
49
|
+
className={cn("rounded-control bg-background-primary", className)}
|
|
50
|
+
role="status"
|
|
51
|
+
aria-label="Loading"
|
|
52
|
+
data-variant={variant}
|
|
53
|
+
>
|
|
54
|
+
{variant === "content" ? <ContentSkeleton /> : <SearchSkeleton />}
|
|
55
|
+
</div>
|
|
56
|
+
);
|
package/src/primitives/Badge.tsx
CHANGED
|
@@ -1,30 +1,40 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { cn } from "../utils/cn";
|
|
3
3
|
|
|
4
|
-
type BadgeColor = "blue" | "green" | "red" | "orange" | "purple" | "grey";
|
|
5
|
-
type BadgeType = "label" | "icon";
|
|
4
|
+
export type BadgeColor = "blue" | "green" | "red" | "orange" | "purple" | "grey";
|
|
5
|
+
export type BadgeType = "label" | "icon";
|
|
6
6
|
|
|
7
7
|
export type BadgeProps = {
|
|
8
8
|
color: BadgeColor;
|
|
9
|
+
/** `label` grows with content (pill). `icon` is a compact circle for a glyph/digit. */
|
|
9
10
|
type?: BadgeType;
|
|
10
11
|
children: ReactNode;
|
|
11
12
|
className?: string;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
const colorStyles: Record<BadgeColor, string> = {
|
|
15
|
-
blue: "bg-meta-blue text-meta-
|
|
16
|
-
green: "bg-meta-green text-meta-
|
|
17
|
-
red: "bg-meta-red text-meta-
|
|
18
|
-
orange: "bg-meta-orange text-meta-
|
|
19
|
-
purple: "bg-meta-purple text-meta-
|
|
16
|
+
blue: "bg-meta-blue text-meta-onBlue",
|
|
17
|
+
green: "bg-meta-green text-meta-onGreen",
|
|
18
|
+
red: "bg-meta-red text-meta-onRed",
|
|
19
|
+
orange: "bg-meta-orange text-meta-onOrange",
|
|
20
|
+
purple: "bg-meta-purple text-meta-onPurple",
|
|
20
21
|
grey: "bg-grey-100 text-display-on-light-secondary",
|
|
21
22
|
};
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Figma Badge (4365:74363) — padding + rounded-full; no fixed width on labels.
|
|
26
|
+
*/
|
|
27
|
+
export const Badge = ({
|
|
28
|
+
color,
|
|
29
|
+
type = "label",
|
|
30
|
+
children,
|
|
31
|
+
className,
|
|
32
|
+
}: BadgeProps) => (
|
|
24
33
|
<span
|
|
25
34
|
className={cn(
|
|
26
|
-
"inline-flex shrink-0 items-center justify-center text-footnote-em",
|
|
27
|
-
type === "label"
|
|
35
|
+
"inline-flex shrink-0 items-center justify-center text-footnote-em leading-none",
|
|
36
|
+
type === "label" && "rounded-full px-1.5 py-0.5",
|
|
37
|
+
type === "icon" && "size-5 rounded-full [&>svg]:size-3",
|
|
28
38
|
colorStyles[color],
|
|
29
39
|
className,
|
|
30
40
|
)}
|
|
@@ -1,67 +1,231 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ButtonHTMLAttributes,
|
|
3
|
+
type ComponentType,
|
|
4
|
+
isValidElement,
|
|
5
|
+
type ReactNode,
|
|
6
|
+
} from "react";
|
|
7
|
+
import { ChevronIcon } from "../icons";
|
|
8
|
+
import type { IconProps } from "../icons";
|
|
2
9
|
import { cn } from "../utils/cn";
|
|
10
|
+
import {
|
|
11
|
+
DropdownMenu,
|
|
12
|
+
DropdownMenuItem,
|
|
13
|
+
} from "./DropdownMenu";
|
|
14
|
+
import {
|
|
15
|
+
getButtonAppearanceClasses,
|
|
16
|
+
getButtonInteractiveClasses,
|
|
17
|
+
type ButtonAppearance,
|
|
18
|
+
type ButtonHierarchy,
|
|
19
|
+
} from "./button-styles";
|
|
3
20
|
|
|
4
|
-
type
|
|
5
|
-
|
|
21
|
+
export type ButtonDropdownOption = {
|
|
22
|
+
label: string;
|
|
23
|
+
onSelect: () => void;
|
|
24
|
+
destructive?: boolean;
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
icon?: ComponentType<IconProps>;
|
|
27
|
+
};
|
|
6
28
|
|
|
7
|
-
export type ButtonProps = Omit<
|
|
29
|
+
export type ButtonProps = Omit<
|
|
30
|
+
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
31
|
+
"children"
|
|
32
|
+
> & {
|
|
8
33
|
hierarchy?: ButtonHierarchy;
|
|
9
|
-
outcome?: ButtonOutcome;
|
|
10
34
|
disabled?: boolean;
|
|
11
|
-
|
|
12
|
-
|
|
35
|
+
icon?: ComponentType<IconProps> | ReactNode;
|
|
36
|
+
startIcon?: ComponentType<IconProps> | ReactNode;
|
|
37
|
+
dropdownOptions?: ButtonDropdownOption[];
|
|
38
|
+
dropdownOpen?: boolean;
|
|
39
|
+
onDropdownOpenChange?: (open: boolean) => void;
|
|
40
|
+
forcedState?: ButtonAppearance;
|
|
13
41
|
children: ReactNode;
|
|
14
42
|
};
|
|
15
43
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
44
|
+
const renderIcon = (icon?: ComponentType<IconProps> | ReactNode) => {
|
|
45
|
+
if (!icon) return null;
|
|
46
|
+
|
|
47
|
+
if (isValidElement(icon)) {
|
|
48
|
+
return <span className="shrink-0 [&>svg]:size-4">{icon}</span>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (
|
|
52
|
+
typeof icon === "string" ||
|
|
53
|
+
typeof icon === "number" ||
|
|
54
|
+
typeof icon === "boolean"
|
|
55
|
+
) {
|
|
56
|
+
return <span className="shrink-0 [&>svg]:size-4">{icon}</span>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const Icon = icon as ComponentType<IconProps>;
|
|
60
|
+
return <Icon size="small" className="shrink-0" />;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const getAppearance = (
|
|
64
|
+
disabled: boolean,
|
|
65
|
+
forcedState?: ButtonAppearance,
|
|
66
|
+
): ButtonAppearance => {
|
|
67
|
+
if (forcedState) return forcedState;
|
|
68
|
+
if (disabled) return "disabled";
|
|
69
|
+
return "idle";
|
|
28
70
|
};
|
|
29
71
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
72
|
+
const getSegmentClasses = (
|
|
73
|
+
hierarchy: ButtonHierarchy,
|
|
74
|
+
appearance: ButtonAppearance,
|
|
75
|
+
forcedState?: ButtonAppearance,
|
|
76
|
+
) => {
|
|
77
|
+
if (forcedState) {
|
|
78
|
+
return getButtonAppearanceClasses(hierarchy, appearance);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (appearance === "disabled") {
|
|
82
|
+
return getButtonAppearanceClasses(hierarchy, "disabled");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (appearance === "hover") {
|
|
86
|
+
return getButtonAppearanceClasses(hierarchy, "hover");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return getButtonInteractiveClasses(hierarchy, false);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const getCursorClass = (disabled: boolean) =>
|
|
93
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer";
|
|
94
|
+
|
|
95
|
+
const withSecondarySplitBorders = (
|
|
96
|
+
hierarchy: ButtonHierarchy,
|
|
97
|
+
segment: "main" | "dropdown",
|
|
98
|
+
classes: string,
|
|
99
|
+
) => {
|
|
100
|
+
if (hierarchy !== "secondary") return classes;
|
|
101
|
+
|
|
102
|
+
return cn(
|
|
103
|
+
classes,
|
|
104
|
+
segment === "main" ? "border-r-0" : "border-l-0",
|
|
105
|
+
);
|
|
39
106
|
};
|
|
40
107
|
|
|
41
108
|
export const Button = ({
|
|
42
109
|
hierarchy = "primary",
|
|
43
|
-
outcome = "action",
|
|
44
110
|
disabled = false,
|
|
111
|
+
icon,
|
|
45
112
|
startIcon,
|
|
46
|
-
|
|
113
|
+
dropdownOptions,
|
|
114
|
+
dropdownOpen,
|
|
115
|
+
onDropdownOpenChange,
|
|
116
|
+
forcedState,
|
|
47
117
|
children,
|
|
48
118
|
className,
|
|
49
119
|
type = "button",
|
|
120
|
+
onClick,
|
|
50
121
|
...props
|
|
51
122
|
}: ButtonProps) => {
|
|
52
|
-
const
|
|
53
|
-
|
|
123
|
+
const resolvedIcon = icon ?? startIcon;
|
|
124
|
+
const hasDropdown = Boolean(dropdownOptions?.length);
|
|
125
|
+
const dropdownDisabled = !dropdownOptions?.some((option) => !option.disabled);
|
|
126
|
+
const mainAppearance = getAppearance(disabled, forcedState);
|
|
127
|
+
const dropdownAppearance = getAppearance(dropdownDisabled, forcedState);
|
|
128
|
+
const mainClasses = getSegmentClasses(
|
|
129
|
+
hierarchy,
|
|
130
|
+
mainAppearance,
|
|
131
|
+
forcedState,
|
|
132
|
+
);
|
|
133
|
+
const dropdownClasses = getSegmentClasses(
|
|
134
|
+
hierarchy,
|
|
135
|
+
dropdownAppearance,
|
|
136
|
+
forcedState,
|
|
137
|
+
);
|
|
138
|
+
const label = (
|
|
139
|
+
<>
|
|
140
|
+
{renderIcon(resolvedIcon)}
|
|
141
|
+
<span className="px-2">{children}</span>
|
|
142
|
+
</>
|
|
143
|
+
);
|
|
54
144
|
|
|
55
|
-
|
|
145
|
+
if (!hasDropdown) {
|
|
146
|
+
return (
|
|
147
|
+
<button
|
|
148
|
+
type={type}
|
|
149
|
+
disabled={disabled}
|
|
150
|
+
onClick={onClick}
|
|
151
|
+
className={cn(
|
|
152
|
+
"inline-flex min-h-10 items-center justify-center rounded-control p-2 text-caption-1 tracking-[0.32px] transition-colors",
|
|
153
|
+
getCursorClass(disabled),
|
|
154
|
+
mainClasses,
|
|
155
|
+
className,
|
|
156
|
+
)}
|
|
157
|
+
{...props}
|
|
158
|
+
>
|
|
159
|
+
<span className="flex min-h-6 items-center [&>*:first-child]:-mr-1 [&>*:last-child]:-mr-1">
|
|
160
|
+
{label}
|
|
161
|
+
</span>
|
|
162
|
+
</button>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const mainButton = (
|
|
56
167
|
<button
|
|
57
168
|
type={type}
|
|
58
169
|
disabled={disabled}
|
|
59
|
-
|
|
170
|
+
onClick={onClick}
|
|
171
|
+
className={cn(
|
|
172
|
+
"inline-flex min-h-10 items-center justify-center rounded-none rounded-l-control p-2 text-caption-1 tracking-[0.32px] transition-colors",
|
|
173
|
+
getCursorClass(disabled),
|
|
174
|
+
withSecondarySplitBorders(hierarchy, "main", mainClasses),
|
|
175
|
+
)}
|
|
60
176
|
{...props}
|
|
61
177
|
>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
178
|
+
<span className="flex min-h-6 items-center [&>*:first-child]:-mr-1 [&>*:last-child]:-mr-1">
|
|
179
|
+
{label}
|
|
180
|
+
</span>
|
|
181
|
+
</button>
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const dropdownTrigger = (
|
|
185
|
+
<button
|
|
186
|
+
type="button"
|
|
187
|
+
disabled={dropdownDisabled}
|
|
188
|
+
aria-label="Open menu"
|
|
189
|
+
className={cn(
|
|
190
|
+
"inline-flex min-h-10 shrink-0 items-center justify-center rounded-none rounded-r-control px-1 transition-colors",
|
|
191
|
+
getCursorClass(dropdownDisabled),
|
|
192
|
+
withSecondarySplitBorders(hierarchy, "dropdown", dropdownClasses),
|
|
193
|
+
)}
|
|
194
|
+
>
|
|
195
|
+
<ChevronIcon direction="down" size="small" />
|
|
65
196
|
</button>
|
|
66
197
|
);
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div
|
|
201
|
+
className={cn(
|
|
202
|
+
"inline-flex min-h-10 items-stretch overflow-hidden rounded-control",
|
|
203
|
+
className,
|
|
204
|
+
)}
|
|
205
|
+
>
|
|
206
|
+
{mainButton}
|
|
207
|
+
<DropdownMenu
|
|
208
|
+
open={dropdownOpen}
|
|
209
|
+
onOpenChange={onDropdownOpenChange}
|
|
210
|
+
align="end"
|
|
211
|
+
trigger={dropdownTrigger}
|
|
212
|
+
contentClassName="min-w-[11rem]"
|
|
213
|
+
>
|
|
214
|
+
{dropdownOptions?.map((option) => (
|
|
215
|
+
<DropdownMenuItem
|
|
216
|
+
key={option.label}
|
|
217
|
+
disabled={option.disabled}
|
|
218
|
+
onSelect={option.onSelect}
|
|
219
|
+
className={cn(
|
|
220
|
+
option.destructive &&
|
|
221
|
+
"text-red-600 hover:bg-red-50 focus:bg-red-50 focus:text-red-600",
|
|
222
|
+
)}
|
|
223
|
+
>
|
|
224
|
+
{option.icon ? renderIcon(option.icon) : null}
|
|
225
|
+
{option.label}
|
|
226
|
+
</DropdownMenuItem>
|
|
227
|
+
))}
|
|
228
|
+
</DropdownMenu>
|
|
229
|
+
</div>
|
|
230
|
+
);
|
|
67
231
|
};
|