Skip to content

fix: quiet the task-agent footer, and give it real design-system components#3602

Merged
matthiasn merged 3 commits into
mainfrom
feat/ds_footer_component_gaps
Jul 26, 2026
Merged

fix: quiet the task-agent footer, and give it real design-system components#3602
matthiasn merged 3 commits into
mainfrom
feat/ds_footer_component_gaps

Conversation

@matthiasn

@matthiasn matthiasn commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Closes the design-system gaps behind the task-agent card footer, then applies
the round-5 panel findings that stand on their own merits.

Why this stops here

The footer has been through five rounds of design-panel review. Scores:

round experts personas
1 4.08 3.80
2 6.17 6.00
3 6.50 6.10
4 6.58 6.40
5 6.58 6.50

Round 5 moved the expert average by zero, and the expert spread collapsed to a
single point (five 6.5s and one 7) — agreement at a ceiling, not a disagreement
another round would resolve. What the panel wants next is a different, larger
footer: a new type token, four new ARB keys across 11 locales, a new last-run
timestamp field, and a countdown reformatted to "in 1m 30s" (reversing the
compact tabular countdown its own scorecard calls "excellent"). That is a
second product iteration, not polish, so it is not in this PR.

The six defects in the original brief were fixed in #3591 and #3597.

Shared components

DesignSystemInlineAction — a caption-tier tappable row for metadata
contexts. Skip once and the model-identity row were the same
Material/InkWell scaffold written twice; it bakes in three things each call
site had to get right independently:

  • it wraps itself in an Align, because a stretching parent hands children a
    tight width under which MainAxisSize.min is silently a no-op and the ink
    runs the width of the whole column — the original hover defect;
  • the inset lives inside the ink, so the rounded corners cannot clip the
    leading glyph;
  • ExcludeSemantics sits below the InkWell, never above. Both open-coded
    predecessors excluded above it, which drops the ink's node along with its tap
    and focus actions — a control that announces as a button but that assistive
    tech cannot activate. Caught by the new component's own tests.

DesignSystemButton.alignsLabelToLeadingEdge replaces the open-coded
Transform.translate(-inset) from #3597. Direction-aware.

aiCard.footerWash / footerWashOpen flipped to a white overlay in dark at
the token source. Black at 16% on the near-black card moved the surface by
[2,4,5] per channel — the band was effectively invisible.

Panel fixes

  • Alert tint on the glyph only. The freshness word stays bodyText in both
    states. Tinting it too made the settings band louder than Confirm all, and
    in dark it read at lower contrast than the plain ink it replaced.
  • Skip once loses its underline and moves to bodyText — the register of
    the countdown it acts on. DesignSystemInlineAction drops the underline
    parameter entirely rather than leaving it unused.
  • The attribution row is now the same row box as the tappable row (matching
    inset, matching step8 minimum), so the card's bottom margin no longer
    depends on whether the line is present. The previous revision equalised the
    declared padding and still shifted on screen: the tappable row's ink box
    centres its glyph and contributes optical air a bare text row does not.
  • The card title stops breaking mid-word. German at 320px and 1.3x
    rendered KI-Zusammenf / assung. It now measures its widest run with no
    break opportunity and falls back to one line plus an ellipsis when that run
    cannot fit — truncation reads as shortening, a mid-word break reads as a
    typo. The second line returns as soon as there is room.

Declined, with reasons

  • DesignSystemToggle owning its label. Its built-in label puts the
    control first, forces maxLines: 1 and renders at text.highEmphasis.
    Adopting it would flip the footer's trailing-rail arrangement, regress the
    German two-line wrap the panel itself asked for two rounds earlier, and make
    a metadata label louder than the state beside it.
  • The toggle's off-state thumb, which the component already documents as
    deliberately constant.

Known follow-up

aiCard.footerWash.dark is now byte-identical to subtleWashStrong.dark, and
the band reads elevated in dark while it reads recessed in light. Reverting
restores the invisible band, and retuning the alpha would be an invented visual
value, so it ships as-is with the collision tracked separately. The likely real
fix is at the card-background end — lifting the body so the band can recede —
not at the band's.

Before / after

Captured from the committed opt-in screenshot matrix
(test/features/agents/ui/ai_summary_card/screenshots_test.dart, unchanged by
this PR), so both columns come from the identical harness — "before" is
origin/main, "after" is this branch.

The band is a band (dark)

Black at 16% on a near-black card moved the surface by [2,4,5] per channel.
Note also Skip once losing its underline.

before after
before after

The alert tint is the glyph's job

Out of date was amber, which made the quiet settings band the most
chromatic thing on the card — louder than Confirm all — at lower contrast
than plain ink.

