Skip to content

Drawer

Provides a scroll drawer that uses native HTML5 dialog and CSS scroll-snap property.
Can be dismissed with touch gestures on touch devices.

View Source 

Usage

css
@import "winduum/src/components/drawer/index.css" layer(components);
html
<button class="x-button" id="showDrawerLeftElement">Show drawer</button>
<dialog class="x-drawer" id="drawerLeftElement" inert>
    <nav class="x-drawer-content">
        Drawer content
        <button class="x-button muted" id="closeDrawerLeftElement">Close drawer</button>
    </nav>
</dialog>
liquid
<script type="module">
    import { showDrawer, closeDrawer, scrollDrawer, scrollInitDrawer } from "winduum/src/components/drawer"

    drawerLeftElement.addEventListener('scroll', ({ target }) => scrollDrawer(target))

    showDrawerLeftElement.addEventListener('click', async () => {
        drawerLeftElement.showModal()

        await scrollInitDrawer(drawerLeftElement)

        showDrawer(drawerLeftElement)
    })

    closeDrawerLeftElement.addEventListener('click', () => {
        closeDrawer(drawerLeftElement, drawerLeftElement.scrollWidth)
    })
</script>

Variants

  • default 
  • content 

Props

  • default 
  • content 

Installation

Follow instructions for individual framework usage below

  • winduum 
  • winduum-stimulus 

Examples

Left

Drawer content
html
<button class="x-button" id="showDrawerLeftElement">Show drawer</button>
<dialog class="x-drawer" id="drawerLeftElement" inert>
    <nav class="x-drawer-content">
        Drawer content
        <button class="x-button muted" id="closeDrawerLeftElement">Close drawer</button>
    </nav>
</dialog>
liquid
<script type="module">
    import { showDrawer, closeDrawer, scrollDrawer, scrollInitDrawer } from "winduum/src/components/drawer"

    drawerLeftElement.addEventListener('scroll', ({ target }) => scrollDrawer(target))

    showDrawerLeftElement.addEventListener('click', async () => {
        drawerLeftElement.showModal()

        await scrollInitDrawer(drawerLeftElement)

        showDrawer(drawerLeftElement)
    })

    closeDrawerLeftElement.addEventListener('click', () => {
        closeDrawer(drawerLeftElement, drawerLeftElement.scrollWidth)
    })
</script>
Drawer content
html
<button class="x-button" id="showDrawerRightElement">Show drawer</button>
<dialog class="x-drawer after:-order-last" id="drawerRightElement" inert>
    <nav class="x-drawer-content">
        Drawer content
        <button class="x-button muted" id="closeDrawerRightElement">Close drawer</button>
    </nav>
</dialog>
liquid
<script type="module">
    import { showDrawer, closeDrawer, scrollDrawer, scrollInitDrawer } from "winduum/src/components/drawer"

    drawerRightElement.addEventListener('scroll', ({ target }) => scrollDrawer(target, {
        scrollOpen: target.scrollWidth - target.clientWidth,
        scrollClose: 0,
        opacityRatio: 0
    }))
    showDrawerRightElement.addEventListener('click', async () => {
        drawerRightElement.showModal()

        await scrollInitDrawer(drawerRightElement, 0)

        showDrawer(drawerRightElement, drawerRightElement.scrollWidth)
    })
    closeDrawerRightElement.addEventListener('click', () => closeDrawer(drawerRightElement, 0))
</script>

Bottom

Drawer content
html
<button class="x-button" id="showDrawerBottomElement">Show drawer</button>
<dialog class="x-drawer flex flex-col after:-order-last" id="drawerBottomElement" inert>
    <nav class="x-drawer-content" style="--x-drawer-content-width: 100%;--x-drawer-content-height: calc(100vh - 4rem);">
        Drawer content
        <button class="x-button muted" id="closeDrawerBottomElement">Close drawer</button>
    </nav>
