Move the console onto ReUI PRO

Install ReUI (MCP, skill, @reui registry, Tailwind v4, shadcn base-nova) and move
the shared UI onto it: Button, Tag, Check, Input/Textarea, Segmented, Alert, Panel,
Dialog, Tooltip, Menu and Select (Popover), Toast (sonner), the Table frame
(DataGrid), the Dashboard KPI strip, the shnt Ops palette, Geist and the type scale.

Design only: behaviour, texts and roles are unchanged. Tests that asserted the old
DOM were updated; the tests now format numbers in English wherever they run.
docs/reui-migration-plan.md records the plan and its decisions.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
DenozordecandClaude Sonnet 5.5 committed 2026-10-27 00:06:06 +07:00
commit f3531c64f9
680 files changed
+139836

No files matched your search

+146
View File
@@ -0,0 +1,146 @@
/*
The trigger is the same hole as a text field: in a form, choosing and typing have
to weigh the same. What changes is that this one opens.
*/
.trigger {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--s-6);
width: 100%;
min-height: var(--field-height);
padding: var(--s-5) var(--s-7);
border: 1px solid var(--line-field);
border-radius: var(--r-3);
background-color: var(--field);
color: var(--ink);
font: inherit;
font-size: var(--t-4);
/* `font: inherit` brought the body's 1.55 and the trigger came out 37.4 px:
three px taller than the text field beside it (see `--field-line`). */
line-height: var(--field-line);
text-align: left;
cursor: pointer;
box-shadow: var(--sunken);
transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.trigger:hover:not(:disabled) { border-color: var(--line-ctrl); }
.trigger:focus-visible,
.trigger[aria-expanded='true'] {
outline: none;
border-color: var(--acc-ink);
box-shadow: var(--sunken), var(--halo-focus);
}
.trigger:disabled { opacity: 0.45; cursor: default; }
.value { composes: truncated from './text.module.css'; }
.emptyText { color: var(--faint); }
.chevron { color: var(--mute); flex: none; transition: transform var(--t-fast); }
.trigger[aria-expanded='true'] .chevron { transform: rotate(180deg); }
/*
The list. It is genuinely raised (two steps above the field) because it floats
over the form and has to read as something in front.
*/
.list {
/* The surface (position, border, shadow) is the Popover's. */
max-height: 280px;
scrollbar-width: thin;
overflow-y: auto;
padding: var(--s-3);
}
.option {
display: flex;
align-items: center;
gap: var(--s-5);
padding: var(--s-4) var(--s-5);
border-radius: var(--r-2);
font-size: var(--t-4);
color: var(--ink);
cursor: pointer;
/* Only an option wider than the window wraps, between words; the rest fit on one line. */
overflow-wrap: break-word;
}
.option[data-active='true'] { background: var(--hover-strong); }
.option[aria-selected='true'] { color: var(--acc-ink); font-weight: 600; }
.option[aria-disabled='true'] { color: var(--faint); cursor: default; }
.option[aria-disabled='true'][data-active='true'] { background: none; }
/* Fixed room for the tick: without it, choosing would shift the text. */
.brand {
display: inline-flex;
justify-content: center;
width: 14px;
flex: none;
color: var(--acc-ink);
}
.isEmpty { color: var(--faint); }
/*
`searchable` (the console's own, see `Select.tsx`): the box holds the search field
on top and the listbox under it, and only the listbox scrolls, so the field stays
in view however far down the options go.
*/
.searching {
display: flex;
flex-direction: column;
gap: var(--s-3);
overflow: hidden;
}
.scroll {
min-height: 0;
overflow-y: auto;
scrollbar-width: thin;
}
/* The field of `ui/Field`, one step smaller: it filters the list, it is not a value of the form. */
.search {
flex: none;
width: 100%;
min-width: 0;
min-height: var(--field-height);
padding: var(--s-4) var(--s-6);
border: 1px solid var(--line-field);
border-radius: var(--r-2);
background-color: var(--field);
color: var(--ink);
font: inherit;
font-size: var(--t-4);
line-height: var(--field-line);
box-shadow: var(--sunken);
}
.search::placeholder { color: var(--faint); }
.search:focus {
outline: none;
border-color: var(--acc-ink);
background-color: var(--field-focus);
}
/* An `<optgroup>`'s label: a heading of the options under it, not one of them. */
.groupLabel {
composes: smallCaps from './label.module.css';
margin-top: var(--s-3);
padding: var(--s-4) var(--s-5) var(--s-2);
border-top: 1px solid var(--line);
cursor: default;
}
/* The search matched nothing: the line where the options would be. */
.none {
padding: var(--s-4) var(--s-5);
font-size: var(--t-4);
color: var(--mute);
}
@media (prefers-reduced-motion: reduce) {
.trigger,
.chevron { transition: none; }
}