before after
before after

German, 320 px, 1.3× text scale

KI-Zusammenfassung has one break opportunity, and the token after it still
overflows, so the line breaker split inside the word: KI-Zusammenf / assung
reads as a typo. It now truncates, which reads as shortening.

before after
before after

Attribution no longer changes the card's bottom margin

The This report … line sat flush against the card edge while its absence
left the tappable row's ink box supplying optical air.

before after
before after

Verification

  • dart analyze lib test — no issues.
  • flutter test test/features/agents/ test/features/design_system/
    6165 passed, 2 skipped, 0 failed.
  • Screenshot matrix regenerated across desktop/pro/mini/narrow x dark/light x
    manual/scheduled/running/proposals/split/hover, plus German at 1.3x; the
    title truncation, the missing underline and the glyph-only tint are all
    confirmed in pixels.

No CHANGELOG entry for the four panel fixes: each defect was introduced and
fixed inside the unreleased 0.9.1070 section, so no shipped build showed them.
The dark-mode band entry from the first commit remains, since that one was
released.

Summary by CodeRabbit

  • New Features

    • Added a reusable inline action control with consistent styling, tooltips, icons, and accessibility semantics.
    • Improved AI summary card title wrapping to avoid awkward mid-word truncation.
    • Improved alignment of manual update controls and consistency of card footer spacing.
  • Bug Fixes

    • Made the AI summary card’s update section clearly visible as a distinct band in dark mode.
    • Limited freshness alert coloring to the status icon for clearer text readability.
    • Improved “Skip once” action styling and presentation.

…nt, dark footer wash

Closes the design-system gaps the task-agent footer panel kept returning to
(lotti3-1fn.8). Each was flagged by 2+ experts across rounds 3 and 4, and each
is a shared-surface change rather than a card-local one — which is why they
were split out of #3597 instead of being worked around in the widget.

`DesignSystemInlineAction` is a caption-tier tappable row for actions that
belong to metadata. `_SkipAction` and `_SetupIdentityRow` were the same
Material/InkWell scaffold written twice, each re-deriving radius, target,
inset and state layers; both now use the component. It bakes in three things
that were silently wrong or easy to get wrong at a call site:

- it wraps itself in an `Align`, because a stretching parent hands children a
  tight width under which `MainAxisSize.min` is a no-op and the ink spans the
  whole column — the exact hover defect this whole redesign started from;
- the inset lives inside the ink, so the rounded corners cannot cut the glyph;
- semantics are excluded *below* the `InkWell` rather than above it. Excluding
  above — which both open-coded versions did, and which the identity row has
  done since it was written — drops the ink's own node along with its tap and
  focus actions, leaving a control that announces as a button but that
  assistive tech cannot activate. Caught by the component's own tests.

`DesignSystemButton.alignsLabelToLeadingEdge` replaces the
`Transform.translate(-inset)` #3597 had to open-code. A button's horizontal
padding is internal, so a button box flush on a shared leading column puts its
glyph one inset inside it: invisible beside other buttons, obvious the moment
it sits in a stack of text rows. Direction-aware.

`aiCard.footerWash` / `footerWashOpen` flip to a white overlay in dark at the
token source. Black at 16% over the #0E1A22 card moves it [2,4,5] per channel
— the band was effectively invisible — where white at 5% moves [12,11,11].
Every other wash in the group already flips direction per theme; these two
were the exceptions. Light values unchanged. Regenerated via
`make design_system_import`.

Not done, deliberately, both recorded on the beads issue:

- The panel wants `DesignSystemToggle`'s off-state thumb resolved from the
  surface state layers. The component already documents why it is constant: a
  state- or theme-varying thumb "makes OFF rows out-shine ON rows or strands a
  dark knob on a dark accent track". The panel could not see that rationale;
  the maintainer confirmed keeping it.
- The panel wants the toggle to own its label. Its built-in label places the
  control first, forces `maxLines: 1`, and renders at `text.highEmphasis` —
  which would flip the footer's trailing-rail arrangement, regress the German
  two-line wrap the panel itself asked for, and make a metadata label louder
  than the state beside it.
…id-word

Round 5 of the design panel came back flat — 6.58/6.50 against round 4's
6.58/6.40 — so this takes the findings that stand on their own merits and
stops the loop rather than chasing a target that has stopped moving.

The alert tint is now spent on the freshness glyph alone; the word stays at
bodyText in both states. Tinting the word as well made the quiet settings
band the most chromatic thing on the card, louder than "Confirm all" — the
action that actually changes the user's task — and in dark it rendered at
*lower* contrast than the plain ink it replaced. The state is still said
twice, by the glyph and by the word, so colour is not carrying it alone.

