cssints 0.14.0 → 0.15.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/docs/API.md +43 -0
- package/package.json +2 -2
package/docs/API.md
CHANGED
|
@@ -1291,6 +1291,49 @@ createConfirm(options?: { id?: string | undefined; onOpenChange?(open: boolean):
|
|
|
1291
1291
|
|
|
1292
1292
|
`confirm()` resolves `true` on confirm and `false` on cancel, Escape and a backdrop click. A second request while one is pending rejects with `ConfirmPendingError` (it is not queued). Focus goes to the cancel button on open and back to the element that had it when `confirm()` was called. While it is open the dialog has a shell: Tab and Shift+Tab cycle inside it, `overflow: hidden` is set on `document.documentElement` (restored on close; counted, so nested confirms restore it once), and Escape is read from the document in the capture phase, so it works with the focus outside the dialog. Confirms from different `createConfirm` calls may be open together: the last opened gets Escape and Tab. The default labels stay English; a translating host passes `confirmLabel` and `cancelLabel` with each request.
|
|
1293
1293
|
|
|
1294
|
+
### Headless: `createToast` and `createStatus` (`@cssints/headless`)
|
|
1295
|
+
|
|
1296
|
+
Two live regions with no APG pattern and no Quint spec: `createStatus` is one polite message whose text is replaced, `createToast` queues toasts whose countdown pauses. Their oracle is `packages/headless/test/toast.browser.test.tsx`.
|
|
1297
|
+
|
|
1298
|
+
```ts skip
|
|
1299
|
+
createStatus(options?: { id?: string | undefined }): {
|
|
1300
|
+
message(): string | undefined;
|
|
1301
|
+
show(text: string): void; // replaces the text; nothing is queued
|
|
1302
|
+
clear(): void;
|
|
1303
|
+
statusProps: { id; role: "status"; "aria-live": "polite"; "aria-atomic": "true" };
|
|
1304
|
+
};
|
|
1305
|
+
|
|
1306
|
+
createToast(options?: {
|
|
1307
|
+
timeout?: number | undefined; // ms, 5000; 0 dismisses on the next tick
|
|
1308
|
+
max?: number | undefined; // visible toasts, 3; a new one past it drops the oldest
|
|
1309
|
+
pauseOnHover?: boolean | undefined; // true; focus always pauses
|
|
1310
|
+
labels?: { region?: string | undefined } | undefined; // "Notifications"
|
|
1311
|
+
onDismiss?(id: string): void; // every departure: timeout, dismiss, dismissAll, ceiling
|
|
1312
|
+
}): {
|
|
1313
|
+
toasts(): readonly ToastItem[]; // oldest first
|
|
1314
|
+
show(input: {
|
|
1315
|
+
title: string;
|
|
1316
|
+
description?: string | undefined;
|
|
1317
|
+
tone?: "info" | "success" | "error" | undefined; // "info"
|
|
1318
|
+
}): string; // the id
|
|
1319
|
+
dismiss(id: string): void;
|
|
1320
|
+
dismissAll(): void;
|
|
1321
|
+
regionProps: { role: "region"; "aria-label": string }; // the F6 target
|
|
1322
|
+
toastProps(id: string): {
|
|
1323
|
+
role: "alert" | "status"; // "alert" for tone "error", "status" otherwise
|
|
1324
|
+
"aria-atomic": "true";
|
|
1325
|
+
onMouseEnter(): void;
|
|
1326
|
+
onMouseLeave(): void;
|
|
1327
|
+
onFocusIn(): void;
|
|
1328
|
+
onFocusOut(): void;
|
|
1329
|
+
};
|
|
1330
|
+
};
|
|
1331
|
+
```
|
|
1332
|
+
|
|
1333
|
+
`createStatus` renders one `role=status` region that the host keeps mounted; `show()` replaces its text, so a burst of "Link copied" / "Saved" reads as the last state, not as a queue. A status is never for errors: an error is `createAlert` (`role=alert`), and a titled message with a timeout is a toast.
|
|
1334
|
+
|
|
1335
|
+
A toast is its own live region inside the `role=region` landmark: `role=alert` for `tone: "error"` (assertive) and `role=status` otherwise (polite). The host renders the `title` and `description` handed to `show` inside that element, so the toast's own text is the announcement — `aria-atomic` reads all of it, a close button's label included, so keep a toast to its title and description and give a close button no more than an icon with a label. The role sits on the toast rather than on one container per tone: the container is the `region` landmark, so it cannot also be the live region, and a role per toast needs no second region from the host. One timer per toast honours `timeout`; hover pauses it when `pauseOnHover` is true and focus always pauses, and both resume with the time that was left rather than restarting the deadline. `max` drops the oldest toast past the ceiling, and `onDismiss` fires for every toast that leaves. F6 into the region is the host's handler (hotkeys are a separate bean, cssints-h0d5): give `regionProps` an element with `tabindex="-1"` and focus it, remembering where focus was.
|
|
1336
|
+
|
|
1294
1337
|
### Headless: `createPopover` (`@cssints/headless`)
|
|
1295
1338
|
|
|
1296
1339
|
**No APG pattern exists** for a popover (APG has Dialog, which is modal), so it has no Quint spec and no ported scenarios: `packages/headless/test/popover.browser.test.tsx` is its oracle. The behaviour is copied from Base UI's Popover (a trigger click toggles, Enter / Space / ArrowDown open, an outside `pointerdown` light-dismisses without stealing focus) and React Aria's `usePopover` (focus into the content on open and back to the trigger on close, `role="dialog"` without `aria-modal`, a placement that flips at the viewport edge).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cssints",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "CSS in TypeScript: typed css.* calls compiled to atomic CSS at build time (a Vite plugin)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@cssints/css-grammar": "^0.
|
|
75
|
+
"@cssints/css-grammar": "^0.15.0",
|
|
76
76
|
"culori": "^4.0.2",
|
|
77
77
|
"effect": "4.0.6",
|
|
78
78
|
"happy-dom": "^20.14.5",
|