@lateralus-ai/shipping-ui 2.0.0-dev.20 → 2.0.0-dev.21
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/domain/Filters/FilterDropdown.d.ts +93 -0
- package/dist/domain/Filters/FilterPill.d.ts +12 -5
- package/dist/domain/Filters/FilterPills.d.ts +21 -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.esm.js +7299 -5989
- package/package.json +2 -1
- package/src/components/EmptyState.tsx +44 -44
- package/src/components/Modal.tsx +141 -141
- package/src/components/PageHeader.tsx +132 -132
- package/src/components/ScrollableList.tsx +61 -61
- package/src/components/Tabs.tsx +146 -146
- package/src/components/index.ts +56 -56
- package/src/domain/Filters/FilterDropdown.tsx +438 -0
- package/src/domain/Filters/FilterPill.tsx +54 -18
- package/src/domain/Filters/FilterPills.tsx +41 -0
- package/src/domain/Filters/FilteredPill.tsx +40 -23
- package/src/domain/Filters/FiltersBar.tsx +15 -19
- package/src/domain/Filters/formatActiveFilterChipLabel.ts +23 -0
- package/src/domain/Filters/index.ts +35 -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 +85 -85
- package/src/patterns/Search/ResultRow.tsx +44 -44
- package/src/patterns/Search/SearchModal.tsx +310 -310
- package/src/patterns/Search/index.ts +31 -31
- 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 -56
- package/src/primitives/button-styles.ts +92 -92
- package/src/stories/canvases/ButtonsCanvas.tsx +107 -107
- package/src/stories/canvases/ButtonsMatrixCanvas.tsx +65 -65
- package/src/stories/canvases/ContentCanvas.tsx +353 -353
- package/src/stories/canvases/FiltersCanvas.tsx +156 -30
- package/src/stories/canvases/SearchCanvas.tsx +150 -150
- 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 +186 -186
- package/src/theme-entry.ts +2 -2
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
1
2
|
import {
|
|
2
|
-
|
|
3
|
-
FilteredPill,
|
|
3
|
+
FilterDropdown,
|
|
4
4
|
FilterPill,
|
|
5
|
+
FilterPills,
|
|
6
|
+
FilteredPill,
|
|
7
|
+
FiltersBar,
|
|
8
|
+
formatActiveFilterChipLabel,
|
|
9
|
+
type FilterCategoryRow,
|
|
5
10
|
} from "../../domain/Filters";
|
|
6
11
|
import {
|
|
7
12
|
FigmaContent,
|
|
@@ -11,31 +16,152 @@ import {
|
|
|
11
16
|
} from "../_layout";
|
|
12
17
|
import { FIGMA_WIDTHS } from "./figma-widths";
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
19
|
+
const demoOptions = {
|
|
20
|
+
status: [
|
|
21
|
+
{ value: "approved", label: "Approved" },
|
|
22
|
+
{ value: "reviewed", label: "Reviewed" },
|
|
23
|
+
{ value: "pending", label: "Pending" },
|
|
24
|
+
],
|
|
25
|
+
vessel: [
|
|
26
|
+
{ value: "aurora", label: "Aurora" },
|
|
27
|
+
{ value: "north", label: "North Star" },
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const FiltersCanvas = () => {
|
|
32
|
+
const [status, setStatus] = useState<string[]>([]);
|
|
33
|
+
const [vessel, setVessel] = useState<string[]>([]);
|
|
34
|
+
const [groupByVessel, setGroupByVessel] = useState(false);
|
|
35
|
+
|
|
36
|
+
const selectedValuesBySelectionKey = useMemo(
|
|
37
|
+
() => ({ status, vessel }),
|
|
38
|
+
[status, vessel],
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const categoryRows: FilterCategoryRow[] = useMemo(
|
|
42
|
+
() => [
|
|
43
|
+
{
|
|
44
|
+
id: "status",
|
|
45
|
+
label: "Status",
|
|
46
|
+
content: {
|
|
47
|
+
type: "options",
|
|
48
|
+
selectionKey: "status",
|
|
49
|
+
selectionMode: "multi",
|
|
50
|
+
options: demoOptions.status,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "vessel",
|
|
55
|
+
label: "Vessel",
|
|
56
|
+
content: {
|
|
57
|
+
type: "options",
|
|
58
|
+
selectionKey: "vessel",
|
|
59
|
+
selectionMode: "multi",
|
|
60
|
+
options: demoOptions.vessel,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
kind: "toggle",
|
|
65
|
+
id: "group",
|
|
66
|
+
label: "Group by Vessel",
|
|
67
|
+
checked: groupByVessel,
|
|
68
|
+
onCheckedChange: setGroupByVessel,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
[groupByVessel],
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const chips = useMemo(() => {
|
|
75
|
+
const next: {
|
|
76
|
+
key: string;
|
|
77
|
+
label: string;
|
|
78
|
+
onRemove: () => void;
|
|
79
|
+
}[] = [];
|
|
80
|
+
if (status.length > 0) {
|
|
81
|
+
const labels = status.map(
|
|
82
|
+
(v) => demoOptions.status.find((o) => o.value === v)?.label ?? v,
|
|
83
|
+
);
|
|
84
|
+
next.push({
|
|
85
|
+
key: "status",
|
|
86
|
+
label: formatActiveFilterChipLabel("Status", labels),
|
|
87
|
+
onRemove: () => setStatus([]),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (vessel.length > 0) {
|
|
91
|
+
const labels = vessel.map(
|
|
92
|
+
(v) => demoOptions.vessel.find((o) => o.value === v)?.label ?? v,
|
|
93
|
+
);
|
|
94
|
+
next.push({
|
|
95
|
+
key: "vessel",
|
|
96
|
+
label: formatActiveFilterChipLabel("Vessel", labels),
|
|
97
|
+
onRemove: () => setVessel([]),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return next;
|
|
101
|
+
}, [status, vessel]);
|
|
102
|
+
|
|
103
|
+
const activeFilterCount = chips.length;
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<FigmaPage title="Filters" width={FIGMA_WIDTHS.filters}>
|
|
107
|
+
<FigmaContent>
|
|
108
|
+
<FigmaSection label="Filter Pill (trigger)">
|
|
109
|
+
<FigmaGrid gap={16}>
|
|
110
|
+
<FilterPill />
|
|
111
|
+
<FilterPill activeFilterCount={2} />
|
|
112
|
+
</FigmaGrid>
|
|
113
|
+
</FigmaSection>
|
|
114
|
+
|
|
115
|
+
<FigmaSection label="Filtered Pill">
|
|
116
|
+
<FigmaGrid gap={16}>
|
|
117
|
+
<FilteredPill label="Approved" onRemove={() => undefined} />
|
|
118
|
+
<FilteredPill label="Reviewed" onRemove={() => undefined} />
|
|
119
|
+
</FigmaGrid>
|
|
120
|
+
</FigmaSection>
|
|
121
|
+
|
|
122
|
+
<FigmaSection label="FilterDropdown + FilterPills (interactive)">
|
|
123
|
+
<div className="flex w-full items-center justify-between gap-4">
|
|
124
|
+
<FilterPills chips={chips} />
|
|
125
|
+
<div className="flex shrink-0 items-center gap-4">
|
|
126
|
+
<FilterDropdown
|
|
127
|
+
align="end"
|
|
128
|
+
categoryRows={categoryRows}
|
|
129
|
+
selectedValuesBySelectionKey={selectedValuesBySelectionKey}
|
|
130
|
+
activeFilterCount={activeFilterCount}
|
|
131
|
+
onSelectOption={(key, value) => {
|
|
132
|
+
if (key === "status") {
|
|
133
|
+
setStatus((prev) =>
|
|
134
|
+
prev.includes(value)
|
|
135
|
+
? prev.filter((v) => v !== value)
|
|
136
|
+
: [...prev, value],
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (key === "vessel") {
|
|
140
|
+
setVessel((prev) =>
|
|
141
|
+
prev.includes(value)
|
|
142
|
+
? prev.filter((v) => v !== value)
|
|
143
|
+
: [...prev, value],
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}}
|
|
147
|
+
onResetAll={() => {
|
|
148
|
+
setStatus([]);
|
|
149
|
+
setVessel([]);
|
|
150
|
+
setGroupByVessel(false);
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
</FigmaSection>
|
|
156
|
+
|
|
157
|
+
<FigmaSection label="Filters Bar (layout stub)">
|
|
158
|
+
<div className="space-y-6">
|
|
159
|
+
<FiltersBar />
|
|
160
|
+
<FiltersBar filters="on" activeTab="Reports" />
|
|
161
|
+
<FiltersBar tabs="off" searchPlaceholder="Search workflows..." />
|
|
162
|
+
</div>
|
|
163
|
+
</FigmaSection>
|
|
164
|
+
</FigmaContent>
|
|
165
|
+
</FigmaPage>
|
|
166
|
+
);
|
|
167
|
+
};
|
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Pill,
|
|
3
|
-
PillInfo,
|
|
4
|
-
ResultRow,
|
|
5
|
-
SearchModalPanel,
|
|
6
|
-
SectionHeader,
|
|
7
|
-
} from "../../patterns/Search";
|
|
8
|
-
import {
|
|
9
|
-
FigmaContent,
|
|
10
|
-
FigmaGrid,
|
|
11
|
-
FigmaPage,
|
|
12
|
-
FigmaSection,
|
|
13
|
-
FigmaVariant,
|
|
14
|
-
} from "../_layout";
|
|
15
|
-
import { FIGMA_WIDTHS } from "./figma-widths";
|
|
16
|
-
|
|
17
|
-
const recentItems = [
|
|
18
|
-
{ variant: "report" as const, title: "Engine Room Oil Leak" },
|
|
19
|
-
{ variant: "chat" as const, title: "Low Water Pressure on Board" },
|
|
20
|
-
{
|
|
21
|
-
variant: "chat" as const,
|
|
22
|
-
title: "Generator Vibrating Excessively",
|
|
23
|
-
state: "active" as const,
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
variant: "issue" as const,
|
|
27
|
-
title:
|
|
28
|
-
"Intermittent Flickering of Navigation Lights Possibly Due to Bulb Failure or Signal Unit Errors",
|
|
29
|
-
},
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
const resultItems = [
|
|
33
|
-
{
|
|
34
|
-
variant: "report" as const,
|
|
35
|
-
title: "Persistent Engine Room Oil Leak",
|
|
36
|
-
subtitle: (
|
|
37
|
-
<>
|
|
38
|
-
We’ve got a persistent oil leak from the{" "}
|
|
39
|
-
<span className="text-caption-2-em text-display-on-light-primary">
|
|
40
|
-
fuel pump
|
|
41
|
-
</span>
|
|
42
|
-
. I’ve tightened what I could, but it keeps seeping.
|
|
43
|
-
</>
|
|
44
|
-
),
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
variant: "chat" as const,
|
|
48
|
-
title: "Ballast Pump Not Starting",
|
|
49
|
-
subtitle: (
|
|
50
|
-
<>
|
|
51
|
-
The{" "}
|
|
52
|
-
<span className="text-caption-2-em text-display-on-light-primary">
|
|
53
|
-
fuel pump
|
|
54
|
-
</span>{" "}
|
|
55
|
-
won’t start consistently. Sometimes it works, sometimes it doesn’t.
|
|
56
|
-
</>
|
|
57
|
-
),
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
variant: "issue" as const,
|
|
61
|
-
title:
|
|
62
|
-
"Excessive Rust on Fuel Pump and Piping with Unclear Material Specifications and Corrosion Protection Measures",
|
|
63
|
-
subtitle: "Created by Jake Silva on March 28",
|
|
64
|
-
state: "active" as const,
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
variant: "report" as const,
|
|
68
|
-
title: "Engine Room Oil Leak",
|
|
69
|
-
subtitle: (
|
|
70
|
-
<>
|
|
71
|
-
We’ve spotted a steady oil leak near the{" "}
|
|
72
|
-
<span className="text-caption-2-em text-display-on-light-primary">
|
|
73
|
-
fuel pump
|
|
74
|
-
</span>
|
|
75
|
-
. Not sure if it’s a gasket or a cracked line.
|
|
76
|
-
</>
|
|
77
|
-
),
|
|
78
|
-
},
|
|
79
|
-
];
|
|
80
|
-
|
|
81
|
-
export const SearchCanvas = () => (
|
|
82
|
-
<FigmaPage title="Search" width={FIGMA_WIDTHS.search}>
|
|
83
|
-
<FigmaContent>
|
|
84
|
-
<FigmaSection label="Pill">
|
|
85
|
-
<FigmaGrid gap={16}>
|
|
86
|
-
<Pill>All</Pill>
|
|
87
|
-
<Pill state="active">Reports</Pill>
|
|
88
|
-
<Pill size="small">Issues</Pill>
|
|
89
|
-
<Pill size="small" state="active">
|
|
90
|
-
Chats
|
|
91
|
-
</Pill>
|
|
92
|
-
</FigmaGrid>
|
|
93
|
-
</FigmaSection>
|
|
94
|
-
|
|
95
|
-
<FigmaSection label="Pill Info">
|
|
96
|
-
<FigmaGrid gap={16}>
|
|
97
|
-
<PillInfo />
|
|
98
|
-
<PillInfo type="completed" />
|
|
99
|
-
</FigmaGrid>
|
|
100
|
-
</FigmaSection>
|
|
101
|
-
|
|
102
|
-
<FigmaSection label="Result Row">
|
|
103
|
-
<div className="max-w-xl space-y-2">
|
|
104
|
-
<ResultRow />
|
|
105
|
-
<ResultRow
|
|
106
|
-
variant="chat"
|
|
107
|
-
title="Port state control discussion"
|
|
108
|
-
subtitle="2 days ago"
|
|
109
|
-
/>
|
|
110
|
-
<ResultRow
|
|
111
|
-
variant="issue"
|
|
112
|
-
title="Critical valve malfunction"
|
|
113
|
-
subtitle="Open · High priority"
|
|
114
|
-
/>
|
|
115
|
-
</div>
|
|
116
|
-
</FigmaSection>
|
|
117
|
-
|
|
118
|
-
<FigmaSection label="Section Header">
|
|
119
|
-
<div className="max-w-xl">
|
|
120
|
-
<SectionHeader label="Reports" />
|
|
121
|
-
</div>
|
|
122
|
-
</FigmaSection>
|
|
123
|
-
|
|
124
|
-
<FigmaSection label="Search Modal">
|
|
125
|
-
<FigmaGrid gap={32}>
|
|
126
|
-
<FigmaVariant label="Idle">
|
|
127
|
-
<div className="w-[700px] overflow-hidden rounded-xl border border-divider-primary bg-background-primary shadow-raise3">
|
|
128
|
-
<SearchModalPanel state="idle" recentItems={recentItems} />
|
|
129
|
-
</div>
|
|
130
|
-
</FigmaVariant>
|
|
131
|
-
<FigmaVariant label="Loading">
|
|
132
|
-
<div className="w-[700px] overflow-hidden rounded-xl border border-divider-primary bg-background-primary shadow-raise3">
|
|
133
|
-
<SearchModalPanel state="loading" query="fuel pump" />
|
|
134
|
-
</div>
|
|
135
|
-
</FigmaVariant>
|
|
136
|
-
<FigmaVariant label="Results">
|
|
137
|
-
<div className="w-[700px] overflow-hidden rounded-xl border border-divider-primary bg-background-primary shadow-raise3">
|
|
138
|
-
<SearchModalPanel
|
|
139
|
-
state="results"
|
|
140
|
-
query="fuel pump"
|
|
141
|
-
filter="all"
|
|
142
|
-
resultItems={resultItems}
|
|
143
|
-
/>
|
|
144
|
-
</div>
|
|
145
|
-
</FigmaVariant>
|
|
146
|
-
</FigmaGrid>
|
|
147
|
-
</FigmaSection>
|
|
148
|
-
</FigmaContent>
|
|
149
|
-
</FigmaPage>
|
|
150
|
-
);
|
|
1
|
+
import {
|
|
2
|
+
Pill,
|
|
3
|
+
PillInfo,
|
|
4
|
+
ResultRow,
|
|
5
|
+
SearchModalPanel,
|
|
6
|
+
SectionHeader,
|
|
7
|
+
} from "../../patterns/Search";
|
|
8
|
+
import {
|
|
9
|
+
FigmaContent,
|
|
10
|
+
FigmaGrid,
|
|
11
|
+
FigmaPage,
|
|
12
|
+
FigmaSection,
|
|
13
|
+
FigmaVariant,
|
|
14
|
+
} from "../_layout";
|
|
15
|
+
import { FIGMA_WIDTHS } from "./figma-widths";
|
|
16
|
+
|
|
17
|
+
const recentItems = [
|
|
18
|
+
{ variant: "report" as const, title: "Engine Room Oil Leak" },
|
|
19
|
+
{ variant: "chat" as const, title: "Low Water Pressure on Board" },
|
|
20
|
+
{
|
|
21
|
+
variant: "chat" as const,
|
|
22
|
+
title: "Generator Vibrating Excessively",
|
|
23
|
+
state: "active" as const,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
variant: "issue" as const,
|
|
27
|
+
title:
|
|
28
|
+
"Intermittent Flickering of Navigation Lights Possibly Due to Bulb Failure or Signal Unit Errors",
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const resultItems = [
|
|
33
|
+
{
|
|
34
|
+
variant: "report" as const,
|
|
35
|
+
title: "Persistent Engine Room Oil Leak",
|
|
36
|
+
subtitle: (
|
|
37
|
+
<>
|
|
38
|
+
We’ve got a persistent oil leak from the{" "}
|
|
39
|
+
<span className="text-caption-2-em text-display-on-light-primary">
|
|
40
|
+
fuel pump
|
|
41
|
+
</span>
|
|
42
|
+
. I’ve tightened what I could, but it keeps seeping.
|
|
43
|
+
</>
|
|
44
|
+
),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
variant: "chat" as const,
|
|
48
|
+
title: "Ballast Pump Not Starting",
|
|
49
|
+
subtitle: (
|
|
50
|
+
<>
|
|
51
|
+
The{" "}
|
|
52
|
+
<span className="text-caption-2-em text-display-on-light-primary">
|
|
53
|
+
fuel pump
|
|
54
|
+
</span>{" "}
|
|
55
|
+
won’t start consistently. Sometimes it works, sometimes it doesn’t.
|
|
56
|
+
</>
|
|
57
|
+
),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
variant: "issue" as const,
|
|
61
|
+
title:
|
|
62
|
+
"Excessive Rust on Fuel Pump and Piping with Unclear Material Specifications and Corrosion Protection Measures",
|
|
63
|
+
subtitle: "Created by Jake Silva on March 28",
|
|
64
|
+
state: "active" as const,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
variant: "report" as const,
|
|
68
|
+
title: "Engine Room Oil Leak",
|
|
69
|
+
subtitle: (
|
|
70
|
+
<>
|
|
71
|
+
We’ve spotted a steady oil leak near the{" "}
|
|
72
|
+
<span className="text-caption-2-em text-display-on-light-primary">
|
|
73
|
+
fuel pump
|
|
74
|
+
</span>
|
|
75
|
+
. Not sure if it’s a gasket or a cracked line.
|
|
76
|
+
</>
|
|
77
|
+
),
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
export const SearchCanvas = () => (
|
|
82
|
+
<FigmaPage title="Search" width={FIGMA_WIDTHS.search}>
|
|
83
|
+
<FigmaContent>
|
|
84
|
+
<FigmaSection label="Pill">
|
|
85
|
+
<FigmaGrid gap={16}>
|
|
86
|
+
<Pill>All</Pill>
|
|
87
|
+
<Pill state="active">Reports</Pill>
|
|
88
|
+
<Pill size="small">Issues</Pill>
|
|
89
|
+
<Pill size="small" state="active">
|
|
90
|
+
Chats
|
|
91
|
+
</Pill>
|
|
92
|
+
</FigmaGrid>
|
|
93
|
+
</FigmaSection>
|
|
94
|
+
|
|
95
|
+
<FigmaSection label="Pill Info">
|
|
96
|
+
<FigmaGrid gap={16}>
|
|
97
|
+
<PillInfo />
|
|
98
|
+
<PillInfo type="completed" />
|
|
99
|
+
</FigmaGrid>
|
|
100
|
+
</FigmaSection>
|
|
101
|
+
|
|
102
|
+
<FigmaSection label="Result Row">
|
|
103
|
+
<div className="max-w-xl space-y-2">
|
|
104
|
+
<ResultRow />
|
|
105
|
+
<ResultRow
|
|
106
|
+
variant="chat"
|
|
107
|
+
title="Port state control discussion"
|
|
108
|
+
subtitle="2 days ago"
|
|
109
|
+
/>
|
|
110
|
+
<ResultRow
|
|
111
|
+
variant="issue"
|
|
112
|
+
title="Critical valve malfunction"
|
|
113
|
+
subtitle="Open · High priority"
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
</FigmaSection>
|
|
117
|
+
|
|
118
|
+
<FigmaSection label="Section Header">
|
|
119
|
+
<div className="max-w-xl">
|
|
120
|
+
<SectionHeader label="Reports" />
|
|
121
|
+
</div>
|
|
122
|
+
</FigmaSection>
|
|
123
|
+
|
|
124
|
+
<FigmaSection label="Search Modal">
|
|
125
|
+
<FigmaGrid gap={32}>
|
|
126
|
+
<FigmaVariant label="Idle">
|
|
127
|
+
<div className="w-[700px] overflow-hidden rounded-xl border border-divider-primary bg-background-primary shadow-raise3">
|
|
128
|
+
<SearchModalPanel state="idle" recentItems={recentItems} />
|
|
129
|
+
</div>
|
|
130
|
+
</FigmaVariant>
|
|
131
|
+
<FigmaVariant label="Loading">
|
|
132
|
+
<div className="w-[700px] overflow-hidden rounded-xl border border-divider-primary bg-background-primary shadow-raise3">
|
|
133
|
+
<SearchModalPanel state="loading" query="fuel pump" />
|
|
134
|
+
</div>
|
|
135
|
+
</FigmaVariant>
|
|
136
|
+
<FigmaVariant label="Results">
|
|
137
|
+
<div className="w-[700px] overflow-hidden rounded-xl border border-divider-primary bg-background-primary shadow-raise3">
|
|
138
|
+
<SearchModalPanel
|
|
139
|
+
state="results"
|
|
140
|
+
query="fuel pump"
|
|
141
|
+
filter="all"
|
|
142
|
+
resultItems={resultItems}
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
145
|
+
</FigmaVariant>
|
|
146
|
+
</FigmaGrid>
|
|
147
|
+
</FigmaSection>
|
|
148
|
+
</FigmaContent>
|
|
149
|
+
</FigmaPage>
|
|
150
|
+
);
|
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
/** Figma Buttons > Content > Button frame — 414×312, slots 106×40 */
|
|
2
|
-
|
|
3
|
-
export const FIGMA_BUTTONS_GRID = {
|
|
4
|
-
width: 414,
|
|
5
|
-
height: 312,
|
|
6
|
-
} as const;
|
|
7
|
-
|
|
8
|
-
export type ButtonVisualState = "idle" | "hover" | "disabled";
|
|
9
|
-
|
|
10
|
-
export type ButtonGridSlot = {
|
|
11
|
-
hierarchy:
|
|
12
|
-
| "primary"
|
|
13
|
-
| "secondary"
|
|
14
|
-
| "tertiary"
|
|
15
|
-
| "quaternary"
|
|
16
|
-
| "destructive";
|
|
17
|
-
visualState: ButtonVisualState;
|
|
18
|
-
x: number;
|
|
19
|
-
y: number;
|
|
20
|
-
width: number;
|
|
21
|
-
height: number;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const BUTTON_WIDTH = 106;
|
|
25
|
-
const BUTTON_HEIGHT = 40;
|
|
26
|
-
const COLUMN_X = [24, 154, 284] as const;
|
|
27
|
-
const ROW_Y = [24, 80, 136, 192, 248] as const;
|
|
28
|
-
|
|
29
|
-
const hierarchies = [
|
|
30
|
-
"primary",
|
|
31
|
-
"secondary",
|
|
32
|
-
"tertiary",
|
|
33
|
-
"quaternary",
|
|
34
|
-
"destructive",
|
|
35
|
-
] as const;
|
|
36
|
-
|
|
37
|
-
const visualStates: ButtonVisualState[] = ["idle", "hover", "disabled"];
|
|
38
|
-
|
|
39
|
-
export const FIGMA_BUTTON_SLOTS: ButtonGridSlot[] = hierarchies.flatMap(
|
|
40
|
-
(hierarchy, rowIndex) =>
|
|
41
|
-
visualStates.map((visualState, columnIndex) => ({
|
|
42
|
-
hierarchy,
|
|
43
|
-
visualState,
|
|
44
|
-
x: COLUMN_X[columnIndex],
|
|
45
|
-
y: ROW_Y[rowIndex],
|
|
46
|
-
width: BUTTON_WIDTH,
|
|
47
|
-
height: BUTTON_HEIGHT,
|
|
48
|
-
})),
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
export type ButtonVariantSlot = {
|
|
52
|
-
hierarchy: (typeof hierarchies)[number];
|
|
53
|
-
variant: "noIcon" | "noDropdown";
|
|
54
|
-
x: number;
|
|
55
|
-
y: number;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const VARIANT_COLUMN_X = [414, 544] as const;
|
|
59
|
-
|
|
60
|
-
/** Extra canvas slots — excluded from `data-figma-buttons-grid` visual clip */
|
|
61
|
-
export const BUTTON_VARIANT_SLOTS: ButtonVariantSlot[] = hierarchies.flatMap(
|
|
62
|
-
(hierarchy, rowIndex) => [
|
|
63
|
-
{
|
|
64
|
-
hierarchy,
|
|
65
|
-
variant: "noIcon" as const,
|
|
66
|
-
x: VARIANT_COLUMN_X[0],
|
|
67
|
-
y: ROW_Y[rowIndex],
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
hierarchy,
|
|
71
|
-
variant: "noDropdown" as const,
|
|
72
|
-
x: VARIANT_COLUMN_X[1],
|
|
73
|
-
y: ROW_Y[rowIndex],
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
export const FIGMA_BUTTONS_CANVAS = {
|
|
79
|
-
figmaGridWidth: FIGMA_BUTTONS_GRID.width,
|
|
80
|
-
figmaGridHeight: FIGMA_BUTTONS_GRID.height,
|
|
81
|
-
width: VARIANT_COLUMN_X[1] + BUTTON_WIDTH + 24,
|
|
82
|
-
height: FIGMA_BUTTONS_GRID.height,
|
|
83
|
-
} as const;
|
|
1
|
+
/** Figma Buttons > Content > Button frame — 414×312, slots 106×40 */
|
|
2
|
+
|
|
3
|
+
export const FIGMA_BUTTONS_GRID = {
|
|
4
|
+
width: 414,
|
|
5
|
+
height: 312,
|
|
6
|
+
} as const;
|
|
7
|
+
|
|
8
|
+
export type ButtonVisualState = "idle" | "hover" | "disabled";
|
|
9
|
+
|
|
10
|
+
export type ButtonGridSlot = {
|
|
11
|
+
hierarchy:
|
|
12
|
+
| "primary"
|
|
13
|
+
| "secondary"
|
|
14
|
+
| "tertiary"
|
|
15
|
+
| "quaternary"
|
|
16
|
+
| "destructive";
|
|
17
|
+
visualState: ButtonVisualState;
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const BUTTON_WIDTH = 106;
|
|
25
|
+
const BUTTON_HEIGHT = 40;
|
|
26
|
+
const COLUMN_X = [24, 154, 284] as const;
|
|
27
|
+
const ROW_Y = [24, 80, 136, 192, 248] as const;
|
|
28
|
+
|
|
29
|
+
const hierarchies = [
|
|
30
|
+
"primary",
|
|
31
|
+
"secondary",
|
|
32
|
+
"tertiary",
|
|
33
|
+
"quaternary",
|
|
34
|
+
"destructive",
|
|
35
|
+
] as const;
|
|
36
|
+
|
|
37
|
+
const visualStates: ButtonVisualState[] = ["idle", "hover", "disabled"];
|
|
38
|
+
|
|
39
|
+
export const FIGMA_BUTTON_SLOTS: ButtonGridSlot[] = hierarchies.flatMap(
|
|
40
|
+
(hierarchy, rowIndex) =>
|
|
41
|
+
visualStates.map((visualState, columnIndex) => ({
|
|
42
|
+
hierarchy,
|
|
43
|
+
visualState,
|
|
44
|
+
x: COLUMN_X[columnIndex],
|
|
45
|
+
y: ROW_Y[rowIndex],
|
|
46
|
+
width: BUTTON_WIDTH,
|
|
47
|
+
height: BUTTON_HEIGHT,
|
|
48
|
+
})),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
export type ButtonVariantSlot = {
|
|
52
|
+
hierarchy: (typeof hierarchies)[number];
|
|
53
|
+
variant: "noIcon" | "noDropdown";
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const VARIANT_COLUMN_X = [414, 544] as const;
|
|
59
|
+
|
|
60
|
+
/** Extra canvas slots — excluded from `data-figma-buttons-grid` visual clip */
|
|
61
|
+
export const BUTTON_VARIANT_SLOTS: ButtonVariantSlot[] = hierarchies.flatMap(
|
|
62
|
+
(hierarchy, rowIndex) => [
|
|
63
|
+
{
|
|
64
|
+
hierarchy,
|
|
65
|
+
variant: "noIcon" as const,
|
|
66
|
+
x: VARIANT_COLUMN_X[0],
|
|
67
|
+
y: ROW_Y[rowIndex],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
hierarchy,
|
|
71
|
+
variant: "noDropdown" as const,
|
|
72
|
+
x: VARIANT_COLUMN_X[1],
|
|
73
|
+
y: ROW_Y[rowIndex],
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
export const FIGMA_BUTTONS_CANVAS = {
|
|
79
|
+
figmaGridWidth: FIGMA_BUTTONS_GRID.width,
|
|
80
|
+
figmaGridHeight: FIGMA_BUTTONS_GRID.height,
|
|
81
|
+
width: VARIANT_COLUMN_X[1] + BUTTON_WIDTH + 24,
|
|
82
|
+
height: FIGMA_BUTTONS_GRID.height,
|
|
83
|
+
} as const;
|