@aiquants/daily-report 0.49.0 → 0.50.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/CHANGELOG.md +48 -0
- package/README.md +59 -15
- package/dist/client.js +5 -5
- package/dist/client.mjs +5 -5
- package/dist/styles/daily-report.standalone.css +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@aiquants/daily-report` are documented here.
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- **`@aiquants/swipe-overlay` のピアの下限が、`useSwipeOverlayDialog`・`useOverlayPresence`・`SWIPE_OVERLAY_SCROLL_AREA_STYLE` を持つ版へ上がる**。
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **粗いポインター (`(pointer: coarse)`) では日報のどの操作の的も 44 × 44 CSS px 以上 (`TARGET_SIZE_PX` = 11u。WCAG 2.5.5)**: 操作ボタン (List のカードと DetailList の
|
|
14
|
+
見出しと側面ペインのスター・既読・編集・削除、コメントのゴミ箱) は 44px の丸い的、ビューのタブと側面ペインのタブ (側面ペインの並びは 4 + 44 + 4 = 52px)・作成のボタン・検索の切り替えと入力欄と
|
|
15
|
+
消去のボタン・コメントの入力欄と送信・削除の確認・オーバーレイと誤りの知らせの閉じるボタン・2 つの再試行・編集フォームの `Button` と `Input`・添付のダウンロードと行のリンクは
|
|
16
|
+
44px 以上の箱 (`COARSE_TARGET_CLASS_NAME`。最小の大きさで育つ)。自動既読のスイッチは見た目の 40 × 24 のまま中央の 44 × 44 の当たりを持つ。List のカードは粗いポインターで
|
|
17
|
+
2 列の格子になり、スターと既読をプレビューの右 (2 行目) へ移すので、行の枠の高さ P は根 16px で 160 のまま (`listRowSlotHeight(R, T)` = 4⌈(52 + 2R + max(4.75R, T)) / 4⌉。T は
|
|
18
|
+
粗いポインターでだけ高さを持つ隠れた探りから読む)。側面ペインの操作ボタンは件名の下の自分の 44px の行へ移り、添付のタイルの最後の行は 48px (44 を 8 へ切り上げ、タイルは
|
|
19
|
+
装置の画素の格子に乗ったまま)。操作列の帯の部品 (ビューのタブ・作成のボタン・自動既読のスイッチの行・検索の入力欄と 2 つの切り替え) も同じ 48px の高さ
|
|
20
|
+
(`LATTICE_TARGET_SIZE_PX`。44 のままでは 2.625 の画素密度で部品の下の縁が装置の画素の間に落ちる) で、操作列の並びは 4 + 48 + 4 = 56px (2 行に折り返せば 112px)、
|
|
21
|
+
検索の行の 1 行目は 8 + 48 = 56px。ビューの幅が 320px 未満なら検索の絞り込みの切り替えは自分の行へ折り返す (境目は粗いポインターの行の最小の幅から求めた値)。細かいポインター
|
|
22
|
+
(マウス・トラックパッド・ペン) では的も配置も変わらず 24px (2.5.8) なので、2.5.5 は粗いポインターでだけ満たし、全体としては主張しない。例外: List のリサイズの取っ手と
|
|
23
|
+
スクロールバー・ホストの絞り込みの選択の部品・開発用の箱の再読み込みとキャッシュの消去 (24 × 24 の的。同じ箱の SSE のスイッチは中央の 44 × 44 の当たりを持ち、
|
|
24
|
+
粗いポインターでは箱の項目の間を 4 + (44 − 40) / 2 = 6px に広げて、当たりが再読み込みの的に重ならない)・VirtualScroll のタップスクロールの円。オーバーレイの閉じるボタンは
|
|
25
|
+
粗いポインターで 36 → 44px。Tailwind でクラスを作るホストは、`pointer-coarse:` のユーティリティを Tailwind CSS v4.1 以上で生成する (それより前の v4 では粗いポインターの規則が
|
|
26
|
+
作られず、的は細かいポインターの大きさのまま)。
|
|
27
|
+
- **入力欄の文字の大きさは画面の幅ではなくポインターで決まる**: 粗いポインターでは 16px (iOS のフォーカス時の拡大を防ぐ)、細かいポインターでは 14px (編集フォームの `Input` と
|
|
28
|
+
`Textarea` の幅で決めていた `md:text-sm` を外した)。検索の入力欄に `enterkeyhint="search"`、コメントの入力欄に `"send"`。オーバーレイの中身は上下左右に 16px と
|
|
29
|
+
`env(safe-area-inset-*)` の大きい方だけ内側へ寄る。
|
|
30
|
+
- **モバイルの詳細オーバーレイのダイアログの部品を `@aiquants/swipe-overlay` の共有のフックへ移した**: ダイアログの開閉 (`showModal()`・`close()`・`inert`)・
|
|
31
|
+
最初のフォーカス (日報の見出し)・閉じる要求の経路 (Escape・`cancel`・プラットフォームが強いた閉じ・背景・スワイプ) は `useSwipeOverlayDialog`、閉じて滑り出す間の
|
|
32
|
+
マウントは `useOverlayPresence` (閉じてから `SWIPE_OVERLAY_EXIT_MS` = 300 ms)。`@aiquants/contact-map` の詳細のオーバーレイと同じフックで、振る舞いは
|
|
33
|
+
変わらない (下の修正を除く)。Tab の巡回・誤りの知らせの置き場・自動既読の留まり・履歴の項目はパッケージが持ったまま。
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- **モバイルのオーバーレイの中でピンチの拡大が効く**: 面は `touch-action: none`、側面ペインのタブの中身は `pan-y` で、面の上では 2 本の指の拡大まで止めていた
|
|
38
|
+
(背景は `manipulation`)。面と背景は `pinch-zoom`、タブの中身は `pan-y pinch-zoom` になり、オーバーレイのどこでもピンチでページを拡大できる (横の動きは閉じるスワイプのまま)。
|
|
39
|
+
デスクトップの配置の側面ペインのタブの中身も `pan-y` を外し (スワイプが無いので触れ方を絞らない)、タッチの画面でピンチの拡大が効く。
|
|
40
|
+
- **オーバーレイの中のスクロールが背後のページへつながらない**: 側面ペインのタブの中身 (オーバーレイの縦のスクロール領域) は `overscroll-behavior-y: contain` を持ち、
|
|
41
|
+
端まで送ったスクロールはページへつながらない (Android の引いて再読み込みにならない)。面と背景の上の縦の動きも何も引っ張らない。
|
|
42
|
+
- **IME の変換を終える Escape が、重いページでもオーバーレイを閉じない**: オーバーレイが断った Escape (IME の変換を終えるもの、閉じるのを
|
|
43
|
+
拒まれたもの) が起こすプラットフォームの閉じる要求は、キーから 50ms 以内なら捨てていたため、キーの処理に 50ms より掛かるとその要求で閉じた。
|
|
44
|
+
要求はキーの既定動作として同じタスクの中で届くので、断った Escape のタスクの中の要求を捨てる (`@aiquants/swipe-overlay` の
|
|
45
|
+
`useSwipeOverlayDialog`)。後のタスクの要求 (Android の戻る) は捨てない。
|
|
46
|
+
- **スワイプで閉じた直後や、オーバーレイの見出しの帯・背景を引いた直後のタップが効く**: ブラウザーはパンできない 1 本の指の動きを自分のパンの
|
|
47
|
+
試みとして扱い続け、離してからおよそ 1 秒のタップを `click` にしないことがあった (閉じた直後に次の日報のカードをタップしても開かない)。
|
|
48
|
+
その `touchmove` をページが取る (`@aiquants/swipe-overlay`。閉じるスワイプと決まった後の動きと、面のスクロールの領域の外と背景の 1 本の指の動き)。
|
|
49
|
+
- **端末を回してもオーバーレイの履歴の項目が溜まらない**: オーバーレイを開いたまま配置がデスクトップへ切り替わる (端末を横にする) と、オーバーレイは
|
|
50
|
+
閉じても自分が積んだ履歴の項目を残し、回し戻して開き直すたびに同じ URL の項目が増えて、戻る操作が何もしないように見えた。デスクトップの配置への
|
|
51
|
+
切り替えで閉じるときも、積んだ項目を戻す。
|
|
52
|
+
|
|
5
53
|
## 0.49.0 (2026-10-21)
|
|
6
54
|
|
|
7
55
|
### Breaking
|
package/README.md
CHANGED
|
@@ -106,7 +106,8 @@ label catalog reuses its engine keys (every label key `@aiquants/virtualscroll`
|
|
|
106
106
|
`DailyReportRevealOptions`, the options of the test handle's `revealIndex`, is `@aiquants/virtualscroll`'s `scrollToIndex` options type, which takes
|
|
107
107
|
`align: "nearest"` since 3.11.0, and DetailList rows stay at the tree's tops and heights after a batch of re-measurements whose deltas cancel only
|
|
108
108
|
because its row memo follows the tree revision (3.11.0).
|
|
109
|
-
The peer floor of `@aiquants/swipe-overlay` is **1.
|
|
109
|
+
The peer floor of `@aiquants/swipe-overlay` is **1.3.0**: install 1.3.0 or later. The mobile overlay is its modal dialog (`useSwipeOverlayDialog`), stays mounted
|
|
110
|
+
while it slides out (`useOverlayPresence`) and gives its scroll areas the swipe surface's touch contract, the style that package exports for them (1.3.0).
|
|
110
111
|
The mobile overlay, the comment delete confirmation and the built-in error notice leave `Escape` to its `Escape` stack, which lets an `Escape` that
|
|
111
112
|
cancels an IME composition pass; the mobile overlay's entry listens on the document of the overlay's element, an iframe's document included (1.2.6).
|
|
112
113
|
`@aiquants/sse` (the SSE wire contract, server response helpers and the reopening client) is a regular **dependency**: it arrives transitively, so
|
|
@@ -179,6 +180,9 @@ utilities are generated in one canonical build, define the `dark:` variant, and
|
|
|
179
180
|
|
|
180
181
|
The host must also:
|
|
181
182
|
|
|
183
|
+
- Build with Tailwind CSS v4.1 or later. The coarse-pointer targets (**Coarse pointers** in Selection and focus appearance) are
|
|
184
|
+
`pointer-coarse:` utilities, a variant Tailwind added in v4.1; an older v4 build generates none of them, so every target keeps its fine-pointer
|
|
185
|
+
size on a touch screen.
|
|
182
186
|
- Load the `tailwindcss-animate` plugin. The components use `animate-in` / `fade-in` / `zoom-in-95` / `slide-in-from-bottom-2` entrance animations
|
|
183
187
|
(all under `motion-safe:`); without `@plugin "tailwindcss-animate"` those classes are not generated and the animations silently no-op.
|
|
184
188
|
- Define the shadcn CSS variables themselves (`--background`, `--muted`, `--radius`, ...).
|
|
@@ -3362,8 +3366,8 @@ the resize handle and the side pane lie outside the list.
|
|
|
3362
3366
|
on Shift+Tab the container of a roving-focus widget around the origin, such as the tabs' `tablist`, is not counted before it, because real Shift+Tab
|
|
3363
3367
|
leaves such a widget without stopping at it), and Escape closes it unless the key belongs to an IME composition.
|
|
3364
3368
|
Every close request goes through the overlay's own close path, which also pops the history entry the overlay pushed: the platform's `cancel` (an
|
|
3365
|
-
Escape the overlay's key handling did not take, Android's back gesture) is default-prevented and routed there, except one
|
|
3366
|
-
Escape the overlay declined
|
|
3369
|
+
Escape the overlay's key handling did not take, Android's back gesture) is default-prevented and routed there, except one that an
|
|
3370
|
+
Escape the overlay declined (an IME composition, or a close the overlay refused) caused in its own task; when the platform closes the dialog by itself (a `cancel` the page is not allowed to stop),
|
|
3367
3371
|
the close path runs too, and the dialog opens modally again when the close is refused.
|
|
3368
3372
|
Closing it by any means (close button, Escape, backdrop, browser back, a switch to the desktop layout) first blurs the focus inside the dialog, then
|
|
3369
3373
|
ends the modal state with `close()` (the platform returns focus, without scrolling, to the element that had it when the dialog opened, when that
|
|
@@ -3376,6 +3380,13 @@ the resize handle and the side pane lie outside the list.
|
|
|
3376
3380
|
The dialog itself takes focus (`tabIndex=-1`), so pressing a non-focusable part of it never drops focus to `body`. The backdrop is a decorative
|
|
3377
3381
|
layer (`data-daily-report-overlay-backdrop`, `aria-hidden`, without a role or a name, not focusable): pressing it closes the overlay, while keyboard
|
|
3378
3382
|
and assistive-technology users close it with Escape or the close button. Its transitions run only under `prefers-reduced-motion: no-preference`.
|
|
3383
|
+
Touch: the panel and the backdrop take `touch-action: pinch-zoom`, and the side pane's tab panels, the overlay's vertical scroll areas, take
|
|
3384
|
+
`touch-action: pan-y pinch-zoom` with `overscroll-behavior-y: contain`, so a pinch zooms the page anywhere in the overlay, a horizontal move that
|
|
3385
|
+
starts anywhere on the panel is the swipe that closes it, and no scroll in it reaches the page behind (no scroll chaining, no pull-to-refresh).
|
|
3386
|
+
The dialog's lifecycle (its modality and `inert`, the first focus, the close-request path, the swipe) is `@aiquants/swipe-overlay`'s
|
|
3387
|
+
`useSwipeOverlayDialog` and its slide-out mount is `useOverlayPresence` (mounted for the swipe's exit, 300 ms, after it closes), the same hooks as
|
|
3388
|
+
`@aiquants/contact-map`'s detail overlay; the package adds the Tab wrap, the error notice's slot, the dwell signal of the auto-read and the history
|
|
3389
|
+
entry.
|
|
3379
3390
|
- **Iframes and shadow roots**: the views never read the global `document`; focus checks, the handoff, the body scroll lock and the overlay use the
|
|
3380
3391
|
view's own document or shadow root, the Tab-stop search walks open shadow roots, and script-driven scrolling reads the reduced-motion preference of
|
|
3381
3392
|
the element's own window.
|
|
@@ -3450,12 +3461,15 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3450
3461
|
`resolution: <dpr>dppx` of each of the twelve ratios with `calc(⌊2·dpr⌋px / dpr)`), and the lift reads it
|
|
3451
3462
|
(`translate-y-[calc(-1*var(--aqdr-hover-lift))]`); every class is a literal, so a host's Tailwind build and the package's standalone stylesheet
|
|
3452
3463
|
compile the same rules.
|
|
3453
|
-
- **List slot P**: the List card's content is sized in rem, so the slot follows the page's root font size R
|
|
3454
|
-
|
|
3455
|
-
stays on the
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3464
|
+
- **List slot P**: the List card's content is sized in rem (its toggles in px under a coarse pointer), so the slot follows the page's root font size R
|
|
3465
|
+
and the toggles' target size T on the card's second line: P(R, T) = 4 · ⌈(2G + 2 × (1 + 15) (the card's border and padding) + 4 (spare) + 2R +
|
|
3466
|
+
max(4.75R, T)) / 4⌉ = 4 · ⌈(52 px + 2 rem + max(4.75 rem, T)) / 4⌉, the sum rounded up to the 4 px layout lattice, so every row top stays on the
|
|
3467
|
+
lattice. T is 0 under a fine pointer (the toggles sit on the header line) and 44 under a coarse one (the toggles move beside the preview, **List
|
|
3468
|
+
card** below); at a 16 px root 4.75 rem = 76 px is taller than 44, so P is 160 under either pointer.
|
|
3469
|
+
R is read from the root element's computed style and T from the height of a hidden probe that is 44 px tall only under a coarse pointer
|
|
3470
|
+
(`data-daily-report-target-size-probe`); one `ResizeObserver` reads both again whenever the hidden 1 rem probe
|
|
3471
|
+
(`data-daily-report-root-font-size-probe`) or the target probe changes size, and the List renders its `VirtualScroll` only once P is known
|
|
3472
|
+
(measured before the first paint).
|
|
3459
3473
|
That one value sizes the row frames, `VirtualScroll`'s rows and the keyboard's row geometry, and when it changes the List keeps the first visible
|
|
3460
3474
|
row in place by rescaling the scroll position. At the default 16 px root the sum is exactly 160, so P = 160: the card is P − 2G = 144 px, cards are
|
|
3461
3475
|
16 px apart and an edge-aligned card sits 8 px from the edge (exactly 8 when the view's height is a whole number of device pixels, see **G-symmetric
|
|
@@ -3497,6 +3511,10 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3497
3511
|
The content of a full card is 6.75 rem: the pills' line 1.5 rem + 0.5 + three one-line preview paragraphs of 1.25 rem, 0.5 rem apart (24 + 8 + 3 ×
|
|
3498
3512
|
20 + 2 × 8 = 108 px at a 16 px root), inside a 1 + 15 inset at the top and the bottom (the inset counts the border, below), so 1 + 15 + 6.75R + 15 +
|
|
3499
3513
|
1 ≤ P − 2G with at least 4 px to spare at every root font size (140 ≤ 144 at 16 px).
|
|
3514
|
+
Under a coarse pointer the card is a two-column grid (`minmax(0, 1fr)` and `auto`): the primary button and the markers share the header line, and the
|
|
3515
|
+
44 px star and read toggles sit in the second column of the second line, 4 px apart, beside the preview, so the header line stays 1.5 rem and P keeps
|
|
3516
|
+
its value at a 16 px root. Under a fine pointer the two groups that hold the markers and the toggles make no box (`display: contents`), so the card
|
|
3517
|
+
lays out exactly as above.
|
|
3500
3518
|
- **Forced colours**: the ring (a box shadow) disappears, so the row frame draws the selection itself: a 2 px solid `Highlight` outline at offset −8
|
|
3501
3519
|
(−G), which puts the line in the ring's band, 0–2 px outside the surface. The frame's corner radius is the surface's radius plus G
|
|
3502
3520
|
(`calc(var(--radius-2xl) + 8px)`, 24 at a 16 px root), so the line is concentric with the surface at every root font size.
|
|
@@ -3756,7 +3774,9 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3756
3774
|
inside the band: one more 32 px block), so the views start q + the band below the column's top — 4 + 32 = 36 px at the multiples of 1/4 and 8 + 32 =
|
|
3757
3775
|
40 px at the odd eighths, or 4 + 64 = 68 px and 8 + 64 = 72 px with the search row — on the lattice at every ratio.
|
|
3758
3776
|
The search row's 24 px controls stand at its bottom, so the gap above them is 32 − 24 = 8 = G from the toolbar's bar and their bottom edge is G
|
|
3759
|
-
above the view's first surface.
|
|
3777
|
+
above the view's first surface. Under a coarse pointer the band's controls are 48 px (44 rounded up to 8), so the bar is 4 + 48 + 4 = 56 px (112 px
|
|
3778
|
+
when it wraps) and the search row's first line 8 + 48 = 56 px: all multiples of 8, so every edge inside the band, not only its bottom, lands on a
|
|
3779
|
+
whole device pixel at every ratio. The band stacks above the views (`relative z-[1]`), so the 4 px focus outline of a search control that ends at the
|
|
3760
3780
|
view's top paints over the view's G strip.
|
|
3761
3781
|
Measured in Chromium at 1280 × 800 and 1.125 under a 32 px host header: the toolbar, the view and the first row surface start at device pixels 45,
|
|
3762
3782
|
81 and 90 (with a 4 px inset and no band they started at 40.5, 76.5 and 85.5, half a device pixel off, and every row edge, ring and outline below
|
|
@@ -3865,24 +3885,48 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3865
3885
|
refuses one without a registered surface, and measures each against its surfaces. The quiet text (section labels, metadata, placeholders, the empty
|
|
3866
3886
|
view, inactive tabs) is one token, `--aqdr-text-quiet` (light `oklch(44% 0.046 257.417)`, dark `oklch(77% 0.040 256.788)`: slate-500's and
|
|
3867
3887
|
slate-400's hue and chroma), whose lightness `src/client/ui/aaa-quiet-text.spec.ts` solves from the surfaces it sits on (light 7.06–7.73, dark
|
|
3868
|
-
7.07–9.75). A source badge's colours are the host's (**External Source Badge Configuration**).
|
|
3869
|
-
List's resize handle with its 10 px hit area and the 8 px scroll bar beside it (**Side pane** above);
|
|
3888
|
+
7.07–9.75). A source badge's colours are the host's (**External Source Badge Configuration**). Under a fine pointer targets stay at WCAG 2.5.8's
|
|
3889
|
+
24 px, except the List's resize handle with its 10 px hit area and the 8 px scroll bar beside it (**Side pane** above); under a coarse pointer they
|
|
3890
|
+
reach 2.5.5's 44 px (**Coarse pointers** below), so 2.5.5 is not claimed overall.
|
|
3870
3891
|
- **WCAG 2.2 AAA beyond contrast**: met are 1.4.9 (no images of text), 2.1.3 (every function by the keyboard, the List splitter's arrow keys
|
|
3871
3892
|
included), 2.2.3 (nothing on a timer; **The built-in notice**), 2.3.2 (no flashes), 2.3.3 (motion follows `prefers-reduced-motion`), 2.4.8 (the page
|
|
3872
3893
|
and the report headings tell where the viewer is), 2.4.9 (links name their purpose), 2.4.10 (sections carry headings), 2.4.12 and 2.4.13 (the focus
|
|
3873
3894
|
is never obscured, and its outline is 2 px at 3:1), 3.1.3, 3.1.4 (abbreviated source badges, **External Source Badge Configuration**), 3.2.5 and
|
|
3874
3895
|
3.3.6. Not met, by decision: 2.2.4 (Interruptions): live updates (SSE) apply as they arrive, with no pause, and
|
|
3875
3896
|
the scroll anchoring keeps the rows on screen in place. Not met at AA: 2.5.8 for the List's resize handle and the scroll bar beside it (**Side pane** above): larger hit areas for the handle and the
|
|
3876
|
-
bar wait for the same layout pass as 2.5.5.
|
|
3897
|
+
bar wait for the same layout pass as 2.5.5 under a fine pointer. Met under a coarse pointer only: 2.5.5 (44 px targets; **Coarse pointers** below).
|
|
3898
|
+
Not claimed yet: 2.5.5 under a fine pointer, 1.4.8 (a line measure and the List preview's
|
|
3877
3899
|
leading) and 3.3.5 (a help control for the search syntax), which need a layout pass, and 3.1.6 (readings of names), which needs readings from the
|
|
3878
3900
|
host's directory. 2.2.5 (Re-authenticating) is met with the host: at a session end the package pauses without reloading and keeps every draft, the
|
|
3879
3901
|
open edit form, the selection, the search and the scroll in memory; the host lets the viewer sign in again without leaving the page and advances
|
|
3880
3902
|
`sessionEpoch`, and the package resumes and sends nothing again by itself ([Client wiring](#client-wiring)). 2.2.6 (Timeouts) is the host's: the
|
|
3881
3903
|
package keeps unsent work only in the open tab's memory until it is closed, and the host states how long a session lasts and what ends it. The floating tap-scroll circle hides while the view root carries `data-daily-report-keyboard-focus` (through the class both views pass in
|
|
3882
3904
|
`VirtualScroll`'s tap-scroll circle options).
|
|
3905
|
+
- **Coarse pointers (touch screens)**: under `@media (pointer: coarse)` every target is at least 44 × 44 CSS px (WCAG 2.5.5's enhanced size, T =
|
|
3906
|
+
44 = 11 units of the 4 px lattice, written in px so it never shrinks with the root font size): the action buttons, the toolbar's and
|
|
3907
|
+
the side pane's tabs (the side pane's bar becomes 4 + 44 + 4 = 52 px), the create button, the search box's toggles, field and clear button, the comment field
|
|
3908
|
+
and its send button, the delete confirmation, the overlay's and the notice's close buttons, both retry buttons, `Button` and `Input` of the edit form,
|
|
3909
|
+
and the attachments' download and row links (a tile's last line becomes 48 px, 44 rounded up to 8, so tiles stay on the device-pixel lattice). The toolbar band's
|
|
3910
|
+
controls take that 48 px height too (the view tabs, the create button, the auto-read switch's line, the search field and both toggles), because
|
|
3911
|
+
both edges of each must land on whole device pixels at the odd-eighth ratios (a 44 px box is 115.5 device pixels at 2.625): the toolbar's bar
|
|
3912
|
+
becomes 4 + 48 + 4 = 56 px (112 px when it wraps to two lines) and the search row's first line 8 + 48 = 56 px. A round
|
|
3913
|
+
or pill-shaped control also gets a transparent square hit area over its padding box, because hit testing follows the rounded corners and a 44 px circle
|
|
3914
|
+
does not hold a 44 × 44 square (a bordered control about 44 px wide adds `pointer-coarse:before:-inset-px` so the square also covers its border,
|
|
3915
|
+
as the search box's pills and the List's mobile overlay close button do). Each box grows only through a minimum size, so nothing changes under a fine pointer (mouse, trackpad, pen), where targets keep the 24 px geometry of WCAG
|
|
3916
|
+
2.5.8; 2.5.5 is therefore met under a coarse pointer only and not claimed overall. The auto-read switch keeps its 40 × 24 look and gets a centred
|
|
3917
|
+
44 × 44 hit area in the band's 48 px line; the side pane's action buttons move to a 44 px line of their own under the subject, at its end. Exceptions under a
|
|
3918
|
+
coarse pointer: the List's resize handle and the views' scroll bars, the host's filter select controls, the dev toolbox's reload and clear-cache
|
|
3919
|
+
icon buttons (24 × 24 targets in its 24 px box; its SSE switch has the switch's centred 44 × 44 hit area, and under a coarse pointer the toolbox
|
|
3920
|
+
spaces its items 6 px apart, 4 + (44 − 40) / 2, so that hit area does not cover the reload button's target) and `VirtualScroll`'s tap-scroll
|
|
3921
|
+
circle. A Tailwind host generates these coarse-pointer utilities from Tailwind CSS v4.1 on (**Tailwind v4 host** above). Text fields use 16 px text under a coarse pointer (14 px under a fine one), so focusing them does not zoom the page on touch
|
|
3922
|
+
browsers; the search field's Enter key is labelled as search (`enterkeyhint="search"`) and the comment field's as send (`enterkeyhint="send"`). When
|
|
3923
|
+
the views are narrower than 320 px (the search row's smallest coarse-pointer width: the band's insets, both toggles, two 8 px gaps and a field that
|
|
3924
|
+
keeps one 44 px target of text room), the search box's filter toggle moves to a line of its own under the field. The mobile overlay keeps its
|
|
3925
|
+
content at least its 16 px padding and at least the display's safe-area insets (`env(safe-area-inset-*)`) from each edge.
|
|
3883
3926
|
- **Action buttons and icons**: the List card's star and read toggles, the star, read, edit and delete buttons of the DetailList header and the side
|
|
3884
|
-
pane, and the trash button of the viewer's comments share one 24 px round target
|
|
3885
|
-
|
|
3927
|
+
pane, and the trash button of the viewer's comments share one 24 px round target under a fine pointer (44 × 44 under a coarse one, **Coarse
|
|
3928
|
+
pointers** above), which never shrinks, with a 16 px SVG icon centred in it (4 px on every side, 14 px in the coarse box), so the icons sit on the
|
|
3929
|
+
4 px grid without depending on a font. In the List card the markers and toggles stand 4 px apart; the header
|
|
3886
3930
|
pills and the source badge are 24 px tall like the targets.
|
|
3887
3931
|
The star is a regular five-pointed star, outlined when off and filled gold when on (with a darker gold edge in the light theme); read is a check,
|
|
3888
3932
|
unread an 8 px dot, edit a pencil, delete a trash can. Every icon state reaches at least 3.59:1 against each background it sits on, the button's
|