@aiquants/daily-report 0.50.0 → 0.51.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.
- package/CHANGELOG.md +50 -0
- package/README.md +88 -67
- package/dist/client.js +5 -5
- package/dist/client.mjs +5 -5
- package/dist/styles/daily-report.standalone.css +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,56 @@ All notable changes to `@aiquants/daily-report` are documented here.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **低い窓でもビューが 0 に潰れない (WCAG 1.4.10)**: 0.51.0 で操作列の帯がどのポインターでも 56px (折り返せば 112px)、検索の行の帯が 56〜112px になったため、
|
|
10
|
+
400 % の拡大 (320 × 256 CSS px、マウス) ではホストの見出し 148px と 2 つの帯 224px が列を使い切り、List と DetailList のビューの高さが 0 になって行に届かなかった。
|
|
11
|
+
ビューの根要素は最小の高さとして List の行の枠の高さ 1 つ分 P (`VIEW_MIN_BLOCK_SIZE_CLASS_NAME` = 4⌈(52px + 2rem + max(4.75rem, 44px)) / 4⌉。根 16px で 160。
|
|
12
|
+
`round()` を持たない描画エンジンは切り上げる前の和) を持ち、ページの箱からビューの根要素までの箱 (ページの枠・内容の列・ビューのタブ・タブの中身。
|
|
13
|
+
`PAGE_FILL_COLUMN_CLASS_NAME`) は中身の最小 (帯とビューの最小の高さ) より小さくならない。帯とビューの最小の高さが収まらない窓では、ページの箱がホストの列から
|
|
14
|
+
はみ出し、ホストの列 (かその祖先) の縦のスクロールがページ (見出し・帯・ビュー) を動かす。ホストはその列を `overflow-y: auto` にする (はみ出しを切る列ではビューが
|
|
15
|
+
隠れる。README の「Host scroll for short windows」)。ふつうの高さの窓では何も変わらない (ビューは列の残りを埋め、ページはスクロールしない)。
|
|
16
|
+
- **側面ペインの記事のスクロールの箱が潰れない (WCAG 1.4.10)**: 同じ 400 % の拡大で List のカードから開くモバイルのオーバーレイ (ダイアログ 256px) では、ペインの帯
|
|
17
|
+
(見出しの列とタブの並び) の下で記事のスクロールの箱が 12px まで潰れ、スクロールで見せたスターと既読のボタン (44px) の中心が箱の外に落ちて押せなかった。
|
|
18
|
+
記事と相関のタブの中身は最小の高さとして的の行 1 行 (`SIDE_PANE_SCROLL_PANEL_MIN_BLOCK_SIZE_CLASS_NAME` = `--spacing(2)` + T + 4px。根 16px で 56px) を持ち、
|
|
19
|
+
帯 (`SIDE_PANE_HEADER_BOX_CLASS_NAME`) は縮まず、タブの根は中身に基づく最小の高さを保つ。ペインが帯と的の行 1 行を入れきれない高さでは、見出しの列とタブの根を
|
|
20
|
+
包む中身の箱 (`SIDE_PANE_CONTENT_BOX_CLASS_NAME`) が縦にスクロールする (見出し・タブ・記事が一緒に動く。デスクトップでは細いバーにビューのスクロールバーの組の色、
|
|
21
|
+
オーバーレイでは面の縦のスクロール領域 `SWIPE_OVERLAY_SCROLL_AREA_STYLE` で、閉じるボタンは箱の下に残る)。ふつうの高さでは何も変わらない (スクロールの範囲が
|
|
22
|
+
無い)。オーバーレイの中身の箱はスクロール領域なので、見出しとタブの並びで始まった縦の 1 本指の動きも記事の上と同じくブラウザーのスクロールへ渡る (横の動きは
|
|
23
|
+
今まで通りスワイプ)。
|
|
24
|
+
- **オーバーレイの知らせの置き場が空のとき場所を取らない**: 置き場には知らせの提供者の警告の領域 (見えない `role="alert"`) が常に入るので `:empty` で隠れず、
|
|
25
|
+
高さ 0 の項目として列の間隔 16px を 2 つ並べていた (320 × 256 では日報の箱から 16px を奪った)。置き場は見える知らせを持つ間だけ flex の箱になり、それ以外は
|
|
26
|
+
箱を作らない (`display: contents`。警告の領域は読み上げの木に残る)。どの高さでもオーバーレイの日報の箱が 16px 高くなる (閉じるボタンの位置は変わらない)。
|
|
27
|
+
|
|
28
|
+
## 0.51.0 (2026-10-25)
|
|
29
|
+
|
|
30
|
+
### Breaking
|
|
31
|
+
|
|
32
|
+
- **的の大きさと配置がどのポインターでも同じ (マウス・トラックパッド・ペンでも 44 × 44 CSS px。WCAG 2.5.5)**: 0.50.0 で粗いポインター
|
|
33
|
+
(`(pointer: coarse)`) にだけ当てた的の箱と配置が、媒体条件の無い規則になる。操作ボタン (List のカード・DetailList の見出し・側面ペインのスター・既読・編集・削除、
|
|
34
|
+
コメントのゴミ箱) は 44px の丸い的、ビューと側面ペインのタブ・作成のボタン・検索の切り替えと入力欄と消去のボタン・コメントの入力欄と送信・削除の確認・オーバーレイと
|
|
35
|
+
誤りの知らせの閉じるボタン・2 つの再試行・編集フォームの `Button` と `Input`・添付のダウンロードと行のリンクは 44px 以上の箱 (`TARGET_CLASS_NAME`)、自動既読のスイッチは
|
|
36
|
+
中央の 44 × 44 の当たりを持つ。List のカードは 2 列の格子 (スターと既読はプレビューの右の 2 行目。行の枠の高さ P は根 16px で 160 のまま)、側面ペインの操作ボタンは件名の
|
|
37
|
+
下の自分の 44px の行、操作列の帯の部品は 48px で、操作列の並びは 4 + 48 + 4 = 56px (折り返せば 112px)、検索の行の 1 行目は 56px、ビューの幅が 320px 未満なら検索の
|
|
38
|
+
絞り込みの切り替えは自分の行へ折り返す。添付のタイルの最後の行は 48px (タイルは h + 80)、コメントの削除の枠と失敗の札は 44px の行。デスクトップのホストでは操作列の帯が
|
|
39
|
+
32px から 56px (検索の行があれば 64px から 112px) になってビューの上端が下がり、DetailList の見出し・コメント・側面ペイン・List のカードの並びと高さが変わる。
|
|
40
|
+
大きさの段の高さが的を下回る部品は高さのクラスを持たない (的の箱だけが大きさを決める。操作列の作成のボタンは `Button` の大きさの段を持たない)。
|
|
41
|
+
- **的のトークンの名前から `COARSE_` を外した** (どれもパッケージの外へは公開しない): `COARSE_TARGET_CLASS_NAME` → `TARGET_CLASS_NAME`、
|
|
42
|
+
`COARSE_FIELD_TARGET_CLASS_NAME` → `FIELD_TARGET_CLASS_NAME`、`COARSE_TARGET_LINE_CLASS_NAME` → `TARGET_LINE_CLASS_NAME`、
|
|
43
|
+
`COARSE_LATTICE_TARGET_CLASS_NAME` → `LATTICE_TARGET_CLASS_NAME`、`SEARCH_FILTERS_TOGGLE_COARSE_WRAP_CLASS_NAME` → `SEARCH_FILTERS_TOGGLE_WRAP_CLASS_NAME`。
|
|
44
|
+
細かいポインターのための値は消した: コメントのゴミ箱の負の余白 `ACTION_BUTTON_INLINE_INSET_CLASS_NAME`、操作ボタンと区切りのトリガーと検索の欄と切り替えの 24px の高さ、
|
|
45
|
+
添付のダウンロードの `after:` の 24px の的、List のカードの折り返す flex の行と、目印と切り替えの 2 つの群を包んでいた操作の並び (カードの要素は 1 つ減る)、
|
|
46
|
+
切り替えの的の大きさの探りの高さ 0 (`TARGET_SIZE_PROBE_CLASS_NAME` は `h-[44px]`)。
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- **粗いポインターの媒体条件のまま残す規則は、欄の 16px の文字 (`pointer-coarse:text-base`) だけ**: 編集フォームの `Input` と `Textarea`・コメントと検索の
|
|
51
|
+
入力欄は、粗いポインターでは 16px (iOS の Safari のフォーカスでの拡大を防ぐ)、細かいポインターでは 14px のまま。Tailwind でクラスを作るホストが v4.1 以上を
|
|
52
|
+
要るのはこの規則のため (それより前の v4 では 16px の文字が作られない)。的の例外 (List のリサイズの取っ手とスクロールバー・ホストの絞り込みの選択の部品・
|
|
53
|
+
開発用の箱の再読み込みとキャッシュの消去・VirtualScroll のタップスクロールの円) は今のままで、2.5.5 は全体としては主張しない。
|
|
54
|
+
|
|
55
|
+
## 0.50.0 (2026-10-24)
|
|
56
|
+
|
|
7
57
|
### Breaking
|
|
8
58
|
|
|
9
59
|
- **`@aiquants/swipe-overlay` のピアの下限が、`useSwipeOverlayDialog`・`useOverlayPresence`・`SWIPE_OVERLAY_SCROLL_AREA_STYLE` を持つ版へ上がる**。
|
package/README.md
CHANGED
|
@@ -180,9 +180,9 @@ utilities are generated in one canonical build, define the `dark:` variant, and
|
|
|
180
180
|
|
|
181
181
|
The host must also:
|
|
182
182
|
|
|
183
|
-
- Build with Tailwind CSS v4.1 or later. The
|
|
184
|
-
`pointer-coarse:`
|
|
185
|
-
|
|
183
|
+
- Build with Tailwind CSS v4.1 or later. The fields' 16 px text on touch screens (**Target size** in Selection and focus appearance) is a
|
|
184
|
+
`pointer-coarse:` utility, a variant Tailwind added in v4.1; an older v4 build does not generate it, so focusing a field zooms the page on a touch
|
|
185
|
+
browser.
|
|
186
186
|
- Load the `tailwindcss-animate` plugin. The components use `animate-in` / `fade-in` / `zoom-in-95` / `slide-in-from-bottom-2` entrance animations
|
|
187
187
|
(all under `motion-safe:`); without `@plugin "tailwindcss-animate"` those classes are not generated and the animations silently no-op.
|
|
188
188
|
- Define the shadcn CSS variables themselves (`--background`, `--muted`, `--radius`, ...).
|
|
@@ -2205,7 +2205,7 @@ failed, and the filter row while it is open.
|
|
|
2205
2205
|
Enter, Esc and the debounce wait while an IME composes.
|
|
2206
2206
|
The filter row is inside the landmark, so its cells belong to the search for assistive technology and Tab goes from the field to the filter toggle and
|
|
2207
2207
|
on into the cells; the landmark has no name (the screen has one search landmark), and the filter row's own name comes from the filter toggle.
|
|
2208
|
-
The row's first line is one
|
|
2208
|
+
The row's first line is one 56 px lattice block whose 48 px controls stand at its bottom, so they sit G = 8 under the toolbar's bar and, while the
|
|
2209
2209
|
filter row is closed and no search failed, their bottom edge is G above the view's first surface; its second line holds the failure line.
|
|
2210
2210
|
The band carries the toolbar's start inset G and the active view's end inset, so the field ends where the cards end in both views, and it stacks above
|
|
2211
2211
|
the view, so a control's focus outline paints over the view's G strip (**Origin on the lattice** in
|
|
@@ -2228,7 +2228,7 @@ while the screen shows searching as the indicator and a failure on the failure l
|
|
|
2228
2228
|
line wraps instead of truncating;
|
|
2229
2229
|
it comes first in the field's description (before the syntax help), and the field is `aria-invalid` only for an invalid query (busy, unavailable and
|
|
2230
2230
|
other failures are no input errors).
|
|
2231
|
-
The AND / OR toggle and the filter toggle share one look: a
|
|
2231
|
+
The AND / OR toggle and the filter toggle share one look: a 48 px tall pill (the band's control height) with 12 px semibold text, in the field face (OR; the closed filter row), whose
|
|
2232
2232
|
boundary comes from the text-field token as the field's does, or the filled face (AND; the open filter row), blue-800 under white text (dark: a light
|
|
2233
2233
|
blue-300 fill under slate-950 text) and `Highlight` under `HighlightText` in forced colours (**Text fields** in [Selection and focus appearance](#selection-and-focus-appearance)).
|
|
2234
2234
|
The faces differ only in colour, so a toggle that changes its face moves nothing. Each toggle stacks its current label and an invisible reserved label
|
|
@@ -2786,9 +2786,16 @@ view, and no script computes or writes a height.
|
|
|
2786
2786
|
(`display: flex; flex-direction: column`) whose height is bounded — a definite height, or the growing item of a column with a minimum height, such
|
|
2787
2787
|
as a `min-height: 100dvh` shell whose footer follows the content. The header that `renderHeader` returns and the page box are items of that
|
|
2788
2788
|
container, and the page box takes the rest of it. Nothing is bound and no host variable is read.
|
|
2789
|
-
Outside such a container the view has
|
|
2789
|
+
Outside such a container the view has only its minimum (below): its size is contained, so its content cannot size it.
|
|
2790
|
+
- **Host scroll for short windows**: a view never gets shorter than one List row slot P (**The view's minimum** below). When the container is shorter
|
|
2791
|
+
than the toolbar band plus that minimum (a 400 % zoom, a short window), the page box grows past the container instead of the view collapsing, so the
|
|
2792
|
+
container or one of its ancestors must scroll in the block axis (`overflow-y: auto`, not `hidden` or `clip`): the page scrolls (the host's header,
|
|
2793
|
+
the bands and the view) and every row stays reachable (WCAG 1.4.10). A container that clips its overflow hides the view. At ordinary window sizes the
|
|
2794
|
+
minimum is below the space left, the page box just fills the container and nothing scrolls.
|
|
2790
2795
|
- **The fill chain**: every box from the page box down to a view's root — the page box, its centred width-capped wrapper, the view-mode tabs and the
|
|
2791
|
-
active tab panel — fills the rest of its parent column (`flex: 1 1 0
|
|
2796
|
+
active tab panel — fills the rest of its parent column (`flex: 1 1 0%`), never gets smaller than its content's minimum (`min-height: auto`: the band
|
|
2797
|
+
and the view's minimum) and declares no height. The view's root fills the tab panel at `flex: 1 1 0%` with the view's minimum as its
|
|
2798
|
+
`min-height`. The wrapper's padding is the block
|
|
2792
2799
|
quantum q of the device-pixel lattice at the top and the sides (4 px, 8 px at the odd multiples of 1/8; **Row slots on the lattice**) and none at
|
|
2793
2800
|
the bottom, so the view's box ends exactly at the page's bottom edge.
|
|
2794
2801
|
Between the wrapper's top and the active tab panel sits the band of the view-mode toolbar (the search row too, when configured), which does not
|
|
@@ -2797,9 +2804,28 @@ view, and no script computes or writes a height.
|
|
|
2797
2804
|
box (the fill rule and the page surface, slate-50 / dark slate-950) and its centred column (the fill rule, at most `max-w-6xl`, q from the frame's
|
|
2798
2805
|
top and side edges, starting on the lattice; the column carries q itself). So the page keeps its colour in both schemes while loading ends (a dark
|
|
2799
2806
|
page never shows the light surface first) and the content does not move sideways between the screens.
|
|
2807
|
+
- **The view's minimum**: one List row slot P = 4 · ⌈(52 px + 2 rem + max(4.75 rem, 44 px)) / 4⌉ (**List slot P**; 160 px at a 16 px root), the
|
|
2808
|
+
smallest whole row the views draw, as the root's `min-height` in the slot's own expression (an engine without `round()` takes the unrounded sum,
|
|
2809
|
+
less than 4 px below P). A view of that height shows at least one whole List card; a DetailList row, taller than P, scrolls inside the view.
|
|
2810
|
+
- **The side pane's minimum and its own scroll**: the side pane (the desktop frame beside the List and the mobile overlay's pane box) stacks two
|
|
2811
|
+
bands, the header column (business date and author) and the tab list, above its tab panel, a scroll box. The bands never shrink, and the tab panel
|
|
2812
|
+
never gets shorter than one whole target row inside its own block padding: `--spacing(2)` (its top padding) + T (44 px) + 4 px (the focus-ring
|
|
2813
|
+
reach at its bottom), 56 px (14 lattice units) at a 16 px root, so a 44 px control scrolled into view lies inside the box with its focus ring
|
|
2814
|
+
(4 + 44 + 4 = 52 within the scroll padding). The tabs root keeps its content's minimum (the tab list plus that row). When the pane cannot hold the
|
|
2815
|
+
bands plus that row (a 400 % zoom, a short window), the pane's content box (around the header column and the tabs, its clipping edges 4 px
|
|
2816
|
+
outside its content) overflows and scrolls in the block axis, so the header, the tabs and the article move together. On the desktop its thin bar
|
|
2817
|
+
wears the views' scroll-bar colours; in the overlay it is a vertical scroll area of the swipe overlay's panel (`touch-action: pan-y pinch-zoom`
|
|
2818
|
+
and `overscroll-behavior-y: contain`) and the close button stays below it. It never scrolls sideways, so a horizontal move on the overlay's pane
|
|
2819
|
+
is still the swipe.
|
|
2820
|
+
At ordinary heights the content fits, there is no scroll range and nothing moves. The pane scrolls inside the view's box, so the host needs
|
|
2821
|
+
nothing for it.
|
|
2822
|
+
- **The overlay's notice slot takes room only for the notice**: the slot of the error notice in the overlay, between the pane box and the close
|
|
2823
|
+
button, always holds the provider's alert region (a visually hidden `role="alert"` element), so it is never empty. It generates no box
|
|
2824
|
+
(`display: contents`) unless it holds the visible notice, so the column keeps one 16 px gap between the pane box and the close button; the alert
|
|
2825
|
+
region, absolutely positioned, stays in the accessibility tree.
|
|
2800
2826
|
- **The view's root contains its size** (the fill rule, `contain: size` and `overflow: clip`, its children in block flow): its box is sized as if it
|
|
2801
2827
|
were empty, so what the view renders — a `VirtualScroll` given the measured height — never feeds back into the root's size, into the intrinsic size
|
|
2802
|
-
of an ancestor (a host column with a minimum height does not grow) or into the document's scroll height. The clip keeps rows drawn for the previous
|
|
2828
|
+
of an ancestor (a host column with a minimum height does not grow) or into the document's scroll height; only the view's minimum does. The clip keeps rows drawn for the previous
|
|
2803
2829
|
height from painting outside the box during the one frame before the view renders the new height.
|
|
2804
2830
|
The root's layout and paint are not contained: either would make the root the containing block of the mobile overlay, a fixed-position descendant,
|
|
2805
2831
|
and as a flex item of its column the root could not be a relayout boundary anyway (Chromium makes no flex or grid item one, contained or not).
|
|
@@ -3461,13 +3487,12 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3461
3487
|
`resolution: <dpr>dppx` of each of the twelve ratios with `calc(⌊2·dpr⌋px / dpr)`), and the lift reads it
|
|
3462
3488
|
(`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
|
|
3463
3489
|
compile the same rules.
|
|
3464
|
-
- **List slot P**: the List card's content is sized in rem (its toggles in px
|
|
3490
|
+
- **List slot P**: the List card's content is sized in rem (its toggles in px), so the slot follows the page's root font size R
|
|
3465
3491
|
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
3492
|
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
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
(`data-daily-report-target-size-probe`); one `ResizeObserver` reads both again whenever the hidden 1 rem probe
|
|
3493
|
+
lattice. T is 44, the toggles beside the preview (**List card** below); at a 16 px root 4.75 rem = 76 px is taller than 44, so P is 160.
|
|
3494
|
+
R is read from the root element's computed style and T from the height of a hidden 44 px probe (`data-daily-report-target-size-probe`, 0 until it
|
|
3495
|
+
is laid out); one `ResizeObserver` reads both again whenever the hidden 1 rem probe
|
|
3471
3496
|
(`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
3497
|
(measured before the first paint).
|
|
3473
3498
|
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
|
|
@@ -3504,17 +3529,14 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3504
3529
|
8 px (2 u), and 440 px (110 u) until it has measured one; the view applies a changed estimate only at rest, with the first visible report kept in
|
|
3505
3530
|
place — also on the lattice at every ratio of the domain, so the unmeasured rows above the window move the rows below by whole device pixels. An image attachment tile is padded to q as well (**Tile** in
|
|
3506
3531
|
[Attachment display](#attachment-display)), so the rows below an image grid stay on whole device pixels.
|
|
3507
|
-
- **List card**: a
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
the
|
|
3532
|
+
- **List card**: a two-column grid (`minmax(0, 1fr)` and `auto`): the primary button and the markers share the header line, and the 44 px star and
|
|
3533
|
+
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 160 at a
|
|
3534
|
+
16 px root. The primary button takes the first column but never less than 96 px, enough for the business-date pill, and the card clips what no
|
|
3535
|
+
longer fits. The markers and the toggles are two groups that are the grid's own items; no element wraps them.
|
|
3511
3536
|
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 ×
|
|
3512
3537
|
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 +
|
|
3513
3538
|
1 ≤ P − 2G with at least 4 px to spare at every root font size (140 ≤ 144 at 16 px).
|
|
3514
|
-
|
|
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.
|
|
3539
|
+
|
|
3518
3540
|
- **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
|
|
3519
3541
|
(−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
|
|
3520
3542
|
(`calc(var(--radius-2xl) + 8px)`, 24 at a 16 px root), so the line is concentric with the surface at every root font size.
|
|
@@ -3750,7 +3772,7 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3750
3772
|
The frame height is not snapped to 4 px: snapping moves the frame's shape more than 0.01 away from 3 : 2 (196 → 132 gives |t / h − 3 / 2| = 0.0152,
|
|
3751
3773
|
171 → 116 gives 0.026) and letterboxes a 3 : 2 image, which fills an unsnapped frame exactly.
|
|
3752
3774
|
The tile around the frame is on the lattice anyway: its last line carries the pad δ(t) = ⌈h / q⌉ · q − h (0 to q − 1 px, q the block quantum of
|
|
3753
|
-
**Row slots on the lattice**) as a bottom margin, so every tile is ⌈h / q⌉ · q +
|
|
3775
|
+
**Row slots on the lattice**) as a bottom margin, so every tile is ⌈h / q⌉ · q + 80 px tall, every tile row top and every grid's height are
|
|
3754
3776
|
multiples of q, and what follows a grid stays on whole device pixels (**Tile** in [Attachment display](#attachment-display)).
|
|
3755
3777
|
A bordered box counts its border in its inset, so that its content edge sits on the grid measured from the visible edge: border + padding is on the
|
|
3756
3778
|
ladder — 16 for the card surfaces, the error panel, the sides of the error notice and the mobile overlay's close button (1 + 15), 8 for the form
|
|
@@ -3761,8 +3783,8 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3761
3783
|
posted comment and the bordered pill (1 + 11); a 24 px pill has the same 12 px padding at its round ends. The tab bars are not in that tier: their 4
|
|
3762
3784
|
px inset makes them concentric with their 8 px tabs (12 − 4 = 8).
|
|
3763
3785
|
The only other exceptions are the visually hidden text (Tailwind's `sr-only`, and inside virtualized rows and for every attachment file name the
|
|
3764
|
-
package's transparent 1 px box, which clips nothing and contains its own layout) and the
|
|
3765
|
-
searching indicator and the clear
|
|
3786
|
+
package's transparent 1 px box, which clips nothing and contains its own layout) and the 68 px the search field keeps free at its end for the
|
|
3787
|
+
24 px searching indicator and the 44 px clear target inside its box. `src/client/ui/spacing-ladder.guard.spec.ts` checks every class the package writes, that every
|
|
3766
3788
|
bordered box's border + padding is on the ladder or equals its corner, and that every 12 px-corner panel's inset is 12.
|
|
3767
3789
|
- **Origin on the lattice**: the views' centred column (at most 72 rem, `max-w-6xl`, centred with `mx-auto`) starts at the centring offset rounded
|
|
3768
3790
|
down to a multiple of the block quantum q (`ml-[max(0px,round(down,calc((100%-72rem)/2),var(--aqdr-lattice-block)))]`, on the column that carries q
|
|
@@ -3771,16 +3793,14 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3771
3793
|
8 px at the odd multiples of 1/8), so every inline edge built on the origin — G, the ladder steps of 8 and 16, the card, the row frame — starts on a
|
|
3772
3794
|
whole device pixel: on a 412 px phone at 2.625 a DetailList surface's left edge is 16 px in, at device pixel 42.
|
|
3773
3795
|
Below the column's top inset the view-mode toolbar sits in its band, as tall as its content rounded up to q (the search row, when configured, is
|
|
3774
|
-
inside the band: one more
|
|
3775
|
-
|
|
3776
|
-
The
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
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
|
|
3783
|
-
inherited the half pixel).
|
|
3796
|
+
inside the band: one more 56 px block), so the views start q + the band below the column's top — 4 + 56 = 60 px at the multiples of 1/4 and 8 + 56 =
|
|
3797
|
+
64 px at the odd eighths, or 4 + 112 = 116 px and 8 + 112 = 120 px with the search row — on the lattice at every ratio.
|
|
3798
|
+
The band's controls are 48 px (44 rounded up to 8), so the bar is 4 + 48 + 4 = 56 px (112 px when it wraps) and the search row's first line
|
|
3799
|
+
8 + 48 = 56 px, its controls at its bottom G = 8 under the bar and G above the view's first surface: all multiples of 8, so every edge inside the
|
|
3800
|
+
band, not only its bottom, lands on a whole device pixel at every ratio. The band stacks above the views (`relative z-[1]`), so the 4 px focus
|
|
3801
|
+
outline of a search control that ends at the view's top paints over the view's G strip.
|
|
3802
|
+
At 1280 × 800 and 1.125 under a 32 px host header the toolbar, the view and the first row surface therefore start at device pixels 45, 108 and 117
|
|
3803
|
+
(with a 4 px inset and no band they would start half a device pixel off, and every row edge, ring and outline below would inherit the half pixel).
|
|
3784
3804
|
Still off the lattice at the odd eighths (measured, open): an inline edge at an odd multiple of 4 px inside a surface (the 12 px tier's insets, the
|
|
3785
3805
|
4 px insets of the tab bars and of the toolbar inside its band); the focus outline's 4 px offset, 10.5 device pixels at 2.625, which no CSS length
|
|
3786
3806
|
moves, since Chromium 148 rounds `outline-offset` down to whole CSS px (`calc(10px / 2.625)` gives 3 px); and the positions the browser chooses
|
|
@@ -3829,8 +3849,8 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3829
3849
|
- **Tab bars are one segmented control**: the side pane's tabs and the view-mode toolbar share one geometry. The bar has a 12 px corner (`rounded-xl`)
|
|
3830
3850
|
and a total inset of 4 px that counts its border (4 px padding without a border; 1 px border + 3 px padding with one), the same at the top and at
|
|
3831
3851
|
the sides.
|
|
3832
|
-
The tabs are
|
|
3833
|
-
with its bar: 12 − 4 = 8. Because xl − lg = 4 equals the inset both in Tailwind's scale and in a host `--radius` scale (lg = `--radius`, xl =
|
|
3852
|
+
The tabs are 44 px tall (the target T; 48 px in the toolbar's band) with 12 px labels and an 8 px corner (`rounded-lg`), so the side pane's bar is
|
|
3853
|
+
4 + 44 + 4 = 52 px and the toolbar's 4 + 48 + 4 = 56 px tall, and every tab is concentric with its bar: 12 − 4 = 8. Because xl − lg = 4 equals the inset both in Tailwind's scale and in a host `--radius` scale (lg = `--radius`, xl =
|
|
3834
3854
|
`--radius` + 4 px), the pair stays concentric for any host radius; the toolbar's children at its end corners (the create button, the development
|
|
3835
3855
|
box) are `rounded-lg` too.
|
|
3836
3856
|
- **View-mode toolbar** (`DailyReportResolvedContent`, above every view): its band carries the insets, so the toolbar and the search row share them:
|
|
@@ -3885,57 +3905,58 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3885
3905
|
refuses one without a registered surface, and measures each against its surfaces. The quiet text (section labels, metadata, placeholders, the empty
|
|
3886
3906
|
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
|
|
3887
3907
|
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
|
|
3888
|
-
7.07–9.75). A source badge's colours are the host's (**External Source Badge Configuration**).
|
|
3889
|
-
|
|
3890
|
-
|
|
3908
|
+
7.07–9.75). A source badge's colours are the host's (**External Source Badge Configuration**). Targets reach WCAG 2.5.5's 44 px under every pointer
|
|
3909
|
+
(**Target size** below), except the List's resize handle with its 10 px hit area and the 8 px scroll bar beside it (**Side pane** above) and the
|
|
3910
|
+
other exceptions listed there, so 2.5.5 is not claimed overall.
|
|
3891
3911
|
- **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
|
|
3892
3912
|
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
|
|
3893
3913
|
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
|
|
3894
3914
|
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
|
|
3895
3915
|
3.3.6. Not met, by decision: 2.2.4 (Interruptions): live updates (SSE) apply as they arrive, with no pause, and
|
|
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**
|
|
3897
|
-
|
|
3898
|
-
|
|
3916
|
+
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**
|
|
3917
|
+
above), which keep their thin hit areas. Not claimed overall: 2.5.5, whose 44 px every other target of the package meets under every pointer
|
|
3918
|
+
(**Target size** below), the exceptions listed there aside.
|
|
3919
|
+
Not claimed yet: 1.4.8 (a line measure and the List preview's
|
|
3899
3920
|
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
|
|
3900
3921
|
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
|
|
3901
3922
|
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
|
|
3902
3923
|
`sessionEpoch`, and the package resumes and sends nothing again by itself ([Client wiring](#client-wiring)). 2.2.6 (Timeouts) is the host's: the
|
|
3903
3924
|
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
|
|
3904
3925
|
`VirtualScroll`'s tap-scroll circle options).
|
|
3905
|
-
- **
|
|
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
|
|
3926
|
+
- **Target size (every pointer)**: under every pointer (mouse, trackpad, pen or finger) every target is at least 44 × 44 CSS px (WCAG 2.5.5's enhanced
|
|
3927
|
+
size, T = 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
|
|
3928
|
+
the side pane's tabs (the side pane's bar is 4 + 44 + 4 = 52 px), the create button, the search box's toggles, field and clear button, the comment field
|
|
3908
3929
|
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
|
|
3930
|
+
and the attachments' download and row links (a tile's last line is 48 px, 44 rounded up to 8, so tiles stay on the device-pixel lattice). The toolbar band's
|
|
3910
3931
|
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
3932
|
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
|
-
|
|
3933
|
+
is 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
3934
|
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 `
|
|
3915
|
-
as the search box's pills and the List's mobile overlay close button do). Each box grows
|
|
3916
|
-
|
|
3917
|
-
44 × 44 hit area in the band's 48 px line; the side pane's action buttons
|
|
3918
|
-
|
|
3919
|
-
icon buttons (24 × 24 targets in its 24 px box; its SSE switch has the switch's centred
|
|
3920
|
-
spaces its items 6 px apart, 4 + (44 − 40) / 2, so that hit area does not cover the reload button's target) and
|
|
3921
|
-
|
|
3922
|
-
browsers; the
|
|
3923
|
-
|
|
3924
|
-
|
|
3935
|
+
does not hold a 44 × 44 square (a bordered control about 44 px wide adds `before:-inset-px` so the square also covers its border,
|
|
3936
|
+
as the search box's pills and the List's mobile overlay close button do). Each box grows through a minimum size, so a control that declares a larger
|
|
3937
|
+
size keeps it (the edit form's `Button` sizes). The auto-read switch keeps its 40 × 24 look and gets a centred
|
|
3938
|
+
44 × 44 hit area in the band's 48 px line; the side pane's action buttons take a 44 px line of their own under the subject, at its end, and the List
|
|
3939
|
+
card puts its toggles beside the preview (**List card** above). Exceptions: the List's resize handle and the views' scroll bars, the host's filter
|
|
3940
|
+
select controls, the dev toolbox's reload and clear-cache icon buttons (24 × 24 targets in its 24 px box; its SSE switch has the switch's centred
|
|
3941
|
+
44 × 44 hit area, and the toolbox spaces its items 6 px apart, 4 + (44 − 40) / 2, so that hit area does not cover the reload button's target) and
|
|
3942
|
+
`VirtualScroll`'s tap-scroll circle. Text fields use 16 px text under a coarse pointer (14 px under a fine one), so focusing them does not zoom the
|
|
3943
|
+
page on touch browsers; this text is the only rule the package keys on the pointer, and a Tailwind host generates it from Tailwind CSS v4.1 on
|
|
3944
|
+
(**Tailwind v4 host** above). The search field's Enter key is labelled as search (`enterkeyhint="search"`) and the comment field's as send
|
|
3945
|
+
(`enterkeyhint="send"`). When the views are narrower than 320 px (the search row's smallest width: the band's insets, both toggles, two 8 px gaps
|
|
3946
|
+
and a field that 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
3947
|
content at least its 16 px padding and at least the display's safe-area insets (`env(safe-area-inset-*)`) from each edge.
|
|
3926
3948
|
- **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
|
|
3927
|
-
pane, and the trash button of the viewer's comments share one
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
pills and the source badge are 24 px tall like the targets.
|
|
3949
|
+
pane, and the trash button of the viewer's comments share one 44 px round target (**Target size** above), which never shrinks, with a 16 px SVG
|
|
3950
|
+
icon centred in it by flexbox (14 px on every side), so the icons do not depend on a font. In the List card the markers and toggles stand 4 px
|
|
3951
|
+
apart; the header pills and the source badge are 24 px tall (they are not targets).
|
|
3931
3952
|
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,
|
|
3932
3953
|
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
|
|
3933
3954
|
hover background included, in both themes; in forced colours the star is drawn in `CanvasText` (off) and `Highlight` (on). The side pane shows them
|
|
3934
|
-
in the order star, read, edit, delete,
|
|
3955
|
+
in the order star, read, edit, delete, on a 44 px line of their own under the subject, at its end.
|
|
3935
3956
|
Unread is shown by the dot on the read toggle and by the row state in the description; no surface changes its border or its layout for it (a card's
|
|
3936
3957
|
border is the same 1 px in every state).
|
|
3937
|
-
The comment's trash button
|
|
3938
|
-
|
|
3958
|
+
The comment's trash button sits in a 44 px line of the comment header that holds its whole 44 px target (an overhanging target would cover the
|
|
3959
|
+
comment above and the text), turns red while its confirmation waits (at least 3.59:1 on the comment surfaces), and the confirmation pill carries the control
|
|
3939
3960
|
focus outline.
|
|
3940
3961
|
|
|
3941
3962
|
### Attachment display
|
|
@@ -3981,9 +4002,9 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3981
4002
|
pixel ratio of 2).
|
|
3982
4003
|
- **Tile**: one link to the original wraps the thumbnail frame and the file name; below it one line holds the size and the download link. The frame is
|
|
3983
4004
|
decorative (`aria-hidden="true"`, no link of its own), so the tile link is named by the file name and a tile has two Tab stops (the preview, then
|
|
3984
|
-
the download). The download link
|
|
4005
|
+
the download). The download link's own box is its 44 × 44 target, and its accessible name is the download label followed by the file name.
|
|
3985
4006
|
The tile root (the grid item) is the tile's one inline-size container, exactly as wide as its track, so `100cqi` inside the tile is t. A tile is the
|
|
3986
|
-
frame (h, below), the 8 px gap, the 20 px name, the 4 px gap and the
|
|
4007
|
+
frame (h, below), the 8 px gap, the 20 px name, the 4 px gap and the 48 px last line, h + 80 px in all (80 and the grid gap of 16 are multiples of
|
|
3987
4008
|
8), and h need not be a multiple of 4.
|
|
3988
4009
|
The last line therefore carries a bottom margin, the lattice pad δ(t) = ⌈h / q⌉ · q − h
|
|
3989
4010
|
(`margin-block-end: calc(round(up, h, var(--aqdr-lattice-block)) - h)`, where h is the frame height's own expression, resolved against the same
|