fix(settings): raise every Settings control to the touch floor
#56 named 44px and #195 took the page header there. Settings is the other half of #186 and much the larger one: swept on the reference device (TLP301, 424x439) with all eleven config-sections expanded, **120 controls** were under the floor -- not the 93 the issue's table implies, and config-field is eight of them. The bulk is behind the disclosures, which is why nobody had counted it: 36 .column-arrow-btn 16x14 <- smallest in the app 29 .column-toggle 16x16 26 shortcut-capture button 80x25 8 download format checkbox 16x16 7 config-field select 335x30 6 wa-input / wa-button 204x20, 185x21 **The density argument, measured rather than guessed, and it is smaller than it looks.** The rows were already near the floor -- .column-item is 335x36 and .shortcut-row 335x37; it is the controls *inside* them that were 14-25px. So a control grows into the row it already occupies and the row goes 36 to 44. Measured after: the two column lists went 373->447 and 690->850, +234px over the whole page. Half a screen of extra scroll on a page that already scrolls, against 36 targets of 16x14. **Settings is cheaper than the header was, and for a stated reason.** There is no overflow fit on this page, so the header's "only width is contested" rule does not bind at all and nothing here needs padding with a negative margin. Height is a min-size, and the two square controls can simply be square. Three shapes, because one rule does not fit three kinds of control: **A native checkbox is targeted through its label.** It cannot grow its hit area without growing its paint, and a 44px checkbox is not what anyone wants -- so .column-label is a real <label for> now and the column's *name* is the target, 70x44 rather than 16x16. That is the argument config-field already makes one file over ("a real label association also makes the label text a click target, which is behaviour, not annotation"), and here it is the whole fix. The download formats already had the label; they only needed the height. **The arrows take padding, which is invisible.** They carry background: none and a transparent border, so 16x14 -> 44x44 changes nothing anyone can see until hover -- #186's Direction exactly. **Web Awesome's controls come from the library's own API.** Their height is decided inside somebody else's shadow root, and --wa-form-control-height is the variable that decides it. A custom property inherits through a shadow boundary, so a :host declaration reaches them; styles/wa-touch-floor.css.ts is that, once, adopted rather than written at :root in index.css -- a :root rule would be invisible to the component tier, which renders a component and no page stylesheet. **Two controls no sweep can see are fixed by name**, and they are the trap this issue keeps setting. config-field's toggle has an <input> that is opacity: 0; width: 0; height: 0, so a walk of every input skips it as a zero-sized node -- what a finger hits is the <label>, which measured **34x19**, smaller than anything in either of #186's tables and absent from both. It is 44x44 with the pill still painted at 2.5em x 1.4em and negative inline margins keeping it flush with the inputs above. And shortcut-capture's reset button renders only for a shortcut somebody has rebound, so a sweep of a fresh install never meets it. Verified on the device, same method as the sweep that filed it: 120 controls under the floor before, 42 after. All 42 are accounted for -- 37 are checkboxes whose labels measure 70x44 and 57x44, four are wa-input's inner input at 204x**42**, which is the control measured *inside* its own 1px border (part=base is 238x44), and one is the skip link, which #186 already ruled out as keyboard-only. The e2e suite passes, top-bar-fit and header-action-overflow included -- but that is **chromium**, which is half an answer, and saying so is the whole of what #195's second commit was about. What can be argued rather than run: library-filter is the only thing here in a container that measures itself, and its width did not change. The fit measures inline size. Two page-header screenshots are refreshed because they are this issue's own debris -- #195's taller sort control, merged last session, with its references never re-recorded. app-sidebar's and now-playing's are deliberately left: they are unrelated drift, and blessing an unrelated screenshot is how the sidebar reference came to still list a destination #27 retired. That is #196.
This commit is contained in:
@@ -85,6 +85,21 @@ export class ConfigField extends LitElement {
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
/* Every control here meets the app's 44px touch floor (#186).
|
||||
|
||||
This is the shape every row in Settings uses, so it is the
|
||||
one rule that covers the most controls -- and it is the
|
||||
*cheapest* place to reach the floor, because there is no
|
||||
overflow fit on this page. The page header's had one (#69),
|
||||
which is why that pass had to grow padding and hand the
|
||||
width back with a negative margin; here the control is a
|
||||
block in a column and a taller box costs nothing but the
|
||||
height it takes.
|
||||
|
||||
Measured on the reference device before this: the select
|
||||
335x30, the text and number inputs the same, the browse
|
||||
button 30 tall, the colour swatch 33x33 and the toggle
|
||||
**34x19**. */
|
||||
input[type='text'],
|
||||
input[type='number'] {
|
||||
background: var(--yj-bg-elevated, #343a40);
|
||||
@@ -95,6 +110,7 @@ export class ConfigField extends LitElement {
|
||||
font-size: 0.85em;
|
||||
font-family: inherit;
|
||||
min-width: 0;
|
||||
min-block-size: 44px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@@ -117,6 +133,7 @@ export class ConfigField extends LitElement {
|
||||
font-size: 0.85em;
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
min-block-size: 44px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@@ -139,6 +156,7 @@ export class ConfigField extends LitElement {
|
||||
font-size: 0.85em;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
min-block-size: 44px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
@@ -158,8 +176,12 @@ export class ConfigField extends LitElement {
|
||||
}
|
||||
|
||||
input[type='color'] {
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
/* border-box, or the 2px border makes this 48 and the
|
||||
assertion below reads as passing by four pixels of
|
||||
border rather than by the rule. */
|
||||
box-sizing: border-box;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border: 2px solid var(--yj-border, #444);
|
||||
border-radius: 4px;
|
||||
padding: 0;
|
||||
@@ -187,12 +209,32 @@ export class ConfigField extends LitElement {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-block-size: 44px;
|
||||
}
|
||||
|
||||
/* The toggle is the one control here whose target and paint
|
||||
must differ, and it is also the one no sweep can see.
|
||||
|
||||
Its <input> is opacity: 0; width: 0; height: 0, so a
|
||||
walk of every input on the page skips it as a zero-sized
|
||||
node -- the thing a finger actually hits is this <label>,
|
||||
which measured **34x19**. That is smaller than anything in
|
||||
#186's original table and it is absent from it for exactly
|
||||
that reason.
|
||||
|
||||
A 44px pill is not what a switch should look like, so the
|
||||
box is 44px and the paint is not: .toggle-slider is a
|
||||
2.5em x 1.4em child centred in it rather than an absolute
|
||||
fill. The negative inline margins hand the extra width back
|
||||
to the layout, so the pill stays flush with the right edge
|
||||
of the inputs in the rows above it -- the header pass's
|
||||
shape, used here for alignment rather than for a fit. */
|
||||
.toggle-switch {
|
||||
position: relative;
|
||||
width: 2.5em;
|
||||
height: 1.4em;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
inline-size: 44px;
|
||||
block-size: 44px;
|
||||
margin-inline: calc((2.5em - 44px) / 2);
|
||||
}
|
||||
|
||||
.toggle-switch input {
|
||||
@@ -202,9 +244,10 @@ export class ConfigField extends LitElement {
|
||||
}
|
||||
|
||||
.toggle-slider {
|
||||
position: absolute;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
inset: 0;
|
||||
inline-size: 2.5em;
|
||||
block-size: 1.4em;
|
||||
background: var(--yj-bg-overlay, #495057);
|
||||
border-radius: 1em;
|
||||
transition: background 0.2s;
|
||||
|
||||
@@ -176,6 +176,13 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.15s ease;
|
||||
white-space: nowrap;
|
||||
/* The app's 44px touch floor (#56, #186), stated once for
|
||||
all 41 buttons this page renders rather than per class.
|
||||
Height is free here: Settings has no overflow fit, so
|
||||
the header's "only width is contested" rule does not
|
||||
bind, and the two classes that need more than a height
|
||||
say so below. */
|
||||
min-block-size: 44px;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
@@ -509,11 +516,24 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* The two column lists are the densest thing in the app, and
|
||||
the density argument is why they are shaped the way they
|
||||
are rather than simply grown (#186).
|
||||
|
||||
Measured on the reference device: the row was already
|
||||
335x36 -- it is the controls *inside* it that were 16x16 and
|
||||
**16x14**, the smallest anywhere in this app, 36 of them.
|
||||
So the fix grows the controls into the row they already
|
||||
occupy and only takes the row from 36 to 44, which over the
|
||||
two lists (10 and 19 items) is 232px of extra scroll on a
|
||||
439px screen. Growing each control to its own 44px row
|
||||
instead would have cost four screens. */
|
||||
.column-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
gap: 0.5em;
|
||||
padding: 0.5em 0.75em;
|
||||
padding: 0 0.75em;
|
||||
min-block-size: 44px;
|
||||
border-bottom: 1px solid
|
||||
var(--yj-border-subtle, #333);
|
||||
font-size: 0.85em;
|
||||
@@ -531,8 +551,19 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
color: var(--yj-text-tertiary, #888);
|
||||
}
|
||||
|
||||
/* A native checkbox cannot grow its hit area without growing
|
||||
its paint, and a 44px checkbox is not what anyone wants. So
|
||||
the target is the label instead: .column-label is a real
|
||||
<label for> now, which makes the column's *name* the thing
|
||||
you tap -- ~250x44 rather than 16x16.
|
||||
|
||||
That is the argument config-field already makes one file
|
||||
over for its own labels: "a real label association also
|
||||
makes the label text a click target for the control, which
|
||||
is behaviour, not annotation". Here it is the whole fix. */
|
||||
.column-toggle {
|
||||
cursor: pointer;
|
||||
align-self: center;
|
||||
accent-color: var(
|
||||
--yj-accent,
|
||||
#ffd43b
|
||||
@@ -541,20 +572,32 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
|
||||
.column-label {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
min-block-size: 44px;
|
||||
}
|
||||
|
||||
.view-note {
|
||||
color: var(--yj-text-tertiary, #888);
|
||||
font-size: var(--yj-font-size-sm, 0.85rem);
|
||||
margin-left: auto;
|
||||
/* The row stretches its children so the label can be a
|
||||
full-height target; this is text, not a target. */
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.column-arrows {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0.15em;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* 16x14 before this, and they carry background: none and a
|
||||
transparent border -- so padding out to 44px grows the
|
||||
target and changes nothing anyone can see until hover,
|
||||
which is precisely what #186's Direction asks for. */
|
||||
.column-arrow-btn {
|
||||
background: none;
|
||||
border: 1px solid transparent;
|
||||
@@ -564,6 +607,8 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
font-size: 0.65em;
|
||||
line-height: 1;
|
||||
padding: 0.2em 0.35em;
|
||||
min-inline-size: 44px;
|
||||
min-block-size: 44px;
|
||||
transition:
|
||||
color 0.15s,
|
||||
border-color 0.15s;
|
||||
@@ -711,6 +756,11 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
padding: 0.2em 0.4em;
|
||||
letter-spacing: 2px;
|
||||
border-radius: 4px;
|
||||
/* Square, so it needs the width too -- the shared rule
|
||||
above only gives it a height. It was 31x31, and it is
|
||||
the only route to "Remove library", which is the case
|
||||
#55 settled one component over: the way out is 44px. */
|
||||
min-inline-size: 44px;
|
||||
}
|
||||
|
||||
.overflow-btn:hover {
|
||||
@@ -2003,6 +2053,7 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
class="column-item ${checked ? 'enabled' : 'disabled'}"
|
||||
>
|
||||
<input
|
||||
id="view-${v.id}"
|
||||
type="checkbox"
|
||||
class="column-toggle"
|
||||
aria-label="Show ${v.label} in the navigation"
|
||||
@@ -2014,9 +2065,9 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
(e.target as HTMLInputElement).checked,
|
||||
)}
|
||||
/>
|
||||
<span class="column-label">
|
||||
<label class="column-label" for="view-${v.id}">
|
||||
${v.label}
|
||||
</span>
|
||||
</label>
|
||||
${note
|
||||
? html`<span class="view-note">${note}</span>`
|
||||
: nothing}
|
||||
@@ -2212,6 +2263,7 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
class="column-item ${checked ? 'enabled' : 'disabled'}"
|
||||
>
|
||||
<input
|
||||
id="column-${id}"
|
||||
type="checkbox"
|
||||
class="column-toggle"
|
||||
aria-label="Show the ${columnLabel} column"
|
||||
@@ -2222,11 +2274,12 @@ export class ConfigPage extends ViewLifecycleMixin(LitElement) {
|
||||
id,
|
||||
)}
|
||||
/>
|
||||
<span
|
||||
<label
|
||||
class="column-label"
|
||||
for="column-${id}"
|
||||
>
|
||||
${columnLabel}
|
||||
</span>
|
||||
</label>
|
||||
<span
|
||||
class="column-arrows"
|
||||
>
|
||||
|
||||
@@ -8,6 +8,7 @@ import '@awesome.me/webawesome/dist/components/switch/switch.js';
|
||||
import '@awesome.me/webawesome/dist/components/spinner/spinner.js';
|
||||
import '@awesome.me/webawesome/dist/components/callout/callout.js';
|
||||
import { designTokens } from '../../styles/tokens.css';
|
||||
import { waTouchFloor } from '../../styles/wa-touch-floor.css';
|
||||
import type {
|
||||
DownloadDescriptor,
|
||||
DownloadProvider,
|
||||
@@ -136,6 +137,7 @@ export class DownloadClients extends LitElement {
|
||||
|
||||
static override styles = [
|
||||
designTokens,
|
||||
waTouchFloor,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
@@ -239,12 +241,17 @@ export class DownloadClients extends LitElement {
|
||||
margin-top: 0.4em;
|
||||
}
|
||||
|
||||
/* The checkbox is 16x16 and cannot grow without becoming
|
||||
a 44px checkbox, but it is already wrapped in the label
|
||||
that names it -- so the label is the target and only
|
||||
needs the height (#186). Eight of them. */
|
||||
.format-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4em;
|
||||
font-size: 0.9em;
|
||||
cursor: pointer;
|
||||
min-block-size: 44px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@@ -25,6 +25,11 @@ export class ShortcutCapture extends LitElement {
|
||||
:host {
|
||||
display: inline-block;
|
||||
}
|
||||
/* 80x25, twenty-six of them -- the most numerous control on
|
||||
the Settings page after the column lists (#186). The floor
|
||||
is a height here and nothing else: the width was already
|
||||
past it, and the type stays where it is so a shortcut still
|
||||
reads as a key rather than as a button. */
|
||||
button {
|
||||
font-family: inherit;
|
||||
font-size: var(--yj-text-sm, 13px);
|
||||
@@ -35,6 +40,7 @@ export class ShortcutCapture extends LitElement {
|
||||
color: var(--yj-text-primary, #eee);
|
||||
cursor: pointer;
|
||||
min-width: 80px;
|
||||
min-height: 44px;
|
||||
text-align: center;
|
||||
transition:
|
||||
border-color 0.15s,
|
||||
@@ -61,6 +67,11 @@ export class ShortcutCapture extends LitElement {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
/* Reset renders only for a rebound shortcut, so a sweep of a
|
||||
freshly-installed app never sees it -- it is not in #186's
|
||||
tables for that reason, and it is a touch target the moment
|
||||
anybody uses the feature. It also has no background, so the
|
||||
padding out to 44px is invisible. */
|
||||
.reset-btn {
|
||||
font-size: var(--yj-text-xs, 11px);
|
||||
padding: 2px 6px;
|
||||
@@ -69,7 +80,8 @@ export class ShortcutCapture extends LitElement {
|
||||
background: transparent;
|
||||
color: var(--yj-text-tertiary, #888);
|
||||
cursor: pointer;
|
||||
min-width: auto;
|
||||
min-width: 44px;
|
||||
min-height: 44px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,14 @@ export class LibraryFilter extends LitElement {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 120x32 on the reference device (#186). This control has two
|
||||
placements since #57 -- the desktop top bar and Settings ->
|
||||
Libraries -- and it is the only route to setSelectedLibrary
|
||||
in either, so it is one of the controls #148 argued must not
|
||||
simply be taken away. It is one component, so it reaches the
|
||||
floor in one place. */
|
||||
select {
|
||||
height: 32px;
|
||||
min-height: 44px;
|
||||
padding: 0 8px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid
|
||||
|
||||
Reference in New Issue
Block a user