fix: admin config pickers fit a phone

A segmented bar cannot shrink or wrap, and the five log levels (~300 px) are wider than a phone leaves beside the navigation rail. A choice is a bar only when its labels are short; the rows stack below sm.
This commit is contained in:
2026-09-17 03:53:40 +02:00
parent f92cd9017f
commit 7789db8240
2 changed files with 30 additions and 17 deletions
+11 -3
View File
@@ -340,7 +340,9 @@ function Field({
const showReset = item.is_set && !isBool;
return (
<div className="flex items-start justify-between gap-3 py-3">
// Stacked below `sm`: the control column cannot shrink, and beside a wide control it left the
// label and hint a sliver of a phone's width.
<div className="flex flex-col gap-2 py-3 sm:flex-row sm:items-start sm:justify-between sm:gap-3">
<div className="min-w-0 flex-1">
<div className="text-sm font-medium">{label}</div>
<p className="text-xs text-muted leading-relaxed mt-0.5">
@@ -349,7 +351,7 @@ function Field({
<p className="text-2xs text-muted mt-1">{status}</p>
</div>
<div className="flex flex-col items-end gap-1.5 shrink-0">
<div className="flex max-w-full flex-col items-start gap-1.5 sm:shrink-0 sm:items-end">
{isBool ? (
<Switch
label={label}
@@ -392,7 +394,12 @@ function Field({
// A closed-set key picks from its options instead of taking free text: a segmented bar for a short
// list, a dropdown past six (the house rule for chip vs. select). A cleared draft ("" = reset to the
// default on Save) shows the default as the active option, as a text field shows it as placeholder.
//
// "Short" is also about the words, not just their number: a bar cannot shrink or wrap, and five level
// names (TRACE … WARNING, ~300 px) are wider than a phone leaves beside the navigation rail (~250 px).
// Past MAX_SEGMENT_CHARS of labels, in the language shown, it is a dropdown too.
const MAX_SEGMENTS = 6;
const MAX_SEGMENT_CHARS = 22;
function ChoiceField({
item,
@@ -411,7 +418,8 @@ function ChoiceField({
label: t(`config.choices.${item.key}.${c}`, c),
}));
const current = value || String(item.default ?? "");
if (options.length <= MAX_SEGMENTS) {
const labelChars = options.reduce((sum, o) => sum + o.label.length, 0);
if (options.length <= MAX_SEGMENTS && labelChars <= MAX_SEGMENT_CHARS) {
return (
<SegmentedToggle
options={options}