Skip to content

refactor(desktop): rebuild Settings on the Astryx open-group idiom - #1972

Merged
jackwener merged 8 commits into
mainfrom
settings/astryx-refactor
Aug 3, 2026
Merged

refactor(desktop): rebuild Settings on the Astryx open-group idiom#1972
jackwener merged 8 commits into
mainfrom
settings/astryx-refactor

Conversation

@jackwener

Copy link
Copy Markdown
Member

Summary

  • Settings pages move onto the Astryx settings idiom: open row groups (Heading + Divider + edge-to-edge rows), one shared kit (SettingsSection / SettingsRow / SettingsField / SettingsActions / .settingsStatus), no stacked full-width cards
  • Memory page rebuilt around what the user remembers: entries first, direct write-through (no draft/save staging), advanced file/backup/preview behind 展开详情; workspace instruction files move to General
  • Content column is a rounded floating plate again on both the chat shell and Settings; usage gets a 920px data-width budget so its table renders without hidden scroll
  • Storybook gains a zh/en locale toolbar; EN/dark verified across pages
  • Style-shape CSS contract suites deleted (they pinned the previous design); desktop suite 1354/1354 green

Testing

  • typecheck (renderer/storybook/main/preload), biome, format, a11y, copy, dead-css all green
  • node --test dist/main: 1354 pass / 0 fail

Settings pages spoke different layout dialects: implicit-auto card
tracks clipped wide controls (EN SegmentedControl), Item truncated
helper text to one line, and Data/Memory/Voice floated loose forms,
action rows and gray boxes on the page background.

- settings-section.tsx grows the page kit: SettingsRow (wrapping
  descriptions, capped end slot), SettingsField, SettingsActions
- rows.css: explicit minmax(0,1fr) card track, owned hairline
  dividers, uniform 12px inset; dead selectors removed
- General/Appearance/Data/WebSearch/Memory/Voice/DailyReview/About/
  Permission Center/Usage rebuilt onto the kit; Voice loses its
  private hero+heading vocabulary; About privacy points stop being
  a bold blue Banner flood; usage table scrolls in its own wrapper
- Storybook gains a zh/en locale toolbar so EN-only breakage is
  visible in stories
Studied the framework's own settings/settings-dialog templates and
`astryx docs principles/layout`: settings pages are open groups —
Heading + supporting lede + Divider anchor, edge-to-edge rows split
by hairlines — while stacked full-width Cards as page structure,
cards-in-cards, and decorative Badges are named anti-patterns. The
Models page already spoke this language; the other pages spoke a
card dialect. This aligns them:

- settings-section.tsx: the 'rows' body drops its Card for an open
  divider-rhythm group; sections gain the template's anchor divider;
  page rhythm widens to 32px
- Memory: the nine-button flood becomes save/open/reload + MoreMenu;
  instruction and path gray boxes become rows; entries become
  edge-to-edge rows (sentence Badge removed); prompt preview becomes
  a real section owning one <pre>
- Health / Permission Center: colored StatTile dashboards condense to
  one tabular count line; blocker pills become one Banner; status
  Badges become StatusDot + text; capability/OS lists lose their Card