"Skip once" loses its underline and moves to bodyText, the register of the
countdown it acts on. An action rendered fainter than the static text beside
it inverts the two, and the underline gave the band a third dialect for "this
is tappable" alongside the glyph and the hover fill. DesignSystemInlineAction
drops the `underline` parameter outright rather than leaving it unused — its
only caller was this one, and an unused knob on a shared component is how a
surface acquires dialects.

The attribution row becomes the same row box as the tappable row above it —
matching inset, matching step8 minimum height — so the card's bottom margin
no longer depends on whether the line is present. An earlier revision paid
top-only padding to equalise the *declared* geometry and still shifted on
screen, because the tappable row's ink box centres its glyph and contributes
optical air that a bare text row does not. Space row boxes, not text.

The card title falls back to one line and an ellipsis when its widest run
with no break opportunity cannot fit, instead of letting the line breaker
split inside the word: German at 320px and 1.3x text scale rendered
"KI-Zusammenf / assung", which reads as a typo rather than as shortening.
The choice is measured at the live text scaler, so the second line returns
as soon as the string has room for it.

No CHANGELOG entry: all four defects were introduced and fixed inside the
unreleased 0.9.1070 section, so no shipped build ever showed them.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds a reusable inline action component, updates AI summary card controls and identity-row spacing, improves title truncation, changes dark-mode footer tokens, and adds related tests and release documentation.

Changes

AI summary card UI

