Skip to content

Overlays

Drawer, Tooltip and CommandPalette, on top of native dialog and popover.

For a dialog with a result, use Modal; for a menu or a lightweight dialog, Popover. They all use the top layer of the browser, and leave with a View Transition where it exists.

UIDrawer

A side panel. It is a modal dialog with command, commandfor and closedby: it opens, closes and returns the focus without JavaScript in the browsers that support them; elsewhere, on hydration. Following a link inside closes it at once, because the navigation already is the transition.

Filters

meeko
<UIDrawer title="Filters" triggerLabel="Open filters" side="end" model="open">
  <UICheckbox model="drafts" label="Include drafts" />
  <snippet name="footer"><UIButton on:click="() => (open.value = false)">Apply</UIButton></snippet>
</UIDrawer>
UIDrawer props
Name Type / default Description
title string Required. Name of the dialog.
model Signal<boolean> false Open state, two-way.
side start | end start The side it enters from.
triggerLabel / closeLabel string Text of the trigger and accessible name of the close button.
closedBy any | closerequest | none any What closes it besides its button: the backdrop and Esc, only Esc or nothing.
closeOnNavigate boolean true It closes when following a link.
id / class string Identity and classes.

It accepts the default, footer and trigger(id) snippets, and the close event.

UITooltip

A UIPopover with mode="hint" and the look of a tooltip: it opens with the pointer or the focus, never takes the focus, and the trigger references it with aria-describedby. Write complementary information in it: on touch it is not reliable, because depending on the browser it appears on a tap, only while pressed, or not at all.

meeko
<UITooltip text="It is published when you save" placement="top">
  <snippet name="trigger">When is it published?</snippet>
</UITooltip>
UITooltip props
Name Type / default Description
text string The text; for anything else, the default snippet.
placement PopoverPlacement top Side and alignment.
offset number 6 Separation in pixels.
delay / closeDelay number 300 / 150 Milliseconds before opening and closing.
class / triggerClass / triggerId string Classes of the content and the trigger, and id of the trigger.

It accepts the default, trigger and anchor(trigger) snippets, for a trigger of your own.

UICommandPalette

It does not search: read query in your code, search wherever you want (Pagefind, a server or a local list) and pass it results and status. It opens with its button or with Ctrl and K, and the arrows walk the results without taking the focus out of the field.

meeko
<script lang="ts">
  const query = signal('')
  const pages = [{ title: 'Installation', url: '/installation' }, { title: 'Theming', url: '/theming' }]
  const results = computed(() => pages.filter((page) => page.title.toLowerCase().includes(query.value.toLowerCase())))
</script>

<template>
  <UICommandPalette model:query="query" bind:results="results.value"
    bind:status="results.value.length ? 'ready' : 'empty'" hrefBy="url" labelBy="title" />
</template>
UICommandPalette props
Name Type / default Description
results readonly T[] Required. What shows.
status idle | loading | ready | empty | unavailable ready What the status region announces.
model / model:query / model:active Signal Open state, searched text and active result.
labelBy / hrefBy / childrenBy key or function Label, target and nested results.
label / inputLabel / placeholder / closeLabel string Texts. The default values follow the language of the document.
trigger / shortcut boolean true Paints its button and listens to the shortcut.
inputId / inputName / class / triggerClass string Identity of the field and classes.

It accepts the item(item, state), trigger(modifier) and status(status, query) snippets, and the open, close and choose events. The types UIDrawerProps, UITooltipProps and UICommandPaletteProps are exported from @meekojs/ui/runtime.

Was this page helpful?

Add a comment

It is sent when you choose “Yes” or “No”. Only the page, your answer and the comment are stored: no cookies and no personal data.

0 of 2000 characters