Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ const CONTROL_HEIGHT: ControlHeightCheck[] = [
{ selector: '.maka-list-row-menu-trigger', props: ['width', 'height'], token: '--h-control-lg' },
// Search close and clear actions are shared quiet icon-sm Buttons, sized by
// buttonVariants rather than search-modal-specific CSS.
// 设置 nav / triggers
{ selector: '.settingsBackButton', props: ['height', 'min-height'], token: '--h-control-xl' },
{ selector: '.settingsNavItem', props: ['height', 'min-height'], token: '--h-control-xl' },
// 设置 nav / triggers — same lg tier as the session-list rows so the two
// sidebars share one row rhythm (PR settings-rows-convergence).
{ selector: '.settingsBackButton', props: ['height', 'min-height'], token: '--h-control-lg' },
{ selector: '.settingsNavItem', props: ['height', 'min-height'], token: '--h-control-lg' },
{ selector: '.settingsSelectTrigger', props: ['height'], token: '--h-control-lg' },
{ selector: '.settingsSelectMenuPopup [role="option"]', props: ['min-height'], token: '--h-control-lg' },
{ selector: '.maka-model-switcher-trigger', props: ['height'], token: '--h-control-sm' },
Expand Down Expand Up @@ -307,9 +308,9 @@ describe('control-height whitelist negative cases', () => {
assert.ok(offendersJb.some((o) => o.includes('missing required width')), `missing width must be flagged: ${offendersJb}`);
// .settingsNavItem is mapped with props: ['height', 'min-height'] — both
// required. Deleting either one must flag.
const navCheck: ControlHeightCheck = { selector: '.settingsNavItem', props: ['height', 'min-height'], token: '--h-control-xl' };
assert.ok(checkSelectorTier('.settingsNavItem {\n min-height: var(--h-control-xl);\n}', navCheck).some((o) => o.includes('missing required height')), 'missing height must be flagged');
assert.ok(checkSelectorTier('.settingsNavItem {\n height: var(--h-control-xl);\n}', navCheck).some((o) => o.includes('missing required min-height')), 'missing min-height must be flagged');
const navCheck: ControlHeightCheck = { selector: '.settingsNavItem', props: ['height', 'min-height'], token: '--h-control-lg' };
assert.ok(checkSelectorTier('.settingsNavItem {\n min-height: var(--h-control-lg);\n}', navCheck).some((o) => o.includes('missing required height')), 'missing height must be flagged');
assert.ok(checkSelectorTier('.settingsNavItem {\n height: var(--h-control-lg);\n}', navCheck).some((o) => o.includes('missing required min-height')), 'missing min-height must be flagged');
// A complete fixture (both props present, correct tier) passes.
assert.deepEqual(checkSelectorTier('.maka-chat-jump-bottom {\n width: var(--h-control-md);\n height: var(--h-control-md);\n}', jbCheck), [], 'complete square control must pass');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ const ALLOWLIST: ImportantAllowance[] = [
anchor: '@media (prefers-reduced-motion: reduce)',
reason: 'reduced-motion override',
},
{
// Settings row primitives (consolidated from nav-sidebar.css). Goes
// through the allowlist + `Justified:` path, NOT isA11yOnlyFile: the
// file is the style home for every Settings row, so a whole-file skip
// would blind the audit to future non-a11y `!important` there.
fileSuffix: 'apps/desktop/src/renderer/styles/settings/rows.css',
anchor: '@media (prefers-reduced-motion: reduce)',
reason: 'reduced-motion override',
},
{
fileSuffix: 'apps/desktop/src/renderer/styles/sidebar.css',
anchor: '.maka-session-panel[data-collapsed="true"] .maka-list-stack',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,34 @@ describe('Settings form accessibility labels', () => {
);
});

// PR settings-rows-convergence: styles/settings/rows.css is the single
// style home for the settings row primitives, and both row kinds share
// one typography + padding contract. Before the convergence,
// .settingsFormRow titles rendered 15px while adjacent .settingsRow
// titles on the SAME page rendered 13px with tighter padding. These
// pins match the COMMA-GROUPED shared rules, so both a value drift and
// a fork back into per-kind sibling rules fail.
it('keeps both settings row kinds on the converged typography and padding contract', async () => {
const styles = await readRendererContractCss();
const settingsRow = styles.match(/\.settingsRow\s*\{[\s\S]*?\n\}/)?.[0] ?? '';
const settingsFormRow = styles.match(/\.settingsFormRow\s*\{[\s\S]*?\n\}/)?.[0] ?? '';
const rowTitle = styles.match(/\.settingsRow strong,\s*\.settingsFormRow strong\s*\{[\s\S]*?\n\}/)?.[0] ?? '';
const fieldLabel = styles.match(/\.settingsField span,\s*\.settingsFormGrid label span\s*\{[\s\S]*?\n\}/)?.[0] ?? '';
const hint = styles.match(/\.settingsRow small,\s*\.settingsFormRow small,\s*\.settingsField small\s*\{[\s\S]*?\n\}/)?.[0] ?? '';

for (const [name, block] of [['.settingsRow', settingsRow], ['.settingsFormRow', settingsFormRow]] as const) {
assert.ok(block, `${name} base rule must exist in the aggregated renderer CSS (rows.css import reachable)`);
assert.match(block, /padding:\s*var\(--space-5\)\s+var\(--space-6\);/, `${name} must keep the shared space-5/space-6 row padding`);
}
assert.ok(rowTitle, 'row titles must stay on ONE comma-grouped rule for both row kinds');
assert.match(rowTitle, /font-size:\s*var\(--font-size-heading\);/, 'row titles sit on the heading tier for both row kinds');
assert.match(rowTitle, /font-weight:\s*var\(--font-weight-medium\);/, 'row titles are medium weight');
assert.ok(fieldLabel, 'field labels must stay on ONE comma-grouped rule');
assert.match(fieldLabel, /font-size:\s*var\(--font-size-ui\);/, 'field labels sit one tier BELOW row titles (ui, not heading)');
assert.ok(hint, 'hints must stay on ONE comma-grouped rule across row kinds and fields');
assert.match(hint, /font-size:\s*var\(--font-size-base\);/, 'hints sit on the body tier');
});

// Alignment-governance round (maintainer report: 每日回顾 switches sat
// mid-page while every other row control hugs the right rail). The
// original end-align rule was tag-qualified (`button[role="switch"]`)
Expand Down
7 changes: 4 additions & 3 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,10 @@
--h-control-md: calc(var(--spacing) * 7); /* 28px — compact menu item, sm tab,
round FAB (jump-to-bottom) */
--h-control-lg: var(--space-8); /* 32px — default button, input, tab,
sidebar nav row, session row, select */
--h-control-xl: calc(var(--spacing) * 9); /* 36px — prominent button, settings
nav row, first-run checklist row */
sidebar nav row, session row,
settings nav row, select */
--h-control-xl: calc(var(--spacing) * 9); /* 36px — prominent button,
first-run checklist row */
--h-control-2xl: var(--space-10); /* 40px — toolbar, large touch target */

/* === content measure (#520 PR4 item 16) ================================
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/styles/settings.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* settings.css — entry; rules split into styles/settings/ (issue #253 Round F). */
@import "./settings/form.css";
@import "./settings/rows.css";
@import "./settings/nav-sidebar.css";
@import "./settings/theme-preview.css";
@import "./settings/bot.css";
Expand Down
34 changes: 2 additions & 32 deletions apps/desktop/src/renderer/styles/settings/bot.css
Original file line number Diff line number Diff line change
Expand Up @@ -329,43 +329,13 @@
SimpleStatsTable in usage-settings-page.tsx (inline Tailwind classes,
no public primitive — a single HTML <table> consumer did not justify one). */

.settingsRow {
display: grid;
grid-template-columns: minmax(150px, 0.36fr) minmax(0, 1fr);
align-items: center;
gap: var(--space-4);
padding: var(--space-4) var(--space-5);
border: 0;
border-bottom: var(--border-width-hairline) solid oklch(from var(--foreground) l c h / 0.06);
border-radius: 0;
background: transparent;
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit + alignment-governance round: bare Switch controls sat at
the value column's START (x≈mid-page) while inputs/selects hug the right
rail. The original fix tag-qualified the selector with a button prefix, but
Base UI renders the Switch root as a SPAN — the selector matched nothing
and rotted silently. Tag-AGNOSTIC by rule: role is the contract, the
rendered tag never is. */
.settingsRow > [role="switch"] {
justify-self: end;
}
/* .settingsRow / .settingsRows moved to rows.css — the single style home
for the settings-rows.tsx primitives (PR-SETTINGS-ROWS-CONVERGENCE-0). */

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */

/* PR-SETTINGS-GROUPED-CARD-0 (WAWQAQ msg `1abecd66`): same grouped-
card pattern as `.settingsStructuredPage` — outer card + hairline
dividers, no per-row chrome. */
.settingsRows {
display: grid;
gap: 0;
border: var(--border-width-hairline) solid oklch(from var(--foreground) l c h / 0.08);
overflow: hidden;
}

/* Per-connection card on AccountSettingsPage. Status badge tone derives
* from the closed-form ConnectionUiStatus enum:
* neutral / info / success / warning / destructive.
Expand Down
21 changes: 2 additions & 19 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line number Diff line number Diff line change
Expand Up @@ -213,25 +213,8 @@
.settingsAuthActionPill[data-kind="preview"] {
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.30);
}
/* PR-SETTINGS-GROUPED-CARD-0: rows flush inside outer card, hairline
divider, last-child no border. Matches the reference grouped-list
pattern. */
.settingsRow:last-child {
border-bottom: 0;
}
.settingsRow:hover {
background: var(--state-hover-bg);
}
.settingsRow > div {
min-width: 0;
}
.settingsRow small {
display: block;
margin-top: var(--space-1);
color: var(--muted-foreground);
font-size: var(--font-size-ui);
line-height: var(--leading-snug);
}
/* .settingsRow states + hint moved to rows.css
(PR-SETTINGS-ROWS-CONVERGENCE-0). */
.providersPanel {
min-height: 420px;
display: grid;
Expand Down
Loading
Loading