Layer / File(s) Summary
Inline action foundation
lib/features/design_system/components/buttons/*, test/features/design_system/components/buttons/*, knowledge/features/design_system/component-contracts.md
Adds DesignSystemInlineAction, extends DesignSystemButton with leading-edge alignment, and tests interaction, semantics, sizing, tooltip behavior, and styling.
Automation control rendering
lib/features/agents/ui/task_agent_automation_row.dart, test/features/agents/ui/task_agent_automation_row_test.dart, knowledge/features/agents/ui-surfaces.md
Uses the inline action for “Skip once,” aligns the manual trigger, and applies alert tint only to the freshness glyph.
Identity and title layout
lib/features/agents/ui/task_agent_identity_region.dart, lib/features/agents/ui/ai_summary_card/tldr_section_part.dart, test/features/agents/ui/*
Uses the inline action for identity setup, equalizes attribution-row spacing, and switches between one-line ellipsis and two-line title rendering based on measured text width.
Dark-mode card metadata
assets/design_system/tokens.json, CHANGELOG.md, flatpak/com.matthiasn.lotti.metainfo.xml, knowledge/features/agents/ui-surfaces.md
Updates dark-mode footer wash colors and records the AI summary card rendering correction in release and feature documentation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: refactoring the task-agent footer to use design-system components and cleaner behavior.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ds_footer_component_gaps

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.15%. Comparing base (86356a1) to head (234376e).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3602   +/-   ##
=======================================
  Coverage   99.15%   99.15%           
=======================================
  Files        1784     1785    +1     
  Lines      131153   131174   +21     
=======================================
+ Hits       130041   130062   +21     
  Misses       1112     1112           
Flag Coverage Δ
glados 14.08% <2.06%> (-0.01%) ⬇️
standard 98.90% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c8ae894d73

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/features/design_system/components/buttons/design_system_inline_action.dart Outdated
Comment thread lib/features/design_system/components/buttons/design_system_inline_action.dart Outdated
Comment thread knowledge/features/agents/ui-surfaces.md
…unds

Review findings on #3602, all three valid.

The Tooltip and Semantics wrapped the Align rather than sitting inside it.
The Align deliberately takes the full width a stretching parent offers — that
is how it converts a tight constraint into a loose one so the ink can shrink-
wrap — so anything wrapped around it inherited the full width instead of the
ink's. The tooltip fired over blank footer space and the accessibility focus
rectangle covered places where a tap does nothing, which is the same defect
the component was extracted to prevent, surviving one layer up. Both now sit
on the shrink-wrapped side.

The tooltip also published its message into semantics alongside semanticsLabel,
so a screen reader announced the action twice: literally so for Skip once,
which passes one string as both, and near enough for the identity row, whose
label already ends in "Activate to change setup". It is excluded now, leaving
semanticsLabel as the single announcement the docstring always claimed it was.

The existing bounds test only asserted on the InkWell, which is why this got
through; it now covers the tooltip and semantics rects too.

Both rewritten knowledge concepts get refreshed OKF provenance.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 234376e2e7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

tags: [agents, ui, motion, accessibility]
status: stable
generated: { by: claude-code/opus-5, at: 2026-07-25T23:30:00Z }
generated: { by: claude-code/opus-5, at: 2026-07-26T14:00:00Z }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Record a non-future generation time

Fresh evidence after the earlier provenance comment: this replacement says the concept was generated at 2026-07-26T14:00:00Z, while the reviewed commit's author and committer timestamps are both 2026-07-26T13:04:50Z; the same future value appears in component-contracts.md. The immutable tree therefore claims it was generated 55 minutes after it was committed, making freshness consumers trust an impossible snapshot. Set generated.at to the actual generation time in both concepts.

AGENTS.md reference: AGENTS.md:L120-L123

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair catch, and my error — I wrote a round 14:00:00Z rather than reading the
clock, which put the stamp 55 minutes after the commit it describes. Both
concepts now say 2026-07-26T13:20:00Z, which is behind the commit that
carries them.

make okf_check still passes: 88 concepts, 0 errors, 0 warnings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/features/agents/ui/task_agent_automation_row_test.dart (1)

309-335: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Tap the visible affordance instead of the outer slot key.

DesignSystemInlineAction shrinks its tap target to the InkWell beneath the key, while the key wraps the full width Align. Tap find.text('Skip once') or the InkWell to avoid relying on the current text position.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/features/agents/ui/task_agent_automation_row_test.dart` around lines 309
- 335, The test should tap the visible Skip once affordance rather than the
outer taskAgentSkipScheduledUpdate slot key. Update the tap in the testWidgets
case to target find.text('Skip once') or the underlying InkWell, while
preserving the existing assertion that skips increments once.
🧹 Nitpick comments (1)
lib/features/design_system/components/buttons/design_system_button.dart (1)

201-208: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider direct component-level tests for alignsLabelToLeadingEdge.

The Transform-translate math checks out (direction-aware, cancels sizeSpec.horizontalPadding), and hit-testing/semantics correctly follow the paint transform. However, this new public flag on a shared design-system primitive is only exercised indirectly through task_agent_automation_row_test.dart (icon-position assertions in stacked mode). A dedicated DesignSystemButton test verifying LTR vs. RTL offset direction and the no-op default would give this shared component its own regression safety net independent of any single consumer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/design_system/components/buttons/design_system_button.dart`
around lines 201 - 208, Add direct component-level tests for
DesignSystemButton’s alignsLabelToLeadingEdge behavior, covering the default
false no-op and the true flag’s offset direction in both LTR and RTL layouts.
Exercise the rendered button in isolation and verify the expected horizontal
translation, without relying on task-agent consumer tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/agents/ui/task_agent_identity_region.dart`:
- Around line 172-211: Update the Tooltip in _ReportIdentityRow to set
excludeFromSemantics: true, matching the existing DesignSystemInlineAction
tooltip behavior, while preserving the current message and row rendering.

---

Outside diff comments:
In `@test/features/agents/ui/task_agent_automation_row_test.dart`:
- Around line 309-335: The test should tap the visible Skip once affordance
rather than the outer taskAgentSkipScheduledUpdate slot key. Update the tap in
the testWidgets case to target find.text('Skip once') or the underlying InkWell,
while preserving the existing assertion that skips increments once.

---

Nitpick comments:
In `@lib/features/design_system/components/buttons/design_system_button.dart`:
- Around line 201-208: Add direct component-level tests for DesignSystemButton’s
alignsLabelToLeadingEdge behavior, covering the default false no-op and the true
flag’s offset direction in both LTR and RTL layouts. Exercise the rendered
button in isolation and verify the expected horizontal translation, without
relying on task-agent consumer tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6cb70740-d0be-4b76-9e81-cac6ebe19da8

📥 Commits

Reviewing files that changed from the base of the PR and between 86356a1 and 234376e.

⛔ Files ignored due to path filters (1)
  • lib/features/design_system/theme/generated/design_tokens.g.dart is excluded by !**/generated/**
📒 Files selected for processing (14)
  • CHANGELOG.md
  • assets/design_system/tokens.json
  • flatpak/com.matthiasn.lotti.metainfo.xml
  • knowledge/features/agents/ui-surfaces.md
  • knowledge/features/design_system/component-contracts.md
  • lib/features/agents/ui/ai_summary_card/tldr_section_part.dart
  • lib/features/agents/ui/task_agent_automation_row.dart
  • lib/features/agents/ui/task_agent_identity_region.dart
  • lib/features/design_system/components/buttons/design_system_button.dart
  • lib/features/design_system/components/buttons/design_system_inline_action.dart
  • test/features/agents/ui/ai_summary_card/tldr_section_part_test.dart
  • test/features/agents/ui/task_agent_automation_row_test.dart
  • test/features/agents/ui/task_agent_identity_region_test.dart
  • test/features/design_system/components/buttons/design_system_inline_action_test.dart

Comment thread lib/features/agents/ui/task_agent_identity_region.dart
@matthiasn
matthiasn merged commit 78aaad9 into main Jul 26, 2026
29 checks passed
@matthiasn
matthiasn deleted the feat/ds_footer_component_gaps branch July 26, 2026 13:32
matthiasn added a commit that referenced this pull request Jul 26, 2026
Rebasing onto #3602 moved the last-commit date of `tokens.json`, the
design-system theme directory and `database_config_flags.dart` — the last of
those because this branch edited its comment. Two entries inherited from main
were also a day ahead of the files they cite. All 238 repo-path sources match
`git log -1` again.
matthiasn added a commit that referenced this pull request Jul 26, 2026
The settings band was a third of the card on a phone, and the space around the
automatic-updates row was the worst of it: 33.5 logical px above the switch and
38 below, measured ink-to-ink, against declared gaps of 16 and 12.

Two causes, both invisible in the source.

The switch sat in a `ConstrainedBox(minWidth: step9, minHeight: step9)` whose
comment claimed it "keeps a full-size interaction target for anyone who cannot
land on 24px". It did not. `DesignSystemToggle` owns its own `InkWell` wrapping
the 40x24 track, and that outer box is not a gesture detector — so it reserved
48px of column height while the only thing a finger could actually hit stayed
the 24px track. It bought airiness and paid for nothing.

And every row in the band is a touch-target box taller than its own ink, each
contributing ~10px of air above and below the visible text. The declared gaps
sat on top of that, so the band paid for the same space twice.

So: the whole settings row is the gesture now — tapping the label toggles the
setting, which is a target the width of the band rather than a 40x24 track —
and it drops to the `step8` minimum every other row in the footer already uses.
The row publishes `excludeFromSemantics` so it does not add a second unlabelled
button node beside the switch's own. The stacked column and the gap before the
identity region declare no vertical space at all; the row boxes supply the
rhythm.

Measured, ink-to-ink: trigger row to switch row 33.5 -> 13.5, switch row to
model row 38.0 -> 22.0. Card height: 466 -> 430 on a phone, 716 -> 647 in
German at 320px and 1.3x, 386 -> 366 on desktop. The split-attribution state
nets to zero, because the attribution row's own step8 box costs back what the
gap removal saves — the trade that keeps the card's bottom margin from moving.

Also two more review findings on #3602:

The report row's tooltip entered semantics. Excluding it alone would have made
that row worse — its visible route sheds whole segments, so the children and
the tooltip carry different strings, and excluding only the tooltip leaves the
*shortened* route as the sole announcement. It now publishes one node with the
untruncated attribution, the shape `DesignSystemInlineAction` uses a row above.

And both concepts carried a `generated.at` of 14:00:00Z against a 13:04:50Z
commit, claiming a snapshot from the future.
matthiasn added a commit that referenced this pull request Jul 26, 2026
Build only — 0.9.1070+4258 -> +4259; the version string is unchanged.

The 4258 tag contains the footer redesign but not #3602, so the over-spaced
settings band actually shipped. That makes this a fix to a released state
rather than a defect introduced and resolved inside an unreleased version, so
it carries a CHANGELOG entry and the matching metainfo line.
matthiasn added a commit that referenced this pull request Jul 26, 2026
Review findings on #3604.

Making the whole settings row tappable gave it a focus stop of its own beside
the switch's, so Tab landed twice on one setting and both stops toggled it.
`excludeFromSemantics` suppresses the semantic node and does nothing whatever
to traversal. The wrapper is pointer-only now via `canRequestFocus: false`, and
a test counts focusable InkWells in the row — it reports 2 without the flag.

The concept also stated the old layout contract in two places the new prose
contradicted: the flow diagram's stack node still promised "a larger gap above"
the schedule, and the automation section still claimed "the toggle keeps a full
`spacing.step9` interaction slot around its 40x24 track" — the very claim this
branch exists to delete, since that slot was inert. Both now describe the
full-row target on the shared `step8` minimum. The one remaining step9 mention
narrates the earlier revision as history, not as a contract.

And `component-contracts.md` is dropped from this branch entirely. Its only
change here was a `generated.at` rewound from 14:00:00Z to 13:56:33Z — bulk
collateral from #3602 that rode along in the cherry-pick — which would have
claimed an unchanged document predates its own revision. `ui-surfaces.md` keeps
its bump because its prose does change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant