swarm ui: one review page
The two review tabs, runs and try-out, are one: /review. It is a column of three sections: try a classification and the classifier settings, each a folded bar (the settings' bar says what they are now), then the recent runs, always open. The settings had been pinned under the try-out form; they are now a section of their own. A new Disclosure primitive is the folding bar, a native details wearing the Panel's classes, so the folded and open sections read as the same surface. /review-runs and /review-tryout are gone, with no redirect.
This commit is contained in:
parent
7b1435eaea
commit
a68d73fa74
19 changed files with 223 additions and 45 deletions
50
frontend/packages/swarm-ui/src/ui/disclosure/Disclosure.tsx
Normal file
50
frontend/packages/swarm-ui/src/ui/disclosure/Disclosure.tsx
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// <Disclosure> — a Panel that folds: the header row is the control, and the
|
||||
// body shows only while it is open. For a section a page keeps within reach
|
||||
// but that is not the point of the page, such as a form used now and then.
|
||||
// It is a native `<details>`, so the keyboard and assistive tech get the
|
||||
// open/closed state for free, and it wears the Panel's own classes, so a
|
||||
// Disclosure and a Panel on one page read as the same kind of surface.
|
||||
//
|
||||
// Controlled: `open` and `onToggle`, so a page can open it for the user (a
|
||||
// run started, say). The body stays in the DOM while it is shut, so what was
|
||||
// typed into it survives a fold. `hint` is a short line beside the title that
|
||||
// says what is in there without opening it.
|
||||
import type { ComponentChildren } from "preact";
|
||||
import "../panel/Panel.css";
|
||||
import "./Disclosure.css";
|
||||
|
||||
export function Disclosure({
|
||||
title,
|
||||
icon,
|
||||
hint,
|
||||
open,
|
||||
onToggle,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
icon?: string;
|
||||
hint?: ComponentChildren;
|
||||
open: boolean;
|
||||
onToggle: (open: boolean) => void;
|
||||
children: ComponentChildren;
|
||||
}) {
|
||||
return (
|
||||
<details
|
||||
class="ui-panel ui-disclosure"
|
||||
open={open}
|
||||
onToggle={(e) => onToggle((e.currentTarget as HTMLDetailsElement).open)}
|
||||
>
|
||||
<summary class="ui-panel-header ui-disclosure-summary">
|
||||
{icon ? (
|
||||
<span class="ui-panel-icon" aria-hidden="true">
|
||||
{icon}
|
||||
</span>
|
||||
) : null}
|
||||
<h2 class="ui-panel-title">{title}</h2>
|
||||
{hint ? <span class="ui-disclosure-hint">{hint}</span> : null}
|
||||
<span class="ui-disclosure-chevron" aria-hidden="true" />
|
||||
</summary>
|
||||
<div class="ui-panel-body">{children}</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue