@hideyukimori/nene2-ui 0.6.0 → 0.7.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 CHANGED
@@ -179,6 +179,24 @@ own ends.
179
179
 
180
180
  🔑 **The scale is the set you keep to. The slots are what your brand looks like.**
181
181
 
182
+ ### 🔴 One slot is not yours to tune
183
+
184
+ `--text-x-slot-control-touch-size` is a **device constraint, not a design choice**. iOS Safari
185
+ zooms the whole page when a focused control is under 16px, so lowering this brings that back.
186
+
187
+ It is a slot at all only because the kit cannot know your rem base — not because the value is
188
+ open. Set `--text-x-slot-control-size` to whatever suits your body text; leave the touch one
189
+ pointing at `--text-x-ios-floor`.
190
+
191
+ Until 0.7.0 the kit wrote this as `max(var(--text-x-md), var(--text-x-ios-floor))`, which is
192
+ the same idea expressed in a way that cannot work: `max()` picks the larger number and cannot
193
+ ask what kind of device it is on, so every desktop control was pushed to 16px too — visibly
194
+ larger than the text beside it in any product whose body is 14px. The two slots split that
195
+ into "the size you chose" and "the floor the device imposes", and the components apply the
196
+ second only under `@media (pointer: coarse)`.
197
+
198
+ 🔑 **Pointer, not width.** An iPad in landscape is wide and still zooms.
199
+
182
200
  ### Composing a slot
183
201
 
184
202
  A slot can hold several steps — four-sided padding is just CSS:
@@ -3,7 +3,7 @@ import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
4
  import { CONTROL_CLASS } from '../lib/states.js';
5
5
  import { useFieldWiring } from '../forms/field-context.js';
6
- const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size text-text-primary placeholder:text-text-muted ${CONTROL_CLASS}`;
6
+ const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-text-primary placeholder:text-text-muted ${CONTROL_CLASS}`;
7
7
  /**
8
8
  * Text input primitive. forwardRef so it works directly with react-hook-form `register`.
9
9
  * Visual values come from theme tokens only.
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/primitives/Input.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,yMAAyM,aAAa,EAAE,CAAC;AAE5O;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAA+B,SAAS,KAAK,CAC1E,EACE,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,gBAAO,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,CAAC;AACzF,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/primitives/Input.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,uPAAuP,aAAa,EAAE,CAAC;AAE1R;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAA+B,SAAS,KAAK,CAC1E,EACE,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,gBAAO,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,CAAC;AACzF,CAAC,CAAC,CAAC"}
@@ -3,7 +3,7 @@ import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
4
  import { CONTROL_CLASS } from '../lib/states.js';
5
5
  import { useFieldWiring } from '../forms/field-context.js';
6
- const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size text-text-primary ${CONTROL_CLASS}`;
6
+ const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-text-primary ${CONTROL_CLASS}`;
7
7
  /**
8
8
  * Select primitive. forwardRef so it works directly with react-hook-form `register`.
9
9
  * Visual values come from theme tokens only.
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","sourceRoot":"","sources":["../../src/primitives/Select.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA6C,MAAM,OAAO,CAAC;AAC9E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAM3D,MAAM,UAAU,GAAG,6KAA6K,aAAa,EAAE,CAAC;AAEhN;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAiC,SAAS,MAAM,CAC9E,EACE,QAAQ,EACR,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,CACL,iBAAQ,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,YACzE,QAAQ,GACF,CACV,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Select.js","sourceRoot":"","sources":["../../src/primitives/Select.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA6C,MAAM,OAAO,CAAC;AAC9E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAM3D,MAAM,UAAU,GAAG,2NAA2N,aAAa,EAAE,CAAC;AAE9P;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAiC,SAAS,MAAM,CAC9E,EACE,QAAQ,EACR,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,CACL,iBAAQ,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,YACzE,QAAQ,GACF,CACV,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -3,7 +3,7 @@ import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
4
  import { CONTROL_CLASS } from '../lib/states.js';
5
5
  import { useFieldWiring } from '../forms/field-context.js';
6
- const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size text-text-primary placeholder:text-text-muted ${CONTROL_CLASS}`;
6
+ const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-text-primary placeholder:text-text-muted ${CONTROL_CLASS}`;
7
7
  /**
8
8
  * Multi-line text input. Deliberately identical to `Input` apart from the element, so the
9
9
  * two never drift: five ships wrote their own `Textarea.tsx` and the kit shipped without
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../src/primitives/Textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA+B,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,yMAAyM,aAAa,EAAE,CAAC;AAE5O;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAqC,SAAS,QAAQ,CACtF,EACE,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,mBAAU,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,CAAC;AAC5F,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../src/primitives/Textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA+B,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,uPAAuP,aAAa,EAAE,CAAC;AAE1R;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAqC,SAAS,QAAQ,CACtF,EACE,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,mBAAU,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,CAAC;AAC5F,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hideyukimori/nene2-ui",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "NeNe fleet shared React UI kit — token-driven primitives on Tailwind v4 @theme. Components carry no design of their own; themes do.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -139,7 +139,18 @@
139
139
  --text-x-slot-field-error-size: var(--text-x-2xs);
140
140
  --text-x-slot-field-label-size: var(--text-x-xs);
141
141
  --font-weight-x-slot-field-label: 500;
142
- --text-x-slot-control-size: max(var(--text-x-md), var(--text-x-ios-floor));
142
+ /* Control text. Two slots, because one value cannot answer "how is this being pointed at".
143
+ *
144
+ * 0.6.0 used `max(var(--text-x-md), var(--text-x-ios-floor))`, which raised every control
145
+ * to 16px — including on a desktop whose body text is 14px, where the inputs then look
146
+ * oversized next to everything else (found by hide on a real screen, 2026-08-23). `max()`
147
+ * cannot ask what kind of device it is on; it only ever picks the larger number.
148
+ *
149
+ * 🔴 The touch slot is a device constraint, not a design choice. iOS Safari zooms the whole
150
+ * page when a focused control is under 16px, so lowering it re-introduces that. It is a slot
151
+ * only because the kit cannot know a product's rem base — not because it is yours to tune. */
152
+ --text-x-slot-control-size: var(--text-x-md);
153
+ --text-x-slot-control-touch-size: var(--text-x-ios-floor);
143
154
 
144
155
  /* Sentinel for the consumer's build (#316). Zero-width, so applying it does nothing.
145
156
  * Its only job is to exist: `p-x-source-probe` appears nowhere except this kit's `dist`,