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 numberDiff line numberDiff line change
Expand Up@@ -10,15 +10,19 @@ describe('renderer style pruning contract', () => {
it('does not keep CSS for retired renderer hooks', async () => {
const styles = await readFile(STYLES_PATH, 'utf8');
const retiredHooks = [
'connectionStatus',
'maka-indeterminate-bar',
'maka-nav-disclosure',
'maka-nav-primary',
'maka-nav-tree',
'maka-session-archive-link',
'maka-session-filter',
'maka-session-panel-help-chip',
'maka-session-search-clear',
'maka-sidebar-brand',
'maka-skill-workbench-rail',
'maka-streaming-token-fade-in',
'providerCatalog',
'settingsCardProviders',
'settingsFeatureStatusHeroActions',
'settingsHeader',
Expand Down
46 changes: 6 additions & 40 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,13 +91,7 @@ import {
Input,
OverlayScrollArea,
RelativeTime,
SelectItem,
SelectPopup,
SelectPortal,
SelectPositioner,
SelectRoot,
SelectTrigger,
SelectValue,
SettingsSelect,
PrimitiveBadge,
Switch as BaseUiSwitch,
Textarea,
Expand DownExpand Up@@ -179,39 +173,11 @@ function radioTabIndex<T extends string>(value: T, current: T, values: readonly
return !values.includes(current) && values[0] === value ? 0 : -1;
}

function SettingsSelect<T extends string>(props: {
value: T;
options: ReadonlyArray<readonly [T, string]>;
onChange(value: T): void;
ariaLabel: string;
disabled?: boolean;
}) {
return (
<SelectRoot
value={props.value}
items={props.options.map(([value, label]) => ({ value, label }))}
disabled={props.disabled}
onValueChange={(value) => {
if (value !== null) props.onChange(value);
}}
>
<SelectTrigger className="settingsBaseSelectTrigger w-full" aria-label={props.ariaLabel}>
<SelectValue />
</SelectTrigger>
<SelectPortal>
<SelectPositioner alignItemWithTrigger={false} sideOffset={6}>
<SelectPopup className="settingsBaseSelectPopup">
{props.options.map(([value, label]) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</SelectPositioner>
</SelectPortal>
</SelectRoot>
);
}
// `SettingsSelect` moved to `packages/ui/src/primitives/settings-select.tsx`
// in PR round-AB-shared-select (yuejing 2026-06-25). The Plan Reminder
// platform select now uses the same primitive, so option shape,
// selected-trigger icon rendering, and chrome contract are one source
// of truth (kenji styles inventory task #128). Imported via `@maka/ui`.

// `SettingsNavGroup` + `NAV_GROUP_ORDER` moved to `nav-group-summary.ts`
// (PR-HEALTH-1) so the H1/H2 group-summary assertions can be pinned with
Expand Down
67 changes: 17 additions & 50 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -806,28 +806,6 @@ button:active {
color: currentColor;
}

.maka-session-panel[data-collapsed="true"] .maka-nav-primary {
width: 28px;
min-width: 28px;
height: 28px;
min-height: 28px;
display: grid;
grid-template-columns: 1fr;
place-items: center;
gap: 0;
margin-inline: auto;
padding: 0;
border-radius: 6px;
}

.maka-session-panel[data-collapsed="true"] .maka-nav-primary span {
display: none;
}

.maka-session-panel[data-collapsed="true"] .maka-nav-primary {
background: var(--foreground-5);
}

.maka-nav-icon {
width: var(--icon-size);
height: var(--icon-size);
Expand DownExpand Up@@ -3251,8 +3229,14 @@ button:active {
box-shadow: 0 0 0 2px oklch(from var(--accent) l c h / 0.12);
}

.maka-plan-select {
width: 100%;
/* PR round-AB-shared-select (yuejing 2026-06-25): the Plan Reminder
delivery select and the 5 Settings selects used to ship two slightly
different wrappers — different option shapes, different selected
trigger renderers, different CSS recipes. They are now one
`SettingsSelect` primitive in `@maka/ui` (see kenji styles inventory
`notes/maka-styles-css-inventory-2026-06-25-task-128.md`). These
`.settingsSelect*` rules pin the unified chrome. */
.settingsSelectTrigger {
min-width: 0;
height: 34px;
justify-content: space-between;
Expand All@@ -3261,24 +3245,21 @@ button:active {
font-weight: 600;
}

.maka-plan-select-popup {
.settingsSelectPopup {
min-width: var(--anchor-width);
}

/* PR audit2-bundled (@kenji audit msg `e4cfbfb0` finding #2): the Plan
Reminder delivery picker now carries real IM brand logos so it reads
the same as Settings → 机器人对话. The icon slot lines up with the
text via inline-flex; the icon tile is a fixed 16x16 to absorb
Iconify's size: '100%' rendering of the lazy-loaded simple-icons
svg without pushing the option row height around. */
.maka-plan-select-option {
/* The icon slot lines up with the text via inline-flex; the icon tile
is a fixed 16x16 to absorb Iconify's size: '100%' rendering of the
simple-icons svg without pushing option row height around. */
.settingsSelectOption {
display: inline-flex;
align-items: center;
gap: 8px;
min-width: 0;
}

.maka-plan-select-option-icon {
.settingsSelectOptionIcon {
flex: 0 0 auto;
width: 16px;
height: 16px;
Expand DownExpand Up@@ -4311,9 +4292,6 @@ button:active {
grid-template-columns: minmax(0, 1fr);
}

.maka-skill-workbench-rail {
position: static;
}
.maka-skill-library-row {
grid-template-columns: 38px minmax(0, 1fr) max-content;
gap: 6px;
Expand DownExpand Up@@ -7437,9 +7415,7 @@ button:active {
justify-self: end;
}

.settingsRow[data-control-width="select"] > .settingsBaseSelectTrigger {
max-width: 320px;
width: 100%;
.settingsRow[data-control-width="select"] > .settingsSelectTrigger {
justify-self: end;
}

Expand DownExpand Up@@ -7863,7 +7839,7 @@ button:active {
PR-SETTINGS-INPUT-POLISH-0: cap from 280 → 320 since rows are now
roomier (24px L/R padding). */
.settingsField[data-orient="horizontal"] > input,
.settingsField[data-orient="horizontal"] > .settingsBaseSelectTrigger {
.settingsField[data-orient="horizontal"] > .settingsSelectTrigger {
max-width: 320px;
}
/* WAWQAQ msg `0951e3b1` 2026-06-25 + @kenji audit #5 (msg `26a221be`):
Expand DownExpand Up@@ -9397,14 +9373,6 @@ button:active {
line-height: 1.4;
}

.providerCatalog {
min-width: 0;
display: grid;
grid-template-rows: auto 1fr auto;
gap: 12px;
overflow: hidden;
}

.catalogTabs {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
Expand DownExpand Up@@ -9831,8 +9799,7 @@ button:active {
flex-wrap: wrap;
}

.providerError,
.connectionStatus[data-ok="false"] {
.providerError {
color: var(--destructive-text);
}

Expand Down
78 changes: 10 additions & 68 deletions packages/ui/src/components.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@ import {
IconifyIcon,
} from './icons.js';
import { BOT_BRAND } from './bot-brand.js';
import { SettingsSelect, type SettingsSelectOption } from './primitives/settings-select.js';
import { redactSecrets } from './redact.js';
import { DeepResearchEmptyHero, EmptyChatHero } from './chat-empty-hero.js';
import {
Expand DownExpand Up@@ -1992,80 +1993,21 @@ function DailyReviewTopList(props: { title: string; entries: ReadonlyArray<Daily
);
}

// PR audit2-bundled (@kenji msg `e4cfbfb0` finding #2): the third
// tuple slot lets callers pass a leading icon (e.g. the real IM brand
// logo) so the Plan Reminder delivery picker reads identically to
// Settings → 机器人对话, instead of falling back to plain Chinese text.
type PlanReminderOption<T extends string> =
| readonly [T, string]
| readonly [T, string, ReactNode];

// PR round-AB-shared-select (yuejing 2026-06-25, kenji styles inventory
// task #128): `PlanReminderSelect` is now a thin specialization of the
// shared `SettingsSelect` primitive — `width="full"` to preserve the
// existing edge-to-edge sizing inside `.maka-plan-delivery-grid`.
// Plan Reminder and Settings selects share one component so option
// shape, trigger/popup chrome, and the selected-trigger icon contract
// can't drift apart again.
function PlanReminderSelect<T extends string>(props: {
value: T;
options: ReadonlyArray<PlanReminderOption<T>>;
options: ReadonlyArray<SettingsSelectOption<T>>;
onChange(value: T): void;
ariaLabel: string;
disabled?: boolean;
}) {
// PR audit3 (@kenji msg `232aec0f` finding #2): the dropdown items
// already render the brand icon, but the collapsed `<SelectValue />`
// was falling back to the plain label string — open dropdown showed
// a logo, but the picked value collapsed back to text. Build a
// value→{label,icon} lookup and have `SelectValue`'s function child
// render the icon + label together so the selected state matches the
// option state.
const optionByValue = new Map<T, { label: string; icon: ReactNode | null }>();
for (const option of props.options) {
const [value, label] = option;
optionByValue.set(value, {
label,
icon: option.length === 3 ? option[2] : null,
});
}
const renderOptionRow = (label: string, icon: ReactNode | null, className = 'maka-plan-select-option') =>
icon ? (
<span className={className}>
<span className="maka-plan-select-option-icon" aria-hidden="true">{icon}</span>
<span>{label}</span>
</span>
) : (
<>{label}</>
);
return (
<SelectRoot
value={props.value}
items={props.options.map(([value, label]) => ({ value, label }))}
disabled={props.disabled}
onValueChange={(value) => {
if (value !== null) props.onChange(value);
}}
>
<SelectTrigger className="maka-plan-select w-full" aria-label={props.ariaLabel}>
<SelectValue>
{(value: T) => {
const entry = optionByValue.get(value);
if (!entry) return null;
return renderOptionRow(entry.label, entry.icon);
}}
</SelectValue>
</SelectTrigger>
<SelectPortal>
<SelectPositioner alignItemWithTrigger={false} sideOffset={6}>
<SelectPopup className="maka-plan-select-popup">
{props.options.map((option) => {
const [value, label] = option;
const icon = option.length === 3 ? option[2] : null;
return (
<SelectItem key={value} value={value}>
{renderOptionRow(label, icon)}
</SelectItem>
);
})}
</SelectPopup>
</SelectPositioner>
</SelectPortal>
</SelectRoot>
);
return <SettingsSelect width="full" {...props} />;
}

function PlanReminderPanel(props: {
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,7 @@ export * from './primitives/menu.js';
export * from './primitives/group.js';
export * from './primitives/frame.js';
export * from './primitives/preview-card.js';
export * from './primitives/settings-select.js';
export * from './primitives/input-group.js';
export * from './primitives/pagination.js';
export * from './primitives/sidebar.js';
Expand Down
Loading