@crewlethq/ui 0.12.0 → 0.13.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 +66 -5
- package/dist/AppShell/index.js +2 -1
- package/dist/Avatar/index.js +1 -1
- package/dist/{Avatar-QHYOFID3.css → Avatar-BPJ36QZR.css} +1 -1
- package/dist/AvatarPicker/index.js +6 -6
- package/dist/Breadcrumb/Breadcrumb.d.ts +68 -0
- package/dist/Breadcrumb/index.d.ts +3 -0
- package/dist/Breadcrumb/index.js +3 -0
- package/dist/Breadcrumb-YMWVM3SV.css +193 -0
- package/dist/ChoiceButtons/ChoiceButtons.d.ts +43 -0
- package/dist/ChoiceButtons/index.d.ts +3 -0
- package/dist/ChoiceButtons/index.js +3 -0
- package/dist/ChoiceButtons-DJ5EOGUA.css +127 -0
- package/dist/Combobox/index.js +2 -2
- package/dist/CommandPalette/CommandPalette.d.ts +48 -1
- package/dist/CommandPalette/index.js +3 -3
- package/dist/{CommandPalette-C5AMKGN2.css → CommandPalette-HBTNKHZQ.css} +55 -2
- package/dist/DataTable/index.js +4 -4
- package/dist/DataView/index.js +11 -11
- package/dist/DateTimePicker/index.js +2 -2
- package/dist/Document/Document.d.ts +56 -0
- package/dist/Document/index.d.ts +3 -0
- package/dist/Document/index.js +2 -0
- package/dist/Document-PQGXJHB7.css +288 -0
- package/dist/EntityChip/index.js +1 -1
- package/dist/Highlight/Highlight.d.ts +45 -0
- package/dist/Highlight/index.d.ts +3 -0
- package/dist/Highlight/index.js +2 -0
- package/dist/Highlight-DXLV2R6L.css +29 -0
- package/dist/HuePicker/index.js +3 -3
- package/dist/ImageUpload/index.js +2 -2
- package/dist/{ImageUpload-L2GE4JUM.css → ImageUpload-NVGMN7DP.css} +9 -6
- package/dist/InboxList/InboxList.d.ts +116 -0
- package/dist/InboxList/index.d.ts +3 -0
- package/dist/InboxList/index.js +5 -0
- package/dist/InboxList-YMFWKGGS.css +252 -0
- package/dist/KeyChip/KeyChip.d.ts +21 -0
- package/dist/KeyChip/index.d.ts +3 -0
- package/dist/KeyChip/index.js +2 -0
- package/dist/KeyChip-4XJU4BBE.css +30 -0
- package/dist/Link/Link.d.ts +17 -2
- package/dist/Link/index.js +1 -1
- package/dist/{Link-6BEFNMN2.css → Link-WPMVLKLY.css} +36 -1
- package/dist/ListInput/index.js +2 -2
- package/dist/Listbox/index.d.ts +2 -0
- package/dist/Listbox/index.js +1 -1
- package/dist/Listbox/useHighlightRest.d.ts +35 -0
- package/dist/MarkdownEditor/MarkdownEditor.d.ts +93 -0
- package/dist/MarkdownEditor/format.d.ts +34 -0
- package/dist/MarkdownEditor/index.d.ts +5 -0
- package/dist/MarkdownEditor/index.js +12 -0
- package/dist/MarkdownEditor-ZLSHTOIZ.css +146 -0
- package/dist/Modal/Modal.d.ts +5 -1
- package/dist/Modal/index.js +1 -1
- package/dist/{Modal-BNT3TDV2.css → Modal-3YJ2GG2T.css} +33 -0
- package/dist/OrgLabel/index.js +1 -1
- package/dist/OrgNode/index.js +1 -1
- package/dist/OrgTable/index.js +5 -5
- package/dist/Outline/Outline.d.ts +72 -0
- package/dist/Outline/index.d.ts +3 -0
- package/dist/Outline/index.js +2 -0
- package/dist/Outline-VCXKKU3E.css +78 -0
- package/dist/Popover/Popover.d.ts +21 -1
- package/dist/Popover/index.js +1 -1
- package/dist/ReadingPane/ReadingPane.d.ts +95 -0
- package/dist/ReadingPane/index.d.ts +3 -0
- package/dist/ReadingPane/index.js +4 -0
- package/dist/ReadingPane-5UOLPWY5.css +194 -0
- package/dist/SegmentedControl/SegmentedControl.d.ts +9 -1
- package/dist/SegmentedControl/index.js +3 -3
- package/dist/{SegmentedControl-76HODRBT.css → SegmentedControl-PKBLJVSA.css} +18 -0
- package/dist/Select/Select.d.ts +22 -0
- package/dist/Select/index.js +2 -2
- package/dist/{Select-4ANVLHUY.css → Select-XMZ44RWY.css} +24 -0
- package/dist/SidebarNav/index.js +2 -1
- package/dist/{SidebarNav-X5NLZNWA.css → SidebarNav-KF66MLOM.css} +4 -19
- package/dist/Switcher/Switcher.d.ts +151 -0
- package/dist/Switcher/index.d.ts +3 -0
- package/dist/Switcher/index.js +16 -0
- package/dist/Switcher-B44Q4WF4.css +346 -0
- package/dist/Tabs/Tabs.d.ts +7 -1
- package/dist/Tabs/index.js +1 -1
- package/dist/{Tabs-5I5Q5KKM.css → Tabs-ITJYJFMU.css} +49 -0
- package/dist/TagsInput/index.js +3 -3
- package/dist/ThemeGallery/ThemeGallery.d.ts +65 -0
- package/dist/ThemeGallery/index.d.ts +3 -0
- package/dist/ThemeGallery/index.js +6 -0
- package/dist/ThemeGallery-NITASULQ.css +93 -0
- package/dist/ThemeSwatch/ThemeSwatch.d.ts +71 -0
- package/dist/ThemeSwatch/index.d.ts +3 -0
- package/dist/ThemeSwatch/index.js +2 -0
- package/dist/ThemeSwatch-4DL457ZB.css +256 -0
- package/dist/ThemeSwitcher/ThemeSwitcher.d.ts +5 -1
- package/dist/ThemeSwitcher/index.js +4 -4
- package/dist/ThemeToggle/ThemeToggle.d.ts +1 -1
- package/dist/ThemeToggle/index.js +1 -1
- package/dist/TimeWindowPicker/index.js +4 -4
- package/dist/Toaster/index.js +1 -1
- package/dist/{Toaster-NVDCEIP5.css → Toaster-KZ7YE2HA.css} +1 -0
- package/dist/Tree/index.d.ts +1 -1
- package/dist/Tree/index.js +1 -1
- package/dist/Tree/useTreeState.d.ts +37 -7
- package/dist/TreeCanvas/index.js +2 -2
- package/dist/TreeGrid/TreeGrid.d.ts +22 -2
- package/dist/TreeGrid/index.js +2 -2
- package/dist/{TreeGrid-NSW7VMOX.css → TreeGrid-FBX3MSJA.css} +19 -0
- package/dist/{chunk-EBBAAQDY.js → chunk-26PEPONN.js} +3 -1
- package/dist/{chunk-HV6IZFBK.js → chunk-4FFHJBEN.js} +2 -2
- package/dist/{chunk-JHQUT4WJ.js → chunk-4LDTQWS7.js} +1 -1
- package/dist/{chunk-GXYNEDNA.js → chunk-4Y7WKXAW.js} +1 -1
- package/dist/{chunk-MCPKHYMC.js → chunk-6LXMLQUM.js} +17 -4
- package/dist/{chunk-3UK4VFSK.js → chunk-6NIZCQUM.js} +1 -1
- package/dist/{chunk-ORNOOMVY.js → chunk-6TSZCBID.js} +2 -2
- package/dist/{chunk-ZMJHK7DR.js → chunk-75WOCYGC.js} +2 -2
- package/dist/chunk-77IEHFY4.js +299 -0
- package/dist/chunk-A5YKNRG6.js +94 -0
- package/dist/{chunk-HLBRPES3.js → chunk-B2CITO6R.js} +2 -2
- package/dist/{chunk-TEEJSTFG.js → chunk-CF6DTETT.js} +1 -1
- package/dist/{chunk-LAQK4V3Z.js → chunk-DJMLHCLD.js} +1 -1
- package/dist/{chunk-6MU7HNB4.js → chunk-F73MC7EZ.js} +47 -2
- package/dist/{chunk-ZPSOF6VL.js → chunk-FBSEJO2C.js} +1 -1
- package/dist/chunk-FYTIJM2T.js +40 -0
- package/dist/{chunk-ZHOM65MI.js → chunk-GG2QEZO2.js} +2 -2
- package/dist/chunk-H6VKCIWV.js +41 -0
- package/dist/{chunk-XV65NTIT.js → chunk-HKGS67VG.js} +94 -41
- package/dist/chunk-IG75YMUN.js +22 -0
- package/dist/{chunk-JCNUQ3US.js → chunk-JDPAA2JU.js} +1 -1
- package/dist/chunk-KLIEPFEZ.js +95 -0
- package/dist/{chunk-7LD6P32I.js → chunk-L3CTFFLZ.js} +2 -18
- package/dist/{chunk-UG5ZMAXW.js → chunk-LELD5KPA.js} +1 -1
- package/dist/chunk-MNFU2RNT.js +74 -0
- package/dist/{chunk-S3BCVWTU.js → chunk-MY374UUD.js} +49 -31
- package/dist/{chunk-K5Q2DK3P.js → chunk-NXDEPUVG.js} +1 -1
- package/dist/{chunk-PDUZO35I.js → chunk-O2ZDZZS7.js} +15 -6
- package/dist/{chunk-5WEVLIB6.js → chunk-RZ7RGECB.js} +1 -1
- package/dist/chunk-S3IENQ3E.js +336 -0
- package/dist/{chunk-WEIINZPA.js → chunk-SBRE7IML.js} +6 -2
- package/dist/{chunk-IVFJD7WY.js → chunk-UCCC7YVZ.js} +3 -2
- package/dist/{chunk-IINFVK3W.js → chunk-UZPHPW3Z.js} +6 -6
- package/dist/chunk-VWNC2L6W.js +110 -0
- package/dist/chunk-VYY56AMX.js +2 -0
- package/dist/chunk-WI6K5M5X.js +24 -0
- package/dist/{chunk-GOUKOXJK.js → chunk-WY2NLRZN.js} +3 -3
- package/dist/{chunk-SEFMO2EV.js → chunk-XFE5W2I4.js} +44 -5
- package/dist/chunk-XYCADWZN.js +100 -0
- package/dist/chunk-YSJC7AZC.js +62 -0
- package/dist/chunk-ZAJHGDAW.js +93 -0
- package/dist/generated/index.d.ts +12 -0
- package/dist/generated/index.js +65 -52
- package/dist/index.js +65 -52
- package/dist/styles.css +2449 -161
- package/dist/utils/highlight.d.ts +17 -0
- package/dist/utils/useMediaMatch.d.ts +12 -0
- package/package.json +3 -3
- package/dist/chunk-UAQIUSSK.js +0 -2
- package/dist/{chunk-74OVQWA5.js → chunk-6AR2T5Y4.js} +0 -0
- package/dist/{chunk-GARACZAH.js → chunk-LZP7FGT7.js} +1 -1
package/dist/HuePicker/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import '../chunk-EXHQ2QVW.js';
|
|
2
|
-
export { HuePicker } from '../chunk-
|
|
2
|
+
export { HuePicker } from '../chunk-NXDEPUVG.js';
|
|
3
3
|
import '../chunk-AYKXMIOR.js';
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
4
|
+
import '../chunk-26PEPONN.js';
|
|
5
|
+
import '../chunk-4LDTQWS7.js';
|
|
6
6
|
import '../chunk-CBOICT64.js';
|
|
7
7
|
import '../chunk-BHHIIK3M.js';
|
|
8
8
|
import '../chunk-BZFWDIV6.js';
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* ImageUpload, the click-to-upload affordance built on Avatar.
|
|
3
3
|
*
|
|
4
|
-
* WHITE ON THE SCRIM, from tokens, in
|
|
4
|
+
* WHITE ON THE SCRIM, from tokens, in every theme. The overlay used to spell
|
|
5
5
|
* its own rgba(0, 0, 0, 0.5) and three shades of white; the scrim and the
|
|
6
|
-
* on-
|
|
7
|
-
*
|
|
6
|
+
* on-scrim step are the two values the palette measures for exactly this,
|
|
7
|
+
* which is a label drawn on something dark whatever is behind it. The
|
|
8
|
+
* on-accent step is not: a theme whose accent is light labels it dark. The
|
|
9
|
+
* remove button is the danger fill, and takes the on-danger step for the
|
|
10
|
+
* same reason.
|
|
8
11
|
*
|
|
9
12
|
* NO LITERAL FALLBACKS INSIDE var(). A fallback is what renders whenever the
|
|
10
13
|
* token name is misspelt, so it hides the very failure it looks like
|
|
@@ -91,7 +94,7 @@
|
|
|
91
94
|
justify-content: center;
|
|
92
95
|
gap: 2px;
|
|
93
96
|
background: var(--color-surface-scrim);
|
|
94
|
-
color: var(--color-text-on-
|
|
97
|
+
color: var(--color-text-on-scrim);
|
|
95
98
|
opacity: 0;
|
|
96
99
|
transition: opacity var(--motion-duration-base) var(--motion-easing-default);
|
|
97
100
|
pointer-events: none;
|
|
@@ -136,7 +139,7 @@
|
|
|
136
139
|
height: calc(var(--crewlet-image-upload-size) * 0.3);
|
|
137
140
|
border-radius: var(--radius-circle);
|
|
138
141
|
border: 2px solid var(--color-surface-scrim);
|
|
139
|
-
border-top-color: var(--color-text-on-
|
|
142
|
+
border-top-color: var(--color-text-on-scrim);
|
|
140
143
|
animation: crewlet-image-upload-spin calc(var(--motion-duration-slow) * 2.5) linear infinite;
|
|
141
144
|
}
|
|
142
145
|
|
|
@@ -166,7 +169,7 @@
|
|
|
166
169
|
border-radius: var(--radius-circle);
|
|
167
170
|
background: var(--color-feedback-danger);
|
|
168
171
|
border: 2px solid var(--color-surface-background);
|
|
169
|
-
color: var(--color-text-on-
|
|
172
|
+
color: var(--color-text-on-danger);
|
|
170
173
|
cursor: pointer;
|
|
171
174
|
opacity: 0;
|
|
172
175
|
transition: opacity var(--motion-duration-fast) var(--motion-easing-default);
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type HTMLAttributes, type LiHTMLAttributes, type MouseEvent, type ReactNode } from 'react';
|
|
2
|
+
import { type HeadingLevel } from '../utils/headingLevel.js';
|
|
3
|
+
export interface InboxListProps extends HTMLAttributes<HTMLElement> {
|
|
4
|
+
/** Names the list as a landmark: "Inbox". */
|
|
5
|
+
label: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The column of an inbox: what reached a person, grouped, one row each, read
|
|
9
|
+
* in full in a pane beside it.
|
|
10
|
+
*
|
|
11
|
+
* A NAVIGATION, NOT A TABLE. Every row opens something, and a reader moves
|
|
12
|
+
* between them to read one at a time. It promises no columns, so it draws
|
|
13
|
+
* none, and its rows are as tall as their words rather than one fixed height.
|
|
14
|
+
*/
|
|
15
|
+
export declare function InboxList({ label, className, children, ...rest }: InboxListProps): import("react").JSX.Element;
|
|
16
|
+
export declare namespace InboxList {
|
|
17
|
+
var Group: typeof InboxGroup;
|
|
18
|
+
var Row: typeof InboxRow;
|
|
19
|
+
var More: typeof InboxMore;
|
|
20
|
+
var Toggle: typeof InboxToggle;
|
|
21
|
+
}
|
|
22
|
+
export interface InboxGroupProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
23
|
+
/** The group's name: "Needs you", "Updates". */
|
|
24
|
+
label: ReactNode;
|
|
25
|
+
/**
|
|
26
|
+
* Names the group for a screen reader only. For rows a control above them
|
|
27
|
+
* already introduces, such as the snoozed ones under their own toggle.
|
|
28
|
+
*/
|
|
29
|
+
hideLabel?: boolean | undefined;
|
|
30
|
+
/** Overrides the level the label is rendered at. */
|
|
31
|
+
headingLevel?: HeadingLevel | undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A labelled run of rows. The label is a heading set in the micro-label
|
|
35
|
+
* register, so a reader navigating by heading lands on each group and a
|
|
36
|
+
* reader scanning sees where one ends.
|
|
37
|
+
*/
|
|
38
|
+
export declare function InboxGroup({ label, hideLabel, headingLevel, className, children, ...rest }: InboxGroupProps): import("react").JSX.Element;
|
|
39
|
+
export type InboxRowTone = 'default' | 'danger';
|
|
40
|
+
export interface InboxRowProps extends Omit<LiHTMLAttributes<HTMLLIElement>, 'onClick' | 'title'> {
|
|
41
|
+
/** Who the row is from: a seat's or a person's name. */
|
|
42
|
+
title: ReactNode;
|
|
43
|
+
/** A word after the name where the row is not a plain question or update: "coding run", "stopped". */
|
|
44
|
+
qualifier?: ReactNode;
|
|
45
|
+
/** `danger` sets the qualifier in the danger ink, for a seat that has stopped. */
|
|
46
|
+
qualifierTone?: InboxRowTone | undefined;
|
|
47
|
+
/** At the end of the first line: when it arrived. */
|
|
48
|
+
meta?: ReactNode;
|
|
49
|
+
/** Before the words: an avatar, drawn at the target size. */
|
|
50
|
+
leading?: ReactNode;
|
|
51
|
+
/** What the row says, in up to three lines. */
|
|
52
|
+
children?: ReactNode;
|
|
53
|
+
/** Drawn after the words in the quiet ink, inside the same three lines: a comment's own text. */
|
|
54
|
+
excerpt?: ReactNode;
|
|
55
|
+
/**
|
|
56
|
+
* Under the row and OUTSIDE its control, so it can be a control of its own:
|
|
57
|
+
* the task the row is about, as a link.
|
|
58
|
+
*/
|
|
59
|
+
aside?: ReactNode;
|
|
60
|
+
/** This row is the one open beside the list. */
|
|
61
|
+
selected?: boolean | undefined;
|
|
62
|
+
/** Not read yet: the name is heavier, the words take the primary ink, and the state is read out. */
|
|
63
|
+
unread?: boolean | undefined;
|
|
64
|
+
/** Read after the row's words when `unread`. */
|
|
65
|
+
unreadLabel?: string | undefined;
|
|
66
|
+
/** It waits on the reader: the words take the primary ink. */
|
|
67
|
+
actionable?: boolean | undefined;
|
|
68
|
+
/** Settled: the words are struck through in the quiet ink, and the state is read out. */
|
|
69
|
+
done?: boolean | undefined;
|
|
70
|
+
/** Read after the row's words when `done`: "Answered", "Resolved". */
|
|
71
|
+
doneLabel?: string | undefined;
|
|
72
|
+
/** Opens the row as a link. */
|
|
73
|
+
href?: string | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Opens the row as a button, or, beside `href`, takes the press first: a
|
|
76
|
+
* router calls `preventDefault` on a plain click and lets a modified one
|
|
77
|
+
* open the link in a tab.
|
|
78
|
+
*/
|
|
79
|
+
onClick?: ((event: MouseEvent<HTMLElement>) => void) | undefined;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* One row: WHO, then WHAT in up to three lines, then the task it is about.
|
|
83
|
+
*
|
|
84
|
+
* THE ROW IS ONE CONTROL and the task is another. A link nested inside a
|
|
85
|
+
* button is invalid and unreachable by keyboard, so the task sits under the
|
|
86
|
+
* control, in the same item, and lines up with the words above it. The item
|
|
87
|
+
* takes the hover and the selected fill as a whole, so the two read as one row.
|
|
88
|
+
*
|
|
89
|
+
* THE SELECTED FILL IS NEUTRAL. An inbox is read one row after another, and an
|
|
90
|
+
* accent tint on the open row made the column read as a column of alerts; the
|
|
91
|
+
* pressed fill says "here" without saying "look". The control carries
|
|
92
|
+
* `aria-current`, so the row is announced as the open one where focus is.
|
|
93
|
+
*
|
|
94
|
+
* NOTHING IS CUT AT THE EDGE. The name ellipsizes, the time never wraps, and
|
|
95
|
+
* the words take up to three lines before they stop, so a row says what it is
|
|
96
|
+
* rather than its first few words.
|
|
97
|
+
*/
|
|
98
|
+
export declare function InboxRow({ title, qualifier, qualifierTone, meta, leading, excerpt, aside, selected, unread, unreadLabel, actionable, done, doneLabel, href, onClick, className, children, ...rest }: InboxRowProps): import("react").JSX.Element;
|
|
99
|
+
export type InboxMoreProps = HTMLAttributes<HTMLDivElement>;
|
|
100
|
+
/**
|
|
101
|
+
* The end of the list: the quiet toggles that open what is not in it by
|
|
102
|
+
* default, the snoozed rows and the earlier ones. Two words at the bottom
|
|
103
|
+
* rather than a filter bar at the top, because a reader opens them rarely
|
|
104
|
+
* and a filter bar is read every time.
|
|
105
|
+
*/
|
|
106
|
+
export declare function InboxMore({ className, children, ...rest }: InboxMoreProps): import("react").JSX.Element;
|
|
107
|
+
export interface InboxToggleProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'> {
|
|
108
|
+
/** Whether the rows it opens are shown. */
|
|
109
|
+
expanded: boolean;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* One of those toggles: a word in the quiet ink that opens rows under it.
|
|
113
|
+
* Its own `aria-expanded` says whether they are open, and the ink steps up to
|
|
114
|
+
* the primary while they are.
|
|
115
|
+
*/
|
|
116
|
+
export declare function InboxToggle({ expanded, className, children, ...rest }: InboxToggleProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The inbox's column: groups of rows, each row a control with the task it is
|
|
3
|
+
* about under it, and the quiet toggles at the end.
|
|
4
|
+
*
|
|
5
|
+
* EVERY TRACK IS minmax(0, 1fr). An `auto` track grows to its widest content,
|
|
6
|
+
* and a row holding a long unbroken word pushed the whole column past its
|
|
7
|
+
* edge, cutting every row off at the right.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.crewlet-inbox-list {
|
|
11
|
+
display: grid;
|
|
12
|
+
grid-template-columns: minmax(0, 1fr);
|
|
13
|
+
align-content: start;
|
|
14
|
+
gap: 2px;
|
|
15
|
+
min-width: 0;
|
|
16
|
+
font-size: var(--font-size-compact);
|
|
17
|
+
line-height: var(--font-line-height-body);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.crewlet-inbox-list__group {
|
|
21
|
+
display: grid;
|
|
22
|
+
grid-template-columns: minmax(0, 1fr);
|
|
23
|
+
gap: 2px;
|
|
24
|
+
min-width: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* The heading's own line box is the label's, so the label sits where it is drawn. */
|
|
28
|
+
.crewlet-inbox-list__label {
|
|
29
|
+
margin: 0;
|
|
30
|
+
padding: var(--spacing-3) var(--spacing-2) var(--spacing-1);
|
|
31
|
+
font: inherit;
|
|
32
|
+
font-size: var(--font-size-2xs);
|
|
33
|
+
line-height: var(--font-line-height-snug);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.crewlet-inbox-list__rows {
|
|
37
|
+
display: grid;
|
|
38
|
+
grid-template-columns: minmax(0, 1fr);
|
|
39
|
+
gap: 2px;
|
|
40
|
+
margin: 0;
|
|
41
|
+
padding: 0;
|
|
42
|
+
list-style: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* ---- The row ------------------------------------------------------------ */
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* The ITEM takes the hover and the selected fill, so the control and the task
|
|
49
|
+
* under it read as one row. The selected fill is the neutral pressed step, and
|
|
50
|
+
* a selected row takes no hover on top of it: both are a background on the
|
|
51
|
+
* same element, and a composite of the two is a colour nothing has measured.
|
|
52
|
+
*/
|
|
53
|
+
.crewlet-inbox-row {
|
|
54
|
+
min-width: 0;
|
|
55
|
+
border-radius: var(--radius-md);
|
|
56
|
+
transition: background var(--motion-duration-fast) var(--motion-easing-default);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.crewlet-inbox-row:hover {
|
|
60
|
+
background: var(--color-surface-hover);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.crewlet-inbox-row--selected,
|
|
64
|
+
.crewlet-inbox-row--selected:hover {
|
|
65
|
+
background: var(--color-surface-pressed);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* FORCED COLORS repaints every author background to Canvas, which takes the
|
|
70
|
+
* open row's fill with it, so the row the pane is showing would look like
|
|
71
|
+
* every other. An outline is the one mark the mode keeps, drawn inside the row
|
|
72
|
+
* so the scroller does not clip it, in the system's colour for exactly this.
|
|
73
|
+
*/
|
|
74
|
+
@media (forced-colors: active) {
|
|
75
|
+
.crewlet-inbox-row--selected {
|
|
76
|
+
outline: 2px solid Highlight;
|
|
77
|
+
outline-offset: -2px;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.crewlet-inbox-row__control {
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: flex-start;
|
|
84
|
+
gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
|
|
85
|
+
width: 100%;
|
|
86
|
+
min-width: 0;
|
|
87
|
+
padding: calc(var(--spacing-2) + var(--spacing-1) / 2) var(--spacing-2) var(--spacing-1);
|
|
88
|
+
border: 0;
|
|
89
|
+
border-radius: var(--radius-md);
|
|
90
|
+
background: none;
|
|
91
|
+
color: inherit;
|
|
92
|
+
font: inherit;
|
|
93
|
+
text-align: left;
|
|
94
|
+
text-decoration: none;
|
|
95
|
+
cursor: pointer;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* With no task under it, the control closes the row at the same padding it opened with. */
|
|
99
|
+
.crewlet-inbox-row__control:only-child {
|
|
100
|
+
padding-bottom: calc(var(--spacing-2) + var(--spacing-1) / 2);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
* The ring is drawn INSIDE: the list sits in a clipping scroller, where an
|
|
105
|
+
* outset ring is cut off on the first and last rows and painted over by the
|
|
106
|
+
* row below.
|
|
107
|
+
*/
|
|
108
|
+
.crewlet-inbox-row__control:focus-visible {
|
|
109
|
+
outline: 2px solid var(--color-focus);
|
|
110
|
+
outline-offset: var(--size-focus-ring-inset-offset);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.crewlet-inbox-row__leading {
|
|
114
|
+
display: inline-flex;
|
|
115
|
+
flex: none;
|
|
116
|
+
justify-content: center;
|
|
117
|
+
width: var(--size-target-min);
|
|
118
|
+
margin-top: 1px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.crewlet-inbox-row__main {
|
|
122
|
+
display: grid;
|
|
123
|
+
flex: 1;
|
|
124
|
+
gap: 2px;
|
|
125
|
+
min-width: 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.crewlet-inbox-row__head {
|
|
129
|
+
display: flex;
|
|
130
|
+
align-items: baseline;
|
|
131
|
+
gap: var(--spacing-1);
|
|
132
|
+
min-width: 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.crewlet-inbox-row__title {
|
|
136
|
+
min-width: 0;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
text-overflow: ellipsis;
|
|
139
|
+
white-space: nowrap;
|
|
140
|
+
font-weight: var(--font-weight-medium);
|
|
141
|
+
color: var(--color-text-primary);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.crewlet-inbox-row__qualifier {
|
|
145
|
+
flex: none;
|
|
146
|
+
font-size: var(--font-size-xs);
|
|
147
|
+
color: var(--color-text-tertiary);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.crewlet-inbox-row__qualifier--danger {
|
|
151
|
+
color: var(--color-feedback-danger-ink);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.crewlet-inbox-row__meta {
|
|
155
|
+
flex: none;
|
|
156
|
+
margin-inline-start: auto;
|
|
157
|
+
font-size: var(--font-size-xs);
|
|
158
|
+
font-variant-numeric: tabular-nums;
|
|
159
|
+
white-space: nowrap;
|
|
160
|
+
color: var(--color-text-tertiary);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.crewlet-inbox-row__text {
|
|
164
|
+
display: -webkit-box;
|
|
165
|
+
-webkit-box-orient: vertical;
|
|
166
|
+
-webkit-line-clamp: 3;
|
|
167
|
+
line-clamp: 3;
|
|
168
|
+
overflow: hidden;
|
|
169
|
+
overflow-wrap: anywhere;
|
|
170
|
+
line-height: var(--font-line-height-snug);
|
|
171
|
+
color: var(--color-text-secondary);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.crewlet-inbox-row__excerpt {
|
|
175
|
+
color: var(--color-text-tertiary);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* Unread: a heavier name, and the words in the primary ink. */
|
|
179
|
+
.crewlet-inbox-row__control--unread .crewlet-inbox-row__title {
|
|
180
|
+
font-weight: var(--font-weight-semibold);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.crewlet-inbox-row__control--unread .crewlet-inbox-row__text,
|
|
184
|
+
.crewlet-inbox-row__control--actionable .crewlet-inbox-row__text {
|
|
185
|
+
color: var(--color-text-primary);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/*
|
|
189
|
+
* Settled. The strike is drawn in the strong hairline rather than the text's
|
|
190
|
+
* own ink, so the words under it stay legible; the state is also read out,
|
|
191
|
+
* because a line through a word says nothing to somebody listening.
|
|
192
|
+
*/
|
|
193
|
+
.crewlet-inbox-row__control--done .crewlet-inbox-row__text {
|
|
194
|
+
text-decoration: line-through;
|
|
195
|
+
text-decoration-color: var(--color-border-strong);
|
|
196
|
+
color: var(--color-text-tertiary);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/*
|
|
200
|
+
* The task, under the words and lined up with them: the control's start pad,
|
|
201
|
+
* the leading slot and the gap after it.
|
|
202
|
+
*/
|
|
203
|
+
.crewlet-inbox-row__aside {
|
|
204
|
+
min-width: 0;
|
|
205
|
+
padding:
|
|
206
|
+
0 var(--spacing-2) calc(var(--spacing-2) + var(--spacing-1) / 2)
|
|
207
|
+
calc(var(--spacing-2) + var(--size-target-min) + var(--spacing-2) + var(--spacing-1) / 2);
|
|
208
|
+
overflow-wrap: anywhere;
|
|
209
|
+
font-size: var(--font-size-xs);
|
|
210
|
+
line-height: var(--font-line-height-snug);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* ---- The end of the list ---------------------------------------------- */
|
|
214
|
+
|
|
215
|
+
.crewlet-inbox-list__more {
|
|
216
|
+
display: flex;
|
|
217
|
+
flex-wrap: wrap;
|
|
218
|
+
gap: calc(var(--spacing-4) + var(--spacing-1) / 2);
|
|
219
|
+
padding: calc(var(--spacing-3) + var(--spacing-1) / 2) var(--spacing-2) 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.crewlet-inbox-list__toggle {
|
|
223
|
+
padding: 0;
|
|
224
|
+
border: 0;
|
|
225
|
+
border-radius: var(--radius-xs);
|
|
226
|
+
background: none;
|
|
227
|
+
font: inherit;
|
|
228
|
+
font-size: var(--font-size-xs);
|
|
229
|
+
color: var(--color-text-tertiary);
|
|
230
|
+
cursor: pointer;
|
|
231
|
+
transition: color var(--motion-duration-fast) var(--motion-easing-default);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.crewlet-inbox-list__toggle:hover,
|
|
235
|
+
.crewlet-inbox-list__toggle[aria-expanded='true'] {
|
|
236
|
+
color: var(--color-text-primary);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.crewlet-inbox-list__toggle:focus-visible {
|
|
240
|
+
outline: 2px solid var(--color-focus);
|
|
241
|
+
outline-offset: 2px;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@media (prefers-reduced-motion: reduce) {
|
|
245
|
+
.crewlet-inbox-row {
|
|
246
|
+
transition: none;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.crewlet-inbox-list__toggle {
|
|
250
|
+
transition: none;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
export interface KeyChipProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'> {
|
|
3
|
+
/** The key as the system mints it: `FAIR`, `ENG`, `SPLIT`. */
|
|
4
|
+
children: string;
|
|
5
|
+
/**
|
|
6
|
+
* What a search typed. The letters it matched are drawn bold: the start of
|
|
7
|
+
* the key first, then anywhere in it.
|
|
8
|
+
*/
|
|
9
|
+
highlight?: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A project's key, drawn as the small mono chip every surface draws it as: a
|
|
13
|
+
* row in the rail, a crumb, a row in a switcher, a cell in a directory.
|
|
14
|
+
*
|
|
15
|
+
* ONE CHIP. It was drawn by hand twice, by the rail's row and by the
|
|
16
|
+
* dashboard's own stylesheet, with two radii and two paddings for one fact.
|
|
17
|
+
*
|
|
18
|
+
* It is text, not a control, and carries no role: the key is read as part of
|
|
19
|
+
* whatever it labels, so a row reads "FAIR Product and Engineering".
|
|
20
|
+
*/
|
|
21
|
+
export declare function KeyChip({ children, highlight, className, ...rest }: KeyChipProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A project's key as a chip: the raised rung inside the plain hairline, in the
|
|
3
|
+
* mono face at the micro step and the secondary ink.
|
|
4
|
+
*
|
|
5
|
+
* The rail's suite measures this ink on this fill against every ground a rail
|
|
6
|
+
* row can have (SidebarNav.test.tsx), because the rail is where the chip sits
|
|
7
|
+
* on the most grounds: the frame, a pointed row and the current row.
|
|
8
|
+
*/
|
|
9
|
+
.crewlet-key-chip {
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
flex: none;
|
|
13
|
+
padding: 0 calc(var(--spacing-1) + 1px);
|
|
14
|
+
border: 1px solid var(--color-border-default);
|
|
15
|
+
border-radius: var(--radius-xs);
|
|
16
|
+
background: var(--color-surface-elevated);
|
|
17
|
+
color: var(--color-text-secondary);
|
|
18
|
+
font-family: var(--font-family-mono);
|
|
19
|
+
font-size: var(--font-size-2xs);
|
|
20
|
+
font-weight: var(--font-weight-medium);
|
|
21
|
+
letter-spacing: var(--font-letter-spacing-normal);
|
|
22
|
+
line-height: var(--font-line-height-body);
|
|
23
|
+
white-space: nowrap;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* The letters a search matched: the weight carries it, in the primary ink. */
|
|
27
|
+
.crewlet-key-chip__match {
|
|
28
|
+
font-weight: var(--font-weight-bold);
|
|
29
|
+
color: var(--color-text-primary);
|
|
30
|
+
}
|
package/dist/Link/Link.d.ts
CHANGED
|
@@ -3,8 +3,16 @@ export type LinkVariant =
|
|
|
3
3
|
/** A navigation: the accent ink, underlined on hover. */
|
|
4
4
|
'default'
|
|
5
5
|
/** An identity a reader clicks through to: neutral ink, underlined on hover. */
|
|
6
|
-
| 'subtle'
|
|
7
|
-
|
|
6
|
+
| 'subtle'
|
|
7
|
+
/**
|
|
8
|
+
* A reference set among other words, the task a question is about, say: a
|
|
9
|
+
* softer ink than a navigation, never underlined, stepping up to the full
|
|
10
|
+
* accent ink on hover.
|
|
11
|
+
*/
|
|
12
|
+
| 'quiet';
|
|
13
|
+
export type LinkSize = 'body' | 'caption'
|
|
14
|
+
/** The size of the words around it, for a link set inside a sentence. */
|
|
15
|
+
| 'inherit';
|
|
8
16
|
export interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
9
17
|
variant?: LinkVariant | undefined;
|
|
10
18
|
size?: LinkSize | undefined;
|
|
@@ -41,5 +49,12 @@ export interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
|
41
49
|
* instruction, a seat's name in a row, say. It is still underlined on hover
|
|
42
50
|
* and still takes the focus ring, because a link a reader cannot find is not
|
|
43
51
|
* quieter, it is hidden.
|
|
52
|
+
*
|
|
53
|
+
* `quiet` is for a reference that sits in a column of rows or inside a
|
|
54
|
+
* sentence, where every row drawing a full accent link would turn the column
|
|
55
|
+
* into a column of links. It keeps an ink of its own, measured to 4.5:1 on
|
|
56
|
+
* every surface and pressed row, so it is still found by colour and by its
|
|
57
|
+
* place, and it keeps the focus ring. It draws no underline even on hover:
|
|
58
|
+
* the ink stepping up to the accent is the signal that it is live.
|
|
44
59
|
*/
|
|
45
60
|
export declare const Link: import("react").ForwardRefExoticComponent<LinkProps & import("react").RefAttributes<HTMLAnchorElement>>;
|
package/dist/Link/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* A link, in the
|
|
2
|
+
* A link, in the three registers a console needs: a navigation, an identity
|
|
3
|
+
* and a quiet reference.
|
|
3
4
|
*
|
|
4
5
|
* The ink is the accent's INK step, not the accent fill. The fill is a mark
|
|
5
6
|
* and clears 3:1; text has to clear 4.5:1, and at caption size it is exactly
|
|
@@ -32,10 +33,44 @@
|
|
|
32
33
|
color: var(--color-brand-accent-ink);
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
/*
|
|
37
|
+
* A reference among other words. Its own ink sits between the accent ink and
|
|
38
|
+
* the secondary text, so a column of rows that each name a task does not read
|
|
39
|
+
* as a column of links, and the hover steps it up to the full accent ink with
|
|
40
|
+
* no underline. The ink is a token rather than a mix of two, because a mix is
|
|
41
|
+
* a colour nobody measured; this one clears 4.5:1 on every surface and on a
|
|
42
|
+
* pressed row.
|
|
43
|
+
*/
|
|
44
|
+
.crewlet-link--quiet {
|
|
45
|
+
color: var(--color-text-link-quiet);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.crewlet-link--quiet:hover {
|
|
49
|
+
color: var(--color-brand-accent-ink);
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* FORCED COLORS paints every link in LinkText whatever its state, so the step
|
|
55
|
+
* up to the accent ink cannot be seen there, and a hover with no underline is
|
|
56
|
+
* no hover at all. The rule under the words is the one mark the mode leaves to
|
|
57
|
+
* the author, so it is where the quiet variant's hover goes in that mode.
|
|
58
|
+
*/
|
|
59
|
+
@media (forced-colors: active) {
|
|
60
|
+
.crewlet-link--quiet:hover {
|
|
61
|
+
text-decoration: underline;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
35
65
|
.crewlet-link--body {
|
|
36
66
|
font-size: var(--font-size-sm);
|
|
37
67
|
}
|
|
38
68
|
|
|
69
|
+
/* Set inside a sentence: the sentence's own size, whatever it is. */
|
|
70
|
+
.crewlet-link--inherit {
|
|
71
|
+
font-size: inherit;
|
|
72
|
+
}
|
|
73
|
+
|
|
39
74
|
/*
|
|
40
75
|
* A caption-sized link takes the caption's SIZE and keeps the link's ink. It
|
|
41
76
|
* is medium weight and does not wrap, because the thing it names (an event id,
|
package/dist/ListInput/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { ListInput } from '../chunk-
|
|
1
|
+
export { ListInput } from '../chunk-LZP7FGT7.js';
|
|
2
2
|
import '../chunk-SMBKXWML.js';
|
|
3
3
|
import '../chunk-FTEJPHBI.js';
|
|
4
4
|
import '../chunk-PQADV6P6.js';
|
|
5
|
-
import '../chunk-RSAQOKH3.js';
|
|
6
5
|
import '../chunk-4FQT6ZAY.js';
|
|
6
|
+
import '../chunk-RSAQOKH3.js';
|
|
7
7
|
import '../chunk-7RPGY3JE.js';
|
|
8
8
|
import '../chunk-R25RGPUB.js';
|
|
9
9
|
import '../chunk-BZFWDIV6.js';
|
package/dist/Listbox/index.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export { useListbox } from './useListbox.js';
|
|
|
3
3
|
export type { Listbox, ListboxOptions } from './useListbox.js';
|
|
4
4
|
export { TYPE_AHEAD_WINDOW, useOptionKeys } from './useOptionKeys.js';
|
|
5
5
|
export type { OptionKeys, OptionKeysOptions } from './useOptionKeys.js';
|
|
6
|
+
export { HIGHLIGHT_REST_MS, useHighlightRest } from './useHighlightRest.js';
|
|
7
|
+
export type { HighlightRest } from './useHighlightRest.js';
|
package/dist/Listbox/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { TYPE_AHEAD_WINDOW, useListbox, useOptionKeys } from '../chunk-
|
|
1
|
+
export { HIGHLIGHT_REST_MS, TYPE_AHEAD_WINDOW, useHighlightRest, useListbox, useOptionKeys } from '../chunk-F73MC7EZ.js';
|
|
2
2
|
import '../chunk-R25RGPUB.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a list's highlight COMES TO REST, told once per resting place.
|
|
3
|
+
*
|
|
4
|
+
* WHY IT EXISTS. A list that previews what its highlight is on (a theme the
|
|
5
|
+
* whole screen repaints in while the reader decides) has to know where the
|
|
6
|
+
* reader STOPPED, not every row they passed. A key moves the highlight on
|
|
7
|
+
* purpose, so where a key lands is told at once. A pointer crosses rows on
|
|
8
|
+
* its way somewhere else, so a row it passes over is told only once the
|
|
9
|
+
* pointer has rested on it for `HIGHLIGHT_REST_MS`; told on every row it
|
|
10
|
+
* crossed, a list over a screen that repaints would flash every theme between
|
|
11
|
+
* the pointer's start and its goal.
|
|
12
|
+
*
|
|
13
|
+
* THE RULES IT KEEPS.
|
|
14
|
+
*
|
|
15
|
+
* - A RESTING PLACE IS TOLD ONCE. Telling the same row twice is a second
|
|
16
|
+
* repaint of a screen already showing it, so a re-render, or a list handed
|
|
17
|
+
* new option objects for the same rows, says nothing.
|
|
18
|
+
* - A KEY CANCELS A POINTER STILL ON ITS WAY. Where the arrows put the
|
|
19
|
+
* highlight wins over a row the pointer had not yet rested on.
|
|
20
|
+
* - `null` IS NOWHERE, and it is told when the list stops offering anything:
|
|
21
|
+
* it closed, it emptied, the pointer left it, or the component went away.
|
|
22
|
+
* A preview never outlives the list that started it.
|
|
23
|
+
*
|
|
24
|
+
* It owns no markup and no highlight: the component keeps its own, and hands
|
|
25
|
+
* this the KEY of each row the highlight reaches (a value, an id).
|
|
26
|
+
*/
|
|
27
|
+
/** How long a pointer rests on a row before the row is where the highlight rests, in milliseconds. */
|
|
28
|
+
export declare const HIGHLIGHT_REST_MS = 120;
|
|
29
|
+
export interface HighlightRest {
|
|
30
|
+
/** The highlight moved by a key or by the list itself, or left the list (`null`): told now. */
|
|
31
|
+
now: (key: string | null) => void;
|
|
32
|
+
/** The pointer came onto a row: told once it rests there. */
|
|
33
|
+
rest: (key: string) => void;
|
|
34
|
+
}
|
|
35
|
+
export declare function useHighlightRest(onRest: ((key: string | null) => void) | undefined): HighlightRest;
|