Use shared form controls and enforce UI patterns (Refs #110)
CI / checks (push) Successful in 4m51s
CI / checks (push) Successful in 4m51s
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Select from '$ui/components/primitives/Select.svelte';
|
||||
import Field from '$ui/components/primitives/Field.svelte';
|
||||
import Input from '$ui/components/primitives/Input.svelte';
|
||||
import { untrack } from 'svelte';
|
||||
import { beforeNavigate, goto } from '$app/navigation';
|
||||
import { confirmAction } from '$ui/confirm.js';
|
||||
@@ -155,18 +158,18 @@
|
||||
<svelte:window onbeforeunload={beforeUnload} />
|
||||
<div class="settings-layout">
|
||||
<aside class="section-rail">
|
||||
<label class="search-label" for="settings-search">Find a setting</label>
|
||||
<input
|
||||
id="settings-search"
|
||||
type="search"
|
||||
placeholder="Search settings"
|
||||
bind:value={query}
|
||||
disabled={saving}
|
||||
oninput={() => (reviewInvalid = false)}
|
||||
/>
|
||||
<label class="mobile-section"
|
||||
>Section
|
||||
<select
|
||||
<Field label="Find a setting" forId="settings-search">
|
||||
<Input
|
||||
id="settings-search"
|
||||
type="search"
|
||||
placeholder="Search settings"
|
||||
bind:value={query}
|
||||
disabled={saving}
|
||||
oninput={() => (reviewInvalid = false)}
|
||||
/></Field
|
||||
>
|
||||
<Field class="mobile-section" label="Section">
|
||||
<Select
|
||||
aria-label="Settings section"
|
||||
value={selectedGroup}
|
||||
disabled={saving}
|
||||
@@ -177,8 +180,8 @@
|
||||
? ` · ${changed.filter((key) => group.keys.includes(key)).length} changed`
|
||||
: ''}</option
|
||||
>{/each}
|
||||
</select>
|
||||
</label>
|
||||
</Select>
|
||||
</Field>
|
||||
<nav class="group-links" aria-label="Settings sections">
|
||||
{#each settingsGroups as group}
|
||||
{@const count = changed.filter((key) => group.keys.includes(key)).length}
|
||||
@@ -263,30 +266,37 @@
|
||||
>
|
||||
<td class="value-cell">
|
||||
<div class="numeric-value">
|
||||
{#if unlimited}<input
|
||||
id={`setting-${key}`}
|
||||
type="number"
|
||||
disabled
|
||||
placeholder="—"
|
||||
aria-describedby={`setting-${key}-help setting-${key}-default`}
|
||||
/>
|
||||
{:else}<input
|
||||
id={`setting-${key}`}
|
||||
type="number"
|
||||
min={Math.max(1, settingMinimum(key))}
|
||||
max={key.endsWith('Days')
|
||||
? 36500
|
||||
: undefined}
|
||||
step="1"
|
||||
required
|
||||
bind:value={draft[key]}
|
||||
aria-invalid={!!validation}
|
||||
aria-describedby={`setting-${key}-help setting-${key}-default${validation ? ` setting-${key}-error` : ''}`}
|
||||
oninput={() => {
|
||||
error = '';
|
||||
notice = '';
|
||||
}}
|
||||
/>{/if}
|
||||
{#if unlimited}<Field
|
||||
><Input
|
||||
id={`setting-${key}`}
|
||||
type="number"
|
||||
disabled
|
||||
placeholder="—"
|
||||
aria-describedby={`setting-${key}-help setting-${key}-default`}
|
||||
/></Field
|
||||
>
|
||||
{:else}<Field
|
||||
><Input
|
||||
id={`setting-${key}`}
|
||||
type="number"
|
||||
min={Math.max(
|
||||
1,
|
||||
settingMinimum(key)
|
||||
)}
|
||||
max={key.endsWith('Days')
|
||||
? 36500
|
||||
: undefined}
|
||||
step="1"
|
||||
required
|
||||
bind:value={draft[key]}
|
||||
aria-invalid={!!validation}
|
||||
aria-describedby={`setting-${key}-help setting-${key}-default${validation ? ` setting-${key}-error` : ''}`}
|
||||
oninput={() => {
|
||||
error = '';
|
||||
notice = '';
|
||||
}}
|
||||
/></Field
|
||||
>{/if}
|
||||
<span class="unit">{settingUnit(key)}</span>
|
||||
</div>
|
||||
{#if zeroMode}<label
|
||||
@@ -393,13 +403,7 @@
|
||||
gap: var(--space-2);
|
||||
min-width: 0;
|
||||
}
|
||||
.search-label {
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
#settings-search {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.group-links {
|
||||
display: grid;
|
||||
gap: var(--space-1);
|
||||
@@ -521,17 +525,15 @@
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
.numeric-value input {
|
||||
width: 88px;
|
||||
min-height: 32px;
|
||||
padding: 5px var(--space-2);
|
||||
font-family: var(--font-numeric);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
color: var(--text-tertiary);
|
||||
opacity: 0.75;
|
||||
}
|
||||
.numeric-value > :global(.field) {
|
||||
width: 100px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.unit {
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-xs);
|
||||
@@ -646,7 +648,7 @@
|
||||
.notice {
|
||||
color: var(--state-online);
|
||||
}
|
||||
.mobile-section,
|
||||
.section-rail :global(.mobile-section),
|
||||
.mobile-label {
|
||||
display: none;
|
||||
}
|
||||
@@ -680,7 +682,7 @@
|
||||
.group-links {
|
||||
display: none;
|
||||
}
|
||||
.mobile-section {
|
||||
.section-rail :global(.mobile-section) {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
align-items: center;
|
||||
@@ -688,9 +690,6 @@
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.mobile-section select {
|
||||
width: 100%;
|
||||
}
|
||||
.table-wrap {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user