</dialog>
liquid
<script type="module">
    import { showDrawer, closeDrawer, scrollDrawer, scrollInitDrawer } from "winduum/src/components/drawer"


    drawerBottomElement.addEventListener('scroll', ({ target }) => scrollDrawer(target, {
        snapClass: 'snap-y snap-mandatory',
        scrollSize: target.scrollHeight - target.clientHeight,
        scrollDirection: target.scrollTop,
        scrollOpen: target.scrollHeight - target.clientHeight,
        scrollClose: 0,
        opacityRatio: 0
    }))
    showDrawerBottomElement.addEventListener('click', async () => {
        drawerBottomElement.showModal()

        await scrollInitDrawer(drawerBottomElement, 0, 'top')

        showDrawer(drawerBottomElement, drawerBottomElement.scrollHeight, 'top')
    })
    closeDrawerBottomElement.addEventListener('click', () => closeDrawer(drawerBottomElement, 0, 'top'))
</script>

Top

Drawer content
html
<button class="x-button" id="showDrawerTopElement">Show drawer</button>
<dialog class="x-drawer flex flex-col" id="drawerTopElement" inert>
    <nav class="x-drawer-content" style="--x-drawer-content-width: 100%;--x-drawer-content-height: calc(100vh - 4rem);">
        Drawer content
        <button class="x-button muted" id="closeDrawerTopElement">Close drawer</button>
    </nav>
</dialog>
liquid
<script type="module">
    import { showDrawer, closeDrawer, scrollDrawer, scrollInitDrawer } from "winduum/src/components/drawer"

    drawerTopElement.addEventListener('scroll', ({ target }) => scrollDrawer(target, {
        snapClass: 'snap-y snap-mandatory',
        scrollSize: target.scrollHeight - target.clientHeight,
        scrollDirection: target.scrollTop,
        scrollOpen: 0,
        scrollClose: target.scrollHeight - target.clientHeight
    }))
    showDrawerTopElement.addEventListener('click', async () => {
        drawerTopElement.showModal()

        await scrollInitDrawer(drawerTopElement,  drawerTopElement?.scrollHeight, 'top')

        showDrawer(drawerTopElement, 0, 'top')
    })
    closeDrawerTopElement.addEventListener('click', () => closeDrawer(drawerTopElement, drawerTopElement.scrollHeight, 'top'))
</script>

Javascript API

showDrawer

  • Type: (element: HTMLElement | Element, distance: number, direction: 'left' | 'top') => void
  • Kind: sync

Scroll the drawer to open state.

closeDrawer

  • Type: (element: HTMLElement | Element, distance: number, direction: 'left' | 'top') => void
  • Kind: sync

Scroll the drawer to closed state.

scrollInitDrawer

  • Type: (element: HTMLElement | Element, distance?: number, direction?: 'left' | 'top') => void
  • Kind: sync

Initializes the scroll position. Call this before showDrawer method.

scrollDrawer

  • Type: (element: HTMLElement | Element, options: ScrollDrawerOptions) => void
  • Kind: sync

Sets correct classes and attributes upon scroll. Events c-drawer:open and c-drawer:close are dispatched upon opening or closing the drawer.

ScrollDrawerOptions


snapClass
  • Type: string
  • Default: snap-x snap-mandatory

A classes that are added for snapping purposes once the drawer is open.


opacityProperty
  • Type: string
  • Default: --tw-bg-opacity

A CSS property for animating the background opacity upon scroll.


opacityRatio
  • Type: number
  • Default: 1

You can either set 1 or 0 depending on the direction the drawer is opened. Right and bottom drawer should be set to 0.


scrollOpen
  • Type: number
  • Default: 0

Scroll position indicating that the drawer is opened.


scrollClose
  • Type: number
  • Default: element.scrollWidth - element.clientWidth

Scroll position indicating that the drawer is closed.


scrollSize
  • Type: number
  • Default: element.scrollWidth - element.clientWidth

Maximum scroll size of the drawer.


scrollDirection
  • Type: number
  • Default: element.scrollLeft

Current scroll position of the drawer.

Released under the MIT License.