refactor(desktop): rebuild Settings on the Astryx open-group idiom - #1972
Merged
Conversation
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.
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).
This was referenced Aug 3, 2026
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SettingsSection/SettingsRow/SettingsField/SettingsActions/.settingsStatus), no stacked full-width cardsTesting
node --test dist/main: 1354 pass / 0 fail