@clicktap/ui 0.43.5 → 0.43.6
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/components/Input/Input.js +1 -1
- package/docs/migrations/2026/02/ui-2026-02-16-env-utils-from-clicktap-ui.md +1 -1
- package/docs/migrations/2026/07/ui-2026-07-31-ui-exports-bundler-resolution.md +1 -1
- package/docs/migrations/2026/08/ui-2026-08-04-password-reveal-press-and-hold.md +3 -1
- package/docs/migrations/2026/08/ui-2026-08-04-resend-code-control.md +1 -1
- package/docs/migrations/2026/08/ui-2026-08-06-clicktap-ui-loaders-drop-framer-motion.md +1 -1
- package/docs/migrations/2026/08/ui-2026-08-06-clicktap-ui-semantic-tokens.md +1 -1
- package/docs/migrations/2026/08/ui-2026-08-11-password-reveal-toggle.md +75 -0
- package/docs/migrations/README.md +2 -1
- package/docs/migrations/index.json +10 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsxs as s,jsx as e}from"react/jsx-runtime";import{Label as
|
|
1
|
+
"use client";import{jsxs as s,jsx as e}from"react/jsx-runtime";import{Label as f,TextField as v,Input as k,Text as L,FieldError as C}from"react-aria-components";import{forwardRef as I,useState as N}from"react";import{cn as r}from"../../utils/cn.js";import{Skeleton as M}from"../Skeleton/Skeleton.js";import S from"../../hooks/useIsClient.js";function j({className:t}){return s("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:t,children:[e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.64 0 8.577 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.64 0-8.577-3.007-9.963-7.178Z"}),e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"})]})}function y({className:t}){return e("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:t,children:e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"})})}function E({className:t}){return e(M,{className:r("w-full h-10 rounded-md z-20 relative",t)})}const W=I(({inputProps:t,label:l,description:a,errorMessage:p,placeholder:m,className:u,classNames:o,disableSkeleton:x,type:c,...h},b)=>{const w=S(),i=c==="password",[n,g]=N(!1);return!w&&!x?s("div",{className:r("flex flex-col w-full text-fg",u),children:[l?e(f,{className:r("flex text-fg-muted text-xs",o?.label),children:l}):null,e(E,{className:o?.skeleton})]}):s(v,{className:r("flex flex-col w-full text-fg",u),type:i?n?"text":"password":c,...h,children:[e(f,{className:r("flex text-fg-muted text-xs",o?.label),children:l}),s("div",{className:"relative",children:[e(k,{ref:b,placeholder:m,className:r("border-solid border border-border rounded-md","text-sm text-fg placeholder-fg-subtle","h-10 px-2 py-0 m-0 w-full","bg-white","transition-all duration-200 ease-in-out","hover:border-border-emphasis","focus:outline-2 focus:outline focus:outline-border-subtle focus:border-border-emphasis","disabled:border-border-subtle disabled:bg-surface-subtle","invalid:border-danger-soft invalid:bg-danger-surface invalid:text-danger","invalid:hover:border-danger invalid:focus:border-danger invalid:focus:outline-danger-ring",i&&"pr-10",o?.input),...t}),i&&e("button",{type:"button",className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-fg-subtle hover:text-slate-600 bg-transparent border-none cursor-pointer select-none",onMouseDown:d=>d.preventDefault(),onClick:()=>g(d=>!d),"aria-label":n?"Hide password":"Show password","aria-pressed":n,children:n?e(y,{className:"w-5 h-5"}):e(j,{className:"w-5 h-5"})})]}),a&&e(L,{className:r("flex text-fg-muted text-sm",o?.description),slot:"description",children:a}),e(C,{className:r("flex text-danger-soft text-sm",o?.error),children:p})]})});export{W as Input,W as default};
|
|
@@ -56,10 +56,10 @@ import { isDevelopment } from '../../../../../utils/env';
|
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
**After:**
|
|
59
|
-
**Formerly named:** `2026-02-16-env-utils-from-clicktap-ui.md` — renamed 2026-08-07 (CTAP-1143) for global filename uniqueness; an identically-named guide exists in another tree and mirrored folders overwrote each other. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
60
59
|
```ts
|
|
61
60
|
import { isDevelopment } from '@clicktap/ui/utils/env';
|
|
62
61
|
```
|
|
62
|
+
**Formerly named:** `2026-02-16-env-utils-from-clicktap-ui.md` — renamed 2026-08-07 (CTAP-1143) for global filename uniqueness; an identically-named guide exists in another tree and mirrored folders overwrote each other. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
63
63
|
|
|
64
64
|
### Files changed
|
|
65
65
|
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
**Revised:** 2026-08-08 — the test-runner half (CTAP-1195): every runtime subpath entry gains a `default` condition, so CJS resolvers (Jest) stop falling through to the `.d.ts`. See "Test runners (Jest)" below; reported by noco.
|
|
5
5
|
**Package:** `@clicktap/ui`
|
|
6
6
|
**Breaking:** No — additive to the `exports` map. Existing `moduleResolution: node` / `node10`
|
|
7
|
-
**Formerly named:** `2026-07-31-ui-exports-bundler-resolution.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
8
7
|
consumers are unaffected (that resolver ignores `exports`); this only *adds* working resolution under
|
|
9
8
|
`bundler` / `node16` / `nodenext`.
|
|
10
9
|
**Classification:** BUGFIX (packaging) — unblocks `moduleResolution: bundler`, and with it TypeScript 7
|
|
10
|
+
**Formerly named:** `2026-07-31-ui-exports-bundler-resolution.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
11
11
|
|
|
12
12
|
## What was wrong
|
|
13
13
|
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
**Affects:** `@clicktap/ui` — `Input` with `type="password"`.
|
|
6
6
|
**Classification:** IMPROVEMENT (security / UX)
|
|
7
7
|
**Breaking:** Behavioural only — the reveal changed from a click-toggle to press-and-hold. No API/prop
|
|
8
|
-
**Formerly named:** `2026-08-04-password-reveal-press-and-hold.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
9
8
|
change; adoption is automatic.
|
|
10
9
|
**Ticket:** CTAP-1128
|
|
10
|
+
**Status:** ⚠️ **Superseded — do not adopt.** (CTAP-1240)
|
|
11
|
+
**Superseded by:** [`ui-2026-08-11-password-reveal-toggle.md`](./ui-2026-08-11-password-reveal-toggle.md) — press-and-hold made a revealed password impossible to copy into a password manager, so the reveal went back to a click toggle. If you have not applied this guide yet, skip it and apply that one. If you have, that guide tells you how to reverse it.
|
|
12
|
+
**Formerly named:** `2026-08-04-password-reveal-press-and-hold.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
11
13
|
|
|
12
14
|
## Summary
|
|
13
15
|
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
**Classification:** IMPROVEMENT (new capability)
|
|
7
7
|
**Breaking:** No — additive exports.
|
|
8
8
|
**Consumers:** the OTP resend timer — [wire it everywhere](../../../../../../apps/frontend/docs/migrations/2026/08/2026-08-04-otp-resend-timer.md) ·
|
|
9
|
-
**Formerly named:** `2026-08-04-resend-code-control.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
10
9
|
GraphQL contract — [resend mutations](../../../../../../libs/mezzio-modules/user/docs/migrations/2026/08/2026-08-04-otp-resend-mutations.md)
|
|
10
|
+
**Formerly named:** `2026-08-04-resend-code-control.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
11
11
|
|
|
12
12
|
## Summary
|
|
13
13
|
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
**Affects:** `@clicktap/ui` — `Button`, `ButtonLoadingContent`, `Loader/CircularEasing`, `Loader/Pulse`
|
|
6
6
|
**Breaking:** No API change. **One requirement to be aware of** — see below.
|
|
7
7
|
**Requires:** `@import '@clicktap/ui/theme.css'` in your CSS entry
|
|
8
|
-
**Formerly named:** `2026-08-06-clicktap-ui-loaders-drop-framer-motion.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
9
8
|
([tokens guide](./ui-2026-08-06-clicktap-ui-semantic-tokens.md))
|
|
10
9
|
**Classification:** IMPROVEMENT
|
|
10
|
+
**Formerly named:** `2026-08-06-clicktap-ui-loaders-drop-framer-motion.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
11
11
|
|
|
12
12
|
## What changed
|
|
13
13
|
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
**Affects:** `@clicktap/ui`, every app that renders its components
|
|
6
6
|
**Breaking:** **Yes — one required import.** Components render *unstyled* without it.
|
|
7
7
|
**Requires:** Tailwind v4 (`@import 'tailwindcss'` in your CSS entry). See
|
|
8
|
-
**Formerly named:** `2026-08-06-clicktap-ui-semantic-tokens.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
9
8
|
[the v4 upgrade guide](../../../../../../apps/frontend/docs/migrations/2026/07/2026-07-31-tailwind-3-to-4.md).
|
|
10
9
|
**Classification:** COMPATIBILITY
|
|
10
|
+
**Formerly named:** `2026-08-06-clicktap-ui-semantic-tokens.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
|
|
11
11
|
|
|
12
12
|
## Do this
|
|
13
13
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Password reveal is a toggle again, not press-and-hold
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-08-11
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
5
|
+
**Affects:** `@clicktap/ui` — `Input` with `type="password"`.
|
|
6
|
+
**Classification:** IMPROVEMENT (UX / accessibility)
|
|
7
|
+
**Breaking:** Behavioural only — the reveal changed from press-and-hold back to a click toggle, and the
|
|
8
|
+
control entered the tab order. No API/prop change; adoption is automatic.
|
|
9
|
+
**Ticket:** CTAP-1240
|
|
10
|
+
**Supersedes:** [`ui-2026-08-04-password-reveal-press-and-hold.md`](./ui-2026-08-04-password-reveal-press-and-hold.md) (CTAP-1128).
|
|
11
|
+
If you have not applied that guide yet, **skip it** and apply this one instead — the end state is the
|
|
12
|
+
same either way.
|
|
13
|
+
|
|
14
|
+
## Summary
|
|
15
|
+
|
|
16
|
+
The password-field reveal (the eye button in `Input`) is a **toggle** again: one click shows the value
|
|
17
|
+
and it stays shown until you click again. CTAP-1128 had made it press-and-hold — visible only while the
|
|
18
|
+
control was physically held — to shrink the shoulder-surfing window. That traded away more than it
|
|
19
|
+
bought:
|
|
20
|
+
|
|
21
|
+
- **You cannot copy a password you cannot release.** Revealing a password so you can select it and
|
|
22
|
+
paste it into a password manager is a routine thing to do, and press-and-hold makes it impossible.
|
|
23
|
+
- **You cannot watch yourself type.** Holding the button with one hand while typing a long password
|
|
24
|
+
with the other is not a real workflow.
|
|
25
|
+
- **A toggle is the control users already know.** Edge's own built-in password reveal is a toggle, as
|
|
26
|
+
are the Chrome and Safari password managers and effectively every major sign-in form.
|
|
27
|
+
|
|
28
|
+
The reveal is still user-initiated and still resets to hidden on every mount, so a revealed password
|
|
29
|
+
never survives a page load.
|
|
30
|
+
|
|
31
|
+
## What changed
|
|
32
|
+
|
|
33
|
+
The reveal button swapped its pointer press-and-hold handlers back for a click toggle, and picked up
|
|
34
|
+
proper toggle-button semantics:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
// before (CTAP-1128) // after (CTAP-1240)
|
|
38
|
+
onPointerDown={(e) => { onMouseDown={(e) => e.preventDefault()}
|
|
39
|
+
e.preventDefault(); onClick={() => setShowPassword((shown) => !shown)}
|
|
40
|
+
setShowPassword(true); aria-label={showPassword ? 'Hide password' : 'Show password'}
|
|
41
|
+
}} aria-pressed={showPassword}
|
|
42
|
+
onPointerUp={() => setShowPassword(false)}
|
|
43
|
+
onPointerLeave={() => setShowPassword(false)}
|
|
44
|
+
onPointerCancel={() => setShowPassword(false)}
|
|
45
|
+
onContextMenu={(e) => e.preventDefault()}
|
|
46
|
+
aria-label="Show password while pressed"
|
|
47
|
+
tabIndex={-1}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- **`preventDefault()` on mousedown** keeps the caret in the input when you click the eye, so you can
|
|
51
|
+
toggle visibility mid-typing without losing your place.
|
|
52
|
+
- **`tabIndex={-1}` is gone** — the button is now in the tab order and operable with Enter/Space. This
|
|
53
|
+
is the one behavioural change a consumer might notice beyond the reveal itself: **a password field
|
|
54
|
+
now has one extra tab stop between it and the next control.** If you have a test that tabs through a
|
|
55
|
+
sign-in form by counting stops, update it.
|
|
56
|
+
- **`aria-pressed`** exposes the on/off state to assistive tech, and the label swaps between
|
|
57
|
+
`Show password` and `Hide password` instead of the static "Show password while pressed".
|
|
58
|
+
- Press-and-hold was **not** kept as an opt-in mode — there is one reveal behaviour, no new prop.
|
|
59
|
+
|
|
60
|
+
Shipped in `@clicktap/ui` **0.43.6**.
|
|
61
|
+
|
|
62
|
+
## Action required (consumer)
|
|
63
|
+
|
|
64
|
+
- **Using `@clicktap/ui` `Input`:** nothing — the behaviour ships with the component. Re-check any
|
|
65
|
+
keyboard-navigation test that asserts an exact tab order around a password field.
|
|
66
|
+
- **Rolled your own password reveal:** swap the pointer handlers back for the `onClick` toggle above,
|
|
67
|
+
and add `aria-pressed` + the state-dependent `aria-label` while you are in there. The reference
|
|
68
|
+
frontend also updated its one bespoke reveal (`UpdateEmailForm`) to match.
|
|
69
|
+
- **Applied the CTAP-1128 guide:** this reverses it. Nothing to un-install beyond the handler swap.
|
|
70
|
+
|
|
71
|
+
## Verify
|
|
72
|
+
|
|
73
|
+
Click the eye control → the characters show and **stay** shown. Select the revealed text and copy it —
|
|
74
|
+
it lands on the clipboard. Click again → hidden. Tab to the control and press Enter → it toggles.
|
|
75
|
+
Reload the page → the field is hidden again.
|
|
@@ -28,7 +28,8 @@ For migrations affecting the frontend app, see [frontend migrations](../../../..
|
|
|
28
28
|
| 2026-06-17 | [Select standardization — one `<Select searchable>`, `DropdownSelect` removed](./2026/06/ui-2026-06-17-select-standardization.md) ↔ | Yes | *None* |
|
|
29
29
|
| 2026-06-18 | [Select (searchable): fix "setValue is not a function" crash on browser autofill](./2026/06/ui-2026-06-18-select-hiddenselect-setvalue-crash.md) | No | Select standardization |
|
|
30
30
|
| 2026-08-04 | [`ResendCode` control + `useCooldown` hook](./2026/08/ui-2026-08-04-resend-code-control.md) ↔ | No | OTP resend timer (CTAP-1114) |
|
|
31
|
-
| 2026-08-04 | [Password reveal is press-and-hold, not a toggle](./2026/08/ui-2026-08-04-password-reveal-press-and-hold.md) | Behavioural | *None* (CTAP-1128) |
|
|
31
|
+
| 2026-08-04 | [Password reveal is press-and-hold, not a toggle](./2026/08/ui-2026-08-04-password-reveal-press-and-hold.md) ⚠️ superseded | Behavioural | *None* (CTAP-1128) |
|
|
32
32
|
| 2026-08-06 | [`Image` is framework-free; Next's optimizer moves to `@clicktap/ui/next`](./2026/08/ui-2026-08-06-clicktap-ui-image-next-subpath.md) ↔ | Yes (Next consumers) | *None* |
|
|
33
|
+
| 2026-08-11 | [Password reveal is a toggle again, not press-and-hold](./2026/08/ui-2026-08-11-password-reveal-toggle.md) | Behavioural | Supersedes CTAP-1128 |
|
|
33
34
|
|
|
34
35
|
↔ = cross-app migration (has counterpart in frontend app)
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"path": "2026/08/ui-2026-08-11-password-reveal-toggle.md",
|
|
4
|
+
"module": "libs/frontend-modules/ui",
|
|
5
|
+
"package": "@clicktap/ui",
|
|
6
|
+
"date": "2026-08-11",
|
|
7
|
+
"title": "Password reveal is a toggle again, not press-and-hold",
|
|
8
|
+
"classification": "IMPROVEMENT (UX / accessibility)",
|
|
9
|
+
"breaking": "Behavioural only — the reveal changed from press-and-hold back to a click toggle, and the",
|
|
10
|
+
"affects": "`@clicktap/ui` — `Input` with `type=\"password\"`."
|
|
11
|
+
},
|
|
2
12
|
{
|
|
3
13
|
"path": "2026/08/ui-2026-08-07-ui-peer-contract-form-graphql-optional-peers.md",
|
|
4
14
|
"module": "libs/frontend-modules/ui",
|