@invisibleloop/pulse 0.18.1 → 0.18.2

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.
@@ -1436,6 +1436,15 @@ a:hover {
1436
1436
  line-height: 1.4;
1437
1437
  }
1438
1438
 
1439
+ /* iOS Safari auto-zooms when a focused input's font-size is under 16px —
1440
+ touch devices get 16px so tapping the search field never zooms the page. */
1441
+ @media (pointer: coarse) {
1442
+ .sidebar-search,
1443
+ .search-overlay-input {
1444
+ font-size: max(1rem, 16px);
1445
+ }
1446
+ }
1447
+
1439
1448
  .sidebar-search::placeholder {
1440
1449
  color: var(--muted-2);
1441
1450
  }
@@ -367,6 +367,18 @@ html, body {
367
367
  -webkit-appearance: none;
368
368
  }
369
369
 
370
+ /* iOS Safari auto-zooms the page when a focused input's font-size is under
371
+ 16px, forcing the user to pinch back out afterwards. On touch devices form
372
+ controls must never go below 16px — desktop keeps the compact .9rem. */
373
+ @media (pointer: coarse) {
374
+ .ui-input,
375
+ .ui-textarea,
376
+ .ui-select,
377
+ .ui-search-input {
378
+ font-size: max(1rem, 16px);
379
+ }
380
+ }
381
+
370
382
  .ui-input::placeholder { color: var(--ui-muted); }
371
383
 
372
384
  .ui-input:hover:not(:disabled) { border-color: var(--ui-muted); }
@@ -367,6 +367,18 @@ html, body {
367
367
  -webkit-appearance: none;
368
368
  }
369
369
 
370
+ /* iOS Safari auto-zooms the page when a focused input's font-size is under
371
+ 16px, forcing the user to pinch back out afterwards. On touch devices form
372
+ controls must never go below 16px — desktop keeps the compact .9rem. */
373
+ @media (pointer: coarse) {
374
+ .ui-input,
375
+ .ui-textarea,
376
+ .ui-select,
377
+ .ui-search-input {
378
+ font-size: max(1rem, 16px);
379
+ }
380
+ }
381
+
370
382
  .ui-input::placeholder { color: var(--ui-muted); }
371
383
 
372
384
  .ui-input:hover:not(:disabled) { border-color: var(--ui-muted); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invisibleloop/pulse",
3
- "version": "0.18.1",
3
+ "version": "0.18.2",
4
4
  "type": "module",
5
5
  "description": "AI-first frontend framework. The spec is the source of truth.",
6
6
  "license": "MIT",
@@ -1 +1 @@
1
- 0.18.1
1
+ 0.18.2
@@ -367,6 +367,18 @@ html, body {
367
367
  -webkit-appearance: none;
368
368
  }
369
369
 
370
+ /* iOS Safari auto-zooms the page when a focused input's font-size is under
371
+ 16px, forcing the user to pinch back out afterwards. On touch devices form
372
+ controls must never go below 16px — desktop keeps the compact .9rem. */
373
+ @media (pointer: coarse) {
374
+ .ui-input,
375
+ .ui-textarea,
376
+ .ui-select,
377
+ .ui-search-input {
378
+ font-size: max(1rem, 16px);
379
+ }
380
+ }
381
+
370
382
  .ui-input::placeholder { color: var(--ui-muted); }
371
383
 
372
384
  .ui-input:hover:not(:disabled) { border-color: var(--ui-muted); }
package/src/ui/ui.test.js CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { test } from 'node:test'
9
9
  import assert from 'node:assert/strict'
10
+ import { readFileSync } from 'node:fs'
10
11
  import { button } from './button.js'
11
12
  import { badge } from './badge.js'
12
13
  import { card } from './card.js'
@@ -1353,4 +1354,16 @@ test('dropCap: escapes letter and content', () => {
1353
1354
  assert.doesNotMatch(html, /<script>/)
1354
1355
  })
1355
1356
 
1357
+ test('pulse-ui.css: form controls are at least 16px on touch devices (iOS focus-zoom)', () => {
1358
+ // iOS Safari zooms the page when a focused input's font-size is under 16px,
1359
+ // forcing the user to pinch back out. A (pointer: coarse) block must keep
1360
+ // every text-entry control at >= 16px on touch devices.
1361
+ const css = readFileSync(new URL('../../public/pulse-ui.css', import.meta.url), 'utf8')
1362
+ const block = css.match(/@media \(pointer: coarse\) \{[\s\S]*?\n\}/)?.[0] ?? ''
1363
+ for (const sel of ['.ui-input', '.ui-textarea', '.ui-select', '.ui-search-input']) {
1364
+ assert.ok(block.includes(sel), `${sel} missing from the (pointer: coarse) 16px block`)
1365
+ }
1366
+ assert.match(block, /font-size:\s*max\(1rem, 16px\)/)
1367
+ })
1368
+
1356
1369
  console.log('✓ All UI component tests passed')