fix(ui): match Omics header and compact workspace layout
This commit is contained in:
@@ -128,6 +128,8 @@ test("option A has one collapsible global context and preserves the Core draft a
|
||||
await userEvent.click(screen.getByRole("button", { name: /Working context/ }));
|
||||
expect(screen.getAllByRole("combobox", { name: "Workspace" })).toHaveLength(1);
|
||||
expect(screen.getAllByRole("combobox", { name: "Model" })).toHaveLength(1);
|
||||
expect(screen.getByRole("button", { name: "Done" }).closest(".thot-context-fields"))
|
||||
.toBe(screen.getByRole("combobox", { name: "Model" }).closest(".thot-context-fields"));
|
||||
await userEvent.selectOptions(screen.getByRole("combobox", { name: "Workspace" }), "beta");
|
||||
expect(workspacePreferences.load()).toMatchObject({ workspaceId: "beta", provider: "test", model: "test" });
|
||||
await userEvent.click(screen.getByRole("button", { name: "Done" }));
|
||||
|
||||
@@ -190,6 +190,8 @@ test("administrators can explicitly switch to all sessions and see owners", asyn
|
||||
expect(mySessions).toHaveAttribute("tabindex", "0");
|
||||
expect(mySessions).toHaveAttribute("data-tab-state", "active");
|
||||
expect(mySessions).toHaveClass("bg-[oklch(var(--nav-active))]");
|
||||
expect(mySessions).toHaveClass("border-b-0");
|
||||
expect(allSessions).toHaveClass("border-b-0");
|
||||
expect(allSessions).toHaveAttribute("aria-selected", "false");
|
||||
expect(allSessions).toHaveAttribute("aria-controls", "session-scope-panel");
|
||||
expect(allSessions).toHaveAttribute("tabindex", "-1");
|
||||
|
||||
@@ -61,7 +61,7 @@ interface AppShellProps {
|
||||
const SESSION_SCOPES: readonly SessionScope[] = ["mine", "all"];
|
||||
|
||||
function sessionScopeTabClass(selected: boolean): string {
|
||||
const base = "relative -mb-px flex h-8 w-full cursor-pointer items-center justify-center rounded-t-md border border-b-2 px-2 text-xs font-semibold tracking-[0.005em] outline-none focus-visible:z-10 focus-visible:ring-3 focus-visible:ring-[oklch(var(--nav-active-border)/0.28)]";
|
||||
const base = "relative -mb-px flex h-8 w-full cursor-pointer items-center justify-center rounded-t-md border border-b-0 px-2 text-xs font-semibold tracking-[0.005em] outline-none focus-visible:z-10 focus-visible:ring-3 focus-visible:ring-[oklch(var(--nav-active-border)/0.28)]";
|
||||
return selected
|
||||
? `${base} border-[oklch(var(--nav-active-border))] bg-[oklch(var(--nav-active))] text-[oklch(var(--nav-active-foreground))] hover:bg-[oklch(var(--nav-active-hover))]`
|
||||
: `${base} border-border bg-card text-muted-foreground hover:border-muted-foreground/45 hover:bg-muted/55 hover:text-foreground`;
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
.thot-context-trigger[aria-expanded=true] .thot-context-action > svg:last-child { transform: rotate(180deg); }
|
||||
.thot-context-body { margin: 0 var(--thoth-content-gutter) var(--thoth-content-gutter); padding: var(--thoth-content-padding); background: oklch(var(--card)); }
|
||||
.thot-context-body[hidden] { display: none; }
|
||||
.thot-context-fields { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 24px; }
|
||||
.thot-context-fields { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)) auto; align-items: end; gap: 16px; }
|
||||
.thot-context-fields label { display: grid; min-width: 0; gap: 8px; font-size: var(--text-control); }
|
||||
.thot-context-fields label > span { display: flex; align-items: center; gap: 8px; font-weight: 600; }
|
||||
.thot-context-fields select { min-width: 0; width: 100%; padding: 9px 12px; border: 1px solid oklch(var(--border)); border-radius: 6px; background: oklch(var(--card)); }
|
||||
.thot-context-fields select { min-width: 0; width: 100%; height: 32px; padding: 4px 12px; border: 1px solid oklch(var(--border)); border-radius: 6px; background: oklch(var(--card)); }
|
||||
.thot-context-body > p[role] { color: oklch(var(--muted-foreground)); font-size: .75rem; line-height: 1.6; }
|
||||
.thot-context-body > p[role] { margin-top: 12px; }
|
||||
.thot-context-footer { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
|
||||
.thot-context-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
|
||||
.thot-context-shelf :is(button,select):focus-visible { outline: 2px solid oklch(var(--ring)); outline-offset: 3px; }
|
||||
.thot-context-shelf select:disabled { opacity: .65; }
|
||||
@container working-context (max-width: 38rem) {
|
||||
|
||||
@@ -31,11 +31,11 @@ export function WorkingContextShelf({ context, locked, onWorkspace, onModel }: {
|
||||
<option value="" disabled>{translate("Choose a model")}</option>{context.models.map(model => <option key={`${model.provider}/${model.id}`} value={`${model.provider}/${model.id}`}>{model.name}</option>)}
|
||||
</select>
|
||||
</label>
|
||||
<div className="thot-context-actions">{context.error && <Button variant="outline" onClick={context.retry}>{translate("Retry context")}</Button>}{context.ready && <Button variant="outline" onClick={() => setExpanded(false)}>{translate("Done")}</Button>}</div>
|
||||
</div>
|
||||
{locked && <p role="status">{translate("Workspace and model are locked until the current operation finishes.")}</p>}
|
||||
{context.ready && context.error && <p role="status">{translate("Context refresh failed. Your current choices and unsaved work have been retained.")}</p>}
|
||||
{!context.ready && <p role="status">{context.loading ? translate("Loading working context…") : context.error ? translate("Working context is unavailable. Retry or ask the installation operator to check configuration.") : translate("Select an available workspace and model to enable Core and Administration. Unavailable saved choices are not replaced automatically.")}</p>}
|
||||
<div className="thot-context-footer">{context.error && <Button variant="outline" onClick={context.retry}>{translate("Retry context")}</Button>}{context.ready && <Button variant="outline" onClick={() => setExpanded(false)}>{translate("Done")}</Button>}</div>
|
||||
</div>
|
||||
</section>;
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
grid-area: status;
|
||||
min-width: 0;
|
||||
padding-inline: var(--fleet-summary-inset);
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.thot-fleet-ledger .thot-administration-header,
|
||||
|
||||
@@ -38,7 +38,7 @@ export function FullHeader({ onLogout }: { onLogout?: () => Promise<void> }) {
|
||||
|
||||
return (
|
||||
<header className="thot-full-header" aria-label={t("Application header")}>
|
||||
<span className="thot-full-header__brand">Thoth<span className="text-primary">II</span></span>
|
||||
<span className="thot-full-header__brand">Thoth<span>II</span></span>
|
||||
<div className="thot-full-header__controls">
|
||||
<label className="sr-only" htmlFor="thot-ui-language">{t("Interface language")}</label>
|
||||
<select id="thot-ui-language" className="thot-shell-select" value={shell.locale} onChange={event => shell.changeLocale(event.target.value)}>
|
||||
|
||||
Reference in New Issue
Block a user