rift-ds 1.12.0 → 1.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 +8 -2
- package/behaviors/visually-hidden.css +24 -0
- package/bin/rift-ds.mjs +5 -2
- package/chat/ChatAgentPane.css +5 -1
- package/chat/ChatWidget.css +0 -36
- package/chat/ResponseActions.js +2 -1
- package/components/Accordion/Accordion.css +10 -3
- package/components/AgentPlan/AgentPlan.css +0 -12
- package/components/AgentPlan/AgentPlan.js +2 -1
- package/components/AgentStatus/AgentStatus.css +1 -1
- package/components/AnimatedNumber/AnimatedNumber.css +0 -12
- package/components/AnimatedNumber/AnimatedNumber.js +2 -1
- package/components/AppSidebar/AppSidebar.css +2 -2
- package/components/Attachment/Attachment.css +0 -17
- package/components/Attachment/AttachmentTile.js +3 -2
- package/components/BottomNav/BottomNav.css +0 -9
- package/components/BottomNav/BottomNav.js +2 -1
- package/components/CardStack/CardStack.css +0 -11
- package/components/CardStack/CardStack.js +2 -1
- package/components/ChatMessage/ChatMessage.css +0 -12
- package/components/ChatMessage/ChatMessage.js +2 -1
- package/components/Checkbox/Checkbox.css +34 -25
- package/components/Checkbox/Checkbox.d.ts +34 -0
- package/components/Checkbox/Checkbox.js +64 -36
- package/components/CodeDiff/CodeDiff.css +0 -11
- package/components/CodeDiff/CodeDiff.js +3 -2
- package/components/ColourSwatch/ColourSwatch.css +1 -0
- package/components/Combobox/Combobox.css +1 -8
- package/components/Combobox/Combobox.js +2 -1
- package/components/CommandPalette/CommandPalette.css +2 -25
- package/components/CommandPalette/CommandPalette.js +8 -5
- package/components/Composer/Composer.css +0 -12
- package/components/Composer/Composer.js +3 -2
- package/components/ContactCard/ContactCard.css +1 -1
- package/components/ContextMenu/ContextMenu.css +1 -9
- package/components/ContextMenu/ContextMenu.js +3 -2
- package/components/Dialog/Dialog.css +2 -26
- package/components/Dialog/Dialog.js +8 -12
- package/components/Drawer/Drawer.css +2 -26
- package/components/Drawer/Drawer.js +8 -12
- package/components/Dropdown/ChosenMark.css +19 -0
- package/components/Dropdown/Dropdown.css +0 -12
- package/components/Dropdown/Dropdown.d.ts +23 -0
- package/components/Dropdown/Dropdown.js +18 -17
- package/components/DropdownMenu/DropdownMenu.css +3 -9
- package/components/DropdownMenu/DropdownMenu.js +3 -2
- package/components/FilterBar/FilterBar.css +0 -8
- package/components/FilterBar/FilterBar.js +9 -6
- package/components/GanttChart/GanttChart.css +0 -13
- package/components/GanttChart/GanttChart.js +3 -2
- package/components/Inspector/InspectorToggleSwitch.js +5 -10
- package/components/InterruptCard/InterruptCard.css +0 -12
- package/components/InterruptCard/InterruptCard.js +2 -1
- package/components/ModelPicker/ModelPicker.css +4 -45
- package/components/ModelPicker/ModelPicker.js +13 -50
- package/components/MotionSwatch/MotionSwatch.css +1 -1
- package/components/NotificationCenter/NotificationCenter.css +1 -13
- package/components/NotificationCenter/NotificationCenter.js +2 -1
- package/components/PromptSuggestions/PromptSuggestions.css +0 -11
- package/components/PromptSuggestions/PromptSuggestions.js +3 -2
- package/components/QuestionCard/QuestionCard.css +13 -22
- package/components/QuestionCard/QuestionCard.js +8 -13
- package/components/RadioButton/RadioButton.css +27 -11
- package/components/RadioButton/RadioButton.d.ts +18 -0
- package/components/RadioButton/RadioButton.js +12 -2
- package/components/RichDropdown/RichDropdown.css +0 -9
- package/components/RichDropdown/RichDropdown.js +2 -8
- package/components/SegmentedControl/SegmentedControl.css +2 -14
- package/components/SegmentedControl/SegmentedControl.d.ts +7 -0
- package/components/SegmentedControl/SegmentedControl.js +4 -2
- package/components/SelectionCard/SelectionCard.css +29 -160
- package/components/SelectionCard/SelectionCard.js +5 -35
- package/components/SidebarPanel/SidebarPanel.css +1 -1
- package/components/SourceTrail/SourceTrail.css +0 -13
- package/components/SourceTrail/SourceTrail.js +2 -1
- package/components/SpacingSwatch/SpacingSwatch.css +1 -1
- package/components/Stepper/Stepper.css +0 -13
- package/components/Stepper/Stepper.js +2 -1
- package/components/Table/Table.css +0 -22
- package/components/Table/Table.js +3 -2
- package/components/ThreadPanel/ThreadPanel.css +2 -16
- package/components/ThreadPanel/ThreadPanel.js +3 -2
- package/components/ThreadTabs/ThreadTabs.css +1 -15
- package/components/ThreadTabs/ThreadTabs.js +2 -1
- package/components/TimePicker/TimePicker.css +0 -12
- package/components/TimePicker/TimePicker.js +2 -8
- package/components/ToggleGroup/ToggleGroup.css +9 -2
- package/components/ToggleSwitch/ToggleSwitch.css +33 -27
- package/components/ToggleSwitch/ToggleSwitch.d.ts +19 -0
- package/components/ToggleSwitch/ToggleSwitch.js +17 -10
- package/components/Tooltip/Tooltip.css +33 -36
- package/components/Tooltip/Tooltip.d.ts +10 -0
- package/components/Tooltip/Tooltip.js +72 -3
- package/components/Waveform/Waveform.css +0 -12
- package/components/Waveform/Waveform.js +2 -1
- package/index.js +10 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,7 +62,13 @@ Swap the scripted transport for `createFetchTransport('/api/chat')` and the pane
|
|
|
62
62
|
|
|
63
63
|
## Set up your agent
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
The quickest start is one file: save [AGENTS.md](https://rift-ds.com/AGENTS.md) at your project root, or paste it into your agent. It holds the install, the setup, the rules, and where to look things up.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
curl -o AGENTS.md https://rift-ds.com/AGENTS.md
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For the full setup, one command teaches a coding agent the system: it installs the generated agent skills into your project and prints the MCP connect line. The skills cover the library's rules, moving existing screens onto the tokens and components, and auditing styles against them.
|
|
66
72
|
|
|
67
73
|
```bash
|
|
68
74
|
npx rift-ds init
|
|
@@ -74,7 +80,7 @@ The MCP endpoint serves the component catalogue, per-component prop APIs, the to
|
|
|
74
80
|
claude mcp add --transport http rift-ds https://rift-ds.com/api/mcp
|
|
75
81
|
```
|
|
76
82
|
|
|
77
|
-
Every component's prop contract is also plain markdown (append `.md` to its docs URL), and [llms.txt](https://rift-ds.com/llms.txt) indexes every machine surface. A theme made in the [playground](https://rift-ds.com/playground) exports as
|
|
83
|
+
Every component's prop contract is also plain markdown (append `.md` to its docs URL), and [llms.txt](https://rift-ds.com/llms.txt) indexes every machine surface. A theme made in the [playground](https://rift-ds.com/playground) exports as one AGENTS.md that carries the setup, your theme in words and its CSS, so the agent can read the look as well as the code. Then just ask: "Build a settings page with Rift components."
|
|
78
84
|
|
|
79
85
|
## Theming
|
|
80
86
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
VISUALLY HIDDEN
|
|
3
|
+
The one recipe for text that is read but not
|
|
4
|
+
seen: a status for a live region, a control's
|
|
5
|
+
spoken name, a marker beside a visual state.
|
|
6
|
+
Every component imports this sheet and uses
|
|
7
|
+
ds-visually-hidden rather than writing the
|
|
8
|
+
recipe again (scripts/validate-shared-primitives.mjs
|
|
9
|
+
fails a second copy). A hidden native input
|
|
10
|
+
that must stay focusable is not this: it
|
|
11
|
+
keeps its own rule, with the reason beside it.
|
|
12
|
+
============================================ */
|
|
13
|
+
|
|
14
|
+
.ds-visually-hidden {
|
|
15
|
+
position: absolute;
|
|
16
|
+
width: 1px;
|
|
17
|
+
height: 1px;
|
|
18
|
+
padding: 0;
|
|
19
|
+
margin: -1px;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
clip: rect(0, 0, 0, 0);
|
|
22
|
+
white-space: nowrap;
|
|
23
|
+
border: 0;
|
|
24
|
+
}
|
package/bin/rift-ds.mjs
CHANGED
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
* Zero dependencies by design: global fetch plus node:fs, so npx never
|
|
29
29
|
* installs anything beyond the package itself. SITE_ORIGIN, SKILL_NAME,
|
|
30
30
|
* MCP_SERVER_NAME and PACKAGE_NAME are stamped by build-package.mjs from
|
|
31
|
-
* scripts/brand.mjs (the one home for brand facts)
|
|
31
|
+
* scripts/brand.mjs (the one home for brand facts), and CHAT_SLUG from
|
|
32
|
+
* the chat registry, the widget page's slug; running this file
|
|
32
33
|
* straight from source fails fast rather than guessing a domain.
|
|
33
34
|
* SKILL_NAME is the library skill, kept only for --out without --skill,
|
|
34
35
|
* which has always meant that one.
|
|
@@ -41,6 +42,7 @@ const SITE_ORIGIN = 'https://rift-ds.com';
|
|
|
41
42
|
const SKILL_NAME = 'rift-design-system';
|
|
42
43
|
const MCP_SERVER_NAME = 'rift-ds';
|
|
43
44
|
const PACKAGE_NAME = 'rift-ds';
|
|
45
|
+
const CHAT_SLUG = 'ai-chat';
|
|
44
46
|
const MANIFEST_URL = `${SITE_ORIGIN}/skill/manifest.json`;
|
|
45
47
|
const DEFAULT_DIR = join('.claude', 'skills');
|
|
46
48
|
const TEMPLATES_DIR = join(dirname(fileURLToPath(import.meta.url)), 'templates', 'chat');
|
|
@@ -229,7 +231,8 @@ function initChat({ app, dryRun }) {
|
|
|
229
231
|
console.log(
|
|
230
232
|
` 4. Your layout's viewport should set interactiveWidget: "resizes-content", so the phone takeover ends above the keyboard.`
|
|
231
233
|
);
|
|
232
|
-
console.log(`\
|
|
234
|
+
console.log(`\nHow to add it, the protocol and the server options: ${SITE_ORIGIN}/docs/chat`);
|
|
235
|
+
console.log(`Every prop: ${SITE_ORIGIN}/components/${CHAT_SLUG}`);
|
|
233
236
|
}
|
|
234
237
|
|
|
235
238
|
const args = process.argv.slice(2);
|
package/chat/ChatAgentPane.css
CHANGED
|
@@ -31,12 +31,16 @@
|
|
|
31
31
|
margin: 0;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/* The chat's card surface: container fill behind a hairline, like every
|
|
35
|
+
card in the conversation. The radius stays a step under the rail's
|
|
36
|
+
--radius-600, concentric with the shell it nests in. */
|
|
34
37
|
.ds-chat-agent-pane__card {
|
|
35
38
|
display: flex;
|
|
36
39
|
flex-direction: column;
|
|
37
40
|
gap: var(--gap-200);
|
|
38
41
|
padding: var(--padding-300);
|
|
39
|
-
background-color: var(--color-bg-container-
|
|
42
|
+
background-color: var(--color-bg-container-primary);
|
|
43
|
+
border: var(--border-025) solid var(--color-bg-container-border);
|
|
40
44
|
border-radius: var(--radius-400);
|
|
41
45
|
}
|
|
42
46
|
|
package/chat/ChatWidget.css
CHANGED
|
@@ -61,29 +61,6 @@
|
|
|
61
61
|
min-height: calc(40px + var(--padding-150) * 2);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
/* The close button hugs the panel's clipped right edge, so its centred
|
|
65
|
-
bottom tooltip would lose its right cap to overflow: hidden. End-align
|
|
66
|
-
the last header tooltip to the button and walk the arrow back to the
|
|
67
|
-
button's centre (20px in, minus half the 8px arrow). */
|
|
68
|
-
.ds-chat-widget .ds-chat-header__actions .ds-tooltip:last-child .ds-tooltip__panel--bottom,
|
|
69
|
-
.ds-chat-widget__rail-actions .ds-tooltip:last-child .ds-tooltip__panel--bottom {
|
|
70
|
-
left: auto;
|
|
71
|
-
right: 0;
|
|
72
|
-
transform: translateY(-4px);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.ds-chat-widget .ds-chat-header__actions .ds-tooltip:last-child .ds-tooltip__panel--bottom.ds-tooltip__panel--visible,
|
|
76
|
-
.ds-chat-widget__rail-actions .ds-tooltip:last-child .ds-tooltip__panel--bottom.ds-tooltip__panel--visible {
|
|
77
|
-
transform: translateY(0);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.ds-chat-widget .ds-chat-header__actions .ds-tooltip:last-child .ds-tooltip__panel--bottom .ds-tooltip__arrow,
|
|
81
|
-
.ds-chat-widget__rail-actions .ds-tooltip:last-child .ds-tooltip__panel--bottom .ds-tooltip__arrow {
|
|
82
|
-
left: auto;
|
|
83
|
-
right: 16px;
|
|
84
|
-
margin-left: 0;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
64
|
/* The placement menu's wrapper is only there to catch Escape; it must not
|
|
88
65
|
become a box of its own in the header's action row. */
|
|
89
66
|
.ds-chat-widget__placement-menu {
|
|
@@ -560,19 +537,6 @@
|
|
|
560
537
|
}
|
|
561
538
|
}
|
|
562
539
|
|
|
563
|
-
/* Visually hidden, still announced. */
|
|
564
|
-
.ds-chat-widget__sr-only {
|
|
565
|
-
position: absolute;
|
|
566
|
-
width: 1px;
|
|
567
|
-
height: 1px;
|
|
568
|
-
margin: -1px;
|
|
569
|
-
padding: 0;
|
|
570
|
-
overflow: hidden;
|
|
571
|
-
clip: rect(0 0 0 0);
|
|
572
|
-
white-space: nowrap;
|
|
573
|
-
border: 0;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
540
|
/* ============================================
|
|
577
541
|
THE RAILS — the optional session-history rail (leading) and agent pane
|
|
578
542
|
(trailing). Wide widgets seat them inline; narrow ones summon the history
|
package/chat/ResponseActions.js
CHANGED
|
@@ -3,6 +3,7 @@ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { createContext, useContext, useState, useRef, useEffect } from "react";
|
|
4
4
|
import { MOTION_FEEDBACK_RESET_MS } from "../tokens/motion.js";
|
|
5
5
|
import { useChatWidget } from "./context.js";
|
|
6
|
+
import "../behaviors/visually-hidden.css";
|
|
6
7
|
const ResponseActionsLabelsContext = createContext({
|
|
7
8
|
copy: "Copy response",
|
|
8
9
|
copied: "Copied",
|
|
@@ -79,7 +80,7 @@ function ResponseActions({ turn }) {
|
|
|
79
80
|
}
|
|
80
81
|
)
|
|
81
82
|
] }),
|
|
82
|
-
/* @__PURE__ */ jsx("span", { className: "ds-
|
|
83
|
+
/* @__PURE__ */ jsx("span", { className: "ds-visually-hidden", "aria-live": "polite", children: copied ? labels.copiedAnnouncement : "" })
|
|
83
84
|
] });
|
|
84
85
|
}
|
|
85
86
|
export {
|
|
@@ -3,12 +3,17 @@
|
|
|
3
3
|
Collapsible content sections
|
|
4
4
|
============================================ */
|
|
5
5
|
|
|
6
|
+
/* The standard card surface (container fill, hairline border,
|
|
7
|
+
--radius-300), the one SelectionCard's and QuestionCard's option rows
|
|
8
|
+
share, so a collapsible section reads as a card on the page rather than
|
|
9
|
+
a hairline floating over it. */
|
|
6
10
|
.ds-accordion {
|
|
7
11
|
display: flex;
|
|
8
12
|
flex-direction: column;
|
|
9
13
|
width: 100%;
|
|
10
14
|
border: var(--border-025) solid var(--color-bg-container-border);
|
|
11
|
-
border-radius: var(--radius-
|
|
15
|
+
border-radius: var(--radius-300);
|
|
16
|
+
background-color: var(--color-bg-container-primary);
|
|
12
17
|
overflow: hidden;
|
|
13
18
|
}
|
|
14
19
|
|
|
@@ -42,14 +47,16 @@
|
|
|
42
47
|
transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
|
|
43
48
|
}
|
|
44
49
|
|
|
50
|
+
/* Hover steps the header to the secondary fill, the collapsible-section
|
|
51
|
+
convention the agent cards (AgentPlan, SourceTrail, ToolCall) set. */
|
|
45
52
|
.ds-accordion__trigger:hover {
|
|
46
|
-
background-color: var(--color-
|
|
53
|
+
background-color: var(--color-bg-container-secondary);
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
.ds-accordion__trigger:focus-visible {
|
|
50
57
|
outline: 2px solid var(--color-action-primary-bg);
|
|
51
58
|
outline-offset: -2px;
|
|
52
|
-
border-radius: var(--radius-
|
|
59
|
+
border-radius: var(--radius-300);
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
/* ============================================
|
|
@@ -229,18 +229,6 @@
|
|
|
229
229
|
this span announces it.
|
|
230
230
|
============================================ */
|
|
231
231
|
|
|
232
|
-
.ds-agent-plan__sr {
|
|
233
|
-
position: absolute;
|
|
234
|
-
width: 1px;
|
|
235
|
-
height: 1px;
|
|
236
|
-
padding: 0;
|
|
237
|
-
margin: -1px;
|
|
238
|
-
overflow: hidden;
|
|
239
|
-
clip: rect(0, 0, 0, 0);
|
|
240
|
-
white-space: nowrap;
|
|
241
|
-
border: 0;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
232
|
/* Icons take the colour of the text around them. Explicit, not just
|
|
245
233
|
inherited by default: a consumer stylesheet that sets a colour on
|
|
246
234
|
.material-symbols-rounded itself (a common global default) would
|
|
@@ -3,6 +3,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import React, { useId, useState, useCallback } from "react";
|
|
4
4
|
import { Spinner } from "../Spinner/Spinner.js";
|
|
5
5
|
import "./AgentPlan.css";
|
|
6
|
+
import "../../behaviors/visually-hidden.css";
|
|
6
7
|
import "../../fonts/material-symbols.css";
|
|
7
8
|
const STEP_ICONS = {
|
|
8
9
|
pending: "circle",
|
|
@@ -88,7 +89,7 @@ const AgentPlan = React.forwardRef(
|
|
|
88
89
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: step.label }),
|
|
89
90
|
step.detail && /* @__PURE__ */ jsx("span", { className: `${baseClass}__detail`, children: step.detail })
|
|
90
91
|
] }),
|
|
91
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
92
|
+
/* @__PURE__ */ jsx("span", { className: "ds-visually-hidden", children: statusText[status] })
|
|
92
93
|
]
|
|
93
94
|
},
|
|
94
95
|
index
|
|
@@ -219,7 +219,7 @@
|
|
|
219
219
|
display: flex;
|
|
220
220
|
width: 100%;
|
|
221
221
|
padding: var(--padding-150) var(--padding-300);
|
|
222
|
-
background-color: var(--color-bg-container-
|
|
222
|
+
background-color: var(--color-bg-container-primary);
|
|
223
223
|
border: var(--border-025) solid var(--color-bg-container-border);
|
|
224
224
|
border-radius: var(--radius-300);
|
|
225
225
|
}
|
|
@@ -17,15 +17,3 @@
|
|
|
17
17
|
font-variant-numeric: tabular-nums;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
/* Visually hidden settled value — what a screen reader gets instead of the
|
|
21
|
-
rolling digits. */
|
|
22
|
-
.ds-animated-number__sr {
|
|
23
|
-
position: absolute;
|
|
24
|
-
width: 1px;
|
|
25
|
-
height: 1px;
|
|
26
|
-
margin: -1px;
|
|
27
|
-
padding: 0;
|
|
28
|
-
overflow: hidden;
|
|
29
|
-
clip-path: inset(50%);
|
|
30
|
-
white-space: nowrap;
|
|
31
|
-
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
3
|
import React, { useState, useRef, useEffect } from "react";
|
|
4
4
|
import "./AnimatedNumber.css";
|
|
5
|
+
import "../../behaviors/visually-hidden.css";
|
|
5
6
|
import { MOTION_COUNT_UP_MS } from "../../tokens/motion.js";
|
|
6
7
|
const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
7
8
|
const prefersReducedMotion = () => typeof window !== "undefined" && window.matchMedia(REDUCED_MOTION_QUERY).matches;
|
|
@@ -45,7 +46,7 @@ const AnimatedNumber = React.forwardRef(
|
|
|
45
46
|
const classes = [baseClass, className].filter(Boolean).join(" ");
|
|
46
47
|
return /* @__PURE__ */ jsxs("span", { ...rest, ref, className: classes, children: [
|
|
47
48
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__value`, "aria-hidden": "true", children: fmt(display) }),
|
|
48
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
49
|
+
/* @__PURE__ */ jsx("span", { className: "ds-visually-hidden", children: fmt(value) })
|
|
49
50
|
] });
|
|
50
51
|
}
|
|
51
52
|
);
|
|
@@ -211,7 +211,7 @@
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
.ds-app-sidebar__btn--active {
|
|
214
|
-
background-color: var(--color-action-passive-bg-
|
|
214
|
+
background-color: var(--color-action-passive-bg-active);
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
.ds-app-sidebar__btn-left {
|
|
@@ -357,7 +357,7 @@
|
|
|
357
357
|
}
|
|
358
358
|
|
|
359
359
|
.ds-app-sidebar__sub-btn--active {
|
|
360
|
-
background-color: var(--color-action-passive-bg-
|
|
360
|
+
background-color: var(--color-action-passive-bg-active);
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
.ds-app-sidebar__sub-label {
|
|
@@ -481,23 +481,6 @@ button.ds-attachment-tile__body:focus-visible,
|
|
|
481
481
|
outline-offset: 2px;
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
-
/* ============================================
|
|
485
|
-
VISUALLY HIDDEN
|
|
486
|
-
============================================ */
|
|
487
|
-
|
|
488
|
-
.ds-attachment-tile__sr-only,
|
|
489
|
-
.ds-attachment-group__sr-only {
|
|
490
|
-
position: absolute;
|
|
491
|
-
width: 1px;
|
|
492
|
-
height: 1px;
|
|
493
|
-
padding: 0;
|
|
494
|
-
margin: -1px;
|
|
495
|
-
overflow: hidden;
|
|
496
|
-
clip: rect(0, 0, 0, 0);
|
|
497
|
-
white-space: nowrap;
|
|
498
|
-
border: 0;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
484
|
/* ============================================
|
|
502
485
|
REDUCED MOTION
|
|
503
486
|
The global guard collapses the spin to a still arc, which still reads as
|
|
@@ -5,6 +5,7 @@ import { formatBytes, getFileExtension, getFileKind, getFileTypeLabel, matchesAc
|
|
|
5
5
|
import { renderTypeMark } from "./typeMark.js";
|
|
6
6
|
import "../../fonts/material-symbols.css";
|
|
7
7
|
import "./Attachment.css";
|
|
8
|
+
import "../../behaviors/visually-hidden.css";
|
|
8
9
|
const AttachmentTile = React.forwardRef(
|
|
9
10
|
({
|
|
10
11
|
name,
|
|
@@ -97,7 +98,7 @@ const AttachmentTile = React.forwardRef(
|
|
|
97
98
|
const stack = /* @__PURE__ */ jsxs("span", { className: `${baseClass}__stack`, children: [
|
|
98
99
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__mark`, children: mark }),
|
|
99
100
|
/* @__PURE__ */ jsxs("span", { className: `${baseClass}__name`, title: name, children: [
|
|
100
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
101
|
+
/* @__PURE__ */ jsx("span", { className: "ds-visually-hidden", children: name }),
|
|
101
102
|
head !== "" && /* @__PURE__ */ jsx("span", { className: `${baseClass}__name-head`, "aria-hidden": "true", children: head }),
|
|
102
103
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__name-tail`, "aria-hidden": "true", children: tail })
|
|
103
104
|
] }),
|
|
@@ -111,7 +112,7 @@ const AttachmentTile = React.forwardRef(
|
|
|
111
112
|
] });
|
|
112
113
|
} else if (showExcerpt) {
|
|
113
114
|
content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
114
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
115
|
+
/* @__PURE__ */ jsx("span", { className: "ds-visually-hidden", children: name }),
|
|
115
116
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__excerpt`, children: excerpt }),
|
|
116
117
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__corner`, children: cornerMark })
|
|
117
118
|
] });
|
|
@@ -141,15 +141,6 @@
|
|
|
141
141
|
padding: 0;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
.ds-bottom-nav__sr {
|
|
145
|
-
position: absolute;
|
|
146
|
-
width: 1px;
|
|
147
|
-
height: 1px;
|
|
148
|
-
overflow: hidden;
|
|
149
|
-
clip-path: inset(50%);
|
|
150
|
-
white-space: nowrap;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
144
|
.ds-bottom-nav__search {
|
|
154
145
|
display: none;
|
|
155
146
|
}
|
|
@@ -3,6 +3,7 @@ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useLinkComponent } from "../../behaviors/LinkProvider.js";
|
|
5
5
|
import "./BottomNav.css";
|
|
6
|
+
import "../../behaviors/visually-hidden.css";
|
|
6
7
|
import "../../fonts/material-symbols.css";
|
|
7
8
|
const defaultBadgeLabel = (badge) => badge === true ? ", new" : `, ${badge} new`;
|
|
8
9
|
const BottomNav = React.forwardRef(
|
|
@@ -60,7 +61,7 @@ const BottomNav = React.forwardRef(
|
|
|
60
61
|
renderBadge(item.badge)
|
|
61
62
|
] }),
|
|
62
63
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: item.label }),
|
|
63
|
-
badgeText && /* @__PURE__ */ jsx("span", { className:
|
|
64
|
+
badgeText && /* @__PURE__ */ jsx("span", { className: "ds-visually-hidden", children: badgeText })
|
|
64
65
|
] });
|
|
65
66
|
const handleClick = () => {
|
|
66
67
|
item.onClick?.();
|
|
@@ -93,14 +93,3 @@
|
|
|
93
93
|
|
|
94
94
|
/* Screen-reader announcement of the deck position. */
|
|
95
95
|
|
|
96
|
-
.ds-card-stack__sr-only {
|
|
97
|
-
position: absolute;
|
|
98
|
-
width: 1px;
|
|
99
|
-
height: 1px;
|
|
100
|
-
padding: 0;
|
|
101
|
-
margin: -1px;
|
|
102
|
-
overflow: hidden;
|
|
103
|
-
clip: rect(0, 0, 0, 0);
|
|
104
|
-
white-space: nowrap;
|
|
105
|
-
border: 0;
|
|
106
|
-
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
3
|
import React, { useState, useRef, useCallback } from "react";
|
|
4
4
|
import "./CardStack.css";
|
|
5
|
+
import "../../behaviors/visually-hidden.css";
|
|
5
6
|
const INTERACTIVE_SELECTOR = 'a, button, input, select, textarea, summary, [role="button"], [role="link"], [tabindex]';
|
|
6
7
|
const NEXT_KEYS = /* @__PURE__ */ new Set(["ArrowRight", "ArrowDown", " ", "Enter"]);
|
|
7
8
|
const PREV_KEYS = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowUp"]);
|
|
@@ -124,7 +125,7 @@ const CardStack = React.forwardRef(
|
|
|
124
125
|
k
|
|
125
126
|
);
|
|
126
127
|
}),
|
|
127
|
-
count > 1 && /* @__PURE__ */ jsx("div", { className:
|
|
128
|
+
count > 1 && /* @__PURE__ */ jsx("div", { className: "ds-visually-hidden", role: "status", children: positionLabel(index + 1, count) })
|
|
128
129
|
]
|
|
129
130
|
}
|
|
130
131
|
);
|
|
@@ -321,18 +321,6 @@
|
|
|
321
321
|
The pending label is for screen readers only.
|
|
322
322
|
============================================ */
|
|
323
323
|
|
|
324
|
-
.ds-chat-message__sr-only {
|
|
325
|
-
position: absolute;
|
|
326
|
-
width: 1px;
|
|
327
|
-
height: 1px;
|
|
328
|
-
padding: 0;
|
|
329
|
-
margin: -1px;
|
|
330
|
-
overflow: hidden;
|
|
331
|
-
clip: rect(0, 0, 0, 0);
|
|
332
|
-
white-space: nowrap;
|
|
333
|
-
border: 0;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
324
|
/* ============================================
|
|
337
325
|
REDUCED MOTION
|
|
338
326
|
The global guard collapses the loop to its
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import "./ChatMessage.css";
|
|
4
|
+
import "../../behaviors/visually-hidden.css";
|
|
4
5
|
const ChatMessage = React.forwardRef(
|
|
5
6
|
({
|
|
6
7
|
role = "assistant",
|
|
@@ -55,7 +56,7 @@ const ChatMessage = React.forwardRef(
|
|
|
55
56
|
] }),
|
|
56
57
|
attachments && /* @__PURE__ */ jsx("div", { className: `${baseClass}__attachments`, children: attachments }),
|
|
57
58
|
showContent && /* @__PURE__ */ jsx("div", { className: `${baseClass}__content`, children: pending ? /* @__PURE__ */ jsxs("span", { className: `${baseClass}__pending`, role: "status", children: [
|
|
58
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
59
|
+
/* @__PURE__ */ jsx("span", { className: "ds-visually-hidden", children: pendingLabel }),
|
|
59
60
|
/* @__PURE__ */ jsxs("span", { className: `${baseClass}__dots`, "aria-hidden": "true", children: [
|
|
60
61
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__dot` }),
|
|
61
62
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__dot` }),
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
/* ============================================
|
|
2
2
|
CHECKBOX COMPONENT
|
|
3
|
-
Custom checkbox with check / indeterminate icon
|
|
3
|
+
Custom checkbox with check / indeterminate icon.
|
|
4
|
+
The box is CheckboxIndicator, a presentational
|
|
5
|
+
piece every host that offers a checkbox draws
|
|
6
|
+
(Checkbox itself, SelectionCard, QuestionCard,
|
|
7
|
+
FilterBar's multi-select rows): its state is
|
|
8
|
+
keyed on the box's own modifiers, so a host
|
|
9
|
+
needs no classes of its own to show it, and a
|
|
10
|
+
host that carries the ds-control-host class
|
|
11
|
+
lights it on hover.
|
|
4
12
|
============================================ */
|
|
5
13
|
|
|
6
14
|
.ds-checkbox {
|
|
@@ -12,7 +20,7 @@
|
|
|
12
20
|
}
|
|
13
21
|
|
|
14
22
|
/* ============================================
|
|
15
|
-
BOX
|
|
23
|
+
BOX — CheckboxIndicator
|
|
16
24
|
============================================ */
|
|
17
25
|
|
|
18
26
|
.ds-checkbox__box {
|
|
@@ -20,10 +28,10 @@
|
|
|
20
28
|
width: 24px;
|
|
21
29
|
height: 24px;
|
|
22
30
|
box-sizing: border-box;
|
|
23
|
-
border: var(--border-050) solid var(--color-
|
|
31
|
+
border: var(--border-050) solid var(--color-input-border-primary);
|
|
24
32
|
border-radius: var(--radius-200); /* 8px */
|
|
25
|
-
background-color: var(--color-bg-
|
|
26
|
-
display: flex;
|
|
33
|
+
background-color: var(--color-input-bg-primary);
|
|
34
|
+
display: inline-flex;
|
|
27
35
|
align-items: center;
|
|
28
36
|
justify-content: center;
|
|
29
37
|
flex-shrink: 0;
|
|
@@ -82,48 +90,49 @@
|
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
/* ============================================
|
|
85
|
-
CHECKED
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
.ds-checkbox--checked .ds-checkbox__box {
|
|
89
|
-
background-color: var(--color-action-primary-bg);
|
|
90
|
-
border-color: var(--color-action-primary-bg);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.ds-checkbox--checked .ds-checkbox__icon {
|
|
94
|
-
opacity: 1;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/* ============================================
|
|
98
|
-
INDETERMINATE STATE
|
|
93
|
+
CHECKED and INDETERMINATE STATES
|
|
94
|
+
Keyed on the box, so an indicator drawn by
|
|
95
|
+
another host shows the same states.
|
|
99
96
|
============================================ */
|
|
100
97
|
|
|
101
|
-
.ds-
|
|
98
|
+
.ds-checkbox__box--checked,
|
|
99
|
+
.ds-checkbox__box--indeterminate {
|
|
102
100
|
background-color: var(--color-action-primary-bg);
|
|
103
101
|
border-color: var(--color-action-primary-bg);
|
|
104
102
|
}
|
|
105
103
|
|
|
106
|
-
.ds-
|
|
104
|
+
.ds-checkbox__box--checked .ds-checkbox__icon,
|
|
105
|
+
.ds-checkbox__box--indeterminate .ds-checkbox__icon {
|
|
107
106
|
opacity: 1;
|
|
108
107
|
}
|
|
109
108
|
|
|
110
109
|
/* ============================================
|
|
111
110
|
HOVER STATE
|
|
111
|
+
Any host carrying ds-control-host lights the
|
|
112
|
+
box when it is hovered and not disabled.
|
|
112
113
|
============================================ */
|
|
113
114
|
|
|
114
|
-
.ds-
|
|
115
|
+
.ds-control-host:not(:disabled):not([aria-disabled='true']):hover .ds-checkbox__box {
|
|
115
116
|
border-color: var(--color-action-primary-bg);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
.ds-
|
|
119
|
+
.ds-control-host:not(:disabled):not([aria-disabled='true']):hover .ds-checkbox__box--checked,
|
|
120
|
+
.ds-control-host:not(:disabled):not([aria-disabled='true']):hover .ds-checkbox__box--indeterminate {
|
|
119
121
|
background-color: var(--color-action-primary-bg-hover);
|
|
120
122
|
border-color: var(--color-action-primary-bg-hover);
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
/* ============================================
|
|
124
126
|
FOCUS STATE
|
|
127
|
+
The standalone control rings its own box; a
|
|
128
|
+
host that is itself the target (a card, a
|
|
129
|
+
row) rings its own edge instead.
|
|
125
130
|
============================================ */
|
|
126
131
|
|
|
132
|
+
.ds-checkbox:focus-visible {
|
|
133
|
+
outline: none;
|
|
134
|
+
}
|
|
135
|
+
|
|
127
136
|
.ds-checkbox:focus-visible .ds-checkbox__box {
|
|
128
137
|
outline: 2px solid var(--color-action-primary-bg);
|
|
129
138
|
outline-offset: 2px;
|
|
@@ -142,12 +151,12 @@
|
|
|
142
151
|
SIZE — COMPACT
|
|
143
152
|
============================================ */
|
|
144
153
|
|
|
145
|
-
.ds-
|
|
154
|
+
.ds-checkbox__box--compact {
|
|
146
155
|
width: 20px;
|
|
147
156
|
height: 20px;
|
|
148
157
|
}
|
|
149
158
|
|
|
150
|
-
.ds-
|
|
159
|
+
.ds-checkbox__box--compact .ds-checkbox__icon {
|
|
151
160
|
width: 12px;
|
|
152
161
|
height: 12px;
|
|
153
162
|
}
|
|
@@ -88,4 +88,38 @@ type CheckboxGroupOwnProps = {
|
|
|
88
88
|
export interface CheckboxGroupProps extends CheckboxGroupOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof CheckboxGroupOwnProps> {
|
|
89
89
|
}
|
|
90
90
|
export declare const CheckboxGroup: React.ForwardRefExoticComponent<CheckboxGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
91
|
+
/** Props owned by CheckboxIndicator itself — everything else falls through to the <span>. */
|
|
92
|
+
type CheckboxIndicatorOwnProps = {
|
|
93
|
+
/** Whether the box shows its check. */
|
|
94
|
+
checked?: boolean;
|
|
95
|
+
/** Whether the box shows the minus of an indeterminate state (ignored when `checked`). */
|
|
96
|
+
indeterminate?: boolean;
|
|
97
|
+
/** Box size: `default` is 24px, `compact` 20px. */
|
|
98
|
+
size?: 'default' | 'compact';
|
|
99
|
+
/** Additional CSS classes */
|
|
100
|
+
className?: string;
|
|
101
|
+
};
|
|
102
|
+
export interface CheckboxIndicatorProps extends CheckboxIndicatorOwnProps, Omit<React.ComponentPropsWithoutRef<'span'>, keyof CheckboxIndicatorOwnProps | 'children'> {
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The checkbox's box, as a presentational piece for a host that is itself
|
|
106
|
+
* the control: SelectionCard's checkbox mode, QuestionCard's multi rows and
|
|
107
|
+
* FilterBar's multi-select options draw it, so a checkbox looks the same
|
|
108
|
+
* wherever a choice is offered. Hidden from assistive technology; the host
|
|
109
|
+
* carries `role="checkbox"` or `aria-selected` and the state. A host that
|
|
110
|
+
* adds the `ds-control-host` class to its interactive root lights the box
|
|
111
|
+
* on hover, the way Checkbox does.
|
|
112
|
+
*/
|
|
113
|
+
export declare const CheckboxIndicator: React.ForwardRefExoticComponent<CheckboxIndicatorProps & React.RefAttributes<HTMLSpanElement>>;
|
|
114
|
+
/** Props owned by the glyphs themselves — everything else falls through to the <svg>. */
|
|
115
|
+
type ControlGlyphOwnProps = {
|
|
116
|
+
/** Additional CSS classes; the default is the checkbox icon's, which sizes and colours it. */
|
|
117
|
+
className?: string;
|
|
118
|
+
};
|
|
119
|
+
export interface ControlGlyphProps extends ControlGlyphOwnProps, Omit<React.ComponentPropsWithoutRef<'svg'>, keyof ControlGlyphOwnProps | 'children'> {
|
|
120
|
+
}
|
|
121
|
+
/** The check glyph. */
|
|
122
|
+
export declare const CheckIcon: React.ForwardRefExoticComponent<ControlGlyphProps & React.RefAttributes<SVGSVGElement>>;
|
|
123
|
+
/** The minus glyph, for an indeterminate checkbox. */
|
|
124
|
+
export declare const MinusIcon: React.ForwardRefExoticComponent<ControlGlyphProps & React.RefAttributes<SVGSVGElement>>;
|
|
91
125
|
export {};
|