@lateralus-ai/shipping-ui 2.0.0-dev.3 → 2.0.0-dev.30
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/Entry.d.ts +27 -7
- package/dist/components/PageHeader.d.ts +41 -0
- package/dist/components/ScrollableList.d.ts +22 -0
- package/dist/components/Tabs.d.ts +5 -5
- package/dist/components/index.d.ts +4 -2
- package/dist/domain/Filters/FilterDropdown.d.ts +119 -0
- package/dist/domain/Filters/FilterPill.d.ts +22 -5
- package/dist/domain/Filters/FilterPills.d.ts +18 -0
- package/dist/domain/Filters/FilteredPill.d.ts +15 -5
- package/dist/domain/Filters/formatActiveFilterChipLabel.d.ts +11 -0
- package/dist/domain/Filters/index.d.ts +8 -3
- package/dist/index.cjs +33 -33
- package/dist/index.d.ts +2 -2
- package/dist/index.esm.js +6383 -4792
- package/dist/patterns/Search/ResultRow.d.ts +11 -5
- package/dist/patterns/Sidebar/sidebar-styles.d.ts +2 -1
- package/dist/primitives/Badge.d.ts +7 -4
- package/dist/primitives/Button.d.ts +3 -1
- package/dist/primitives/Switch.d.ts +5 -0
- package/dist/primitives/index.d.ts +1 -1
- package/dist/tailwind-theme.d.ts +8 -4
- package/dist/theme-entry-Dwr2mV7_.js +1 -0
- package/dist/{theme-entry-CxDa1D0_.mjs → theme-entry-tLBc6zGT.mjs} +12 -8
- package/dist/theme.cjs +1 -1
- package/dist/theme.esm.js +1 -1
- package/package.json +3 -2
- package/src/components/EmptyState.tsx +44 -44
- package/src/components/Entry.tsx +119 -45
- package/src/components/Modal.tsx +141 -141
- package/src/components/PageHeader.tsx +132 -0
- package/src/components/ScrollableList.tsx +61 -0
- package/src/components/Tabs.tsx +33 -26
- package/src/components/index.ts +15 -1
- package/src/domain/Filters/FilterDropdown.tsx +540 -0
- package/src/domain/Filters/FilterPill.tsx +74 -25
- package/src/domain/Filters/FilterPills.tsx +34 -0
- package/src/domain/Filters/FilteredPill.tsx +59 -39
- package/src/domain/Filters/FiltersBar.tsx +72 -76
- package/src/domain/Filters/formatActiveFilterChipLabel.ts +23 -0
- package/src/domain/Filters/index.ts +37 -3
- 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 +11 -0
- package/src/patterns/Search/ResultRow.tsx +24 -38
- package/src/patterns/Search/SearchModal.tsx +26 -8
- package/src/patterns/Sidebar/CollapsibleNavGroup.tsx +1 -1
- package/src/patterns/Sidebar/SidebarAction.tsx +26 -17
- package/src/patterns/Sidebar/SidebarEntry.tsx +54 -39
- package/src/patterns/Sidebar/SidebarLink.tsx +30 -20
- 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/Sidebar/sidebar-styles.ts +2 -1
- package/src/primitives/Badge.tsx +20 -10
- package/src/primitives/Button.tsx +21 -11
- package/src/primitives/Logo.tsx +20 -8
- package/src/primitives/Switch.tsx +27 -7
- package/src/primitives/button-styles.ts +92 -92
- package/src/primitives/index.ts +1 -1
- package/src/stories/canvases/ButtonsCanvas.tsx +107 -107
- package/src/stories/canvases/ButtonsMatrixCanvas.tsx +65 -65
- package/src/stories/canvases/ContentCanvas.tsx +253 -14
- package/src/stories/canvases/FiltersCanvas.tsx +171 -41
- package/src/stories/canvases/figma-buttons-layout.ts +83 -83
- package/src/stories/canvases/figma-widths.ts +28 -28
- package/src/stories/canvases/helpers.tsx +146 -146
- 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 +8 -4
- package/src/theme-entry.ts +2 -2
- package/src/utils/cn.ts +28 -1
- package/dist/theme-entry-D2X3Ptjf.js +0 -1
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
|
)}
|
|
@@ -34,6 +34,8 @@ export type ButtonProps = Omit<
|
|
|
34
34
|
disabled?: boolean;
|
|
35
35
|
icon?: ComponentType<IconProps> | ReactNode;
|
|
36
36
|
startIcon?: ComponentType<IconProps> | ReactNode;
|
|
37
|
+
/** Renders after the label, inside the same button (no split/dropdown segment). */
|
|
38
|
+
endIcon?: ComponentType<IconProps> | ReactNode;
|
|
37
39
|
dropdownOptions?: ButtonDropdownOption[];
|
|
38
40
|
dropdownOpen?: boolean;
|
|
39
41
|
onDropdownOpenChange?: (open: boolean) => void;
|
|
@@ -110,6 +112,7 @@ export const Button = ({
|
|
|
110
112
|
disabled = false,
|
|
111
113
|
icon,
|
|
112
114
|
startIcon,
|
|
115
|
+
endIcon,
|
|
113
116
|
dropdownOptions,
|
|
114
117
|
dropdownOpen,
|
|
115
118
|
onDropdownOpenChange,
|
|
@@ -121,6 +124,9 @@ export const Button = ({
|
|
|
121
124
|
...props
|
|
122
125
|
}: ButtonProps) => {
|
|
123
126
|
const resolvedIcon = icon ?? startIcon;
|
|
127
|
+
const renderedIcon = renderIcon(resolvedIcon);
|
|
128
|
+
const renderedEndIcon = renderIcon(endIcon);
|
|
129
|
+
const hasIcon = renderedIcon != null || renderedEndIcon != null;
|
|
124
130
|
const hasDropdown = Boolean(dropdownOptions?.length);
|
|
125
131
|
const dropdownDisabled = !dropdownOptions?.some((option) => !option.disabled);
|
|
126
132
|
const mainAppearance = getAppearance(disabled, forcedState);
|
|
@@ -135,11 +141,19 @@ export const Button = ({
|
|
|
135
141
|
dropdownAppearance,
|
|
136
142
|
forcedState,
|
|
137
143
|
);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
|
|
145
|
+
/** Label-only: centered text. With start icon: gap between icon and label. */
|
|
146
|
+
const content = (
|
|
147
|
+
<span
|
|
148
|
+
className={cn(
|
|
149
|
+
"flex min-h-6 items-center justify-center",
|
|
150
|
+
hasIcon && "gap-2",
|
|
151
|
+
)}
|
|
152
|
+
>
|
|
153
|
+
{renderedIcon}
|
|
154
|
+
<span>{children}</span>
|
|
155
|
+
{renderedEndIcon}
|
|
156
|
+
</span>
|
|
143
157
|
);
|
|
144
158
|
|
|
145
159
|
if (!hasDropdown) {
|
|
@@ -156,9 +170,7 @@ export const Button = ({
|
|
|
156
170
|
)}
|
|
157
171
|
{...props}
|
|
158
172
|
>
|
|
159
|
-
|
|
160
|
-
{label}
|
|
161
|
-
</span>
|
|
173
|
+
{content}
|
|
162
174
|
</button>
|
|
163
175
|
);
|
|
164
176
|
}
|
|
@@ -175,9 +187,7 @@ export const Button = ({
|
|
|
175
187
|
)}
|
|
176
188
|
{...props}
|
|
177
189
|
>
|
|
178
|
-
|
|
179
|
-
{label}
|
|
180
|
-
</span>
|
|
190
|
+
{content}
|
|
181
191
|
</button>
|
|
182
192
|
);
|
|
183
193
|
|
package/src/primitives/Logo.tsx
CHANGED
|
@@ -8,20 +8,32 @@ export type LogoProps = {
|
|
|
8
8
|
muted?: boolean;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
// The "A" body only — no topper. Technical adds a straight bar; Compliance
|
|
12
|
+
// adds a curved arc. Previously the bar lived inside this shared path, so the
|
|
13
|
+
// Compliance glyph rendered the technical bar (plus a faint arc) and looked
|
|
14
|
+
// identical to Technical.
|
|
11
15
|
const ASK_CHIEF_A =
|
|
12
|
-
"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.
|
|
16
|
+
"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.01172Z";
|
|
13
17
|
|
|
14
|
-
const
|
|
18
|
+
const TECHNICAL_BAR = "M12.6904 3.375V4.64355H5.61328V3.375H12.6904Z";
|
|
15
19
|
|
|
16
|
-
const
|
|
20
|
+
const TechnicalGlyph = () => (
|
|
17
21
|
<>
|
|
18
22
|
<path d={ASK_CHIEF_A} fill="currentColor" />
|
|
23
|
+
<path d={TECHNICAL_BAR} fill="currentColor" />
|
|
24
|
+
</>
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// Exact Figma export (Logo → Compliance): filled "A" body + filled crescent.
|
|
28
|
+
const ComplianceGlyph = () => (
|
|
29
|
+
<>
|
|
30
|
+
<path
|
|
31
|
+
d="M8.30335 5.84666L5.18335 14.2917H6.33835V14.2883C6.34002 14.2883 6.34168 14.29 6.34168 14.29L8.90668 11.7267H9.06668L11.6283 14.2917H12.8233L9.71668 5.84666H8.30502H8.30335ZM9.21502 10.4433H8.75668L7.15168 12.0483L8.89002 7.25166H9.10168L10.825 12.055L9.21668 10.4433H9.21502Z"
|
|
32
|
+
fill="currentColor"
|
|
33
|
+
/>
|
|
19
34
|
<path
|
|
20
|
-
d="
|
|
21
|
-
|
|
22
|
-
strokeWidth="0.9"
|
|
23
|
-
fill="none"
|
|
24
|
-
strokeLinecap="round"
|
|
35
|
+
d="M8.98839 4.85833C9.87172 4.85833 10.6817 5.23 11.3117 5.84666H12.7967C11.9251 4.54666 10.5434 3.70667 8.98839 3.70667C7.43339 3.70667 6.05172 4.54666 5.18005 5.84666H6.66505C7.29339 5.23 8.10505 4.85833 8.98839 4.85833Z"
|
|
36
|
+
fill="currentColor"
|
|
25
37
|
/>
|
|
26
38
|
</>
|
|
27
39
|
);
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { type ButtonHTMLAttributes } from "react";
|
|
2
2
|
import { cn } from "../utils/cn";
|
|
3
3
|
|
|
4
|
-
export type SwitchProps = Omit<
|
|
4
|
+
export type SwitchProps = Omit<
|
|
5
|
+
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
6
|
+
"onChange"
|
|
7
|
+
> & {
|
|
5
8
|
checked: boolean;
|
|
6
9
|
onChange: (checked: boolean) => void;
|
|
7
10
|
disabled?: boolean;
|
|
8
11
|
};
|
|
9
12
|
|
|
13
|
+
/**
|
|
14
|
+
* On/off control — Figma Switch (3068:65681).
|
|
15
|
+
* Track: 36×16 (grey-400 off / grey-900 on). Thumb: 24×24 white (grey-50 off),
|
|
16
|
+
* 1px border matching track, Raise-2 shadow. Off left / on right, edges flush.
|
|
17
|
+
*/
|
|
10
18
|
export const Switch = ({
|
|
11
19
|
checked,
|
|
12
20
|
onChange,
|
|
@@ -19,19 +27,31 @@ export const Switch = ({
|
|
|
19
27
|
role="switch"
|
|
20
28
|
aria-checked={checked}
|
|
21
29
|
disabled={disabled}
|
|
22
|
-
onClick={() =>
|
|
30
|
+
onClick={(event) => {
|
|
31
|
+
event.stopPropagation();
|
|
32
|
+
onChange(!checked);
|
|
33
|
+
}}
|
|
23
34
|
className={cn(
|
|
24
|
-
"relative inline-flex h-6 w-
|
|
25
|
-
|
|
26
|
-
disabled && "opacity-50",
|
|
35
|
+
"relative inline-flex h-6 w-9 shrink-0 items-center",
|
|
36
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
27
37
|
className,
|
|
28
38
|
)}
|
|
29
39
|
{...props}
|
|
30
40
|
>
|
|
31
41
|
<span
|
|
42
|
+
aria-hidden
|
|
32
43
|
className={cn(
|
|
33
|
-
"
|
|
34
|
-
checked ? "
|
|
44
|
+
"pointer-events-none absolute inset-x-0 top-1/2 h-4 -translate-y-1/2 rounded-full transition-colors",
|
|
45
|
+
checked ? "bg-grey-900" : "bg-grey-400",
|
|
46
|
+
)}
|
|
47
|
+
/>
|
|
48
|
+
<span
|
|
49
|
+
aria-hidden
|
|
50
|
+
className={cn(
|
|
51
|
+
"relative inline-block size-6 rounded-full border border-solid shadow-raise2 transition-[transform,border-color,background-color]",
|
|
52
|
+
checked
|
|
53
|
+
? "translate-x-3 border-grey-900 bg-white"
|
|
54
|
+
: "translate-x-0 border-grey-400 bg-grey-50",
|
|
35
55
|
)}
|
|
36
56
|
/>
|
|
37
57
|
</button>
|
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
export type ButtonHierarchy =
|
|
2
|
-
| "primary"
|
|
3
|
-
| "secondary"
|
|
4
|
-
| "tertiary"
|
|
5
|
-
| "quaternary"
|
|
6
|
-
| "destructive";
|
|
7
|
-
|
|
8
|
-
export type ButtonAppearance = "idle" | "hover" | "disabled";
|
|
9
|
-
|
|
10
|
-
type HierarchyStyleMap = Record<ButtonAppearance, string>;
|
|
11
|
-
|
|
12
|
-
const primaryStyles: HierarchyStyleMap = {
|
|
13
|
-
idle: "bg-action-primary-idle text-action-primary-on-idle",
|
|
14
|
-
hover: "bg-action-primary-hover text-action-primary-on-hover",
|
|
15
|
-
disabled: "bg-action-primary-disabled text-action-primary-on-disabled",
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const secondaryStyles: HierarchyStyleMap = {
|
|
19
|
-
idle:
|
|
20
|
-
"border border-divider-primary bg-action-secondary-idle text-action-secondary-on-idle",
|
|
21
|
-
hover:
|
|
22
|
-
"border border-divider-secondary bg-action-secondary-hover text-action-secondary-on-hover",
|
|
23
|
-
disabled:
|
|
24
|
-
"border border-divider-primary bg-action-secondary-disabled text-action-secondary-on-disabled",
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const tertiaryStyles: HierarchyStyleMap = {
|
|
28
|
-
idle: "bg-action-tertiary-idle text-action-tertiary-on-idle",
|
|
29
|
-
hover: "bg-action-tertiary-hover text-action-tertiary-on-hover",
|
|
30
|
-
disabled: "bg-action-tertiary-disabled text-action-tertiary-on-disabled",
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const quaternaryStyles: HierarchyStyleMap = {
|
|
34
|
-
idle: "bg-action-quaternary-idle text-action-quaternary-on-idle",
|
|
35
|
-
hover: "bg-action-quaternary-hover text-action-quaternary-on-hover",
|
|
36
|
-
disabled: "bg-action-quaternary-disabled text-action-quaternary-on-disabled",
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const destructiveStyles: HierarchyStyleMap = {
|
|
40
|
-
idle: "bg-action-destructive-idle text-action-destructive-on-idle",
|
|
41
|
-
hover: "bg-action-destructive-hover text-action-destructive-on-hover",
|
|
42
|
-
disabled:
|
|
43
|
-
"bg-action-destructive-disabled text-action-destructive-on-disabled",
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const hierarchyStyles: Record<ButtonHierarchy, HierarchyStyleMap> = {
|
|
47
|
-
primary: primaryStyles,
|
|
48
|
-
secondary: secondaryStyles,
|
|
49
|
-
tertiary: tertiaryStyles,
|
|
50
|
-
quaternary: quaternaryStyles,
|
|
51
|
-
destructive: destructiveStyles,
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const interactiveHierarchyStyles: Record<ButtonHierarchy, string> = {
|
|
55
|
-
primary:
|
|
56
|
-
"bg-action-primary-idle text-action-primary-on-idle hover:bg-action-primary-hover hover:text-action-primary-on-hover",
|
|
57
|
-
secondary:
|
|
58
|
-
"border border-divider-primary bg-action-secondary-idle text-action-secondary-on-idle hover:border-divider-secondary hover:bg-action-secondary-hover hover:text-action-secondary-on-hover",
|
|
59
|
-
tertiary:
|
|
60
|
-
"bg-action-tertiary-idle text-action-tertiary-on-idle hover:bg-action-tertiary-hover hover:text-action-tertiary-on-hover",
|
|
61
|
-
quaternary:
|
|
62
|
-
"bg-action-quaternary-idle text-action-quaternary-on-idle hover:bg-action-quaternary-hover hover:text-action-quaternary-on-hover",
|
|
63
|
-
destructive:
|
|
64
|
-
"bg-action-destructive-idle text-action-destructive-on-idle hover:bg-action-destructive-hover hover:text-action-destructive-on-hover",
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const disabledHierarchyStyles: Record<ButtonHierarchy, string> = {
|
|
68
|
-
primary: "bg-action-primary-disabled text-action-primary-on-disabled",
|
|
69
|
-
secondary:
|
|
70
|
-
"border border-divider-primary bg-action-secondary-disabled text-action-secondary-on-disabled",
|
|
71
|
-
tertiary: "bg-action-tertiary-disabled text-action-tertiary-on-disabled",
|
|
72
|
-
quaternary:
|
|
73
|
-
"bg-action-quaternary-disabled text-action-quaternary-on-disabled",
|
|
74
|
-
destructive:
|
|
75
|
-
"bg-action-destructive-disabled text-action-destructive-on-disabled",
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export const getButtonAppearanceClasses = (
|
|
79
|
-
hierarchy: ButtonHierarchy,
|
|
80
|
-
appearance: ButtonAppearance,
|
|
81
|
-
) => hierarchyStyles[hierarchy][appearance];
|
|
82
|
-
|
|
83
|
-
export const getButtonInteractiveClasses = (
|
|
84
|
-
hierarchy: ButtonHierarchy,
|
|
85
|
-
disabled: boolean,
|
|
86
|
-
) => {
|
|
87
|
-
if (disabled) {
|
|
88
|
-
return disabledHierarchyStyles[hierarchy];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return interactiveHierarchyStyles[hierarchy];
|
|
92
|
-
};
|
|
1
|
+
export type ButtonHierarchy =
|
|
2
|
+
| "primary"
|
|
3
|
+
| "secondary"
|
|
4
|
+
| "tertiary"
|
|
5
|
+
| "quaternary"
|
|
6
|
+
| "destructive";
|
|
7
|
+
|
|
8
|
+
export type ButtonAppearance = "idle" | "hover" | "disabled";
|
|
9
|
+
|
|
10
|
+
type HierarchyStyleMap = Record<ButtonAppearance, string>;
|
|
11
|
+
|
|
12
|
+
const primaryStyles: HierarchyStyleMap = {
|
|
13
|
+
idle: "bg-action-primary-idle text-action-primary-on-idle",
|
|
14
|
+
hover: "bg-action-primary-hover text-action-primary-on-hover",
|
|
15
|
+
disabled: "bg-action-primary-disabled text-action-primary-on-disabled",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const secondaryStyles: HierarchyStyleMap = {
|
|
19
|
+
idle:
|
|
20
|
+
"border border-divider-primary bg-action-secondary-idle text-action-secondary-on-idle",
|
|
21
|
+
hover:
|
|
22
|
+
"border border-divider-secondary bg-action-secondary-hover text-action-secondary-on-hover",
|
|
23
|
+
disabled:
|
|
24
|
+
"border border-divider-primary bg-action-secondary-disabled text-action-secondary-on-disabled",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const tertiaryStyles: HierarchyStyleMap = {
|
|
28
|
+
idle: "bg-action-tertiary-idle text-action-tertiary-on-idle",
|
|
29
|
+
hover: "bg-action-tertiary-hover text-action-tertiary-on-hover",
|
|
30
|
+
disabled: "bg-action-tertiary-disabled text-action-tertiary-on-disabled",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const quaternaryStyles: HierarchyStyleMap = {
|
|
34
|
+
idle: "bg-action-quaternary-idle text-action-quaternary-on-idle",
|
|
35
|
+
hover: "bg-action-quaternary-hover text-action-quaternary-on-hover",
|
|
36
|
+
disabled: "bg-action-quaternary-disabled text-action-quaternary-on-disabled",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const destructiveStyles: HierarchyStyleMap = {
|
|
40
|
+
idle: "bg-action-destructive-idle text-action-destructive-on-idle",
|
|
41
|
+
hover: "bg-action-destructive-hover text-action-destructive-on-hover",
|
|
42
|
+
disabled:
|
|
43
|
+
"bg-action-destructive-disabled text-action-destructive-on-disabled",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const hierarchyStyles: Record<ButtonHierarchy, HierarchyStyleMap> = {
|
|
47
|
+
primary: primaryStyles,
|
|
48
|
+
secondary: secondaryStyles,
|
|
49
|
+
tertiary: tertiaryStyles,
|
|
50
|
+
quaternary: quaternaryStyles,
|
|
51
|
+
destructive: destructiveStyles,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const interactiveHierarchyStyles: Record<ButtonHierarchy, string> = {
|
|
55
|
+
primary:
|
|
56
|
+
"bg-action-primary-idle text-action-primary-on-idle hover:bg-action-primary-hover hover:text-action-primary-on-hover",
|
|
57
|
+
secondary:
|
|
58
|
+
"border border-divider-primary bg-action-secondary-idle text-action-secondary-on-idle hover:border-divider-secondary hover:bg-action-secondary-hover hover:text-action-secondary-on-hover",
|
|
59
|
+
tertiary:
|
|
60
|
+
"bg-action-tertiary-idle text-action-tertiary-on-idle hover:bg-action-tertiary-hover hover:text-action-tertiary-on-hover",
|
|
61
|
+
quaternary:
|
|
62
|
+
"bg-action-quaternary-idle text-action-quaternary-on-idle hover:bg-action-quaternary-hover hover:text-action-quaternary-on-hover",
|
|
63
|
+
destructive:
|
|
64
|
+
"bg-action-destructive-idle text-action-destructive-on-idle hover:bg-action-destructive-hover hover:text-action-destructive-on-hover",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const disabledHierarchyStyles: Record<ButtonHierarchy, string> = {
|
|
68
|
+
primary: "bg-action-primary-disabled text-action-primary-on-disabled",
|
|
69
|
+
secondary:
|
|
70
|
+
"border border-divider-primary bg-action-secondary-disabled text-action-secondary-on-disabled",
|
|
71
|
+
tertiary: "bg-action-tertiary-disabled text-action-tertiary-on-disabled",
|
|
72
|
+
quaternary:
|
|
73
|
+
"bg-action-quaternary-disabled text-action-quaternary-on-disabled",
|
|
74
|
+
destructive:
|
|
75
|
+
"bg-action-destructive-disabled text-action-destructive-on-disabled",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const getButtonAppearanceClasses = (
|
|
79
|
+
hierarchy: ButtonHierarchy,
|
|
80
|
+
appearance: ButtonAppearance,
|
|
81
|
+
) => hierarchyStyles[hierarchy][appearance];
|
|
82
|
+
|
|
83
|
+
export const getButtonInteractiveClasses = (
|
|
84
|
+
hierarchy: ButtonHierarchy,
|
|
85
|
+
disabled: boolean,
|
|
86
|
+
) => {
|
|
87
|
+
if (disabled) {
|
|
88
|
+
return disabledHierarchyStyles[hierarchy];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return interactiveHierarchyStyles[hierarchy];
|
|
92
|
+
};
|
package/src/primitives/index.ts
CHANGED
|
@@ -14,5 +14,5 @@ export { Tooltip, TooltipProvider, type TooltipProps, type TooltipSide } from ".
|
|
|
14
14
|
export { ThinkingDot, type ThinkingDotProps } from "./ThinkingDot";
|
|
15
15
|
export { Count, type CountProps } from "./Count";
|
|
16
16
|
export { Switch, type SwitchProps } from "./Switch";
|
|
17
|
-
export { Badge, type BadgeProps } from "./Badge";
|
|
17
|
+
export { Badge, type BadgeProps, type BadgeColor, type BadgeType } from "./Badge";
|
|
18
18
|
export { Callout, type CalloutProps } from "./Callout";
|
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
import { AttachmentIcon } from "../../icons";
|
|
2
|
-
import { Button } from "../../primitives";
|
|
3
|
-
import { FigmaContent, FigmaPage, FigmaSection } from "../_layout";
|
|
4
|
-
import { FIGMA_WIDTHS } from "./figma-widths";
|
|
5
|
-
import {
|
|
6
|
-
BUTTON_VARIANT_SLOTS,
|
|
7
|
-
FIGMA_BUTTON_SLOTS,
|
|
8
|
-
FIGMA_BUTTONS_CANVAS,
|
|
9
|
-
FIGMA_BUTTONS_GRID,
|
|
10
|
-
type ButtonVisualState,
|
|
11
|
-
} from "./figma-buttons-layout";
|
|
12
|
-
import { IconButtonSnapshot } from "./helpers";
|
|
13
|
-
|
|
14
|
-
const demoDropdownOptions = [
|
|
15
|
-
{ label: "Option A", onSelect: () => undefined },
|
|
16
|
-
{ label: "Option B", onSelect: () => undefined },
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
const slotProps = (visualState: ButtonVisualState) => ({
|
|
20
|
-
forcedState: visualState === "idle" ? undefined : visualState,
|
|
21
|
-
disabled: visualState === "disabled",
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
export const ButtonsCanvas = () => (
|
|
25
|
-
<FigmaPage title="Buttons" width={FIGMA_WIDTHS.buttons}>
|
|
26
|
-
<FigmaContent padding={0}>
|
|
27
|
-
<div className="px-8 pb-8 pt-6">
|
|
28
|
-
<FigmaSection label="Button">
|
|
29
|
-
<div
|
|
30
|
-
className="relative"
|
|
31
|
-
style={{
|
|
32
|
-
width: FIGMA_BUTTONS_CANVAS.width,
|
|
33
|
-
height: FIGMA_BUTTONS_CANVAS.height,
|
|
34
|
-
}}
|
|
35
|
-
>
|
|
36
|
-
<div
|
|
37
|
-
data-figma-buttons-grid
|
|
38
|
-
className="absolute left-0 top-0"
|
|
39
|
-
style={{
|
|
40
|
-
width: FIGMA_BUTTONS_GRID.width,
|
|
41
|
-
height: FIGMA_BUTTONS_GRID.height,
|
|
42
|
-
}}
|
|
43
|
-
>
|
|
44
|
-
{FIGMA_BUTTON_SLOTS.map((slot) => (
|
|
45
|
-
<div
|
|
46
|
-
key={`${slot.hierarchy}-${slot.visualState}`}
|
|
47
|
-
className="absolute"
|
|
48
|
-
style={{ left: slot.x, top: slot.y }}
|
|
49
|
-
>
|
|
50
|
-
<Button
|
|
51
|
-
hierarchy={slot.hierarchy}
|
|
52
|
-
icon={AttachmentIcon}
|
|
53
|
-
dropdownOptions={demoDropdownOptions}
|
|
54
|
-
{...slotProps(slot.visualState)}
|
|
55
|
-
>
|
|
56
|
-
Button
|
|
57
|
-
</Button>
|
|
58
|
-
</div>
|
|
59
|
-
))}
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
{BUTTON_VARIANT_SLOTS.map((slot) => (
|
|
63
|
-
<div
|
|
64
|
-
key={`${slot.hierarchy}-${slot.variant}`}
|
|
65
|
-
data-visual-test-only
|
|
66
|
-
className="absolute"
|
|
67
|
-
style={{ left: slot.x, top: slot.y }}
|
|
68
|
-
>
|
|
69
|
-
{slot.variant === "noIcon" ? (
|
|
70
|
-
<Button
|
|
71
|
-
hierarchy={slot.hierarchy}
|
|
72
|
-
dropdownOptions={demoDropdownOptions}
|
|
73
|
-
>
|
|
74
|
-
Button
|
|
75
|
-
</Button>
|
|
76
|
-
) : (
|
|
77
|
-
<Button hierarchy={slot.hierarchy} icon={AttachmentIcon}>
|
|
78
|
-
Button
|
|
79
|
-
</Button>
|
|
80
|
-
)}
|
|
81
|
-
</div>
|
|
82
|
-
))}
|
|
83
|
-
</div>
|
|
84
|
-
</FigmaSection>
|
|
85
|
-
|
|
86
|
-
<FigmaSection label="Icon Button" className="mt-8">
|
|
87
|
-
<div className="flex flex-wrap items-center gap-6">
|
|
88
|
-
<IconButtonSnapshot hierarchy="tertiary" visualState="idle" />
|
|
89
|
-
<IconButtonSnapshot hierarchy="tertiary" visualState="hover" />
|
|
90
|
-
<IconButtonSnapshot hierarchy="quaternary" visualState="idle" />
|
|
91
|
-
<IconButtonSnapshot hierarchy="quaternary" visualState="hover" />
|
|
92
|
-
<IconButtonSnapshot
|
|
93
|
-
hierarchy="quaternary"
|
|
94
|
-
visualState="idle"
|
|
95
|
-
size="small"
|
|
96
|
-
/>
|
|
97
|
-
<IconButtonSnapshot
|
|
98
|
-
hierarchy="quaternary"
|
|
99
|
-
visualState="hover"
|
|
100
|
-
size="small"
|
|
101
|
-
/>
|
|
102
|
-
</div>
|
|
103
|
-
</FigmaSection>
|
|
104
|
-
</div>
|
|
105
|
-
</FigmaContent>
|
|
106
|
-
</FigmaPage>
|
|
107
|
-
);
|
|
1
|
+
import { AttachmentIcon } from "../../icons";
|
|
2
|
+
import { Button } from "../../primitives";
|
|
3
|
+
import { FigmaContent, FigmaPage, FigmaSection } from "../_layout";
|
|
4
|
+
import { FIGMA_WIDTHS } from "./figma-widths";
|
|
5
|
+
import {
|
|
6
|
+
BUTTON_VARIANT_SLOTS,
|
|
7
|
+
FIGMA_BUTTON_SLOTS,
|
|
8
|
+
FIGMA_BUTTONS_CANVAS,
|
|
9
|
+
FIGMA_BUTTONS_GRID,
|
|
10
|
+
type ButtonVisualState,
|
|
11
|
+
} from "./figma-buttons-layout";
|
|
12
|
+
import { IconButtonSnapshot } from "./helpers";
|
|
13
|
+
|
|
14
|
+
const demoDropdownOptions = [
|
|
15
|
+
{ label: "Option A", onSelect: () => undefined },
|
|
16
|
+
{ label: "Option B", onSelect: () => undefined },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const slotProps = (visualState: ButtonVisualState) => ({
|
|
20
|
+
forcedState: visualState === "idle" ? undefined : visualState,
|
|
21
|
+
disabled: visualState === "disabled",
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const ButtonsCanvas = () => (
|
|
25
|
+
<FigmaPage title="Buttons" width={FIGMA_WIDTHS.buttons}>
|
|
26
|
+
<FigmaContent padding={0}>
|
|
27
|
+
<div className="px-8 pb-8 pt-6">
|
|
28
|
+
<FigmaSection label="Button">
|
|
29
|
+
<div
|
|
30
|
+
className="relative"
|
|
31
|
+
style={{
|
|
32
|
+
width: FIGMA_BUTTONS_CANVAS.width,
|
|
33
|
+
height: FIGMA_BUTTONS_CANVAS.height,
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<div
|
|
37
|
+
data-figma-buttons-grid
|
|
38
|
+
className="absolute left-0 top-0"
|
|
39
|
+
style={{
|
|
40
|
+
width: FIGMA_BUTTONS_GRID.width,
|
|
41
|
+
height: FIGMA_BUTTONS_GRID.height,
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
{FIGMA_BUTTON_SLOTS.map((slot) => (
|
|
45
|
+
<div
|
|
46
|
+
key={`${slot.hierarchy}-${slot.visualState}`}
|
|
47
|
+
className="absolute"
|
|
48
|
+
style={{ left: slot.x, top: slot.y }}
|
|
49
|
+
>
|
|
50
|
+
<Button
|
|
51
|
+
hierarchy={slot.hierarchy}
|
|
52
|
+
icon={AttachmentIcon}
|
|
53
|
+
dropdownOptions={demoDropdownOptions}
|
|
54
|
+
{...slotProps(slot.visualState)}
|
|
55
|
+
>
|
|
56
|
+
Button
|
|
57
|
+
</Button>
|
|
58
|
+
</div>
|
|
59
|
+
))}
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
{BUTTON_VARIANT_SLOTS.map((slot) => (
|
|
63
|
+
<div
|
|
64
|
+
key={`${slot.hierarchy}-${slot.variant}`}
|
|
65
|
+
data-visual-test-only
|
|
66
|
+
className="absolute"
|
|
67
|
+
style={{ left: slot.x, top: slot.y }}
|
|
68
|
+
>
|
|
69
|
+
{slot.variant === "noIcon" ? (
|
|
70
|
+
<Button
|
|
71
|
+
hierarchy={slot.hierarchy}
|
|
72
|
+
dropdownOptions={demoDropdownOptions}
|
|
73
|
+
>
|
|
74
|
+
Button
|
|
75
|
+
</Button>
|
|
76
|
+
) : (
|
|
77
|
+
<Button hierarchy={slot.hierarchy} icon={AttachmentIcon}>
|
|
78
|
+
Button
|
|
79
|
+
</Button>
|
|
80
|
+
)}
|
|
81
|
+
</div>
|
|
82
|
+
))}
|
|
83
|
+
</div>
|
|
84
|
+
</FigmaSection>
|
|
85
|
+
|
|
86
|
+
<FigmaSection label="Icon Button" className="mt-8">
|
|
87
|
+
<div className="flex flex-wrap items-center gap-6">
|
|
88
|
+
<IconButtonSnapshot hierarchy="tertiary" visualState="idle" />
|
|
89
|
+
<IconButtonSnapshot hierarchy="tertiary" visualState="hover" />
|
|
90
|
+
<IconButtonSnapshot hierarchy="quaternary" visualState="idle" />
|
|
91
|
+
<IconButtonSnapshot hierarchy="quaternary" visualState="hover" />
|
|
92
|
+
<IconButtonSnapshot
|
|
93
|
+
hierarchy="quaternary"
|
|
94
|
+
visualState="idle"
|
|
95
|
+
size="small"
|
|
96
|
+
/>
|
|
97
|
+
<IconButtonSnapshot
|
|
98
|
+
hierarchy="quaternary"
|
|
99
|
+
visualState="hover"
|
|
100
|
+
size="small"
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
103
|
+
</FigmaSection>
|
|
104
|
+
</div>
|
|
105
|
+
</FigmaContent>
|
|
106
|
+
</FigmaPage>
|
|
107
|
+
);
|