Android: raise the page header and the phone search button to the touch floor #195
@@ -320,10 +320,25 @@ export class PageHeader extends LitElement {
|
||||
query that no tier here renders, which is exactly how
|
||||
the seek bar's phone rule came to be dead for months.
|
||||
|
||||
Only the *width* of this reaches the overflow fit below:
|
||||
that pass measures inline size, so the height costs it
|
||||
nothing, and the two square controls grow the header's
|
||||
content by 22px in total. */
|
||||
**The height is the box and the width is not**, and that
|
||||
asymmetry is the whole of what the overflow fit below
|
||||
cares about. That pass measures inline size, so a taller
|
||||
control costs it nothing and a wider one costs it
|
||||
directly. Growing the two square controls to 44px wide
|
||||
added 22px, which fits at every width Chromium was
|
||||
checked at and clipped the overflow trigger at 320px in
|
||||
**WebKit** -- the engine closest to what actually ships,
|
||||
and the one no machine here can run. So the horizontal
|
||||
half is padding with the margin cancelling it, which is
|
||||
what the issue asked for in the first place: the target
|
||||
grows and the layout does not.
|
||||
|
||||
The cost is that a horizontal target can now overlap a
|
||||
neighbour, which the box version could not. The arrow's
|
||||
is deliberately lopsided for the seek bar's reason
|
||||
(#187): the select is 6px to its left and there is open
|
||||
space to its right, so it takes the side with nothing to
|
||||
steal from. */
|
||||
.sort select {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
@@ -347,9 +362,16 @@ export class PageHeader extends LitElement {
|
||||
padding: 3px 5px;
|
||||
/* 28x21 before this, the smallest control in the
|
||||
header and the only one that failed the floor in
|
||||
both directions. */
|
||||
min-inline-size: 44px;
|
||||
both directions.
|
||||
|
||||
Vertically the box grows, because the header has the
|
||||
room and nothing measures it. Horizontally the box
|
||||
must not: 28 + 2 + 14 is a 44px target over a 28px
|
||||
layout box, weighted right because the select is 6px
|
||||
to the left. */
|
||||
min-block-size: 44px;
|
||||
padding-inline: 5px 21px;
|
||||
margin-inline: 0 -16px;
|
||||
}
|
||||
|
||||
.sort-dir:hover {
|
||||
@@ -417,8 +439,12 @@ export class PageHeader extends LitElement {
|
||||
padding: 6px 10px;
|
||||
/* 38x27, and it is the route to every collapsed
|
||||
action, so it is the last control that should be
|
||||
hard to hit. */
|
||||
min-inline-size: 44px;
|
||||
hard to hit -- and the one WebKit clipped at 320px
|
||||
when this was 6px wider as a box. 38 + 3 + 3 is a
|
||||
44px target over a 38px layout box; the actions row
|
||||
has an 8px gap, so this one can be symmetric. */
|
||||
padding-inline: 13px;
|
||||
margin-inline: -3px;
|
||||
}
|
||||
|
||||
/* The display: flex above outranks the UA stylesheet's
|
||||
|
||||
@@ -73,9 +73,20 @@ export class SearchTrigger extends LitElement {
|
||||
second opinion about it (#186). The rest of that
|
||||
comment said the header's own action buttons are
|
||||
smaller because they carry a label; they are 44px
|
||||
now too, so that no longer distinguishes anything. */
|
||||
now too, so that no longer distinguishes anything.
|
||||
|
||||
The extra width is a target rather than a box, for
|
||||
page-header's reason: this button sits in that
|
||||
header, whose overflow fit (#69) measures inline
|
||||
size, and four pixels there is four pixels the
|
||||
trigger for every collapsed action does not get at
|
||||
320px. Height is free -- nothing measures it. */
|
||||
min-width: 44px;
|
||||
min-height: 44px;
|
||||
/* Border-box, so the 44 above is the whole target and
|
||||
the margin is what hands the four extra pixels back
|
||||
to the row. */
|
||||
margin-inline: -2px;
|
||||
padding: 0;
|
||||
background: none;
|
||||
border: 1px solid var(--yj-border-subtle, #555);
|
||||
|
||||
@@ -90,6 +90,46 @@ describe("the page header's controls", () => {
|
||||
expect(tooSmall(controls)).toEqual([]);
|
||||
});
|
||||
|
||||
it('grows the target without growing the box, so the overflow fit is untouched', async () => {
|
||||
// The regression this exists for, and it was a real one: growing
|
||||
// the two square controls to 44px *wide* added 22px to the header,
|
||||
// which fit at every width Chromium was checked at and clipped the
|
||||
// overflow trigger at 320x600 in WebKit -- the engine closest to
|
||||
// what ships, and the one no machine here can run. #69's fit pass
|
||||
// measures inline size, so a taller control is free and a wider one
|
||||
// is not.
|
||||
//
|
||||
// Negative inline margins are what keep the box out of it: the
|
||||
// padding makes the target, and the margin gives the space back.
|
||||
const el = await fixture<PageHeader>('page-header', {
|
||||
heading: 'Playlists',
|
||||
sortOptions: SORTS,
|
||||
sortField: 'name',
|
||||
actions: actions(),
|
||||
});
|
||||
|
||||
el.style.width = '320px';
|
||||
|
||||
for (let frame = 0; frame < 3; frame += 1) {
|
||||
await new Promise((r) => requestAnimationFrame(r));
|
||||
await el.updateComplete;
|
||||
}
|
||||
|
||||
for (const selector of ['.sort-dir', '.more-button']) {
|
||||
const control = shadowAll<HTMLElement>(el, selector).filter(
|
||||
(c) => !(c as HTMLButtonElement).hidden,
|
||||
)[0];
|
||||
|
||||
expect(control, selector).toBeTruthy();
|
||||
|
||||
const style = getComputedStyle(control!);
|
||||
const added =
|
||||
parseFloat(style.marginInlineStart) + parseFloat(style.marginInlineEnd);
|
||||
|
||||
expect(added, `${selector} gives its extra width back`).toBeLessThan(0);
|
||||
}
|
||||
});
|
||||
|
||||
it('includes the overflow trigger, which is the route to the rest', async () => {
|
||||
// At 320px the fit pass collapses actions into the menu, so the
|
||||
// trigger is rendered — and it is then the only way to reach them,
|
||||
|
||||
Reference in New Issue
Block a user