fix(settings): style the typeless inputs and hold one canvas width

The Settings control block selects on [type='text'], which matches the attribute
and not the resolved default, so four inputs written without a type escaped it
entirely and rendered as raw browser controls - wrong height, wrong colour, and
white whatever the theme. The account username was the visible one; the API key
and the two custom Apprise URL rows had the same fault. They now declare a type,
and :not([type]) is a backstop for the next one.

Those three carry .in-mono, which the block's `font-family: inherit` outspecified,
so the class only ever worked on inputs that escaped the block. Moved after the
block to win on source order - which also restores monospace to the Advanced
numeric fields, where it was always intended.

The shell narrowed from 1400px to 1220px on the Settings view, and the header sits
in that same wrapper, so switching views visibly resized the chrome. One width for
every view now, with the field columns capped instead: 420px in two-column rows and
300px in three-column ones, above the 640px collapse only, and scoped so the modals
- already below both caps at their 700px width - are untouched.
This commit is contained in:
Catubba
2026-08-05 23:25:42 +02:00
parent 3a6865fabb
commit 042efb6b57
5 changed files with 33 additions and 5 deletions
+1
View File
@@ -82,6 +82,7 @@ function Credentials() {
<label htmlFor="acc-user">{t(`${ns}.username`)}</label>
<input
id="acc-user"
type="text"
value={user}
autoComplete="username"
onChange={(e) => edit(() => setUser(e.target.value))}
@@ -220,6 +220,7 @@ export function Integrations() {
<div className="panel-bd stack tight">
<div className="url-row">
<input
type="text"
className="in-mono"
readOnly
value={freshKey ?? (enabled ? t(`${ns}.keyHidden`) : t(`${ns}.keyNone`))}
@@ -266,6 +266,7 @@ export function Notifications() {
{draft.custom_urls.map((url, i) => (
<div className="url-row" key={i}>
<input
type="text"
className="in-mono"
value={url}
spellCheck={false}
@@ -285,6 +286,7 @@ export function Notifications() {
))}
<div className="url-row">
<input
type="text"
className="in-mono"
value={newUrl}
spellCheck={false}
+25 -1
View File
@@ -289,10 +289,15 @@
/* Form controls, scoped to the Settings pane exactly as dashboard.css scopes its own set
to `.modal` — unscoped these would reach into Login and the wizard, which are still
inline-styled. */
inline-styled.
`[type='text']` matches the attribute, not the resolved default, so an input written
without a type escapes this block entirely and renders as a raw browser control — it had
bitten four of them. `:not([type])` is the backstop; write the type anyway. */
.jn-settings input[type='text'],
.jn-settings input[type='password'],
.jn-settings input[type='number'],
.jn-settings input:not([type]),
.jn-settings select,
.jn-settings textarea {
background: var(--jn-input-bg);
@@ -304,6 +309,11 @@
font-family: inherit;
width: 100%;
}
/* Must follow the block: its `font-family: inherit` matches at the same specificity, so an
opt-in `.in-mono` only wins on source order. */
.jn-settings input.in-mono {
font-family: 'IBM Plex Mono', ui-monospace, monospace;
}
.jn-settings textarea {
resize: vertical;
font-family: 'IBM Plex Mono', ui-monospace, monospace;
@@ -330,6 +340,20 @@
color: var(--jn-text-mid);
}
/* The shell is one 1400px canvas for every view, so a settings field would otherwise stretch
to ~680px — a hostname in a half-metre box. Cap the *columns*, not the panel: the grid
left-aligns and the fields keep a readable measure. Scoped to `.jn-settings` so the
modals, whose 700px width already sizes them below these caps, are untouched.
Above the 640px collapse only, or these would outspecify the single-column rules below. */
@media (min-width: 641px) {
.jn-settings .frow {
grid-template-columns: repeat(2, minmax(0, 420px));
}
.jn-settings .frow3 {
grid-template-columns: repeat(3, minmax(0, 300px));
}
}
@media (max-width: 640px) {
.frow,
.frow3 {
+4 -4
View File
@@ -71,10 +71,10 @@ function ShellInner() {
return (
<div className="jn-shell">
{/* The homepage is a two-column operations view and gets the wider 1400px canvas the
design calls for; Settings stays at the ~1220px form width, where longer measures
just make labelled fields harder to scan. */}
<div style={{ maxWidth: view === 'main' ? 1400 : 1220, margin: '0 auto' }}>
{/* One canvas width for every view. Settings used to narrow to 1220px for its form
measures, but the header lives in here too, so switching views visibly resized the
chrome — worse than a slightly long field row. */}
<div style={{ maxWidth: 1400, margin: '0 auto' }}>
{stale && <Banner tone="red"> {t('common.backendUnreachable')}</Banner>}
{/* The first-run CTA: flow A also covers the PBS, so one button is the whole setup.
It opens from the shell rather than from Settings so a fresh install never has to