The phone's top bar is about to go, and the search box is the one thing in it that is an action rather than chrome. It becomes a button in the row that already says which page you are on, opening a wa-dialog with the real search box in it. Three decisions worth the words. **A wa-dialog, and that is a mechanism rather than a taste.** wa-popup renders `<div popover="manual">` and feature-detects the Popover API, falling back to `strategy: "fixed"` where there is none -- which is Chrome 113, the reference device, since `popover` is Chrome 114. And `position: fixed` escapes ancestor overflow but not `contain: paint`, which `.main-panel` carries, so a popup-shaped search panel opened from a view's header is structurally clipped on that device. `<dialog>` / `showModal()` is Chrome 37 and uses the real top layer. No tier here can see the difference -- CI's Chromium and WebKit both have the Popover API -- so the component test asserts the *mechanism*, a native `<dialog>` in the tree, rather than the symptom. **An element, not a PageAction.** Two of the seven searchable views are detail views with no page-header; they filter on the term and say so in their own headers. Declaring search as an action would mean seven hosts each writing it out, which is a second list of searchable views, and it would put a phone mode for actions inside page-header, which that component documents its refusal to grow. search-store's own map is the condition, asked by one component placed three times. **The modal carries the real search-bar**, so there is still one debounce, one clear button and one view-scoped placeholder. Escape closes it and *keeps* the term -- the input treats Escape as "clear the search", which is right in a header where the box stays on screen and wrong in a surface whose dismissal would then discard the search.
103 lines
4.8 KiB
HTML
103 lines
4.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
|
<link href="./index.css" rel="stylesheet" />
|
|
<title>yellowjacket</title>
|
|
<script src="/index.ts" type="module"></script>
|
|
</head>
|
|
|
|
<body>
|
|
<!-- a11y.30. First focusable thing in the document, so a keyboard
|
|
user is not walked through the header, the library filter, the
|
|
search box and eleven nav items on every navigation. -->
|
|
<a class="skip-link" href="#main-content">Skip to content</a>
|
|
<!-- Below 600px this bar is not in the layout at all (#57): index.css
|
|
takes its grid row away and leaves the element visually hidden,
|
|
carrying nothing but the `h1` below. Every control in it has
|
|
somewhere else to be there -- `nav-history` is the platform's
|
|
own back gesture, `job-indicator` is `<job-band>`, `search-bar`
|
|
is `<search-dialog>` opened from the view's own header, and
|
|
`library-filter` is Settings -> Libraries (#148). -->
|
|
<header class="top-bar">
|
|
<hgroup>
|
|
<h1 class="title">YellowJacket</h1>
|
|
<!-- a11y.29: a heading level was being used for type size. -->
|
|
<p class="subtitle">Music how it was meant to bee.</p>
|
|
</hgroup>
|
|
<!-- Global back/forward (#6). Before the library filter so the
|
|
two navigation controls in this bar are adjacent, and after
|
|
the brand because that is where a window's chrome ends and
|
|
the app's begins. Hidden below 600px by index.css: the
|
|
phone has a system back, and this bar has no room. -->
|
|
<nav-history></nav-history>
|
|
<library-filter></library-filter>
|
|
<search-bar></search-bar>
|
|
<job-indicator></job-indicator>
|
|
</header>
|
|
<!-- The phone's view of background work (#62): below 600px the
|
|
indicator above stands down and its rows appear here instead,
|
|
in the layout rather than over it. `display: none` above that
|
|
width in index.css, which is also what keeps it out of the
|
|
desktop grid -- an in-flow child with no named area is
|
|
auto-placed into one of the shell's rows, which is the trap the
|
|
skip link is absolutely positioned to avoid. -->
|
|
<job-band></job-band>
|
|
<div class="sidebar">
|
|
<app-sidebar></app-sidebar>
|
|
</div>
|
|
<div class="content-area">
|
|
<main class="main-panel" data-active-view="tracks" data-testid="main-content" id="main-content"
|
|
tabindex="-1">
|
|
<track-list></track-list>
|
|
</main>
|
|
<queue-panel id="queue-panel"></queue-panel>
|
|
</div>
|
|
<!-- Three columns, and the outer two are the same width, which is
|
|
what makes the middle one *centred* rather than merely in the
|
|
middle of what is left (#23). The transport used to sit in a
|
|
`320px 1fr auto` grid, so its centre was ~140px right of the
|
|
window's.
|
|
|
|
That is also why the volume moved out of `audio-player` and
|
|
into the bar (#42): the transport column has to contain the
|
|
transport and nothing else, or "centred" means centred with a
|
|
slider bolted to one side. It joins the queue button in
|
|
`.bar-end`, whose width is what the left column is matched
|
|
against. -->
|
|
<footer class="bottom-bar">
|
|
<now-playing></now-playing>
|
|
<audio-player></audio-player>
|
|
<div class="bar-end">
|
|
<volume-control></volume-control>
|
|
<button aria-label="Toggle queue" aria-controls="queue-panel" aria-expanded="false"
|
|
id="queue-button">
|
|
<!-- ICON_QUEUE in src/utils/icon-language.ts, written out
|
|
because this file has no module scope. It was `list`,
|
|
which is the Playlists destination's icon. -->
|
|
<wa-icon name="bars-staggered"></wa-icon>
|
|
</button>
|
|
</div>
|
|
</footer>
|
|
<!-- The phone's primary navigation, hidden above 600px by
|
|
index.css. Eager rather than a chunk, for the reason
|
|
notification-host is: it is the only way to move around the
|
|
app on a phone. After the footer, because that is where it
|
|
renders -- the tab bar sits below the transport, and DOM order
|
|
is what a screen reader and the tab sequence follow. -->
|
|
<bottom-nav></bottom-nav>
|
|
<first-run-wizard></first-run-wizard>
|
|
<notification-host></notification-host>
|
|
<shortcuts-overlay></shortcuts-overlay>
|
|
<!-- The phone's search surface (#57). A singleton here for the
|
|
reason shortcuts-overlay is one: one instance, one document
|
|
listener, and no `data-testid="search-input"` resolving to two
|
|
elements. It renders nothing while shut, so the header's box
|
|
is still the only one on a desktop. -->
|
|
<search-dialog></search-dialog>
|
|
</body>
|
|
|
|
</html>
|