@clicktap/ui 1.0.2 → 1.1.1

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.
@@ -1 +1 @@
1
- "use client";import{jsx as o}from"react/jsx-runtime";import{Link as u}from"react-aria-components";import{cn as i}from"../../utils/cn.js";function c({children:e,className:r,...t}){return o(u,{className:i("text-slate-600 no-underline cursor-pointer","focus-visible:outline-2 focus-visible:outline focus-visible:outline-border-subtle","hover:text-fg hover:underline","current:cursor-default current:text-fg current:font-semibold","disabled:cursor-default disabled:text-fg-subtle disabled:current:text-fg",r),...t,children:e})}export{c as BreadcrumbLink,c as default};
1
+ "use client";import{jsx as u}from"react/jsx-runtime";import{Link as o}from"react-aria-components";import{cn as i}from"../../utils/cn.js";function f({children:e,className:r,...t}){return u(o,{className:i("text-fg-muted no-underline cursor-pointer","focus-visible:outline-2 focus-visible:outline focus-visible:outline-border-subtle","hover:text-fg hover:underline","current:cursor-default current:text-fg current:font-semibold","disabled:cursor-default disabled:text-fg-subtle disabled:current:text-fg",r),...t,children:e})}export{f as BreadcrumbLink,f as default};
@@ -1 +1 @@
1
- "use client";import{jsx as e}from"react/jsx-runtime";import{Breadcrumb as i}from"react-aria-components";import{cn as n}from"../../utils/cn.js";function c({children:r,className:t,...o}){return e(i,{className:n("flex items-center text-slate-600","my-0 mx-2",t),...o,children:r??e("svg",{"aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",className:"w-4 h-4",children:e("path",{d:"M6 12L10 8L6 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})}export{c as BreadcrumbSeparator,c as default};
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import{Breadcrumb as i}from"react-aria-components";import{cn as n}from"../../utils/cn.js";function d({children:r,className:t,...o}){return e(i,{className:n("flex items-center text-fg-muted","my-0 mx-2",t),...o,children:r??e("svg",{"aria-hidden":"true",xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",className:"w-4 h-4",children:e("path",{d:"M6 12L10 8L6 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})}export{d as BreadcrumbSeparator,d as default};
@@ -5,6 +5,7 @@
5
5
  **Affects:** every consumer — the peer ranges are the declaration your package manager installs against.
6
6
  **Classification:** COMPATIBILITY
7
7
  **Breaking:** Yes for a consumer already past a ceiling. No code change; the contract narrowed.
8
+ **Read before updating:** the capped ranges are the contract your install resolves against — decide before taking `@clicktap/ui` 1.x, not after
8
9
  **Ticket:** CTAP-1241
9
10
 
10
11
  ## Summary
@@ -53,6 +54,35 @@ in your own app, confirm it matches what `@clicktap/ui` resolves. The split abov
53
54
  without symptoms, and duplicate react-aria/stately instances surface as subtle focus and overlay bugs
54
55
  rather than as an error.
55
56
 
57
+ ### When the duplicate is transitive — nothing of yours to pin
58
+
59
+ The paragraph above assumes the second copy comes from a declaration you own. Often it does not:
60
+ crispi resolves `react-stately` 3.49.0 cleanly across every workspace member and still carries a
61
+ second copy at 3.46.0, arriving via `@adobe/react-spectrum` → `react-aria-components`. No manifest of
62
+ theirs names it, so there is no pin to correct.
63
+
64
+ Decide it in this order:
65
+
66
+ 1. **Ask whether the two copies ever share a context.** The hazard is not two versions existing; it
67
+ is two versions of the same *provider* — `@react-aria/overlays`' focus scope and dismiss stack,
68
+ most of all — being live in one tree at once. Two design systems that each portal their own
69
+ overlays, never nesting one inside the other, can hold separate copies indefinitely. Two copies
70
+ reached through the same `OverlayProvider` cannot.
71
+ 2. **If they do share one, force a single resolution with `pnpm.overrides`:**
72
+ ```json
73
+ { "pnpm": { "overrides": { "react-stately": "3.49.0" } } }
74
+ ```
75
+ A bare-name override collapses every copy in the tree whatever any package declares. Verify with
76
+ `pnpm why react-stately` and then exercise the *other* library's overlays — you have moved it onto
77
+ a version it did not choose, which is the cost of this lever.
78
+ 3. **If they do not, record the decision and move on.** `@clicktap/ui` externalizes `react-stately`
79
+ and `@react-stately/*`, so the copy under a foreign design system is never the copy this package
80
+ imports.
81
+
82
+ What you should not do is leave the check unresolved either way. A duplicate you have decided is
83
+ harmless is a different state from one you have not looked at, and only the first survives the next
84
+ person reading `pnpm why`.
85
+
56
86
  ## Verify
57
87
 
58
88
  ```bash
@@ -0,0 +1,80 @@
1
+ # The breadcrumb trail is fully tokenised, so a dark-ground app can re-theme it
2
+
3
+ **Date:** 2026-08-14
4
+ **Package:** `@clicktap/ui`
5
+ **Affects:** any consumer rendering `Breadcrumbs` — and, for the diagnosis below, any consumer on a
6
+ dark ground.
7
+ **Classification:** BUGFIX
8
+ **Breaking:** No. One small visual change in light mode: the ancestor crumbs and the chevron move
9
+ from `slate-600` to the `fg-muted` token (`slate-500`), one step lighter. The current crumb is
10
+ unchanged.
11
+
12
+ ## What was wrong
13
+
14
+ `BreadcrumbLink` and `BreadcrumbSeparator` still carried a literal `text-slate-600` — residue from
15
+ the CTAP-1123 token sweep. A literal palette class cannot be re-themed at all: a consumer overriding
16
+ `--color-fg-muted` for a dark ground got no effect on the trail, because nothing in it read that
17
+ token.
18
+
19
+ Both now use `text-fg-muted`, so the whole trail re-themes with the rest of the library.
20
+
21
+ ## The reported symptom, and what actually causes it
22
+
23
+ The report (CTAP-1304) was that the **current** crumb is illegible on a dark ground — roughly
24
+ 1.2:1 against a black body. That crumb is styled `current:text-fg`, which is already a token, so
25
+ this fix does not change it. The cause is one level up:
26
+
27
+ > `@clicktap/ui` ships **light** token defaults and deliberately does not assume a ground. Re-theming
28
+ > is a runtime override of the tokens — see the top of `theme.css`.
29
+
30
+ An app that paints `body { background-color: #000 }` without overriding `--color-fg` gets
31
+ `slate-900` text on black. That is not specific to breadcrumbs: **`text-fg` appears 132 times across
32
+ 39 components**, so the same app has the same problem everywhere. Breadcrumbs is simply where QA
33
+ noticed, because the current crumb is the item you most expect to stand out.
34
+
35
+ The fix on the consumer side is two lines, and it repairs all 39 components at once:
36
+
37
+ ```css
38
+ :root[data-theme='dark'] {
39
+ --color-fg: oklch(98% 0 0);
40
+ --color-fg-muted: oklch(70.4% 0.04 256.788);
41
+ }
42
+ ```
43
+
44
+ The new `DarkGround` story shows exactly this. Delete the two custom properties from it and it
45
+ reproduces the reported bug.
46
+
47
+ ## Overriding just the current crumb
48
+
49
+ If you are not re-theming globally and want to repaint one crumb, there is a sharp edge worth
50
+ knowing — it is why an override can look like it does nothing:
51
+
52
+ > tailwind-merge only drops a conflicting class when the **variant strings match**. `current:text-fg`
53
+ > (ours) and `data-[current]:text-white` (the natural guess) are different variants, so both survive
54
+ > the merge and stylesheet order decides the winner.
55
+
56
+ Claim the same variant and it resolves deterministically:
57
+
58
+ ```tsx
59
+ <BreadcrumbLink className="current:text-white">Product</BreadcrumbLink>
60
+ ```
61
+
62
+ The `OverridingTheCurrentCrumb` story demonstrates it. This is also why a consumer override written
63
+ against `data-[disabled]` never affected the current crumb — `disabled` and `current` are different
64
+ states, so it was never going to match.
65
+
66
+ ## Migration checklist
67
+
68
+ - [ ] Nothing required. The trail keeps working as-is.
69
+ - [ ] If you are on a dark ground, override `--color-fg` and `--color-fg-muted` rather than
70
+ restyling components — and check the rest of your app, since the same tokens drive 39 components.
71
+ - [ ] If you carry a local patch repainting breadcrumb colours, it can go; if you keep one, make
72
+ sure it claims the `current:` variant.
73
+
74
+ ## Known residue
75
+
76
+ Twenty-six literal `text-slate-*` occurrences remain elsewhere in the library (CTAP-1123 residue,
77
+ across `FeatureGate`, `Collection`, `Pagination`, `EmptyResults` and others). They have the same
78
+ un-themeable problem as the two fixed here, but mapping them onto the token ladder is a visual
79
+ judgement per site rather than a mechanical swap — `slate-700` and `slate-800` have no exact token —
80
+ so they are deliberately not swept here. Tracked separately.
@@ -7,7 +7,8 @@
7
7
  "title": "`next` and `@heroui/*` peer ranges are capped; `react-stately` pinned",
8
8
  "classification": "COMPATIBILITY",
9
9
  "breaking": "Yes for a consumer already past a ceiling. No code change; the contract narrowed.",
10
- "affects": "every consumer — the peer ranges are the declaration your package manager installs against."
10
+ "affects": "every consumer — the peer ranges are the declaration your package manager installs against.",
11
+ "read_before_updating": "the capped ranges are the contract your install resolves against — decide before taking `@clicktap/ui` 1.x, not after"
11
12
  },
12
13
  {
13
14
  "path": "2026/08/ui-2026-08-11-password-reveal-toggle.md",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clicktap/ui",
3
- "version": "1.0.2",
3
+ "version": "1.1.1",
4
4
  "private": false,
5
5
  "author": "Clicktap",
6
6
  "description": "A library of React UI components and low-level hooks.",
@@ -102,7 +102,7 @@
102
102
  "tailwind-merge": "^2.6.1"
103
103
  },
104
104
  "devDependencies": {
105
- "@floating-ui/react": "^0.27.20",
105
+ "@floating-ui/react": "0.27.20",
106
106
  "@graphql-typed-document-node/core": "^3.2.0",
107
107
  "@heroui/accordion": "^2.2.0",
108
108
  "@heroui/badge": "^2.2.0",