Files
magpie/internal/gui/assets/sessions.css
T
tsuixl bd33e575f1 gui: let users choose installed interface and code fonts (#1007)
* gui: choose installed interface and code fonts and styles

Discover installed styles through DirectWrite, CoreText and Fontconfig. Keep choices per computer, apply them before paint and notify both desktop webviews after saving; defaults retain platform and Omarchy fallbacks.

Verified seven focused Go tests, including real Windows discovery (90 families, 276 styles), 14 font browser cases in Chromium/WebKit, 68 settings/zoom/Omarchy/web cases, go vet, Windows amd64/arm64 and Linux nogui builds. Against the original assets, the new UI test fails with Settings must offer an interface font picker (0 != 1). Full Windows suites have separately reproduced upstream failures; macOS/Linux native discovery is covered by the added CI step.

* gui: retain bundled Mac fonts and variable style precision

Only filter an undownloaded CoreText face when it is explicitly downloadable; bundled fonts are installed without being downloaded. Use resolved font names when descriptors omit them. Preserve fractional weights and nonnegative CSS widths for named variable styles.

* gui: restore the authored font cascade when returning to defaults

Apply family-only trait overrides only while a custom face is active. The browser regression catches code under a bold parent becoming 700 instead of its original 400. Keep the compatibility shim first, and apply boot fonts before visible content.

* gui: keep font picker review separate from CI integration

Leave the native test sources and manual verification command with the feature. Move the added workflow step to a follow-up so the font picker can take the normal review path requested on PR #1007.
2026-10-06 19:32:56 +08:00

80 lines
5.9 KiB
CSS

/* Sessions: every session of an agent, by folder, to resume or delete (sessions.js) */
.sm-head { gap: 8px; height: auto; min-height: 34px; }
.sm-switch { min-width: 0; flex: 1; display: flex; align-items: center; }
.sm-agents { min-width: 0; max-width: 100%; }
.segs.sm-agents { background: var(--seg-track); }
.sm-agents .opt:not(.on, :hover) { color: var(--ctl-fg); }
.sm-agents .opt { display: inline-flex; align-items: center; gap: 5px; }
.sm-agents .opt.on { background: var(--seg-thumb); box-shadow: var(--seg-edge); }
.sm-agents .opt.on em { color: var(--muted); }
.sm-agents .opt .ic { width: 13px; height: 13px; }
.sm-agent-pick { min-width: 0; max-width: 220px; gap: 6px; color: var(--fg); }
.sm-agent-pick .ic { width: 13px; height: 13px; flex: none; }
.sm-agent-pick em, .sm-agents em, .sm-trash-btn em { font-style: normal; font-size: 10.5px; color: var(--faint); font-variant-numeric: tabular-nums; }
.pop.proto-menu.sm-agent-menu { width: min(280px, calc(100vw - 16px)); max-height: min(360px, 70vh); overflow-y: auto; background: var(--card); }
.sm-agent-menu .pm-words { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex: 1; }
.sm-agent-menu .pm-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sm-agent-menu .pm-note { flex: none; font-variant-numeric: tabular-nums; }
.sm-filter { width: 200px; flex: 0 1 200px; min-width: 110px; }
.sm-trash-btn { display: inline-flex; align-items: center; gap: 5px; flex: none; }
.sm-trash-btn.on { background: var(--pill); color: var(--fg); }
.sm-body { display: flex; flex-direction: column; gap: 8px; flex: none; }
.sm-note { margin: 0 2px; }
.sm-bar { gap: 8px; padding: 0 11px; }
.sm-bar .grow { flex: 1; }
.sm-bar .sm-delete, .sm-bar .sm-empty { display: inline-flex; align-items: center; gap: 5px; }
.sm-bar .sm-delete:disabled { opacity: .45; }
.sm-count { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sm-check { flex: none; margin: 0; width: 14px; height: 14px; accent-color: var(--accent); }
.sm-tree { display: flex; flex-direction: column; gap: 8px; }
.sm-group .skeleton.sk-line { width: 60%; height: 12px; }
.row.sm-folder { min-height: 34px; gap: 8px; }
.row.sm-folder .fold { color: var(--fg-2); font-weight: 500; flex: none; max-width: 45%; }
.row.sm-folder .fold .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row.sm-folder .sm-path { flex: 0 1 auto; min-width: 0; margin: 0; font-family: var(--code-font, var(--code)); font-size: 10.5px; color: var(--faint); }
:where(html[data-fonts]) .row.sm-folder .sm-path { font-style: var(--code-style, inherit); font-weight: var(--code-weight, inherit); font-stretch: var(--code-stretch, 100%); }
.row.sm-folder .grow { flex: 1; }
.row.sm-folder .note { flex: none; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
.row.sm-sess { min-height: 44px; }
.sm-item .sess-detail { padding-left: 34px; }
.row.sess .sm-del:hover { color: var(--red); background: var(--red-soft); }
/* carrying a session on in another agent, and its conversation (#845) */
.row.sm-sess .sess-carry { height: 24px; color: var(--fg); }
.pop.proto-menu.sess-carry-menu { width: min(300px, calc(100vw - 16px)); background: var(--card); }
.sess-talk-btn { height: 22px; padding: 0 8px; font-size: 11.5px; }
.sess-talk { max-height: min(560px, 70vh); overflow-y: auto; margin-top: 4px; padding: 8px 10px 4px; border-radius: 9px; border: 1px solid var(--line-2); background: var(--bg); }
.sm-restore { display: inline-flex; align-items: center; gap: 5px; }
.sm-ask-list { grid-column: 1 / -1; min-width: 0; margin: 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--fg); line-height: 1.6; }
.sm-ask-list li { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sm-ask-list li.more { color: var(--muted); }
.sm-ask-path { grid-column: 1 / -1; min-width: 0; margin: 0; font-family: var(--code-font, var(--code)); font-size: 11px; color: var(--muted); overflow-wrap: anywhere; }
:where(html[data-fonts]) .sm-ask-path { font-style: var(--code-style, inherit); font-weight: var(--code-weight, inherit); font-stretch: var(--code-stretch, 100%); }
@media (max-width: 560px) {
.sm-filter { width: 130px; flex-basis: 130px; }
.row.sm-folder .sm-path { display: none; }
/* the cost stays; the title keeps the room the tokens took (#752) */
.row.sm-sess .num { display: none; }
.row.sm-sess .cost { min-width: 0; }
/* five gaps of 12px left a 420px window's title 90px once the list
scrolled and its scrollbar took 10px */
.row.sess.sm-sess { gap: 8px; }
}
@media (max-width: 420px) {
.sm-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; row-gap: 6px; }
.sm-switch { grid-column: 1 / -1; }
.sm-agent-pick { max-width: 100%; }
.sm-filter { width: 100%; min-width: 0; }
.sm-trash-btn { grid-column: 2; justify-self: end; }
}
/* Codex sessions made with another provider, hidden from Codex's history (#887) */
.row.sm-provider { gap: 10px; min-height: 40px; padding: 8px 11px; height: auto; }
.sm-provider-text { min-width: 0; font-size: 12px; color: var(--fg-2); line-height: 1.45; }
.sm-provider .grow { flex: 1; }
.sm-provider .text { flex: none; display: inline-flex; align-items: center; gap: 5px; }
.sm-prov { display: inline-block; padding: 0 5px; border-radius: 4px; background: var(--pill); color: var(--muted); font-family: var(--code-font, var(--code)); font-size: 10.5px; line-height: 16px; }
:where(html[data-fonts]) .sm-prov { font-style: var(--code-style, inherit); font-weight: var(--code-weight, inherit); font-stretch: var(--code-stretch, 100%); }
.sm-provider-list li label { display: flex; align-items: center; gap: 8px; min-width: 0; cursor: pointer; }
.sm-provider-list li .name { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sm-provider-list li .note { flex: none; font-size: 11px; color: var(--faint); }
.sm-provider-list { max-height: min(300px, 45vh); overflow-y: auto; }