@primitiv-ui/react 0.1.30 → 0.1.32

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primitiv-ui/react",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "Headless, accessible React components built on the WAI-ARIA authoring patterns. Zero styles ship with this package — bring your own (CSS, Tailwind, CSS-in-JS, design tokens).",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -27,7 +27,7 @@ import { RadioCard } from "@primitiv-ui/react";
27
27
  | Export | Element | ARIA / data hooks | `asChild` |
28
28
  |--------|---------|------------------|-----------|
29
29
  | `RadioCard.Root` | `<div>` | `role="radiogroup"` | yes |
30
- | `RadioCard.Item` | `<button>` | `role="radio"`, `aria-checked`, `data-state`, `tabIndex` | yes |
30
+ | `RadioCard.Item` | `<button>` | `role="radio"`, `aria-checked`, `data-state`, `data-disabled`, `tabIndex` | yes |
31
31
  | `RadioCard.Indicator` | `<span>` | `aria-hidden="true"`, `data-state` | yes |
32
32
 
33
33
  ## State modes
@@ -131,3 +131,4 @@ to keep it in the DOM — `data-state="unchecked"` lets a CSS exit animation pla
131
131
  | Attribute | Values | Set on |
132
132
  |-----------|--------|--------|
133
133
  | `data-state` | `"checked"` \| `"unchecked"` | `RadioCard.Item`, `RadioCard.Indicator` |
134
+ | `data-disabled` | `""` (present only while disabled) | `RadioCard.Item` |
@@ -157,8 +157,10 @@ RadioCardRoot.displayName = "RadioCardRoot";
157
157
  * excludes the Item from arrow-key navigation and the roving-tabindex
158
158
  * home base.
159
159
  *
160
- * **Styling hook.** `data-state="checked" | "unchecked"` mirrors the
161
- * selection state for CSS targeting.
160
+ * **Styling hooks.** `data-state="checked" | "unchecked"` mirrors the
161
+ * selection state, and `data-disabled=""` is present while disabled — the
162
+ * same pair `CheckboxCard.Root` publishes, so one stylesheet can dress
163
+ * both.
162
164
  *
163
165
  * **`asChild` prop.** Pass `asChild` to render any consumer element with
164
166
  * the Item's ARIA, data-state, tabIndex, onClick, onKeyDown, disabled, and
@@ -223,6 +225,7 @@ export function RadioCardItem({
223
225
  role: "radio" as const,
224
226
  "aria-checked": isChecked,
225
227
  "data-state": isChecked ? ("checked" as const) : ("unchecked" as const),
228
+ "data-disabled": disabled ? "" : undefined,
226
229
  tabIndex: isTabStop ? 0 : -1,
227
230
  disabled,
228
231
  onClick: composeEventHandlers(onClick, () => select(value)),
@@ -18,6 +18,29 @@ describe("RadioCard disabled items", () => {
18
18
  expect(screen.getByRole("radio", { name: "Starter" })).toBeDisabled();
19
19
  });
20
20
 
21
+ /*
22
+ * The styling hook, not just the native attribute. `[data-disabled]` is what
23
+ * the registry stylesheet keys the dimmed look off — the same hook
24
+ * `CheckboxCard.Root` already publishes — so without it the shipped disabled
25
+ * treatment silently never applies (found by measuring: a disabled RadioCard
26
+ * rendered at opacity 1 while a disabled CheckboxCard correctly dimmed).
27
+ */
28
+ it('sets data-disabled="" on a disabled item, and omits it otherwise', () => {
29
+ // Arrange & Act
30
+ render(
31
+ <RadioCard.Root aria-label="Plan">
32
+ <RadioCard.Item value="starter" disabled>
33
+ Starter
34
+ </RadioCard.Item>
35
+ <RadioCard.Item value="pro">Pro</RadioCard.Item>
36
+ </RadioCard.Root>,
37
+ );
38
+
39
+ // Assert
40
+ expect(screen.getByRole("radio", { name: "Starter" })).toHaveAttribute("data-disabled", "");
41
+ expect(screen.getByRole("radio", { name: "Pro" })).not.toHaveAttribute("data-disabled");
42
+ });
43
+
21
44
  it("does not change selection when a disabled item is clicked", async () => {
22
45
  // Arrange
23
46
  const user = userEvent.setup();