# Drawer / Drawer

> Side panel for filters, settings or details.

Page: https://componentes-lovat.vercel.app/c/drawer/  
License: MIT · Design: coss ui (MIT) · sheet.tsx  
Requires: tokens.css, button, text-field, dialog  
Context: herramienta · Density: media · Tone: sobria

## Files

- Tokens (once): https://componentes-lovat.vercel.app/tokens.css
- Dependency `button`: https://componentes-lovat.vercel.app/r/button.json
- Dependency `text-field`: https://componentes-lovat.vercel.app/r/text-field.json
- Dependency `dialog`: https://componentes-lovat.vercel.app/r/dialog.json
- HTML: https://componentes-lovat.vercel.app/raw/drawer/drawer.html
- CSS: https://componentes-lovat.vercel.app/raw/drawer/drawer.css
- Everything in one file: https://componentes-lovat.vercel.app/r/drawer.html

Dark theme: add class `dark` to `<html>`.

## When to use

- For secondary tasks without losing the page.

## When not to use

- For short confirmations: use a dialog.

## Accessibility

Roles: dialog

| Keys | Action |
|---|---|
| Esc | Closes |
| Tab | Cycles within the panel |

- Also a native <dialog>: focus trapped, Esc and outside click close it.
- Slides in from the right; with reduced motion it appears without sliding.

## Code

```html
<button class="c-btn c-btn--outline" type="button" commandfor="drawer-filters" command="show-modal">Abrir filtros</button>

<dialog class="c-drawer" id="drawer-filters" aria-labelledby="drawer-title" aria-describedby="drawer-desc" closedby="any">
  <form class="c-drawer__form" method="dialog">
    <div class="c-drawer__header">
      <h2 class="c-drawer__title" id="drawer-title">Filtros</h2>
      <p class="c-drawer__description" id="drawer-desc">Ajusta qué proyectos ves en la lista.</p>
    </div>
    <div class="c-drawer__panel">
      <div class="c-field"><label class="c-label" for="drawer-q">Buscar</label><span class="c-input"><input class="c-input__field" id="drawer-q" type="search" placeholder="Nombre del proyecto"></span></div>
      <div class="c-field"><label class="c-label" for="drawer-owner">Responsable</label><span class="c-input"><input class="c-input__field" id="drawer-owner" placeholder="Cualquiera"></span></div>
    </div>
    <div class="c-drawer__footer">
      <button class="c-btn c-btn--ghost" value="reset">Limpiar</button>
      <button class="c-btn c-btn--primary" value="apply">Aplicar</button>
    </div>
    <button class="c-btn c-btn--ghost c-btn--icon c-drawer__close" type="button" commandfor="drawer-filters" command="close" aria-label="Cerrar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>
  </form>
</dialog>
```

```css
/* drawer · Componentes (MIRÓ Labs). Diseño de coss ui (MIT, © coss.com, antes Origin UI).
   Generado por tools/build_css.py desde drawer.tw.json. No editar a mano. Necesita tokens.css. */
.c-drawer__close{position:absolute;inset-inline-end:calc(var(--spacing)*2);top:calc(var(--spacing)*2)}
.c-drawer__footer{margin-top:auto}
.c-drawer{display:flex}
.c-drawer__header{display:flex}
.c-drawer__footer{display:flex}
.c-drawer{max-height:100%;min-height:calc(var(--spacing)*0);width:calc(100% - (calc(var(--spacing)*12)));width:100%;max-width:var(--container-md);min-width:calc(var(--spacing)*0);flex-direction:column}
.c-drawer__header{flex-direction:column}
.c-drawer__footer{flex-direction:column-reverse}
.c-drawer__header{gap:calc(var(--spacing)*2)}
.c-drawer__footer{gap:calc(var(--spacing)*2)}
.c-drawer{border-inline-start-style:var(--tw-border-style);border-inline-start-width:1px;background-color:var(--popover)}
.c-drawer__header{padding:calc(var(--spacing)*6)}
.c-drawer__panel{padding:calc(var(--spacing)*6)}
.c-drawer__footer{padding-inline:calc(var(--spacing)*6)}
.c-drawer__panel{padding-top:calc(var(--spacing)*1)}
.c-drawer__footer{padding-top:calc(var(--spacing)*4);padding-bottom:calc(var(--spacing)*6)}
.c-drawer__description{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}
.c-drawer__title{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height));--tw-leading:1;line-height:1;--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}
.c-drawer__description{color:var(--muted-foreground)}
.c-drawer{color:var(--popover-foreground);--tw-shadow-alpha:5%;--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000000d),0 4px 6px -4px var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}
@supports (color:lab(0% 0 0)){
.c-drawer{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,lab(0% 0 0/.05)),0 4px 6px -4px var(--tw-shadow-color,lab(0% 0 0/.05))}
}
.c-drawer{transition-property:opacity,translate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s;--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out);will-change:transform}
.c-drawer:not(:is(.dark *)){background-clip:padding-box}
.c-drawer:before{content:var(--tw-content);pointer-events:none;content:var(--tw-content);position:absolute;content:var(--tw-content);inset:calc(var(--spacing)*0);content:var(--tw-content);--tw-shadow:0 1px var(--tw-shadow-color,#0000000a)}
@supports (color:color-mix(in lab, red, red)){
.c-drawer:before{--tw-shadow:0 1px var(--tw-shadow-color,color-mix(in oklab,var(--color-black)4%,transparent))}
}
.c-drawer:before{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}
@media not all and (min-width:40rem){
.c-drawer__header{padding-bottom:calc(var(--spacing)*4)}
.c-drawer:before{content:var(--tw-content);display:none}
}
@media (min-width:40rem){
.c-drawer__footer{flex-direction:row;justify-content:flex-end}
}
.c-drawer:is(.dark *):before{content:var(--tw-content);--tw-shadow:0 -1px var(--tw-shadow-color,#ffffff0f)}
@supports (color:color-mix(in lab, red, red)){
.c-drawer:is(.dark *):before{--tw-shadow:0 -1px var(--tw-shadow-color,color-mix(in oklab,var(--color-white)6%,transparent))}
}
.c-drawer:is(.dark *):before{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}
/* propio */
.c-drawer{position:fixed;padding:0;margin:0 0 0 auto;height:100dvh;max-height:100dvh;color:var(--popover-foreground);opacity:0;translate:2rem 0;transition:opacity .2s ease-in-out,translate .2s ease-in-out,overlay .2s allow-discrete,display .2s allow-discrete}
.c-drawer[open]{display:flex;opacity:1;translate:0 0}
@starting-style{.c-drawer[open]{opacity:0;translate:2rem 0}}
.c-drawer::backdrop{background:color-mix(in oklab,#000 32%,transparent);backdrop-filter:blur(4px);opacity:0;transition:opacity .2s,overlay .2s allow-discrete,display .2s allow-discrete}
.c-drawer[open]::backdrop{opacity:1}
@starting-style{.c-drawer[open]::backdrop{opacity:0}}
.c-drawer__close{position:absolute}
.c-drawer__form{display:contents}
.c-drawer__panel{display:grid;gap:1rem;overflow-y:auto}
html:has(.c-drawer[open]:modal){overflow:hidden}
```

## Credits

- coss ui (MIT) · sheet.tsx: https://coss.com/ui
- W3C WAI-ARIA APG, Dialog (Modal): https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/