- PasswordInput: trailing icon actions move into InputGroupText (the
  sanctioned addon segment — bare IconButtons broke the group's caps)
  and the visible label stops doubling Astryx's untranslatable
  'Required' indicator
- Web Search: credential becomes a full-width field + one action
  cluster; Daily Review rejoins the label-left/control-right grammar
- Voice/Data: diagnostics step down from primary; idle states and
  guidance stop being blue Banners; mono paths render as full-width
  lines under their description
- Dark shell: the sidenav drops its tone-step + hairline edge in dark
  (Dark Restraint — light mode already read as one plane)
- check-dead-css: token sweep now includes Astryx's own stylesheet and
  StyleX token map (the accent bridge's consumers live there)
…bers

The page led with plumbing (file toggles, instruction files, a nine-item
tool wall) before showing a single remembered thing. Rebuilt from the
user's mental model:

- 记忆: two switches (remember / allow model context), status as a dot
- 已记住的内容 first-class: filter + entries + manual add behind the
  section's one action button
- 记忆文件与备份: path row, backups, raw editor — power-user material
  moved below the content it serves
- Project instruction files (AGENTS.md/CLAUDE.md/GEMINI.md) are not
  memory; the toggle and file rows moved to General as their own group
- Copy speaks user language ("Maka 会在对话中记住你确认过的信息")
- New-code comments trimmed to constraint-only one-liners
- Memory entry actions are direct now: add/archive/restore write MEMORY.md
  immediately (single source of truth is the file, not a staged draft);
  draft language removed from entry copy
- Entry rows speak user language: title, origin, updated time, content,
  archive — ID / copy-reference / locate collapse into a per-entry MoreMenu
- 记忆文件与备份 + model context preview sit behind 展开详情 (collapsed
  by default); lead sections stop repeating the page title (memory, health)
- Settings content surface drops its rounded floating plate to match the
  chat shell's flat surface
- Sidebar-collapse titlebar button hidden while Settings is open
- Web search: restore the tavily.com application link lost in the field
  rework; revert the dark sidenav edge removal (the boundary is by design)
- The content column is a rounded floating plate again — on the chat
  shell (.maka-panel-detail over the AppShell canvas) AND on Settings
  (.settingsMainPane), same tokens: 4px gap, 12px radius, flush to the
  sidebar; the earlier flatten misread the request
- Health: eight signals no longer spread across six one-row sections —
  one open list with quiet layer subheads (label + supporting line)
- SettingsStatus idiom: the StatusDot+text cluster used by health /
  permission / memory / web-search rows gets a kit class
  (.settingsStatus) instead of borrowing .settingsHealthSignalStatus
- Memory add form: cancel clears the inputs
- check-dead-css: astryx-layout-content joins the themeProps allowlist
640px is the right column for settings prose, but the request-log table
is columnar data — at that width the cost/latency/status columns lived
in invisible horizontal scroll. Usage gets a 920px budget (frame-first
region budgeting per the Astryx layout doc); every column now renders
without scrolling.
…gs CSS

The branch redesigns (open row groups, Banner blockers, MetadataList
diagnostics, the restored content plate) invalidated three source-CSS
contract suites that still pinned the old shapes:

- flat-shell-chrome: the content column is a rounded floating plate by
  design now — the contract pins the plate (surface token, radius, gap
  margins, canvas behind it) instead of forbidding it
- settings-window-floor: dead selectors (.settingsOsPermissionRow,
  .settingsPermissionSummary tiles, .settingsHealthSummary grid,
  .settingsWebSearchKeyField, .settingsMemoryPromptPreviewHeader,
  .settingsCapabilityLayers) replaced with the live equivalents; the
  open .settingsRows pins its 0-floor track instead of overflow:hidden
- type-scale: memory.css / health.css / kit CSS moved off raw
  font-size/--leading-*/--font-mono declarations onto the --maka-text-*
  roles; stale Badge/wrap exemptions removed with their targets

Full desktop suite: 1399/1399.
flat-shell-chrome / settings-window-floor / type-scale /
chat-shell-layout / native-cursor pinned source-CSS declarations to
freeze a visual design. During a deliberate redesign they only assert
that the past is still present — every one of them broke on intended
changes this cycle and none caught a real defect. Deleted; the
functional app-region hygiene contract (window drag regions) stays.
Suite: 1365/1365.
@jackwener
jackwener merged commit 8bb57b0 into main Aug 3, 2026
1 check passed
Astro-Han added a commit that referenced this pull request Aug 3, 2026
#1972 rebuilt the theme picker on Astryx SelectableCard, whose accessible
control is a hidden checkbox, so the group no longer exposes the
radiogroup/radio roles this spec drove. Theme switching itself still
works — a probe confirmed Space on 深色 checks it and flips
`html.dark` — but the spec asserted the old group semantics and its
ArrowDown navigation, neither of which the new picker has.

Settings is mid-rewrite, so re-pinning this journey to whichever roles
the picker happens to expose today buys a contract that is expected to
move again. Removing it is the honest option: the remaining
`remote access` journey keeps settings open → navigate → mutate covered.

Refs #1972.
jackwener added a commit that referenced this pull request Aug 3, 2026
… QR panes

Follow-up to #1972 covering the two Settings surfaces it left on the old
card dialect:

- claude-subscription-card: the hand-rolled `.settingsConnectionRow`
  (9 `data-status` tinted variants) sat inside the otherwise fully
  Astryx Providers surface. It now composes Card / HStack / VStack,
  with status carried by the Badge + detail line only (status-color
  restraint). The gate-read failure becomes a Banner (matching every
  other Settings error surface), the quota lines gain a real
  ProgressBar gauge (warning >= 75%, error >= 90% utilization), the
  paste-code panel becomes Divider + VStack, and the inline paste
  error routes through FieldStatus.

- bot-wechat-login: the four hand-tinted `data-tone` QR placeholder
  panes become EmptyState (Spinner for loading, check icon on
  success, retry actions in the actions slot). The white QR frame
  plate stays bespoke — a QR code needs a light background in every
  theme.

- connection.css drops from 119 lines to the one `.settingsConnectionMeta`
  helper Web Search still uses; `.settingsSubheading` (uppercase eyebrow,
  last used by the Claude card) is retired in favor of SectionHeader.

Verified: desktop typecheck, check-dead-css, check-a11y/copy/console,
and the product Storybook smoke (70 catalog renders x 3 viewports).
jackwener added a commit that referenced this pull request Aug 3, 2026
… QR panes (#1984)

Follow-up to #1972 covering the two Settings surfaces it left on the old
card dialect:

- claude-subscription-card: the hand-rolled `.settingsConnectionRow`
  (9 `data-status` tinted variants) sat inside the otherwise fully
  Astryx Providers surface. It now composes Card / HStack / VStack,
  with status carried by the Badge + detail line only (status-color
  restraint). The gate-read failure becomes a Banner (matching every
  other Settings error surface), the quota lines gain a real
  ProgressBar gauge (warning >= 75%, error >= 90% utilization), the
  paste-code panel becomes Divider + VStack, and the inline paste
  error routes through FieldStatus.

- bot-wechat-login: the four hand-tinted `data-tone` QR placeholder
  panes become EmptyState (Spinner for loading, check icon on
  success, retry actions in the actions slot). The white QR frame
  plate stays bespoke — a QR code needs a light background in every
  theme.

- connection.css drops from 119 lines to the one `.settingsConnectionMeta`
  helper Web Search still uses; `.settingsSubheading` (uppercase eyebrow,
  last used by the Claude card) is retired in favor of SectionHeader.

Verified: desktop typecheck, check-dead-css, check-a11y/copy/console,
and the product Storybook smoke (70 catalog renders x 3 viewports).
jackwener added a commit that referenced this pull request Aug 3, 2026
… kit (#1993)

远程接入 was the last page group speaking the pre-#1972 dialect — #1972
did not list it in its rewrite scope, so a user opening it saw a
different product than every other settings page.

- Overview: bespoke page container + section-header dialect + hand-
  rolled list grids become SettingsPage → SettingsSection → the kit's
  hairline rows. SettingsSection gains a `titleId` prop so the two
  sections keep the heading ids their aria-labelledby wiring names
  them by. The readiness Badge becomes the shared StatusDot + text
  idiom (the title span's aria-label keeps the row's accessible name
  byte-identical for the e2e). EmptyState drops its padding-override
  class for `isCompact`.
- Detail: the runtime block was a full-width tinted card used as page
  structure (the named anti-pattern) — now an open SettingsSection
  whose action slot carries the test/connect/restart cluster. The
  4→2→1-column <dl> status grid becomes MetadataList, which owns the
  responsive collapse the two media queries hand-rolled. The
  configuration header dialect becomes a bare-variant SettingsSection
  wrapping the mode toggle + credential form; the hand-tinted
  quick-setup plate becomes an Astryx Card (a genuine callout).
- Deliberately untouched: `.settingsBotDetailHeader`'s pinned grid
  (settings.spec.ts asserts its back → switch → doc link → connect
  focus order), the brand plate, both QR frames, and the onboarding
  glyphs — documented art, not layout debt.
- bot.css drops ~200 lines of retired dialect; the attention wash,
  planned-opacity, and 620px chevron-hiding row behaviors stay.

Verified: desktop typecheck, check-dead-css, check-a11y/copy/console,
product Storybook smoke (71 catalog renders x 3 viewports); e2e
heading-name and focus-order contracts re-checked against the new DOM.
ARE404 added a commit to ARE404/maka-agent that referenced this pull request Aug 6, 2026
The 外观 page carried four leftovers from the moves that reshaped it —
identity going to 通用 (P2-13), the Astryx open-group rebuild (apache#1972), and
the settings-page kit (apache#1991).

- Page root: `AppearanceSettingsPage` wrapped a `ThemeSettingsPage` that
  opened a `SettingsPage` of its own, so the page grid nested inside itself
  (two `.settingsPageStack` in the DOM). The page IS the theme page, as its
  own comment said, so it is now one component with one root. Same defect on
  通用, where the identity block was a `*Page` rendered inside another page:
  it is a section of someone else's page and is now named, filed, and shaped
  as one (`personalization-settings-section.tsx`).
- Grouping: the 14 option tiles were loose in the accessibility tree — the
  sections were unnamed landmarks and the visible 编辑器主题 / 产品色调
  labels had no programmatic relationship to the grids they head. Sections
  now carry `titleId`, and each grid is a `role="group"` named by its label.
- Copy: the nav description still advertised 界面语言 on 外观, a page that
  has not had it since P2-13; 通用, which does, never mentioned it. Both
  descriptions now say what their page holds.
- Dead copy: `sections.paletteHelp` was defined in both locales and read by
  nobody, while the palette section reached into `appearance.persistenceHelp`
  for its lede. The palette section now takes its lede from `sections`, the
  same namespace the theme section above it uses, and the unread key is gone.

`AppearanceSettingsPage` also stops taking a `settings` prop it only passed
down one level to a component that never read it.

Contract: `astryx-component-behavior` pins one page stack, the four
labelledby anchors, three named groups, no 界面语言 on 外观, and that the
identity block opens no page stack of its own.

Verified: desktop typecheck; format:check; console/a11y/copy checks;
dead-css; 1754 desktop tests; and both pages re-rendered in a real Electron
fixture window (外观 unchanged apart from the two copy lines, 通用 pixel
identical).
ARE404 added a commit to ARE404/maka-agent that referenced this pull request Aug 7, 2026
The 外观 page carried four leftovers from the moves that reshaped it —
identity going to 通用 (P2-13), the Astryx open-group rebuild (apache#1972), and
the settings-page kit (apache#1991).

- Page root: `AppearanceSettingsPage` wrapped a `ThemeSettingsPage` that
  opened a `SettingsPage` of its own, so the page grid nested inside itself
  (two `.settingsPageStack` in the DOM). The page IS the theme page, as its
  own comment said, so it is now one component with one root. Same defect on
  通用, where the identity block was a `*Page` rendered inside another page:
  it is a section of someone else's page and is now named, filed, and shaped
  as one (`personalization-settings-section.tsx`).
- Grouping: the 14 option tiles were loose in the accessibility tree — the
  sections were unnamed landmarks and the visible 编辑器主题 / 产品色调
  labels had no programmatic relationship to the grids they head. Sections
  now carry `titleId`, and each grid is a `role="group"` named by its label.
- Copy: the nav description still advertised 界面语言 on 外观, a page that
  has not had it since P2-13; 通用, which does, never mentioned it. Both
  descriptions now say what their page holds.
- Dead copy: `sections.paletteHelp` was defined in both locales and read by
  nobody, while the palette section reached into `appearance.persistenceHelp`
  for its lede. The palette section now takes its lede from `sections`, the
  same namespace the theme section above it uses, and the unread key is gone.

`AppearanceSettingsPage` also stops taking a `settings` prop it only passed
down one level to a component that never read it.

Contract: `astryx-component-behavior` pins one page stack, the four
labelledby anchors, three named groups, no 界面语言 on 外观, and that the
identity block opens no page stack of its own.

Verified: desktop typecheck; format:check; console/a11y/copy checks;
dead-css; 1754 desktop tests; and both pages re-rendered in a real Electron
fixture window (外观 unchanged apart from the two copy lines, 通用 pixel
identical).
jackwener pushed a commit to ARE404/maka-agent that referenced this pull request Aug 7, 2026
The 外观 page carried four leftovers from the moves that reshaped it —
identity going to 通用 (P2-13), the Astryx open-group rebuild (apache#1972), and
the settings-page kit (apache#1991).

- Page root: `AppearanceSettingsPage` wrapped a `ThemeSettingsPage` that
  opened a `SettingsPage` of its own, so the page grid nested inside itself
  (two `.settingsPageStack` in the DOM). The page IS the theme page, as its
  own comment said, so it is now one component with one root. Same defect on
  通用, where the identity block was a `*Page` rendered inside another page:
  it is a section of someone else's page and is now named, filed, and shaped
  as one (`personalization-settings-section.tsx`).
- Grouping: the 14 option tiles were loose in the accessibility tree — the
  sections were unnamed landmarks and the visible 编辑器主题 / 产品色调
  labels had no programmatic relationship to the grids they head. Sections
  now carry `titleId`, and each grid is a `role="group"` named by its label.
- Copy: the nav description still advertised 界面语言 on 外观, a page that
  has not had it since P2-13; 通用, which does, never mentioned it. Both
  descriptions now say what their page holds.
- Dead copy: `sections.paletteHelp` was defined in both locales and read by
  nobody, while the palette section reached into `appearance.persistenceHelp`
  for its lede. The palette section now takes its lede from `sections`, the
  same namespace the theme section above it uses, and the unread key is gone.

`AppearanceSettingsPage` also stops taking a `settings` prop it only passed
down one level to a component that never read it.

Contract: `astryx-component-behavior` pins one page stack, the four
labelledby anchors, three named groups, no 界面语言 on 外观, and that the
identity block opens no page stack of its own.

Verified: desktop typecheck; format:check; console/a11y/copy checks;
dead-css; 1754 desktop tests; and both pages re-rendered in a real Electron
fixture window (外观 unchanged apart from the two copy lines, 通用 pixel
identical).
jackwener pushed a commit that referenced this pull request Aug 7, 2026
The 外观 page carried four leftovers from the moves that reshaped it —
identity going to 通用 (P2-13), the Astryx open-group rebuild (#1972), and
the settings-page kit (#1991).

- Page root: `AppearanceSettingsPage` wrapped a `ThemeSettingsPage` that
  opened a `SettingsPage` of its own, so the page grid nested inside itself
  (two `.settingsPageStack` in the DOM). The page IS the theme page, as its
  own comment said, so it is now one component with one root. Same defect on
  通用, where the identity block was a `*Page` rendered inside another page:
  it is a section of someone else's page and is now named, filed, and shaped
  as one (`personalization-settings-section.tsx`).
- Grouping: the 14 option tiles were loose in the accessibility tree — the
  sections were unnamed landmarks and the visible 编辑器主题 / 产品色调
  labels had no programmatic relationship to the grids they head. Sections
  now carry `titleId`, and each grid is a `role="group"` named by its label.
- Copy: the nav description still advertised 界面语言 on 外观, a page that
  has not had it since P2-13; 通用, which does, never mentioned it. Both
  descriptions now say what their page holds.
- Dead copy: `sections.paletteHelp` was defined in both locales and read by
  nobody, while the palette section reached into `appearance.persistenceHelp`
  for its lede. The palette section now takes its lede from `sections`, the
  same namespace the theme section above it uses, and the unread key is gone.

`AppearanceSettingsPage` also stops taking a `settings` prop it only passed
down one level to a component that never read it.

Contract: `astryx-component-behavior` pins one page stack, the four
labelledby anchors, three named groups, no 界面语言 on 外观, and that the
identity block opens no page stack of its own.

Verified: desktop typecheck; format:check; console/a11y/copy checks;
dead-css; 1754 desktop tests; and both pages re-rendered in a real Electron
fixture window (外观 unchanged apart from the two copy lines, 通用 pixel
identical).
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