@crewlethq/ui 0.4.3 → 0.5.0
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/README.md +888 -24
- package/dist/Accordion/index.js +2 -2
- package/dist/AddPill/index.js +1 -1
- package/dist/{AddPill-DFWXYLIQ.css → AddPill-IJQYCY6C.css} +9 -0
- package/dist/AppShell/AppShell.d.ts +26 -5
- package/dist/AppShell/index.js +3 -3
- package/dist/{AppShell-NVE6LHNI.css → AppShell-XARELGIH.css} +178 -25
- package/dist/Avatar/Avatar.d.ts +85 -40
- package/dist/Avatar/AvatarStack.d.ts +76 -0
- package/dist/Avatar/index.d.ts +5 -2
- package/dist/Avatar/index.js +1 -1
- package/dist/Avatar-XID7Z74C.css +200 -0
- package/dist/AvatarStack-GEJBNV7E.css +72 -0
- package/dist/BrandLockup/index.js +1 -1
- package/dist/{BrandLockup-6ISDEHPJ.css → BrandLockup-JKGXFCZF.css} +25 -19
- package/dist/Button/Button.d.ts +7 -2
- package/dist/Button/index.js +1 -1
- package/dist/{Button-D4J6B4MA.css → Button-X4B2TJAQ.css} +50 -19
- package/dist/Callout/index.js +1 -1
- package/dist/Canvas/index.js +4 -4
- package/dist/Card/Card.d.ts +9 -5
- package/dist/Card/index.js +1 -1
- package/dist/{Card-RLR254LD.css → Card-GLP7SUV6.css} +25 -18
- package/dist/Charts/BarList.d.ts +18 -1
- package/dist/Charts/ChartTooltip.d.ts +68 -0
- package/dist/Charts/StackedBar.d.ts +25 -7
- package/dist/Charts/StackedColumns.d.ts +112 -0
- package/dist/Charts/TimeSeries.d.ts +33 -2
- package/dist/Charts/dataColor.d.ts +22 -14
- package/dist/Charts/index.d.ts +6 -0
- package/dist/Charts/index.js +1 -1
- package/dist/Charts/useChartHover.d.ts +56 -0
- package/dist/Charts-B3YEF7R4.css +742 -0
- package/dist/Checkbox/index.js +1 -1
- package/dist/{Checkbox-VGW26YLQ.css → Checkbox-BOXQ747I.css} +2 -2
- package/dist/CodeBlock/index.js +4 -4
- package/dist/Combobox/index.js +5 -5
- package/dist/CommandPalette/CommandPalette.d.ts +97 -6
- package/dist/CommandPalette/index.d.ts +1 -1
- package/dist/CommandPalette/index.js +9 -7
- package/dist/CommandPalette-C5AMKGN2.css +259 -0
- package/dist/Copyable/index.js +3 -3
- package/dist/DataTable/index.js +7 -7
- package/dist/{DataTable-ITNACQ2X.css → DataTable-OLHPF7D4.css} +44 -43
- package/dist/DataView/index.js +14 -14
- package/dist/{DataView-256YF32J.css → DataView-N6JX464S.css} +5 -4
- package/dist/DateTimePicker/index.js +5 -5
- package/dist/DiffList/index.js +1 -1
- package/dist/Disclosure/index.js +2 -2
- package/dist/EntityChip/EntityChip.d.ts +9 -12
- package/dist/EntityChip/index.d.ts +1 -1
- package/dist/EntityChip/index.js +2 -2
- package/dist/ErrorBoundary/index.js +2 -2
- package/dist/{ErrorBoundary-ME36CQTA.css → ErrorBoundary-U2PA3LY2.css} +4 -4
- package/dist/IconButton/index.js +1 -1
- package/dist/{IconButton-VQGNMJDI.css → IconButton-TVEUWK6L.css} +2 -2
- package/dist/ImageUpload/ImageUpload.d.ts +10 -7
- package/dist/ImageUpload/index.js +2 -2
- package/dist/{ImageUpload-HKFIZR6D.css → ImageUpload-YCHJMUGX.css} +24 -10
- package/dist/Input/index.js +2 -2
- package/dist/Kbd/Kbd.d.ts +14 -4
- package/dist/Kbd/index.js +1 -1
- package/dist/Kbd-JPLDVJIP.css +71 -0
- package/dist/Layer/index.js +1 -1
- package/dist/Link/index.js +1 -1
- package/dist/List/index.js +1 -1
- package/dist/{List-XTHESXLR.css → List-MYJIV6MP.css} +12 -2
- package/dist/ListInput/index.js +5 -5
- package/dist/Listbox/index.js +2 -2
- package/dist/Listbox/useListbox.d.ts +16 -0
- package/dist/Listbox/useOptionKeys.d.ts +12 -1
- package/dist/{Listbox-X2DOTSQA.css → Listbox-6WJNJQVQ.css} +60 -7
- package/dist/Menu/index.js +4 -4
- package/dist/{Menu-6DE7I66I.css → Menu-BT5PMFJI.css} +15 -0
- package/dist/Meter/Meter.d.ts +103 -16
- package/dist/Meter/index.d.ts +2 -2
- package/dist/Meter/index.js +1 -1
- package/dist/{Meter-SKOOXQBC.css → Meter-5VCSFMZW.css} +46 -7
- package/dist/Modal/index.js +4 -4
- package/dist/{Modal-XYQJ4BL6.css → Modal-JAYBS2KS.css} +13 -4
- package/dist/OrgLabel/OrgLabel.d.ts +60 -24
- package/dist/OrgLabel/index.d.ts +1 -1
- package/dist/OrgLabel/index.js +2 -1
- package/dist/{OrgLabel-D7U6QJZD.css → OrgLabel-CR233G34.css} +9 -18
- package/dist/OrgNode/index.js +3 -2
- package/dist/OrgTable/OrgTable.d.ts +2 -2
- package/dist/OrgTable/index.js +8 -7
- package/dist/Popover/index.js +2 -2
- package/dist/PricingCard/index.js +3 -3
- package/dist/{PricingCard-JFI7RYXP.css → PricingCard-7EFXRSD2.css} +4 -5
- package/dist/SearchTrigger/SearchTrigger.d.ts +23 -4
- package/dist/SearchTrigger/index.d.ts +1 -1
- package/dist/SearchTrigger/index.js +1 -1
- package/dist/SearchTrigger-Z5D4AAY7.css +112 -0
- package/dist/SegmentedControl/index.js +2 -2
- package/dist/SegmentedMeter/SegmentedMeter.d.ts +107 -0
- package/dist/SegmentedMeter/index.d.ts +3 -0
- package/dist/SegmentedMeter/index.js +2 -0
- package/dist/SegmentedMeter-KQNML2TW.css +109 -0
- package/dist/Select/index.js +3 -3
- package/dist/{Select-2X77FSWR.css → Select-E24U5LBC.css} +34 -0
- package/dist/Shortcut/index.js +2 -2
- package/dist/SidebarNav/SidebarNav.d.ts +85 -25
- package/dist/SidebarNav/index.d.ts +1 -1
- package/dist/SidebarNav/index.js +1 -1
- package/dist/SidebarNav-X5NLZNWA.css +424 -0
- package/dist/StatCard/StatCard.d.ts +59 -12
- package/dist/StatCard/index.d.ts +1 -1
- package/dist/StatCard/index.js +1 -1
- package/dist/StatCard-KPAFD4E2.css +204 -0
- package/dist/StatGroup/index.js +1 -1
- package/dist/{StatGroup-TGB6AEKM.css → StatGroup-HVG6O62W.css} +8 -9
- package/dist/StatusDot/StatusDot.d.ts +24 -6
- package/dist/StatusDot/index.js +1 -1
- package/dist/StatusDot-7OMCQCZF.css +186 -0
- package/dist/Stepper/Stepper.d.ts +78 -0
- package/dist/Stepper/index.d.ts +3 -0
- package/dist/Stepper/index.js +4 -0
- package/dist/Stepper-HW4JM3YH.css +176 -0
- package/dist/Table/index.js +1 -1
- package/dist/{Table-MDOLVUAW.css → Table-TGCS4C3F.css} +14 -4
- package/dist/Tabs/index.js +1 -1
- package/dist/{Tabs-VLICJFVB.css → Tabs-XCNPHA7B.css} +79 -27
- package/dist/Tag/Tag.d.ts +29 -22
- package/dist/Tag/index.js +2 -2
- package/dist/{Tag-VNZEYLB6.css → Tag-GBE7LQJP.css} +82 -83
- package/dist/TagsInput/index.js +6 -6
- package/dist/ThemeSwitcher/ThemeSwitcher.d.ts +53 -21
- package/dist/ThemeSwitcher/index.d.ts +3 -3
- package/dist/ThemeSwitcher/index.js +4 -3
- package/dist/ThemeSwitcher/preferences.d.ts +19 -5
- package/dist/ThemeToggle/ThemeToggle.d.ts +40 -0
- package/dist/ThemeToggle/index.d.ts +2 -0
- package/dist/ThemeToggle/index.js +5 -0
- package/dist/TimeWindowPicker/index.js +8 -8
- package/dist/Toaster/index.js +2 -2
- package/dist/Toolbar/index.js +2 -2
- package/dist/{Toolbar-IP6LXN45.css → Toolbar-HUOSMNTH.css} +3 -1
- package/dist/Tooltip/index.js +2 -2
- package/dist/Tree/index.d.ts +2 -2
- package/dist/Tree/index.js +1 -1
- package/dist/Tree/layout.d.ts +103 -28
- package/dist/TreeCanvas/TreeCanvas.d.ts +60 -14
- package/dist/TreeCanvas/index.d.ts +1 -1
- package/dist/TreeCanvas/index.js +6 -6
- package/dist/TreeCanvas/motion.d.ts +3 -2
- package/dist/{TreeCanvas-WBNQPHC7.css → TreeCanvas-HVOV4SQN.css} +154 -30
- package/dist/TreeGrid/index.js +4 -4
- package/dist/{chunk-F6OE5FH3.js → chunk-2FPENTCF.js} +1 -1
- package/dist/chunk-4AK52VHB.js +88 -0
- package/dist/{chunk-7EM5T4ME.js → chunk-4IQD3HUQ.js} +2 -2
- package/dist/{chunk-YODNNSZL.js → chunk-4PZ6FJKW.js} +43 -13
- package/dist/{chunk-F27EPQ7D.js → chunk-4UQ7SMPK.js} +1 -1
- package/dist/chunk-5QWIJSQM.js +73 -0
- package/dist/{chunk-GTOUGQQK.js → chunk-6MU7HNB4.js} +13 -10
- package/dist/{chunk-S2XHHEW4.js → chunk-74KMX7YH.js} +4 -4
- package/dist/{chunk-WNI2WSJF.js → chunk-7KBNFFM3.js} +1 -1
- package/dist/{chunk-DD5BBGBE.js → chunk-AUS5FNQE.js} +9 -5
- package/dist/{chunk-CMEE37QJ.js → chunk-BMYPGGPV.js} +4 -4
- package/dist/{chunk-H4FBTAYS.js → chunk-BNCCEER3.js} +8 -8
- package/dist/chunk-C5WJUZVR.js +56 -0
- package/dist/{chunk-5WS6L6FA.js → chunk-CAIHUYXV.js} +9 -9
- package/dist/{chunk-XV6WRMBC.js → chunk-CQY5NTRS.js} +4 -1
- package/dist/{chunk-UOGSZKLT.js → chunk-D6EVJUGU.js} +2 -2
- package/dist/{chunk-6ZFVFA56.js → chunk-DHPUMOTX.js} +2 -2
- package/dist/{chunk-HZ5XZNPS.js → chunk-DS2C73RJ.js} +3 -3
- package/dist/{chunk-O6232G37.js → chunk-DSUY5F4E.js} +17 -5
- package/dist/{chunk-Q4ZPPART.js → chunk-EFYPAJT3.js} +3 -3
- package/dist/{chunk-WQX73TWF.js → chunk-ERVO6OUF.js} +18 -17
- package/dist/{chunk-BZYDZBAN.js → chunk-ETYEBKR4.js} +3 -3
- package/dist/{chunk-34VGEDVV.js → chunk-FD5UEN6X.js} +30 -30
- package/dist/{chunk-5SDBMKUO.js → chunk-FIFNP6PL.js} +3 -3
- package/dist/{chunk-7HPRF5XN.js → chunk-FUF52K7E.js} +98 -16
- package/dist/{chunk-5KPQ6D7N.js → chunk-FZVJDJFN.js} +2 -2
- package/dist/chunk-IA232OTU.js +156 -0
- package/dist/{chunk-2EOKFKHX.js → chunk-IG27QX7Q.js} +7 -7
- package/dist/chunk-IKB6HFGK.js +55 -0
- package/dist/{chunk-FBZAKNSX.js → chunk-IPVQKAHO.js} +10 -7
- package/dist/{chunk-3EYF6HKB.js → chunk-IVFJD7WY.js} +28 -9
- package/dist/{chunk-WOYYD2YR.js → chunk-JGRNTBF2.js} +11 -11
- package/dist/chunk-K3OWD7BJ.js +121 -0
- package/dist/{chunk-BJSKPEZI.js → chunk-KD4H66L6.js} +7 -20
- package/dist/{chunk-SFZOKW2G.js → chunk-KJ34ZBBI.js} +8 -3
- package/dist/{chunk-HQNHV7D6.js → chunk-LFHCXZO5.js} +6 -6
- package/dist/{chunk-LWKJQTOM.js → chunk-MICH6QSJ.js} +1 -1
- package/dist/chunk-N3DPO6HG.js +226 -0
- package/dist/{chunk-S4GZWSKR.js → chunk-OM5E3TTK.js} +1 -1
- package/dist/{chunk-3QRYCPXQ.js → chunk-OPKIKM35.js} +6 -6
- package/dist/{chunk-5EKIWVOR.js → chunk-PGRPNDWM.js} +2 -2
- package/dist/{chunk-LFJ6UJTI.js → chunk-PQNILU27.js} +9 -9
- package/dist/{chunk-QNCVHRZL.js → chunk-QVAFL2LE.js} +1 -1
- package/dist/{chunk-QEUY3A5P.js → chunk-QY7UU5ZB.js} +3 -2
- package/dist/{chunk-ITHXJHBB.js → chunk-R25RGPUB.js} +1 -0
- package/dist/{chunk-KLJCCMF3.js → chunk-R6735B37.js} +2 -2
- package/dist/{chunk-3ZP55QZE.js → chunk-R6FBDTP3.js} +4 -4
- package/dist/{chunk-7FZ53WDJ.js → chunk-RIAZM6L3.js} +1 -1
- package/dist/chunk-RJM4QCGG.js +550 -0
- package/dist/{chunk-NTRZGNEX.js → chunk-S3BCVWTU.js} +215 -46
- package/dist/chunk-S7KW47IQ.js +121 -0
- package/dist/{chunk-OFHBK7RI.js → chunk-SJQ546ID.js} +34 -14
- package/dist/{chunk-D35VTV2Z.js → chunk-SV7QAONL.js} +1 -1
- package/dist/{chunk-IAJLHVUA.js → chunk-TIWAHZZ6.js} +1 -1
- package/dist/{chunk-2PRH365R.js → chunk-UA7O3KKJ.js} +1 -1
- package/dist/{chunk-NPZY6YYL.js → chunk-UG5ZMAXW.js} +6 -6
- package/dist/{chunk-FEFTGVMF.js → chunk-V2N3BMOT.js} +7 -2
- package/dist/{chunk-NDCATSW7.js → chunk-V34H2YCY.js} +1 -1
- package/dist/chunk-WIATRXEJ.js +22 -0
- package/dist/{chunk-5C5YMZQU.js → chunk-WOFOMTGB.js} +16 -10
- package/dist/{chunk-QYOFACSP.js → chunk-WSOFKOLP.js} +3 -3
- package/dist/{chunk-MNAXYY3R.js → chunk-WUVZDFHS.js} +31 -11
- package/dist/{chunk-UG46QBLT.js → chunk-YIMOT5OO.js} +10 -10
- package/dist/{chunk-2ZQMA2WB.js → chunk-ZPSOF6VL.js} +2 -2
- package/dist/generated/index.d.ts +3 -0
- package/dist/generated/index.js +66 -62
- package/dist/index.js +66 -62
- package/dist/styles.css +2719 -799
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/tone.d.ts +7 -12
- package/package.json +4 -4
- package/scripts/check-css-literals.mjs +159 -23
- package/scripts/check-css-variables.mjs +5 -3
- package/scripts/css-source.mjs +97 -5
- package/dist/Avatar-P2KRQM2B.css +0 -156
- package/dist/Charts-D7G2BSXH.css +0 -277
- package/dist/CommandPalette-CSJDUCQA.css +0 -115
- package/dist/Kbd-W66MXQI5.css +0 -61
- package/dist/SearchTrigger-QXOYAUUY.css +0 -79
- package/dist/SidebarNav-QGSFKZYA.css +0 -319
- package/dist/StatCard-KYPKZUWX.css +0 -111
- package/dist/StatusDot-HA2L2FSX.css +0 -84
- package/dist/chunk-22O7LAW2.js +0 -41
- package/dist/chunk-2HQR4U4D.js +0 -143
- package/dist/chunk-ESCO4XYW.js +0 -144
- package/dist/chunk-F4PJZ4ED.js +0 -245
- package/dist/chunk-PNFASD6F.js +0 -98
- package/dist/chunk-PZSWF74H.js +0 -15
- /package/dist/{chunk-ZCR6YGQ4.js → chunk-PKIN4IMB.js} +0 -0
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The rail's navigation: groups of rows, one of which says where the reader is.
|
|
3
3
|
*
|
|
4
|
-
* THE ROW THE READER IS ON IS
|
|
5
|
-
*
|
|
6
|
-
* and
|
|
7
|
-
*
|
|
4
|
+
* THE ROW THE READER IS ON IS RAISED, WITH A HAIRLINE ROUND IT, AND NO HUE: it
|
|
5
|
+
* is found by its position, its lift and its line, by a reader who sees
|
|
6
|
+
* colour and by one who does not. The accent is the primary action's fill, so
|
|
7
|
+
* a violet row in the rail would read as a second primary on every screen.
|
|
8
8
|
* `aria-current="page"` says the same thing to a screen reader, and the style
|
|
9
9
|
* is drawn FROM that attribute, so the two cannot come apart. The stylesheet
|
|
10
|
-
* carries why
|
|
10
|
+
* carries why the hairline is an outline rather than a shadow.
|
|
11
11
|
*
|
|
12
12
|
* THE LINK ELEMENT BELONGS TO THE APPLICATION (`renderLink`). A router's own
|
|
13
13
|
* link is what carries a client navigation and a leave guard; a plain anchor is
|
|
14
14
|
* what carries a middle click into a new tab. Neither is right everywhere, so
|
|
15
15
|
* neither is built in: the engine keeps plain anchors and the console passes
|
|
16
16
|
* its router's NavLink.
|
|
17
|
+
*
|
|
18
|
+
* A FIGURE AT THE END OF A ROW IS ONE OF TWO THINGS, and the two are two props
|
|
19
|
+
* rather than one prop with a tone. A `count` is how many of something the
|
|
20
|
+
* destination holds (the open tasks in a project), a quiet figure in the
|
|
21
|
+
* tertiary ink; a `badge` is how many things are waiting on the reader (the
|
|
22
|
+
* unread in the inbox), the one filled pill in the chrome. Both are READ as
|
|
23
|
+
* part of the row's name, with the words the caller gives them ("Inbox, 5
|
|
24
|
+
* unread"), because a bare "5" after a name says nothing about what it counts,
|
|
25
|
+
* and both carry those words as required props, so a figure without them does
|
|
26
|
+
* not type-check.
|
|
17
27
|
*/
|
|
18
28
|
import { type MouseEventHandler, type ReactNode } from 'react';
|
|
19
29
|
export interface SidebarNavProps {
|
|
@@ -26,6 +36,24 @@ export interface SidebarNavProps {
|
|
|
26
36
|
className?: string | undefined;
|
|
27
37
|
children?: ReactNode;
|
|
28
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* The one control a group's heading can carry at its end: the add beside
|
|
41
|
+
* "Projects".
|
|
42
|
+
*
|
|
43
|
+
* A DESCRIPTION RATHER THAN AN ELEMENT, because the rail is what draws it: a
|
|
44
|
+
* square at the pointer-target floor, which is exactly the heading's height,
|
|
45
|
+
* named by `label`, with its ring inside its own box like every row in a
|
|
46
|
+
* clipping scroller. A control handed in whole would bring its own step, and
|
|
47
|
+
* the smallest one in the kit is two pixels taller than the heading it sits
|
|
48
|
+
* in.
|
|
49
|
+
*/
|
|
50
|
+
export interface NavGroupAction {
|
|
51
|
+
/** What pressing it does, in words: "New project". It is the control's name. */
|
|
52
|
+
label: string;
|
|
53
|
+
/** The glyph. Decoration: the label is the name. */
|
|
54
|
+
icon: ReactNode;
|
|
55
|
+
onClick: MouseEventHandler<HTMLButtonElement>;
|
|
56
|
+
}
|
|
29
57
|
export interface NavGroupProps {
|
|
30
58
|
/**
|
|
31
59
|
* The group's heading. Without one the rows are simply a run of rows, and an
|
|
@@ -34,6 +62,13 @@ export interface NavGroupProps {
|
|
|
34
62
|
* rail spent on nothing.
|
|
35
63
|
*/
|
|
36
64
|
label?: ReactNode;
|
|
65
|
+
/**
|
|
66
|
+
* A control at the end of the heading. It is a sibling of the heading's
|
|
67
|
+
* words rather than part of them, so the group is still named by its label
|
|
68
|
+
* alone, and it takes its own place in the tab order before the group's
|
|
69
|
+
* first row.
|
|
70
|
+
*/
|
|
71
|
+
action?: NavGroupAction | undefined;
|
|
37
72
|
className?: string | undefined;
|
|
38
73
|
children?: ReactNode;
|
|
39
74
|
}
|
|
@@ -46,33 +81,58 @@ export interface NavLinkProps {
|
|
|
46
81
|
onClick?: MouseEventHandler<HTMLElement> | undefined;
|
|
47
82
|
}
|
|
48
83
|
/**
|
|
49
|
-
*
|
|
84
|
+
* A figure at the end of a row, and what it counts.
|
|
50
85
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* word in a hue, so it still reads to somebody who cannot separate the hue.
|
|
56
|
-
*
|
|
57
|
-
* A TONE RATHER THAN A COMPONENT THE CALLER PASSES IN, because the tint has to
|
|
58
|
-
* clear its floor on the ground the ROW has, which is the accent tint on the
|
|
59
|
-
* reader's own row. That is a fact about the rail, measured in the rail's own
|
|
60
|
-
* stylesheet, and not something a call site can be asked to know.
|
|
86
|
+
* VALUES RATHER THAN AN ELEMENT, because the rail is what paints them: the
|
|
87
|
+
* pair has to clear its floor on every ground a ROW can have, the reader's
|
|
88
|
+
* own raised row included, and that is a fact about the rail, measured in the
|
|
89
|
+
* rail's own stylesheet, not something a call site can be asked to know.
|
|
61
90
|
*/
|
|
62
|
-
export
|
|
91
|
+
export interface NavFigure {
|
|
92
|
+
/** The figure, drawn as given, so the caller decides its formatting. */
|
|
93
|
+
value: number | string;
|
|
94
|
+
/**
|
|
95
|
+
* What is counted, read after the figure as part of the row's name:
|
|
96
|
+
* `unread` makes the inbox row "Inbox, 5 unread". Required, because a
|
|
97
|
+
* figure read with no word after it is a number nobody can place.
|
|
98
|
+
*/
|
|
99
|
+
label: string;
|
|
100
|
+
}
|
|
101
|
+
/** A quiet figure: how many of something the destination holds. */
|
|
102
|
+
export interface NavCount extends NavFigure {
|
|
103
|
+
/**
|
|
104
|
+
* A mark before the figure: the working dot beside a count of agents at
|
|
105
|
+
* work. Decoration, because the label says the same thing in words.
|
|
106
|
+
*/
|
|
107
|
+
mark?: ReactNode;
|
|
108
|
+
}
|
|
63
109
|
export interface NavItemProps {
|
|
64
110
|
/** What the row is called. */
|
|
65
111
|
label: ReactNode;
|
|
66
112
|
/** The row's glyph. Decoration: the label beside it carries the meaning. */
|
|
67
113
|
icon?: ReactNode;
|
|
68
114
|
/**
|
|
69
|
-
* A
|
|
70
|
-
*
|
|
71
|
-
*
|
|
115
|
+
* A short key drawn as a chip before the label, in place of a glyph: a
|
|
116
|
+
* project's `ENG`. It is text, and READ as the start of the row's name
|
|
117
|
+
* ("ENG Core platform"), because it is the prefix every item in that project
|
|
118
|
+
* is filed under and a reader who hears it can find them. A string rather
|
|
119
|
+
* than an element, because the rail paints the chip and measures it.
|
|
120
|
+
*/
|
|
121
|
+
lead?: string | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* How many of something the destination holds, as a quiet figure at the end
|
|
124
|
+
* of the row in the tertiary ink: the open tasks in a project.
|
|
125
|
+
*/
|
|
126
|
+
count?: NavCount | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* How many things at this destination are waiting on the reader, as the one
|
|
129
|
+
* filled pill in the chrome, in the accent: the unread in the inbox. A count
|
|
130
|
+
* of what is waiting on the reader is the one thing in the rail that asks
|
|
131
|
+
* them to act, which is what the accent means; it is a FILL carrying a
|
|
132
|
+
* figure rather than a figure in a hue, so it still reads to somebody who
|
|
133
|
+
* cannot separate the hue. Anything else is a `count`.
|
|
72
134
|
*/
|
|
73
|
-
badge?:
|
|
74
|
-
/** How loudly. Neutral unless this row is what needs a person. */
|
|
75
|
-
badgeTone?: NavBadgeTone | undefined;
|
|
135
|
+
badge?: NavFigure | undefined;
|
|
76
136
|
href?: string | undefined;
|
|
77
137
|
/** Whether this row is the screen the reader is on. */
|
|
78
138
|
current?: boolean | undefined;
|
|
@@ -112,6 +172,6 @@ export declare namespace SidebarNav {
|
|
|
112
172
|
* `<div>` here still carries the label's own padding, which put sixteen blank
|
|
113
173
|
* pixels at the top of the rail and named a group nothing could read.
|
|
114
174
|
*/
|
|
115
|
-
export declare function NavGroup({ label, className, children }: NavGroupProps): import("react").JSX.Element;
|
|
175
|
+
export declare function NavGroup({ label, action, className, children }: NavGroupProps): import("react").JSX.Element;
|
|
116
176
|
/** One row: a glyph, a label, an optional badge, and optionally rows beneath. */
|
|
117
|
-
export declare function NavItem({ label, icon,
|
|
177
|
+
export declare function NavItem({ label, icon, lead, count, badge, href, current, disabledReason, renderLink, onClick, children, expanded, defaultExpanded, onExpandedChange, expandLabel, className, }: NavItemProps): import("react").JSX.Element;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import './SidebarNav.css';
|
|
2
2
|
export { NavGroup, NavItem, SidebarNav } from './SidebarNav.js';
|
|
3
|
-
export type {
|
|
3
|
+
export type { NavCount, NavFigure, NavGroupAction, NavGroupProps, NavItemProps, NavLinkProps, SidebarNavProps, } from './SidebarNav.js';
|
package/dist/SidebarNav/index.js
CHANGED
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The rail's navigation.
|
|
3
|
+
*
|
|
4
|
+
* ONE VERTICAL LINE. The rail pads by --size-nav-gutter and each row pads by
|
|
5
|
+
* --size-nav-row-pad, so the mark, the group labels and every row's text start
|
|
6
|
+
* on the same line: shrink the gutter and grow the pad by the same step and
|
|
7
|
+
* nothing moves. That is why the row's own background takes the full width the
|
|
8
|
+
* gutter leaves it, rather than each row carrying a horizontal margin of its
|
|
9
|
+
* own.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
.crewlet-sidebar-nav {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
gap: var(--spacing-1);
|
|
16
|
+
min-width: 0;
|
|
17
|
+
padding: var(--spacing-2) var(--size-nav-gutter) var(--spacing-4);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* THE ROWS INSIDE A GROUP ARE HALF A STEP APART: the approved design's 2px,
|
|
22
|
+
* which is what keeps a hovered row's tint from touching the raised row under
|
|
23
|
+
* it and reading as one band two rows tall. It is half a step rather than one
|
|
24
|
+
* because a rail holds fifteen destinations and more: at 4px a row the rail
|
|
25
|
+
* stood 823px in a 755px scroller when its rows were 36px, and the last two
|
|
26
|
+
* destinations were reachable only by scrolling it. At the 30px row step the
|
|
27
|
+
* same fifteen rows and fourteen 2px gaps are 478px against 540px flush at the
|
|
28
|
+
* old step, so the gap is paid for many times over by the row it sits beside.
|
|
29
|
+
*/
|
|
30
|
+
.crewlet-nav-group {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
gap: calc(var(--spacing-1) / 2);
|
|
34
|
+
min-width: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* THE HEADING: the group's name and, at its end, an optional control (the add
|
|
39
|
+
* beside "Projects"). It stands at the pointer-target floor, because that
|
|
40
|
+
* control is a target and the heading is the row it is drawn in; with no
|
|
41
|
+
* control the heading keeps the same height, so a rail whose groups differ
|
|
42
|
+
* only in whether they can add something does not change its rhythm.
|
|
43
|
+
*
|
|
44
|
+
* Held off the run above by a margin rather than a padding, so its height
|
|
45
|
+
* does not depend on the document's box-sizing: with the rail's own gap it is
|
|
46
|
+
* 14px, the design's space between two runs, at density 1.
|
|
47
|
+
*
|
|
48
|
+
* Its end inset is a step SHORTER than a row's, because the control is a
|
|
49
|
+
* 24px square with its glyph centred in it: the row pad would put the glyph
|
|
50
|
+
* five pixels inside the line every count above and below it ends on.
|
|
51
|
+
*/
|
|
52
|
+
.crewlet-nav-group__head {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: var(--spacing-2);
|
|
56
|
+
min-width: 0;
|
|
57
|
+
min-height: var(--size-target-min);
|
|
58
|
+
margin-top: calc(var(--spacing-2) + var(--spacing-1) / 2);
|
|
59
|
+
padding: 0 var(--spacing-2) 0 var(--size-nav-row-pad);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* The group's name in the design's register: sentence case at the caption
|
|
64
|
+
* step, not the uppercase micro-label it was. It is the same case as every row
|
|
65
|
+
* it names, so "Projects" reads as the word it is rather than as a label
|
|
66
|
+
* shouted over the rows, and the quieter ink rather than the tracking is what
|
|
67
|
+
* sets it apart from them.
|
|
68
|
+
*/
|
|
69
|
+
.crewlet-nav-group__label {
|
|
70
|
+
flex: 1 1 auto;
|
|
71
|
+
min-width: 0;
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
text-overflow: ellipsis;
|
|
74
|
+
white-space: nowrap;
|
|
75
|
+
font-family: var(--font-family-sans);
|
|
76
|
+
font-size: var(--font-size-xs);
|
|
77
|
+
font-weight: var(--font-weight-regular);
|
|
78
|
+
line-height: var(--font-line-height-tight);
|
|
79
|
+
/* The 4.5:1 step: a group name is a fact a reader has to read, not
|
|
80
|
+
decoration. */
|
|
81
|
+
color: var(--color-text-tertiary);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* The heading's control. Pushed to the end whether or not the heading has
|
|
85
|
+
words, and at the floor the heading stands at. */
|
|
86
|
+
.crewlet-nav-group__action {
|
|
87
|
+
display: inline-flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
justify-content: center;
|
|
90
|
+
flex: none;
|
|
91
|
+
width: var(--size-target-min);
|
|
92
|
+
height: var(--size-target-min);
|
|
93
|
+
margin-left: auto;
|
|
94
|
+
padding: 0;
|
|
95
|
+
border: none;
|
|
96
|
+
border-radius: var(--radius-sm);
|
|
97
|
+
background: transparent;
|
|
98
|
+
color: var(--color-text-tertiary);
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
transition:
|
|
101
|
+
background var(--motion-duration-fast) var(--motion-easing-default),
|
|
102
|
+
color var(--motion-duration-fast) var(--motion-easing-default);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.crewlet-nav-group__action:hover {
|
|
106
|
+
background: var(--color-surface-hover);
|
|
107
|
+
color: var(--color-text-primary);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Inside its own box, like every control in the rail: the rail is a clipping
|
|
111
|
+
scroller. */
|
|
112
|
+
.crewlet-nav-group__action:focus-visible {
|
|
113
|
+
outline: 2px solid var(--color-focus);
|
|
114
|
+
outline-offset: var(--size-focus-ring-inset-offset);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.crewlet-nav-group__action-icon {
|
|
118
|
+
display: inline-flex;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.crewlet-nav-item {
|
|
122
|
+
min-width: 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.crewlet-nav-item__head {
|
|
126
|
+
display: flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
gap: var(--spacing-1);
|
|
129
|
+
min-width: 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.crewlet-nav-item__row {
|
|
133
|
+
display: flex;
|
|
134
|
+
align-items: center;
|
|
135
|
+
/* The design's 10px between a glyph and its word. */
|
|
136
|
+
gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
|
|
137
|
+
flex: 1 1 auto;
|
|
138
|
+
min-width: 0;
|
|
139
|
+
width: 100%;
|
|
140
|
+
/* The rail's own row step, 30px: a list's 36px row spent six pixels fifteen
|
|
141
|
+
times over in a column the height of the window. */
|
|
142
|
+
min-height: var(--size-nav-row);
|
|
143
|
+
padding: 0 var(--size-nav-row-pad);
|
|
144
|
+
border: none;
|
|
145
|
+
/* The chrome's radius, not a card's. A 12px corner on a 30px row leaves the
|
|
146
|
+
tint reading as a lozenge floating in the gutter rather than as a band the
|
|
147
|
+
width of the rail. */
|
|
148
|
+
border-radius: var(--radius-md);
|
|
149
|
+
background: transparent;
|
|
150
|
+
/*
|
|
151
|
+
* A RESTING ROW IS THE SECONDARY STEP, and the reader's own row and a
|
|
152
|
+
* pointed one lift to the primary. That step is what says which row is
|
|
153
|
+
* which before the fill does: at full ink every row carried the current
|
|
154
|
+
* row's own weight, so the rail read heavier and brighter than the approved
|
|
155
|
+
* design and the current row was found by its lift alone. The secondary step
|
|
156
|
+
* is held at 4.5:1 on the rail and under the hover overlay by
|
|
157
|
+
* @crewlethq/tokens (RAIL_PAINTS), so quieter is not fainter.
|
|
158
|
+
*
|
|
159
|
+
* The glyph has no colour of its own: it is drawn in currentColor and so is
|
|
160
|
+
* this ink, on every row, which is what keeps a row from painting its word
|
|
161
|
+
* and its glyph two different answers to "where am I".
|
|
162
|
+
*/
|
|
163
|
+
color: var(--color-text-secondary);
|
|
164
|
+
font-family: var(--font-family-sans);
|
|
165
|
+
/* THE CHROME IS NOT BODY TEXT. A rail row names a destination; it is read at
|
|
166
|
+
a glance and never read through, so it takes the compact step in the
|
|
167
|
+
medium weight, which is what keeps a one-word row legible at 13px. */
|
|
168
|
+
font-size: var(--font-size-compact);
|
|
169
|
+
font-weight: var(--font-weight-medium);
|
|
170
|
+
letter-spacing: var(--font-letter-spacing-snug);
|
|
171
|
+
line-height: var(--font-line-height-tight);
|
|
172
|
+
text-align: left;
|
|
173
|
+
text-decoration: none;
|
|
174
|
+
cursor: pointer;
|
|
175
|
+
transition:
|
|
176
|
+
background var(--motion-duration-fast) var(--motion-easing-default),
|
|
177
|
+
color var(--motion-duration-fast) var(--motion-easing-default);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.crewlet-nav-item__row:hover {
|
|
181
|
+
background: var(--color-surface-hover);
|
|
182
|
+
color: var(--color-text-primary);
|
|
183
|
+
text-decoration: none;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
* WHERE THE READER IS: the row stands on RAISED, with the plain border drawn
|
|
188
|
+
* round it as a hairline INSIDE the row, and lifts to the primary ink.
|
|
189
|
+
*
|
|
190
|
+
* It is found the way a card is found. In light, raised is only dE 1.84 off
|
|
191
|
+
* the frame the rail stands on, so the fill alone is a lift a reader may not
|
|
192
|
+
* see; the hairline is what carries the row, and in dark it is also what
|
|
193
|
+
* tells the current row from a hovered one, whose fill lands only dE 1.56
|
|
194
|
+
* away. @crewlethq/tokens holds both halves by name: the row lifts off the
|
|
195
|
+
* rail by dE 1.5 and the hairline clears dE 3 on the row it is drawn on.
|
|
196
|
+
*
|
|
197
|
+
* It used to be the accent's own soft tint with the label in the accent ink.
|
|
198
|
+
* The accent is the fill of the primary action now, so a violet row in the
|
|
199
|
+
* rail would read as a second primary on every screen, beside the one the
|
|
200
|
+
* screen is actually asking for. Where the reader is, is the row's position,
|
|
201
|
+
* its lift and its line; aria-current says it to a screen reader.
|
|
202
|
+
*
|
|
203
|
+
* THE HAIRLINE IS AN OUTLINE, not an inset box-shadow, for the reason the
|
|
204
|
+
* focus ring is one: forced-colors mode drops every box-shadow and every
|
|
205
|
+
* background and keeps outlines, so drawn as a shadow the current row would
|
|
206
|
+
* be indistinguishable from its neighbours for exactly the readers that mode
|
|
207
|
+
* exists for. The focus ring is the same property, so its rule is declared
|
|
208
|
+
* after this one and a focused current row draws the ring instead.
|
|
209
|
+
*
|
|
210
|
+
* Drawn from aria-current, so the picture and what a screen reader is told
|
|
211
|
+
* cannot come apart. It is declared after :hover deliberately: both selectors
|
|
212
|
+
* weigh the same, a row shows the current lift or the hover overlay and never
|
|
213
|
+
* both, and later is what decides which.
|
|
214
|
+
*/
|
|
215
|
+
.crewlet-nav-item__row[aria-current='page'] {
|
|
216
|
+
background: var(--color-surface-elevated);
|
|
217
|
+
outline: 1px solid var(--color-border-default);
|
|
218
|
+
outline-offset: -1px;
|
|
219
|
+
color: var(--color-text-primary);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.crewlet-nav-item__row[aria-disabled='true'] {
|
|
223
|
+
cursor: not-allowed;
|
|
224
|
+
opacity: 0.55;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.crewlet-nav-item__row[aria-disabled='true']:hover {
|
|
228
|
+
background: transparent;
|
|
229
|
+
color: var(--color-text-secondary);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/*
|
|
233
|
+
* After the current row's rule, which draws its hairline on the same
|
|
234
|
+
* property: both weigh the same, so source order is what lets a focused
|
|
235
|
+
* current row draw the ring rather than the line.
|
|
236
|
+
*/
|
|
237
|
+
.crewlet-nav-item__row:focus-visible {
|
|
238
|
+
outline: 2px solid var(--color-focus);
|
|
239
|
+
/* Inside the row's own box: the rail is a clipping scroller, so an outset
|
|
240
|
+
ring on the first or last row is cut off by it. */
|
|
241
|
+
outline-offset: var(--size-focus-ring-inset-offset);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/*
|
|
245
|
+
* THE GLYPH IS THE LABEL'S INK. Lucide draws in currentColor, so the glyph
|
|
246
|
+
* takes whatever the row is painted in, at rest, pointed and current alike,
|
|
247
|
+
* and there is no second ramp to fall out of step with the word beside it.
|
|
248
|
+
*/
|
|
249
|
+
.crewlet-nav-item__icon {
|
|
250
|
+
display: inline-flex;
|
|
251
|
+
align-items: center;
|
|
252
|
+
justify-content: center;
|
|
253
|
+
flex: none;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.crewlet-nav-item__label {
|
|
257
|
+
flex: 1 1 auto;
|
|
258
|
+
min-width: 0;
|
|
259
|
+
overflow: hidden;
|
|
260
|
+
text-overflow: ellipsis;
|
|
261
|
+
white-space: nowrap;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/*
|
|
265
|
+
* A PROJECT'S KEY, as a chip in the glyph's place: the prefix every item in
|
|
266
|
+
* the project is filed under, in mono so ENG and PROD line up by letter. It
|
|
267
|
+
* is the raised rung inside the plain hairline, in the secondary ink, which
|
|
268
|
+
* the palette suite measures on every ground a row can have; on the reader's
|
|
269
|
+
* own row, which is raised too, the hairline is what draws it.
|
|
270
|
+
*/
|
|
271
|
+
.crewlet-nav-item__lead {
|
|
272
|
+
display: inline-flex;
|
|
273
|
+
align-items: center;
|
|
274
|
+
flex: none;
|
|
275
|
+
padding: 0 calc(var(--spacing-1) + 1px);
|
|
276
|
+
border: 1px solid var(--color-border-default);
|
|
277
|
+
border-radius: var(--radius-xs);
|
|
278
|
+
background: var(--color-surface-elevated);
|
|
279
|
+
color: var(--color-text-secondary);
|
|
280
|
+
font-family: var(--font-family-mono);
|
|
281
|
+
font-size: var(--font-size-2xs);
|
|
282
|
+
font-weight: var(--font-weight-medium);
|
|
283
|
+
letter-spacing: var(--font-letter-spacing-normal);
|
|
284
|
+
line-height: var(--font-line-height-body);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/*
|
|
288
|
+
* THE COUNT: how many of something the destination holds, as a quiet figure
|
|
289
|
+
* at the end of the row. Tabular, so a count that ticks up does not move the
|
|
290
|
+
* words beside it. A mark before it (the working dot beside a count of agents
|
|
291
|
+
* at work) stands half a step off the figure.
|
|
292
|
+
*/
|
|
293
|
+
.crewlet-nav-item__count {
|
|
294
|
+
display: inline-flex;
|
|
295
|
+
align-items: center;
|
|
296
|
+
flex: none;
|
|
297
|
+
margin-left: auto;
|
|
298
|
+
font-size: var(--font-size-2xs);
|
|
299
|
+
font-variant-numeric: tabular-nums;
|
|
300
|
+
color: var(--color-text-tertiary);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.crewlet-nav-item__figure {
|
|
304
|
+
display: inline-flex;
|
|
305
|
+
align-items: center;
|
|
306
|
+
gap: calc(var(--spacing-1) + 1px);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.crewlet-nav-item__mark {
|
|
310
|
+
display: inline-flex;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* The count takes the row's ink on the current row, lifting from the tertiary
|
|
314
|
+
step to the primary ink with the row it sits in: the tertiary step is
|
|
315
|
+
measured on the rail and under the hover overlay, and the raised row is a
|
|
316
|
+
ground it was never held to. */
|
|
317
|
+
.crewlet-nav-item__row[aria-current='page'] .crewlet-nav-item__count {
|
|
318
|
+
color: inherit;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/*
|
|
322
|
+
* THE BADGE, THE ONE FIGURE IN THE CHROME ALLOWED A HUE, and it is the
|
|
323
|
+
* accent. A count of what is waiting on the reader is the one thing in the
|
|
324
|
+
* rail that asks them to act, which is what the accent means, and it is the
|
|
325
|
+
* one thing that should pull the eye out of whatever screen they are on. It
|
|
326
|
+
* is a FILL carrying a figure rather than a figure in a hue, so it reads to
|
|
327
|
+
* somebody who cannot separate the hue at all: the filled pill is the signal,
|
|
328
|
+
* the figure is the count.
|
|
329
|
+
*
|
|
330
|
+
* The design's 18px pill, at least as wide as it is tall so a single digit is
|
|
331
|
+
* a round mark and not a lozenge, and following the density like the xs Tag
|
|
332
|
+
* it matches. The label is the on-accent step, the primary action's own pair,
|
|
333
|
+
* on every row alike, because the fill is opaque.
|
|
334
|
+
*/
|
|
335
|
+
.crewlet-nav-item__badge {
|
|
336
|
+
--crewlet-nav-item-badge-size: calc(18px * var(--density, 1));
|
|
337
|
+
display: inline-flex;
|
|
338
|
+
align-items: center;
|
|
339
|
+
justify-content: center;
|
|
340
|
+
flex: none;
|
|
341
|
+
box-sizing: border-box;
|
|
342
|
+
min-width: var(--crewlet-nav-item-badge-size);
|
|
343
|
+
height: var(--crewlet-nav-item-badge-size);
|
|
344
|
+
margin-left: auto;
|
|
345
|
+
padding: 0 calc(var(--spacing-1) + 1px);
|
|
346
|
+
border-radius: var(--radius-pill);
|
|
347
|
+
background: var(--color-brand-accent);
|
|
348
|
+
color: var(--color-text-on-accent);
|
|
349
|
+
font-size: var(--font-size-2xs);
|
|
350
|
+
font-weight: var(--font-weight-semibold);
|
|
351
|
+
font-variant-numeric: tabular-nums;
|
|
352
|
+
line-height: 1;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* Beside a count the badge is the second figure, not a second push to the
|
|
356
|
+
end: two auto margins would split the room between them and float the
|
|
357
|
+
count into the middle of the row. */
|
|
358
|
+
.crewlet-nav-item__count + .crewlet-nav-item__badge {
|
|
359
|
+
margin-left: var(--spacing-2);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.crewlet-nav-item__toggle {
|
|
363
|
+
display: inline-flex;
|
|
364
|
+
align-items: center;
|
|
365
|
+
justify-content: center;
|
|
366
|
+
flex: none;
|
|
367
|
+
width: var(--size-control-sm);
|
|
368
|
+
height: var(--size-control-sm);
|
|
369
|
+
padding: 0;
|
|
370
|
+
border: none;
|
|
371
|
+
border-radius: var(--radius-sm);
|
|
372
|
+
background: transparent;
|
|
373
|
+
color: var(--color-text-tertiary);
|
|
374
|
+
cursor: pointer;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.crewlet-nav-item__toggle:hover {
|
|
378
|
+
background: var(--color-surface-hover);
|
|
379
|
+
color: var(--color-text-primary);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.crewlet-nav-item__toggle:focus-visible {
|
|
383
|
+
outline: 2px solid var(--color-focus);
|
|
384
|
+
outline-offset: var(--size-focus-ring-inset-offset);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.crewlet-nav-item__chevron {
|
|
388
|
+
display: inline-flex;
|
|
389
|
+
transition: transform var(--motion-duration-fast) var(--motion-easing-default);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.crewlet-nav-item__chevron--open {
|
|
393
|
+
transform: rotate(180deg);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/*
|
|
397
|
+
* Nested rows carry an indent guide rather than more padding, because a run of
|
|
398
|
+
* indents with no line is a hierarchy a reader has to measure by eye. On the
|
|
399
|
+
* path the reader is on the guide steps up to the strong border: the same
|
|
400
|
+
* neutral lift the current row itself takes, and not the accent, which the
|
|
401
|
+
* rail keeps for the one count that asks the reader to act.
|
|
402
|
+
*/
|
|
403
|
+
.crewlet-nav-item__children {
|
|
404
|
+
display: flex;
|
|
405
|
+
flex-direction: column;
|
|
406
|
+
gap: var(--spacing-1);
|
|
407
|
+
margin-left: var(--size-nav-row-pad);
|
|
408
|
+
padding-left: var(--spacing-2);
|
|
409
|
+
border-left: 1px solid var(--color-border-default);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* No type step of its own any more: every row in the rail reads at the compact
|
|
413
|
+
step now, and the indent guide is what says a row is nested. */
|
|
414
|
+
.crewlet-nav-item__children:has(.crewlet-nav-item__row[aria-current='page']) {
|
|
415
|
+
border-left-color: var(--color-border-strong);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@media (prefers-reduced-motion: reduce) {
|
|
419
|
+
.crewlet-nav-group__action,
|
|
420
|
+
.crewlet-nav-item__row,
|
|
421
|
+
.crewlet-nav-item__chevron {
|
|
422
|
+
transition: none;
|
|
423
|
+
}
|
|
424
|
+
}
|