Repository navigation
Add <Search />: site-wide search as a command palette - #377
NullVoxPopuli merged 8 commits into
Conversation
|
|
|
@NullVoxPopuli is attempting to deploy a commit to the universal-ember Team on Vercel. A member of the Team first needs to authorize it. |
`{{on}}` did not typecheck anywhere in `src/`, because two tsconfig settings
disagreed with what Glint needs:
- `moduleResolution: node16` stopped Glint's module augmentations from
attaching, so `on` stayed the bare `Opaque<"modifier:on">` that
ember-source declares and no `resolve` overload accepted it.
- `types` named `@glint/ember-tsc`, which is the tool's own API, rather than
`@glint/ember-tsc/types`, which is the file that carries those
augmentations.
`types` also read ember-source out of `docs-app/node_modules`. It reads the
addon's own copy now.
With the augmentations attached, a real error appears: `getSignature` returns
`undefined` when a declaration carries no signature, and the union check does
not narrow that away.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`<Search />` is `<CommandPalette>` from ember-primitives, filled in with what `searcher` ranks. It renders a trigger button and a modal `<dialog>`, and it needs nothing configured: the `docs()` plugin already wrote every page's title, headings, and prose into the compiled docs. The `:trigger` block replaces the button, and is yielded `open` and the modifier that returns focus to it. The `:result` block replaces the group, title, and excerpt. `stripFormatting` now drops inline HTML, keeping the text it wrapped, so an excerpt reads "press K" rather than "press <kbd>K</kbd>". Lowercase tag names only, so a component written in prose survives. The palette's own stylesheet answers frameworks that style a bare `dialog` as a full-screen box around an `<article>`: `min-width: 100%` outranks any width the palette sets, and centring the children squashes it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
6766713 to
f3b7e20
Compare
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The trigger replaced an `<input>` and did not match its size. Its height came from the key hints, which frameworks draw as a filled block in the body's own colour: right for a keystroke named in prose, and far too loud for a hint on a button. It ran 51px against the input's 42px and read as the loudest thing in the header. The keys are drawn as keys now, quiet and outlined, and sit at the far end of the button with the label at the near end. The palette's own input also takes `height: auto`, since a framework's fixed input height was making the field 98px tall for one line of text. The docs app gets back the two width breakpoints the old header search had. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three things were wrong inside the modal. The site's `header div:first-child` rule reached into the `<dialog>`, because `<Modal>` renders it where it is written. It laid the field out on the baseline with a 1rem gap, so the icon sat above the input's centre. That rule only ever meant the header's own nav group, so it takes a child combinator now, and the field's rule is qualified by the dialog so no host descendant rule can lay it out again. The input carried the site's focus ring, which the dialog clipped: the field runs the full width, out to a rounded corner and `overflow: hidden`. Focus never leaves that input while the palette is open, so the ring was permanent decoration rather than a signal. It is suppressed, specifically enough to outrank a framework's own input focus styles. The icon, each result, and the status line now share one left edge, held in a single custom property rather than restated four times. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The docstring said there was nothing to configure while the signature exposed four knobs, each behind its own `?? DEFAULT` getter. The hotkey is fixed at mod+k, and the rest are constants: how much to type before the index is consulted, how many results to render, and the placeholder. The two blocks stay. They replace markup rather than tune behaviour. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
| </button> | ||
| {{/if}} | ||
|
|
||
| <m.Dialog class='kolay__search'> |
There was a problem hiding this comment.
we need to explain esc to close, like the nvp.ui style. and we need search cancel buttons
There was a problem hiding this comment.
Both done.
The footer carries what the listbox is doing on one side and press [Esc] to close on the other, using <Key> the way nvp.ui's menu does.
A clear button appears beside the input once there is something to clear, and hands the caret back to the input so the reader can carry on typing.
Verified with real key events: Esc closes the dialog and focus returns to the trigger, so the hint is accurate. Two tests added in markdown-only (16 pass).
There was a problem hiding this comment.
Both fixed.
Closing with a mouse. You were right, there was no way. The footer hint is a button now: it reads Close beside the Esc chip, so it still names the key while being a target. The dialog also carries closedby="any", so a click outside dismisses it. Checked with real mouse events at the CDP level, not synthetic ones: both paths close it and return focus to the trigger.
Height. A modal <dialog> is anchored top and bottom, so an auto height fills the viewport instead of the content, then clamps at max-height. That is why it sat at 665px with an empty 549px results box inside it. Releasing the bottom anchor makes it content-sized. Measured: empty 122px, no matches 124px, three results 518px. The results box collapses to 0 rather than holding its padding open.
One thing this turned up: frameworks give buttons a bottom margin, and the close button had picked up 20px of it. Zeroed on all three buttons.
Two tests added, markdown-only is 17 pass.
The footer carries both: what the listbox is doing on one side, and "press Esc to close" on the other, the way nvp.ui's menu says it. Clearing the query was a keyboard-only move. A button appears beside the input once there is something to clear, and hands the caret back so the reader can carry on typing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was no way to close it without a keyboard. The footer's hint is a button now, reading "Close" beside the key it names, and the dialog carries `closedby="any"`, so a click outside dismisses it the way the platform does. The palette was 665px tall with nothing in it. A modal `<dialog>` is anchored top and bottom, so an auto height fills the viewport rather than the content; releasing the bottom anchor lets it be as tall as its results and no taller. The empty state is 122px now. The results box collapses with it, rather than holding a strip of padding open. Frameworks give buttons a bottom margin. None of these want one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The ⌘K for a kolay site. Built on
<CommandPalette>, which shipped in ember-primitives 0.62.0.Nothing to index and nothing to configure. The
docs()plugin already writes every page's title, headings, and prose into the compiled docs, so this issearcherrendered, the utility that shipped in #372 and until now had only the search page to be used by. Same forstripFormattingandhighlightSearch, which produce and mark the excerpts.What it is
<CommandPalette>filled in with kolay's index, inside a<Modal>so the trigger button can sit outside the dialog:<dialog>handles the layer, the focus trap, and returning focus to whatever opened itaria-activedescendanthandles the keyboard, so ↑/↓ move the selection while the caret stays where the reader is typingAsync throughout: a plain
.mdpage's text is fetched on demand, and the palette re-activates the best result whenever the list changes underneath.Arguments and blocks
@hotkey(default"mod+k",""to disable),@minLength(3),@limit(20),@placeholder.Both blocks are optional and replace a default.
:triggeris yieldedopenand the modifier that returns focus to the trigger when the palette closes.:resultis yielded the result and the query.Styling
Default styles ship in
kolay.css, which consumers already import. Colours are--kolay-search-*variables, so a host site sets values rather than restating layout. The docs app maps them to pico's in six lines.The active result is
[data-active="true"], set by the pointer and the keyboard alike. There is no:hoverrule, deliberately: one selector for both inputs means they can never disagree about what Enter will do.The palette's stylesheet also answers frameworks that style a bare
dialogas a full-screen box around an<article>card. Pico is one.min-width: 100%outranks any width the palette sets, and centring the children squashes the input and the results.Two fixes this needed
The addon typecheck.
{{on}}did not typecheck anywhere insrc/, which is why there was no way to write a trigger button by hand. Two tsconfig settings disagreed with what Glint needs:moduleResolution: node16stopped Glint's module augmentations from attaching, soonstayed the bareOpaque<"modifier:on">that ember-source declares; andtypesnamed@glint/ember-tsc, the tool's own API, rather than@glint/ember-tsc/types, the file carrying those augmentations.typesalso read ember-source out ofdocs-app/node_modulesand now reads the addon's own copy. With the augmentations attached, one real error surfaced intypedoc/signature/component.gts, fixed in the same commit.stripFormattingand inline HTML. An excerpt renderedpress <kbd>K</kbd>verbatim. It drops inline HTML now, keeping the text it wrapped. Lowercase tag names only, so<Search />written in prose survives.The docs site
The header's search form is replaced by the palette, which deletes ~75 lines of form and scoped CSS. The
/searchpage stays: the palette is for looking something up and leaving, the page is for a search worth linking to.Verified
Suites: markdown-only 14/14, docs-app 97 (93 pass, 4 pre-existing skips),
test:node250/250,pnpm lint21/21 includinglint:published-typesacross node10, node16, and bundler.Driven in a real browser on the docs app, light and dark: the trigger opens the dialog, the input is a focused combobox, typing gives ranked results with
role="option"and highlighted query marks, ↓ movesaria-activedescendantand[data-active]together, and Enter navigates and closes the dialog.🤖 Generated with Claude Code