@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
|
@@ -13,15 +13,54 @@ import type { HTMLAttributes, ReactNode } from 'react';
|
|
|
13
13
|
* number is never that.
|
|
14
14
|
*/
|
|
15
15
|
export type StatCardTone = 'neutral' | 'success' | 'warning' | 'danger' | 'info';
|
|
16
|
+
/**
|
|
17
|
+
* Whether a change is the one the reader wanted.
|
|
18
|
+
*
|
|
19
|
+
* NOT the direction. The sign in the value already says which way the number
|
|
20
|
+
* moved, and whether up is good is a property of what is counted rather than
|
|
21
|
+
* of the arithmetic: twelve percent more work completed is good news and
|
|
22
|
+
* twelve percent more tokens spent may not be. So the caller, who knows what
|
|
23
|
+
* the tile counts, says which it is, and `neutral` is a change that is neither
|
|
24
|
+
* (four more tasks in progress is not a verdict, it is a fact).
|
|
25
|
+
*/
|
|
26
|
+
export type StatCardDeltaPolarity = 'good' | 'bad' | 'neutral';
|
|
27
|
+
/** A change against an earlier reading, drawn at the head of the second line. */
|
|
28
|
+
export interface StatCardDelta {
|
|
29
|
+
/** The change, already formatted by the caller and carrying its own sign: "+12%", "−3", "+4". */
|
|
30
|
+
value: ReactNode;
|
|
31
|
+
/** Whether it is the change the reader wanted. See the type. */
|
|
32
|
+
polarity: StatCardDeltaPolarity;
|
|
33
|
+
}
|
|
16
34
|
export interface StatCardProps extends HTMLAttributes<HTMLDivElement> {
|
|
17
|
-
/** What is being counted,
|
|
35
|
+
/** What is being counted, in sentence case: "Tasks in progress". */
|
|
18
36
|
label: ReactNode;
|
|
19
37
|
/** The headline value, already formatted by the caller. */
|
|
20
38
|
value: ReactNode;
|
|
21
|
-
/** A unit after the value, at a quieter weight: "ms", "/
|
|
39
|
+
/** A unit after the value, at a quieter weight: "ms", "/ 7", "per turn". */
|
|
22
40
|
unit?: ReactNode;
|
|
23
|
-
/**
|
|
41
|
+
/** The second line: "vs last week · 2 blocked". Its line is reserved either way. */
|
|
24
42
|
sub?: ReactNode;
|
|
43
|
+
/**
|
|
44
|
+
* The STATE the second line reports, when it reports one: "Oldest waiting
|
|
45
|
+
* 2h 10m" is a person being kept waiting, so it is `warning`. Paints the
|
|
46
|
+
* line in that tone's ink, the step measured as text on every rung. The
|
|
47
|
+
* same rule as `tone`: most second lines are a fact, not a state, and stay
|
|
48
|
+
* in the quiet ink. A `delta` keeps the ink of its own polarity.
|
|
49
|
+
*/
|
|
50
|
+
subTone?: StatCardTone;
|
|
51
|
+
/**
|
|
52
|
+
* A change against an earlier reading, drawn first on the second line in
|
|
53
|
+
* the ink of its polarity, with `sub` after it: "+12% vs previous 7 days".
|
|
54
|
+
*/
|
|
55
|
+
delta?: StatCardDelta | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* A small figure at the end of the value's line, such as a `Sparkline`, a
|
|
58
|
+
* `Meter` or a `SegmentedMeter`, or a small control that acts on the
|
|
59
|
+
* number. A figure fills the slot's width and a control keeps its own. The
|
|
60
|
+
* slot is `--crewlet-statcard-trend-width` wide, 96px unless a stylesheet
|
|
61
|
+
* says otherwise.
|
|
62
|
+
*/
|
|
63
|
+
trend?: ReactNode;
|
|
25
64
|
/** A glyph before the label. A component, not a name. */
|
|
26
65
|
icon?: ReactNode;
|
|
27
66
|
/** Colours the VALUE's ink. See the type for when that is right. */
|
|
@@ -39,18 +78,26 @@ export interface StatCardProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
39
78
|
/**
|
|
40
79
|
* One number, with what it counts.
|
|
41
80
|
*
|
|
42
|
-
* THE LABEL SITS ABOVE THE VALUE, in the
|
|
43
|
-
*
|
|
44
|
-
* a reader scans to find the tile they want, and the
|
|
45
|
-
* underneath it. It is also the order a screen reader
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* is
|
|
81
|
+
* THE LABEL SITS ABOVE THE VALUE, in sentence case at the caption step, which
|
|
82
|
+
* is the approved design's tile and the order a board is actually read in:
|
|
83
|
+
* the labels are what a reader scans to find the tile they want, and the
|
|
84
|
+
* number is the answer underneath it. It is also the order a screen reader
|
|
85
|
+
* reads correctly, "tasks in progress, 18, +4 vs last week" rather than "18,
|
|
86
|
+
* tasks in progress". The label is set as it is written: the uppercased,
|
|
87
|
+
* tracked-open register is a table's column head, and five of them over five
|
|
88
|
+
* numbers shouted a heading at every tile.
|
|
89
|
+
*
|
|
90
|
+
* THE VALUE IS THE SCREEN'S ONE DISPLAY NUMBER, at `--font-size-display` with
|
|
91
|
+
* tabular figures, so a number that ticks up moves nothing beside it. A
|
|
92
|
+
* figure showing where it has been going sits at the END of the same line
|
|
93
|
+
* (`trend`), and a change against an earlier reading heads the line under it
|
|
94
|
+
* (`delta`), in the ink of whether it was the change the reader wanted.
|
|
49
95
|
*
|
|
50
96
|
* WHILE IT IS LOADING IT SAYS SO. It used to draw a literal `--`, which a
|
|
51
97
|
* screen reader reads aloud as "dash dash" and which looks exactly like a
|
|
52
98
|
* measured value of nothing. A placeholder line plus `aria-busy` on the tile
|
|
53
99
|
* says the number has not arrived, which is a different fact from the number
|
|
54
|
-
* being zero.
|
|
100
|
+
* being zero. The trend and the delta wait with it: both are readings of the
|
|
101
|
+
* number that has not arrived.
|
|
55
102
|
*/
|
|
56
|
-
export declare const StatCard: ({ label, value, unit, sub, icon, tone, loading, loadingLabel, flush, className, ...rest }: StatCardProps) => import("react").JSX.Element;
|
|
103
|
+
export declare const StatCard: ({ label, value, unit, sub, subTone, delta, trend, icon, tone, loading, loadingLabel, flush, className, ...rest }: StatCardProps) => import("react").JSX.Element;
|
package/dist/StatCard/index.d.ts
CHANGED
package/dist/StatCard/index.js
CHANGED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The stat tile.
|
|
3
|
+
*
|
|
4
|
+
* THE TONE PAINTS THE VALUE, which is what the props always said and what the
|
|
5
|
+
* stylesheet never did: 0.2.0 tinted the ICON, so a caller who passed a tone
|
|
6
|
+
* and no icon got a tile identical to a neutral one. Ink only, and never a
|
|
7
|
+
* fill: a tinted block behind a 28px number reads as a button.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.crewlet-statcard {
|
|
11
|
+
/*
|
|
12
|
+
* The width of the figure at the end of the value's line. 96px is the
|
|
13
|
+
* approved design's sparkline, and its meters and state bars stand within
|
|
14
|
+
* four pixels of it: wide enough that a fortnight of points reads as a
|
|
15
|
+
* shape, narrow enough that five tiles in a row still leave the number its
|
|
16
|
+
* room.
|
|
17
|
+
*/
|
|
18
|
+
--crewlet-statcard-trend-width: 96px;
|
|
19
|
+
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
/* The design's 10px between the three lines, and its 16px inset with 14px
|
|
23
|
+
under the last line: half a scale step each, derived from the steps so
|
|
24
|
+
they follow the density with everything else. */
|
|
25
|
+
gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
|
|
26
|
+
padding: var(--spacing-4) var(--spacing-4) calc(var(--spacing-3) + var(--spacing-1) / 2);
|
|
27
|
+
/*
|
|
28
|
+
* The card recipe: the card's surface, its hairline and its 12px corner,
|
|
29
|
+
* FLAT, as every card is, so a lone tile is the same object as the panel
|
|
30
|
+
* beside it rather than a raised cousin of it.
|
|
31
|
+
*/
|
|
32
|
+
background: var(--color-surface-subtle);
|
|
33
|
+
border: 1px solid var(--color-border-default);
|
|
34
|
+
border-radius: var(--radius-lg);
|
|
35
|
+
color: var(--color-text-primary);
|
|
36
|
+
font-family: var(--font-family-sans);
|
|
37
|
+
min-width: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Inside a StatGroup the row is one card and the tiles are its columns, so a
|
|
41
|
+
tile brings no surface of its own. */
|
|
42
|
+
.crewlet-statcard--flush {
|
|
43
|
+
background: transparent;
|
|
44
|
+
border: 0;
|
|
45
|
+
border-radius: var(--radius-none);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* The label: SENTENCE CASE at the caption step, as the design sets it and as
|
|
50
|
+
* the caller wrote it. The uppercased, tracked-open micro-caps it used to wear
|
|
51
|
+
* are a table's column head: five of them over five numbers put a heading on
|
|
52
|
+
* every tile, and uppercasing is a transform a caller's own words should not
|
|
53
|
+
* have to survive.
|
|
54
|
+
*/
|
|
55
|
+
.crewlet-statcard__label {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: var(--spacing-1);
|
|
59
|
+
font-size: var(--font-size-xs);
|
|
60
|
+
font-weight: var(--font-weight-regular);
|
|
61
|
+
letter-spacing: var(--font-letter-spacing-normal);
|
|
62
|
+
color: var(--color-text-tertiary);
|
|
63
|
+
min-width: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.crewlet-statcard__icon {
|
|
67
|
+
display: inline-flex;
|
|
68
|
+
flex: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/*
|
|
72
|
+
* The value's line: the number at its start, the figure at its end, both on
|
|
73
|
+
* the line's FOOT, so a 28px number and a 28px sparkline share a baseline
|
|
74
|
+
* rather than centring on each other.
|
|
75
|
+
*/
|
|
76
|
+
.crewlet-statcard__reading {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: flex-end;
|
|
79
|
+
justify-content: space-between;
|
|
80
|
+
gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
|
|
81
|
+
min-width: 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
* THE SCREEN'S ONE DISPLAY NUMBER. The display step, semibold, on the tight
|
|
86
|
+
* track, with tabular figures so a number that ticks up moves nothing beside
|
|
87
|
+
* it.
|
|
88
|
+
*
|
|
89
|
+
* ITS LINE IS THE GLYPH'S OWN HEIGHT (a leading of 1). The value is one line
|
|
90
|
+
* that never wraps, and any leading over it is air under the digits that
|
|
91
|
+
* opens between the number and the line below it and stands the number
|
|
92
|
+
* higher than the figure it shares a foot with.
|
|
93
|
+
*
|
|
94
|
+
* A BLOCK, NOT A FLEX ROW, because it is one line of text that has to END
|
|
95
|
+
* rather than stop: `text-overflow` acts on a block container only, and as a
|
|
96
|
+
* flex row the number and its unit were anonymous flex items no rule could
|
|
97
|
+
* reach, so a value too long for its tile was cut mid-digit with nothing to
|
|
98
|
+
* say a digit was lost. The unit sits on the same line as inline text, on
|
|
99
|
+
* the number's baseline.
|
|
100
|
+
*/
|
|
101
|
+
.crewlet-statcard__value {
|
|
102
|
+
display: block;
|
|
103
|
+
flex: 1 1 auto;
|
|
104
|
+
min-width: 0;
|
|
105
|
+
font-size: var(--font-size-display);
|
|
106
|
+
font-weight: var(--font-weight-semibold);
|
|
107
|
+
letter-spacing: var(--font-letter-spacing-tight);
|
|
108
|
+
line-height: 1;
|
|
109
|
+
font-variant-numeric: tabular-nums;
|
|
110
|
+
overflow: hidden;
|
|
111
|
+
text-overflow: ellipsis;
|
|
112
|
+
white-space: nowrap;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* The unit, "/ 7" after the 4: the quiet ink at a text step, medium, so it
|
|
116
|
+
reads as part of the figure rather than as a second one. */
|
|
117
|
+
.crewlet-statcard__unit {
|
|
118
|
+
margin-inline-start: var(--spacing-1);
|
|
119
|
+
font-size: var(--font-size-sm);
|
|
120
|
+
font-weight: var(--font-weight-medium);
|
|
121
|
+
letter-spacing: var(--font-letter-spacing-normal);
|
|
122
|
+
color: var(--color-text-tertiary);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/*
|
|
126
|
+
* The figure at the end of the line. A figure (a sparkline, a meter, a state
|
|
127
|
+
* bar) FILLS the slot, because none of them has a width of its own to offer.
|
|
128
|
+
* A control keeps its own and stands at the slot's end: "Review" is a small
|
|
129
|
+
* button beside the number it acts on, not a bar the width of a sparkline.
|
|
130
|
+
*/
|
|
131
|
+
.crewlet-statcard__trend {
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-direction: column;
|
|
134
|
+
justify-content: flex-end;
|
|
135
|
+
flex: none;
|
|
136
|
+
width: var(--crewlet-statcard-trend-width);
|
|
137
|
+
min-width: 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.crewlet-statcard__trend > :where(button, a) {
|
|
141
|
+
align-self: flex-end;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/*
|
|
145
|
+
* The placeholder is a line, not a pair of dashes. `--` is read aloud as
|
|
146
|
+
* "dash dash" and looks exactly like a measured value of nothing; the tile
|
|
147
|
+
* carries aria-busy instead, and the line says the number is on its way.
|
|
148
|
+
*/
|
|
149
|
+
.crewlet-statcard__placeholder {
|
|
150
|
+
display: inline-block;
|
|
151
|
+
width: 3ch;
|
|
152
|
+
height: 0.7em;
|
|
153
|
+
border-radius: var(--radius-xs);
|
|
154
|
+
background: var(--color-surface-inset);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
* The second line keeps its space whether or not there is one, so a row of
|
|
159
|
+
* tiles where only some carry one still stands at one height: its leading is
|
|
160
|
+
* set here and the reserve is exactly one line of it, where a reserve in `em`
|
|
161
|
+
* was a line shorter than the one a sub actually draws.
|
|
162
|
+
*/
|
|
163
|
+
.crewlet-statcard__sub {
|
|
164
|
+
min-height: calc(1em * var(--font-line-height-body));
|
|
165
|
+
font-size: var(--font-size-xs);
|
|
166
|
+
line-height: var(--font-line-height-body);
|
|
167
|
+
/* The quiet step, with the label. The line qualifies the number rather than
|
|
168
|
+
being a second one. */
|
|
169
|
+
color: var(--color-text-tertiary);
|
|
170
|
+
overflow: hidden;
|
|
171
|
+
text-overflow: ellipsis;
|
|
172
|
+
white-space: nowrap;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/*
|
|
176
|
+
* A CHANGE IS COLOURED BY WHETHER IT WAS WANTED, not by its direction: the
|
|
177
|
+
* sign already says which way the number moved. Good news takes the success
|
|
178
|
+
* ink and bad news the danger ink, the steps measured as TEXT on every rung;
|
|
179
|
+
* a change that is neither takes the secondary ink, a step up from the words
|
|
180
|
+
* after it, so the figure still leads the sentence.
|
|
181
|
+
*/
|
|
182
|
+
.crewlet-statcard__delta {
|
|
183
|
+
font-variant-numeric: tabular-nums;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.crewlet-statcard__delta--good { color: var(--color-feedback-success-ink); }
|
|
187
|
+
.crewlet-statcard__delta--bad { color: var(--color-feedback-danger-ink); }
|
|
188
|
+
.crewlet-statcard__delta--neutral { color: var(--color-text-secondary); }
|
|
189
|
+
|
|
190
|
+
/*
|
|
191
|
+
* A SECOND LINE THAT REPORTS A STATE takes that state's ink ("Oldest waiting
|
|
192
|
+
* 2h 10m" is a person kept waiting: warning), the step measured as text on
|
|
193
|
+
* every rung, as the value's tone does. The delta inside the line keeps its
|
|
194
|
+
* own ink, which is a class on the delta and outranks this one on the line.
|
|
195
|
+
*/
|
|
196
|
+
.crewlet-statcard__sub--success { color: var(--color-feedback-success-ink); }
|
|
197
|
+
.crewlet-statcard__sub--warning { color: var(--color-feedback-warning-ink); }
|
|
198
|
+
.crewlet-statcard__sub--danger { color: var(--color-feedback-danger-ink); }
|
|
199
|
+
.crewlet-statcard__sub--info { color: var(--color-feedback-info-ink); }
|
|
200
|
+
|
|
201
|
+
.crewlet-statcard--success .crewlet-statcard__value { color: var(--color-feedback-success-ink); }
|
|
202
|
+
.crewlet-statcard--warning .crewlet-statcard__value { color: var(--color-feedback-warning-ink); }
|
|
203
|
+
.crewlet-statcard--danger .crewlet-statcard__value { color: var(--color-feedback-danger-ink); }
|
|
204
|
+
.crewlet-statcard--info .crewlet-statcard__value { color: var(--color-feedback-info-ink); }
|
package/dist/StatGroup/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { StatGroup } from '../chunk-
|
|
1
|
+
export { StatGroup } from '../chunk-QVAFL2LE.js';
|
|
2
2
|
import '../chunk-ODEQTPFM.js';
|
|
@@ -10,14 +10,13 @@
|
|
|
10
10
|
.crewlet-stat-group {
|
|
11
11
|
display: grid;
|
|
12
12
|
grid-template-columns: repeat(var(--crewlet-stat-group-cols, 4), minmax(0, 1fr));
|
|
13
|
-
/* The flush-panel recipe: the surface,
|
|
14
|
-
`overflow: hidden`, which is what lets
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
/* The flush-panel recipe: the card's surface, its hairline and its 12px
|
|
14
|
+
corner, flat as every card is, and `overflow: hidden`, which is what lets
|
|
15
|
+
the tiles inside sit against the corners without their own hairlines
|
|
16
|
+
escaping past them. */
|
|
17
17
|
background: var(--color-surface-subtle);
|
|
18
18
|
border: 1px solid var(--color-border-default);
|
|
19
19
|
border-radius: var(--radius-lg);
|
|
20
|
-
box-shadow: var(--shadow-xs), var(--shadow-hairline);
|
|
21
20
|
overflow: hidden;
|
|
22
21
|
}
|
|
23
22
|
|
|
@@ -38,7 +37,6 @@
|
|
|
38
37
|
background: transparent;
|
|
39
38
|
border: 0;
|
|
40
39
|
border-radius: var(--radius-none);
|
|
41
|
-
box-shadow: none;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
/*
|
|
@@ -57,13 +55,14 @@
|
|
|
57
55
|
|
|
58
56
|
/*
|
|
59
57
|
* Two columns under the shell breakpoint, which is where the engine drops its
|
|
60
|
-
* own stat row
|
|
61
|
-
*
|
|
58
|
+
* own stat row, and strictly under it, as the shell switches. The step is
|
|
59
|
+
* 1024px, a 236px rail, the 8px inset and a 780px floor for the sheet, and it
|
|
60
|
+
* is the width at which the shell stops holding the page beside the rail. The
|
|
62
61
|
* rules are written for the general case rather than per column count: the
|
|
63
62
|
* first tile of each pair loses its left hairline, and everything on the
|
|
64
63
|
* second row and below gains a top one.
|
|
65
64
|
*/
|
|
66
|
-
@media (
|
|
65
|
+
@media (width < 1024px) {
|
|
67
66
|
.crewlet-stat-group {
|
|
68
67
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
69
68
|
}
|
|
@@ -1,12 +1,30 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { Tone } from '../utils/tone.js';
|
|
2
3
|
export interface StatusDotProps {
|
|
3
|
-
/** Which state, or which phase. Neutral says "nothing in particular". */
|
|
4
|
-
tone?: Tone | PhaseTone | undefined;
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Which state. Neutral says "nothing in particular", and it is also the dot
|
|
6
|
+
* beside a category's word, such as a phase's: a category has no hue.
|
|
7
|
+
*/
|
|
8
|
+
tone?: Tone | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* A halo that breathes out round the dot and back, in the tone's soft step,
|
|
11
|
+
* for a state that is still happening: the approved design pulses the
|
|
12
|
+
* `info` dot, which is working. One round is `--motion-duration-breath`. The
|
|
13
|
+
* dot itself never fades, and the halo never touches it: it is cast from a
|
|
14
|
+
* ring 2px out, so the dot always stands on the surface its fill clears 3:1
|
|
15
|
+
* against. Held still under a reduced-motion preference, where the dot rests
|
|
16
|
+
* at its fill with no halo and the word beside it still says the work is
|
|
17
|
+
* under way. The ring is drawn on the dot's `::after`, and a `position` of
|
|
18
|
+
* your own on the dot still wins over the one the ring needs.
|
|
8
19
|
*/
|
|
9
20
|
pulse?: boolean | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* The word the dot belongs to: "Reviewing !231". Given one, the dot and the
|
|
23
|
+
* word are drawn as one line, `.crewlet-status`, with the room between them
|
|
24
|
+
* the kit decides rather than the caller (see the stylesheet), and
|
|
25
|
+
* `className` goes on that line. The word is read; the dot still is not.
|
|
26
|
+
*/
|
|
27
|
+
children?: ReactNode;
|
|
10
28
|
className?: string | undefined;
|
|
11
29
|
}
|
|
12
30
|
/**
|
|
@@ -22,4 +40,4 @@ export interface StatusDotProps {
|
|
|
22
40
|
* it can sit on, because a mark is read the way a glyph is rather than the way
|
|
23
41
|
* text is.
|
|
24
42
|
*/
|
|
25
|
-
export declare function StatusDot({ tone, pulse, className }: StatusDotProps): import("react").JSX.Element;
|
|
43
|
+
export declare function StatusDot({ tone, pulse, children, className }: StatusDotProps): import("react").JSX.Element;
|
package/dist/StatusDot/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { StatusDot } from '../chunk-
|
|
1
|
+
export { StatusDot } from '../chunk-WIATRXEJ.js';
|
|
2
2
|
import '../chunk-ODEQTPFM.js';
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The status dot: a 7px mark in its tone's fill, beside the word it belongs
|
|
3
|
+
* to. See the component doc for why it is hidden from assistive technology.
|
|
4
|
+
*
|
|
5
|
+
* 7px is the approved design's dot. The size is written out rather than
|
|
6
|
+
* taken from a scale because it is the measure of one mark, not a step
|
|
7
|
+
* anything else shares, and it is fixed at every density: a mark read the
|
|
8
|
+
* way a glyph is does not shrink with the gaps around it.
|
|
9
|
+
*
|
|
10
|
+
* TWO VALUES PER TONE: the fill the dot is painted in, and the HALO a pulsing
|
|
11
|
+
* dot breathes out in, which is the same tone's soft step. The halo is held to
|
|
12
|
+
* being SEEN rather than to a contrast ratio: it never touches the dot (see the
|
|
13
|
+
* pulse below), so the dot clears 3:1 against the surface it stands on at every
|
|
14
|
+
* point of the round, and the word beside it says the state. The halo only has
|
|
15
|
+
* to stand off its ground by the dE 3 the palette suite holds every "can a
|
|
16
|
+
* reader notice it" difference to. Every soft step does, by 4.48 at the least.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
.crewlet-status-dot {
|
|
20
|
+
display: inline-block;
|
|
21
|
+
width: 7px;
|
|
22
|
+
height: 7px;
|
|
23
|
+
border-radius: var(--radius-circle);
|
|
24
|
+
/*
|
|
25
|
+
* The quiet state is still a mark, so it takes the tertiary step rather than
|
|
26
|
+
* the decoration one the engine spends here: a 7px dot has to clear 3:1 to
|
|
27
|
+
* be seen at all, and --color-text-muted measures 2.33:1 on a light page and
|
|
28
|
+
* 2.25:1 on a dark one at their worst grounds. The tertiary step measures
|
|
29
|
+
* 4.87:1 and 4.65:1 on the same pair, and is the nearest step that holds.
|
|
30
|
+
*/
|
|
31
|
+
background: var(--color-text-tertiary);
|
|
32
|
+
/*
|
|
33
|
+
* The neutral family has no soft step, because it has no hue to tint with,
|
|
34
|
+
* so its halo is a translucent overlay. Pressed is the one that reads like
|
|
35
|
+
* the tones' halos: it stands dE 6.09 off its faintest ground (the light
|
|
36
|
+
* frame) and 8.84 in dark, inside the 4.48 to 8.50 the soft steps span. The
|
|
37
|
+
* hover overlay stands 3.03, on the floor, and the inset well 1.79, under it.
|
|
38
|
+
*/
|
|
39
|
+
--crewlet-status-dot-halo: var(--color-surface-pressed);
|
|
40
|
+
flex: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.crewlet-status-dot--info {
|
|
44
|
+
background: var(--color-feedback-info);
|
|
45
|
+
--crewlet-status-dot-halo: var(--color-feedback-info-soft);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.crewlet-status-dot--success {
|
|
49
|
+
background: var(--color-feedback-success);
|
|
50
|
+
--crewlet-status-dot-halo: var(--color-feedback-success-soft);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.crewlet-status-dot--warning {
|
|
54
|
+
background: var(--color-feedback-warning);
|
|
55
|
+
--crewlet-status-dot-halo: var(--color-feedback-warning-soft);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.crewlet-status-dot--danger {
|
|
59
|
+
background: var(--color-feedback-danger);
|
|
60
|
+
--crewlet-status-dot-halo: var(--color-feedback-danger-soft);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.crewlet-status-dot--brand {
|
|
64
|
+
background: var(--color-brand-accent);
|
|
65
|
+
--crewlet-status-dot-halo: var(--color-brand-accent-soft);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* STILL HAPPENING: a halo breathes out round the dot and back in, the approved
|
|
70
|
+
* design's working pulse. Five things are deliberate.
|
|
71
|
+
*
|
|
72
|
+
* THE DOT NEVER FADES. The halo is a box-shadow and it is the only property
|
|
73
|
+
* the keyframes touch, so the fill stays at the step measured to 3:1 through
|
|
74
|
+
* the whole round. The pulse this replaced faded the dot itself to 0.35, and
|
|
75
|
+
* at the bottom of that fade every fill measured 1.35:1 to 2.17:1 against the
|
|
76
|
+
* surfaces it sits on: for part of every round, a mark under its own floor.
|
|
77
|
+
*
|
|
78
|
+
* NOR DOES THE HALO TOUCH IT. The design casts the halo from the dot itself,
|
|
79
|
+
* and a spread shadow starts at the edge of the box that casts it, so for the
|
|
80
|
+
* whole round the dot's ground would be its own soft step on the surface
|
|
81
|
+
* rather than the surface. On that ground the light info, success and warning
|
|
82
|
+
* fills measure 2.65:1 to 2.95:1 (warning and success on the frame, where they
|
|
83
|
+
* clear 3.00:1 and 3.01:1 bare): the same fault as the fade, smaller. So the
|
|
84
|
+
* halo is cast by a RING BOX 2px outside the dot, the offset the Avatar state
|
|
85
|
+
* ring and the outer focus ring stand at, and an outer shadow is never painted
|
|
86
|
+
* inside the box that casts it: a band of the real ground always stands
|
|
87
|
+
* between the dot and its halo, so the dot always stands on the surface its
|
|
88
|
+
* fill was measured against. The fill does not move. Nothing in this kit
|
|
89
|
+
* holds a mark to its own soft step, which is also why a Tag draws its dot in
|
|
90
|
+
* its ink.
|
|
91
|
+
*
|
|
92
|
+
* A SHADOW ON A PSEUDO-ELEMENT, not an outline at the same offset, because an
|
|
93
|
+
* outline's width is snapped to whole device pixels, as a border's is: at 1x
|
|
94
|
+
* a width breathing to 3px is drawn 1px and then 2px and reaches 3px for an
|
|
95
|
+
* instant, a flicker between two rings rather than a breath, where a spread
|
|
96
|
+
* shadow grows smoothly. The ring box is absolutely positioned, so it takes
|
|
97
|
+
* no room, and the pulsing dot is its containing block through a rule written
|
|
98
|
+
* in :where(), which weighs nothing, so a position of your own on the dot
|
|
99
|
+
* still wins, and any position but static keeps the ring on it.
|
|
100
|
+
*
|
|
101
|
+
* IT REACHES THE DESIGN'S 5PX, 2 of ground and 3 of halo, painted outside
|
|
102
|
+
* every box, so it moves nothing beside the dot. Like the 7px it surrounds,
|
|
103
|
+
* it is the measure of this one mark and is fixed at every density.
|
|
104
|
+
*
|
|
105
|
+
* ONE ROUND IS --motion-duration-breath, which is a PERIOD rather than a
|
|
106
|
+
* transition: out by the half, back by the end, and no `alternate`, which
|
|
107
|
+
* would play each half as a whole duration and take twice as long. That is
|
|
108
|
+
* 0.45 rounds a second, far under the three flashes a second that are a
|
|
109
|
+
* seizure risk, and the in-out ease makes both ends a rest. The halo is read
|
|
110
|
+
* through the custom property each tone sets above, which the ring box
|
|
111
|
+
* inherits, so whichever tone pulses breathes in its own soft step.
|
|
112
|
+
*/
|
|
113
|
+
:where(.crewlet-status-dot.is-pulsing) {
|
|
114
|
+
position: relative;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.crewlet-status-dot.is-pulsing::after {
|
|
118
|
+
content: '';
|
|
119
|
+
position: absolute;
|
|
120
|
+
inset: -2px;
|
|
121
|
+
border-radius: var(--radius-circle);
|
|
122
|
+
/* Paint, never a target: the box reaches 2px past the dot. */
|
|
123
|
+
pointer-events: none;
|
|
124
|
+
animation: crewlet-status-dot-pulse var(--motion-duration-breath) var(--motion-easing-in-out) infinite;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/*
|
|
128
|
+
* The spread moves and nothing else: the rests and the peak are one shadow in
|
|
129
|
+
* one colour, so the only thing that interpolates is how far it reaches.
|
|
130
|
+
*/
|
|
131
|
+
@keyframes crewlet-status-dot-pulse {
|
|
132
|
+
0%,
|
|
133
|
+
100% {
|
|
134
|
+
box-shadow: 0 0 0 0 var(--crewlet-status-dot-halo);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
50% {
|
|
138
|
+
box-shadow: 0 0 0 3px var(--crewlet-status-dot-halo);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* A DOT WITH ITS WORD: one line, the dot and then the word, the way every
|
|
144
|
+
* dot in this kit is meant to be read.
|
|
145
|
+
*
|
|
146
|
+
* THE GAP CLEARS THE HALO. A pulsing dot's halo reaches 5px past its edge, 2
|
|
147
|
+
* of ground and 3 of halo, painted outside every box, so it takes no room and
|
|
148
|
+
* a gap narrower than that puts the halo on the first letter at every peak:
|
|
149
|
+
* at the 4px an ordinary mark stands off its word, it struck the R of
|
|
150
|
+
* "Reviewing". 7px is that reach and 2px of ground on the far side of it, the
|
|
151
|
+
* same band that stands between the dot and its halo, so at the peak the word
|
|
152
|
+
* stands off the halo exactly as the halo stands off the dot. It is written in
|
|
153
|
+
* pixels, not a spacing step, because what it clears is fixed at every
|
|
154
|
+
* density like the dot and the halo themselves, and it is the same for EVERY
|
|
155
|
+
* tone, pulsing or not, so a column of statuses starts its words on one line
|
|
156
|
+
* whichever of them is breathing.
|
|
157
|
+
*/
|
|
158
|
+
.crewlet-status {
|
|
159
|
+
display: inline-flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
gap: 7px;
|
|
162
|
+
min-width: 0;
|
|
163
|
+
max-width: 100%;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* A status is one line, and the word is what gives way: the dot never does. */
|
|
167
|
+
.crewlet-status__label {
|
|
168
|
+
min-width: 0;
|
|
169
|
+
overflow: hidden;
|
|
170
|
+
text-overflow: ellipsis;
|
|
171
|
+
white-space: nowrap;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/*
|
|
175
|
+
* HELD, not slowed: a mark that loops for as long as the work runs is exactly
|
|
176
|
+
* what the setting is for. The stop names the selector that starts the pulse
|
|
177
|
+
* and comes after it, so it wins on source order at the same specificity,
|
|
178
|
+
* which is the pairing the package's literal check holds every stylesheet to.
|
|
179
|
+
* The dot rests at its own fill with no halo, and the word beside it still
|
|
180
|
+
* says the work is under way.
|
|
181
|
+
*/
|
|
182
|
+
@media (prefers-reduced-motion: reduce) {
|
|
183
|
+
.crewlet-status-dot.is-pulsing::after {
|
|
184
|
+
animation: none;
|
|
185
|
+
}
|
|
186
|
+
}
|