OYNA

Drawer ​

A panel standing at an edge of the screen, for something longer than a popover holds and less final than a dialog: filters, the details of a row, a short form. The page stays behind it.

vue
<script setup lang="ts">
import { ref } from 'vue'

const open = ref(false)
</script>

<template>
  <OButton hotkey="KeyF" @click="open = true">Filters</OButton>

  <ODrawer v-model:open="open" title="Filters" description="Applied to the list of requests.">
    <OSwitch v-model="onlyErrors">Only errors</OSwitch>
    <OSwitch v-model="slow">Slower than 1 s</OSwitch>
    <OButton variant="primary" hotkey="Enter" @click="apply">Apply</OButton>
  </ODrawer>
</template>

A drawer is a dialog in another place: the same header, the same Esc, focus kept inside, and hotkeys of the page switched off while it is open. Everything on the Dialog page about focus and hotkeys holds here.

It fades in and does not slide: the library uses light, not movement.

Sides ​

side is right (the default), left or bottom. A bottom drawer is a sheet: on a phone it is the natural place for a menu or a set of filters, within reach of the thumb.

vue
<ODrawer v-model:open="open" title="Navigation" side="left">…</ODrawer>

<ODrawer v-model:open="open" title="Share" side="bottom">…</ODrawer>

Size ​

A side drawer is 420px wide and never wider than the screen; a sheet is at most 85% of the screen's height and scrolls inside. Change either with a CSS variable:

vue
<ODrawer v-model:open="open" title="Details" style="--o-drawer-width: 560px">…</ODrawer>

<ODrawer v-model:open="open" title="Share" side="bottom" style="--o-drawer-height: 50dvh">…</ODrawer>

Props ​

PropTypeDefaultDescription
titlestringrequired
v-model:openbooleanfalse
descriptionstring—A line under the title, read out with it
side'right' | 'left' | 'bottom''right'The edge it stands at
closeLabelstring'Close'Text of the close button

Built on the library's Dialog, which is Reka UI Dialog.