Drawer
Provides a scroll drawer that uses native CSS scroll-snap
property.
Can be dismissed with touch gestures on touch devices.
Usage
@import "winduum/src/components/drawer/index.css" layer(components);
<button class="ui-btn" id="showDrawerLeftElement">Show drawer</button>
<div class="c-drawer invisible" id="drawerLeftElement" inert>
<nav class="c-drawer-content">
Drawer content
<button class="ui-btn muted" id="closeDrawerLeftElement">Close drawer</button>
</nav>
</div>
<script type="module">
import { showDrawer, closeDrawer, scrollDrawer } from "winduum/src/components/drawer"
drawerLeftElement?.scroll({ left: drawerLeftElement?.scrollWidth , behavior: 'instant' })
drawerLeftElement?.classList.remove('invisible')
drawerLeftElement.addEventListener('scroll', ({ target }) => scrollDrawer(target))
showDrawerLeftElement.addEventListener('click', () => showDrawer(drawerLeftElement))
closeDrawerLeftElement.addEventListener('click', () => closeDrawer(drawerLeftElement))
</script>
Variants
Props
Installation
Follow instructions for individual framework usage below
Examples
Left
<button class="ui-btn" id="showDrawerLeftElement">Show drawer</button>
<div class="c-drawer invisible" id="drawerLeftElement" inert>
<nav class="c-drawer-content">
Drawer content
<button class="ui-btn muted" id="closeDrawerLeftElement">Close drawer</button>
</nav>
</div>
<script type="module">
import { showDrawer, closeDrawer, scrollDrawer } from "winduum/src/components/drawer"
drawerLeftElement?.scroll({ left: drawerLeftElement?.scrollWidth , behavior: 'instant' })
drawerLeftElement?.classList.remove('invisible')
drawerLeftElement.addEventListener('scroll', ({ target }) => scrollDrawer(target))
showDrawerLeftElement.addEventListener('click', () => showDrawer(drawerLeftElement))
closeDrawerLeftElement.addEventListener('click', () => closeDrawer(drawerLeftElement))
</script>
Right
<button class="ui-btn" id="showDrawerRightElement">Show drawer</button>
<div class="c-drawer invisible after:-order-last" id="drawerRightElement" inert>
<nav class="c-drawer-content">
Drawer content
<button class="ui-btn muted" id="closeDrawerRightElement">Close drawer</button>
</nav>
</div>
<script type="module">
import { showDrawer, closeDrawer, scrollDrawer } from "winduum/src/components/drawer"
drawerRightElement?.scroll({ left: 0, behavior: 'instant' });
drawerRightElement?.classList.remove('invisible')
drawerRightElement.addEventListener('scroll', ({ target }) => scrollDrawer(target, {
scrollOpen: target.scrollWidth - target.clientWidth,
scrollClose: 0,
opacityRatio: 0
}))
showDrawerRightElement.addEventListener('click', () => showDrawer(drawerRightElement, drawerRightElement.scrollWidth))
closeDrawerRightElement.addEventListener('click', () => closeDrawer(drawerRightElement, 0))
</script>
Bottom
<button class="ui-btn" id="showDrawerBottomElement">Show drawer</button>
<div class="c-drawer invisible flex-col after:-order-last" id="drawerBottomElement" inert>
<nav class="c-drawer-content" style="--c-drawer-content-width: 100%;--c-drawer-content-height: calc(100vh - 4rem);">
Drawer content
<button class="ui-btn muted" id="closeDrawerBottomElement">Close drawer</button>
</nav>
</div>
<script type="module">
import { showDrawer, closeDrawer, scrollDrawer } from "winduum/src/components/drawer"
drawerBottomElement?.scroll({ top: 0, behavior: 'instant' });
drawerBottomElement?.classList.remove('invisible')
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', () => showDrawer(drawerBottomElement, drawerBottomElement.scrollHeight, 'top'))
closeDrawerBottomElement.addEventListener('click', () => closeDrawer(drawerBottomElement, 0, 'top'))
</script>
Top
<button class="ui-btn" id="showDrawerTopElement">Show drawer</button>
<div class="c-drawer invisible flex-col" id="drawerTopElement" inert>
<nav class="c-drawer-content" style="--c-drawer-content-width: 100%;--c-drawer-content-height: calc(100vh - 4rem);">
Drawer content
<button class="ui-btn muted" id="closeDrawerTopElement">Close drawer</button>
</nav>
</div>
<script type="module">
import { showDrawer, closeDrawer, scrollDrawer } from "winduum/src/components/drawer"
drawerTopElement?.scroll({ top: drawerTopElement.scrollHeight, behavior: 'instant' });
drawerTopElement?.classList.remove('invisible')
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', () => showDrawer(drawerTopElement, 0, 'top'))
closeDrawerTopElement.addEventListener('click', () => closeDrawer(drawerTopElement, drawerTopElement.scrollHeight, 'top'))
</script>
Dialog
Moves the drawer to top layer, traps focus in and can be closed with esc
.
<button class="ui-btn" id="showDrawerDialogElement">Show drawer</button>
<dialog class="c-drawer invisible after:-order-last backdrop:hidden" id="drawerDialogElement" inert>
<nav class="c-drawer-content">
Drawer content
<button class="ui-btn muted" id="closeDrawerDialogElement">Close drawer</button>
</nav>
</dialog>
<script type="module">
import { showDrawer, closeDrawer, scrollDrawer } from "winduum/src/components/drawer"
drawerDialogElement?.scroll({ left: 0, behavior: 'instant' });
drawerDialogElement?.classList.remove('invisible')
drawerDialogElement.addEventListener('scroll', ({ target }) => scrollDrawer(target, {
scrollOpen: target.scrollWidth - target.clientWidth,
scrollClose: 0,
opacityRatio: 0
}))
showDrawerDialogElement.addEventListener('click', () => {
drawerDialogElement.showModal()
showDrawer(drawerDialogElement, drawerDialogElement.scrollWidth)
})
closeDrawerDialogElement.addEventListener('click', () => closeDrawer(drawerDialogElement, 0))
drawerDialogElement?.addEventListener('c-drawer:close', () => drawerDialogElement.close())
drawerDialogElement?.addEventListener('close', () => closeDrawer(drawerDialogElement, 0))
</script>
Javascript API
showDrawer
- Type:
(element: HTMLElement | Element, distance: number, direction: 'left' | 'top') => void
- Kind:
sync
Scrolls the drawer to opened state.
closeDrawer
- Type:
(element: HTMLElement | Element, distance: number, direction: 'left' | 'top') => void
- Kind:
sync
Scrolls the drawer to closed state.
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.