![Namecheap Takes Down Polyfill.io Service Following Supply Chain Attack](https://cdn.sanity.io/images/cgdhsj6q/production/6af25114feaaac7179b18127c83327568ff592d1-1024x1024.webp?w=800&fit=max&auto=format)
Security News
Namecheap Takes Down Polyfill.io Service Following Supply Chain Attack
Polyfill.io has been serving malware for months via its CDN, after the project's open source maintainer sold the service to a company based in China.
@vrembem/drawer
Advanced tools
Changelog
v1.38.0 (2022-02-05)
popover
, tooltip
, vrembem
Readme
A container component that slides in from the left or right. Typically containing menus, search or other content.
npm install @vrembem/drawer
@use "@vrembem/drawer";
import Drawer from '@vrembem/drawer';
const drawer = new Drawer({ autoInit: true });
Drawers are composed using classes for styling and data attributes for JavaScript functionality. To link a drawer toggle, open or close trigger to a drawer, use a unique identifier as the values for both the trigger and drawer's respective data attributes. Close buttons can be left value-less if placed inside a drawer element they're meant to close.
data-drawer="[unique-id]"
data-drawer-dialog
data-drawer-toggle="[unique-id]"
data-drawer-open="[unique-id]"
data-drawer-close="[unique-id]"
(or value-less if inside drawer)<div class="drawer__wrapper">
<aside data-drawer="[unique-id]" class="drawer">
<div data-drawer-dialog class="drawer__dialog">
<button data-drawer-close>...</button>
</div>
</aside>
<div class="drawer__main">
<button data-drawer-toggle="[unique-id]">...</button>
<button data-drawer-open="[unique-id]">...</button>
<button data-drawer-close="[unique-id]">...</button>
</div>
</div>
Drawer dialogs are the actual dialog element within a drawer and are defined using a the value-less data-drawer-dialog
attribute. The dialog component is a great fit for composing a drawer’s content.
<aside data-drawer="[unique-id]" class="drawer">
<div data-drawer-dialog class="drawer__dialog dialog">
<div class="dialog__header">
...
<button data-drawer-close>...</button>
</div>
<div class="dialog__body">
...
</div>
<div class="dialog__footer">
...
</div>
</div>
</aside>
data-drawer-breakpoint
In cases where you'd like a drawer to switch to a drawer modal on a specific breakpoint, use the data-drawer-breakpoint
data attribute with either a breakpoint key or a specific pixel value.
<!-- Switches to modal below `md` breakpoint viewports -->
<aside data-drawer="[unique-id]" data-drawer-breakpoint="md" class="drawer">
...
</aside>
<!-- Switches to modal below 900px viewports -->
<aside data-drawer="[unique-id]" data-drawer-breakpoint="900px" class="drawer">
...
</aside>
A custom breakpoints object can be passed in using the breakpoints
option. Otherwise, default values are set via the core variables module.
const drawer = new Drawer({
breakpoints: {
xs: '480px',
sm: '620px',
md: '760px',
lg: '990px',
xl: '1380px'
}
});
data-drawer-focus
Drawer dialogs are given focus on open by default as long as the setTabindex
option is set to true
or if the drawer dialog has tabindex="-1"
set manually. If focus on a specific element inside a drawer is preferred, give it the data-drawer-focus
attribute. The focus in either case is returned to the trigger element once the drawer is closed.
<div cass="drawer__wrapper">
<!-- Focuses the drawer dialog on open -->
<aside data-drawer="[unique-id]" class="drawer">
<div data-drawer-dialog class="drawer__dialog">
...
</div>
</aside>
<!-- Focuses an inner element on open -->
<aside data-drawer="[unique-id]" class="drawer">
<div data-drawer-dialog class="drawer__dialog">
<button data-drawer-focus>...</button>
</div>
</aside>
<div class="drawer__main">
<!-- Return focus to toggle on close -->
<button data-drawer-toggle="[unique-id]">...</button>
</div>
</div>
By default, the state of a drawer is saved to local storage and applied persistently under the "DrawerState" local storage variable. Set stateSave: false
to disable save state. Use stateKey: "[CUSTOM-KEY]"
to change the key that save state is stored under.
Drawers when in their modal context follow a set of patterns expected from other modals on the web. Here's what to expect:
esc
key or clicking outside the dialog.To take full advantage of drawer modal's accessibility features, it's recommended to that you set the selectorInert
option to all elements that are outside the drawer modal (most likely the drawer__main
element). All elements that match the selectorInert
selector will be given the inert
attribute as well as aria-hidden="true"
when a modal is opened.
Inert is not currently widely supported by all browsers. Consider using a polyfill such as wicg-inert or Google's inert-polyfill.
Here's an example where we want the [role="main"]
content area to be inaccessible while drawer modals are open. We also want to disable other scrollable elements using the selectorOverflow
option.
const drawer = new Drawer({
autoInit: true,
selectorInert: '[role="main"]',
selectorOverflow: 'body, [role="main"]'
});
drawer_modal
Convert a drawer into it’s modal state with the drawer_modal
modifier class. Only one modal can be open at a time.
<div class="drawer__wrapper">
<aside data-drawer="[unique-id]" class="drawer drawer_modal">
...
</aside>
<div class="drawer__main">
<button data-drawer-toggle="[unique-id]">
...
</button>
</div>
</div>
drawer_pos_[value]
Drawers can slide in from the left or right using the position modifiers:
drawer_pos_left
drawer_pos_right
<div class="drawer__wrapper">
<aside data-drawer="[unique-id]" class="drawer drawer_pos_left">
...
</aside>
<aside data-drawer="[unique-id]" class="drawer drawer_pos_right">
...
</aside>
<div class="drawer__main">
<button data-drawer-toggle="[unique-id]">
...
</button>
<button data-drawer-toggle="[unique-id]">
...
</button>
</div>
</div>
If a position modifier is not provided, the drawer will appear based on it’s location in the DOM relative to the main content area and other drawers.
Variable | Default | Description |
---|---|---|
$prefix-block | null | String to prefix blocks with. |
$prefix-element | "__" | String to prefix elements with. |
$prefix-modifier | "_" | String to prefix modifiers with. |
$prefix-modifier-value | "_" | String to prefix modifier values with. |
$width | 18em | The width of drawers. |
$max-width | 100% | The max-width of drawers. |
$border | null | Border applied to drawer items with position modifiers. Shown on side of drawers facing drawer main. |
$sep-border | null | Border color applied to dialog components within drawer items. |
$background | core.$shade | Background color applied to drawer items. |
$box-shadow | none | Box shadow applied to drawer items. |
$travel | 5em | Distance that drawers travel during their transition. |
$transition-duration | core.$transition-duration | Duration of drawer transition. |
$transition-timing-function | core.$transition-timing-function | Timing function used for drawer transitions. |
$wrapper-height | 100% | The height given to drawer wrapper element. |
$modal-z-index | 900 | Modal z-index to help control the stack order. Should be highest priority as modal. |
$modal-width | $width | The width of modal drawers. |
$modal-max-width | 80% | The max-width of modal drawers. |
$modal-sep-border | null | Border color applied to dialog components within modal drawer items. |
$modal-background | core.$white | Background color applied to modal drawer items. |
$modal-box-shadow | core.$box-shadow-24dp | Box shadow applied to modal drawer items. |
$modal-screen-background | core.$night | Background color of modal screen. |
$modal-screen-background-alpha | 0.8 | The alpha channel for the modal screen. |
Key | Default | Description |
---|---|---|
autoInit | false | Automatically initializes the instance. |
dataDrawer | 'drawer' | Data attribute for a drawer. |
dataDialog | 'drawer-dialog' | Data attribute for a drawer dialog. |
dataToggle | 'drawer-toggle' | Data attribute for a drawer toggle trigger. |
dataOpen | 'drawer-open' | Data attribute for a drawer open trigger. |
dataClose | 'drawer-close' | Data attribute for a drawer close trigger. |
dataBreakpoint | 'drawer-breakpoint' | Data attribute for setting a drawer's breakpoint. |
dataFocus | 'drawer-focus' | Data attribute for setting a drawer's focus element. |
stateOpen | 'is-opened' | Class used for open state. |
stateOpening | 'is-opening' | Class used for transitioning to open state. |
stateClosing | 'is-closing' | Class used for transitioning to closed state. |
stateClosed | 'is-closed' | Class used for closed state. |
classModal | 'drawer_modal' | Class used for toggling the drawer modal state. |
selectorInert | null | Applies inert and aria-hidden attributes to all matching elements when a modal drawer is opened. |
selectorOverflow | null | Applies overflow:hidden styles on all matching elements when a modal drawer is opened. |
breakpoints | core.breakpoints | An object with key/value pairs defining a breakpoints set. |
customEventPrefix | 'drawer:' | Prefix to be used on custom events. |
eventListeners | true | Whether or not to set the document event listeners on init. |
stateSave | true | Toggles the save state feature. |
stateKey | "DrawerState" | Defines the localStorage key where drawer states are saved. |
setTabindex | true | Whether or not to set tabindex="-1" on all drawer dialog elements on init. |
transition | true | Toggle the transition animation for the drawer. Set to false to disable. |
drawer:opened
Emits when the drawer has opened.drawer:closed
Emits when the drawer has closed.drawer:breakpoint
Emits when the drawer has hit a breakpoint.drawer:toModal
Emits when the drawer is switched to it's modal state.drawer:toDefault
Emits when the drawer is switched to it's default state.drawer.init(options)
Initializes the drawer instance. During initialization, the following processes are run:
stateSet()
to apply the initial state for all drawers.setTabindex()
to apply tabindex for all drawer dialogs.breakpoint.init()
to initialize all breakpoints for drawers.click
event listener to the document.keydown
event listener for closing modal drawers with the esc
key.Parameters
options [Object] (optional) (default null)
An options object for passing your custom settings.const drawer = new Drawer();
drawer.init();
drawer.destroy()
Destroys and cleans up the drawer instantiation. During cleanup, the following processes are run:
breakpoint.destroy()
to remove all active breakpoints.drawer.memory
object.drawer.state
object.click
event listener from the document.keydown
event listener from the document.const drawer = new Drawer();
drawer.init();
// ...
drawer.destroy();
drawer.initEventListeners()
Set the document event listeners for click, touchend and keydown events.
const drawer = new Drawer({ eventListeners: false });
drawer.init();
drawer.initEventListeners();
drawer.destroyEventListeners()
Remove the document event listeners for click, touchend and keydown events.
const drawer = new Drawer();
drawer.init();
// ...
drawer.destroyEventListeners();
drawer.toggle(key)
Toggles a drawer when provided the drawer key and returns a promise that resolves to the drawer object once the transition has finished.
Parameters
key [String]
A unique key that matches the value of a drawer data-drawer
attribute.Returns
Promise
The returned promise value will either be the HTML object
of the drawer that was toggled, or error
if a drawer was not found.<div class="drawer" data-drawer="drawer-key">...</div>
// Toggle drawer
drawer.toggle('drawer-key');
// Run some code after promise resolves
drawer.toggle('drawer-key').then((result) => {
console.log(result);
});
drawer.open(key)
Opens a drawer when provided the drawer key and returns a promise that resolves to the drawer object once the transition has finished.
Parameters
key [String]
A unique key that matches the value of a drawer data-drawer
attribute.Returns
Promise
The returned promise value will either be the HTML object
of the drawer that was opened, or error
if a drawer was not found.<div class="drawer" data-drawer="drawer-key">...</div>
// Open drawer
drawer.open('drawer-key');
// Run some code after promise resolves
drawer.open('drawer-key').then((result) => {
console.log(result);
});
drawer.close(key)
Closes a drawer when provided the drawer key and returns a promise that resolves to the drawer object once the transition has finished.
Parameters
key [String]
A unique key that matches the value of a drawer data-drawer
attribute.Returns
Promise
The returned promise value will either be the HTML object
of the drawer that was closed, or error
if a drawer was not found.<div class="drawer" data-drawer="drawer-key">...</div>
// Close drawer
drawer.close('drawer-key');
// Run some code after promise resolves
drawer.close('drawer-key').then((result) => {
console.log(result);
});
drawer.getDrawer(key)
Returns a drawer that matches the provided unique drawer key.
Parameters
key [String]
A unique key that matches the value of a drawer data-drawer
attribute.Returns
HTML object
The matching drawer element.<div class="drawer" data-drawer="drawer-key">...</div>
const el = drawer.getDrawer('drawer-key');
// Returns HTML Element Object
console.log(el);
drawer.setTabindex()
Sets the tabindex="-1"
attribute on all drawer dialogs. This makes it possible to set focus on the dialog when opened but won't allow users to focus it using the keyboard. This is ran automatically on drawer.init()
if the setTabindex
option is set to true
.
<!-- Initial HTML -->
<aside data-drawer="[unique-id]" class="drawer">
<div data-drawer-dialog class="drawer__dialog">
...
</div>
</aside>
drawer.setTabindex();
<!-- Result -->
<aside data-drawer="[unique-id]" class="drawer">
<div data-drawer-dialog class="drawer__dialog" tabindex="-1">
...
</div>
</aside>
drawer.breakpoint.init()
Initializes the drawer breakpoint feature. During initialization, all drawers with data-drawer-breakpoint
are retrieved and a MediaQueryList
is created for each. Each MediaQueryList
and it's associated drawer key is stored in the drawer.mediaQueryLists
array. This is ran automatically on drawer.init()
.
<aside data-drawer="drawer-1" data-drawer-breakpoint="420px" class="drawer">
...
</aside>
<aside data-drawer="drawer-2" data-drawer-breakpoint="740px" class="drawer">
...
</aside>
// Initialize breakpoints
drawer.breakpoint.init();
// Output stored lists
console.log(drawer.mediaQueryLists);
// Log result
[{
mql: MediaQueryList // Obj
drawer: 'drawer-1' // String
}, {
mql: MediaQueryList // Obj
drawer: 'drawer-2' // String
}]
drawer.breakpoint.destroy()
Destroys the drawer breakpoint feature. This process involves removeing all attached media match listeners from the stored MediaQueryList
s and then clearing the stored array. This is ran automatically on drawer.destroy()
.
// Initialize breakpoints
drawer.breakpoint.destroy();
// Output stored lists
console.log(drawer.mediaQueryLists);
// Log result
null
drawer.breakpoint.check()
Force a check of any drawers that meet their breakpoint condition. If their state doesn't match the current breakpoint condition, they'll be updated. This is useful when used with frameworks that dynamically re-render components on the fly.
<!-- Initial HTML -->
<aside data-drawer="[unique-id]" data-drawer-breakpoint="sm" class="drawer">
...
</aside>
// Manually run a breakpoint check
drawer.breakpoint.check();
<!-- Output if matches breakpoint -->
<aside data-drawer="[unique-id]" data-drawer-breakpoint="sm" class="drawer drawer_modal">
...
</aside>
drawer.switchToModal(key)
Switches a drawer to it's modal state.
Parameters
key [String]
A unique key that matches the value of a drawer data-drawer
attribute.<!-- Initial HTML -->
<div class="drawer" data-drawer="drawer-key">...</div>
// Switch a drawer to modal state
drawer.switchToModal('drawer-key');
<!-- Output -->
<div class="drawer drawer_modal" data-drawer="drawer-key">...</div>
drawer.switchToDefault(key)
Switches a drawer to it's default non-modal state.
Parameters
key [String]
A unique key that matches the value of a drawer data-drawer
attribute.<!-- Initial HTML -->
<div class="drawer drawer_modal" data-drawer="drawer-key">...</div>
// Switch a drawer to default non-modal state
drawer.switchToDefault('drawer-key');
<!-- Output -->
<div class="drawer" data-drawer="drawer-key">...</div>
drawer.stateSet()
Sets the current saved state of all drawer elements based on the values set in localStorage and updates the instance drawer.state
object.
<!-- Initial HTML -->
<aside data-drawer="drawer-1" class="drawer is-opened">...</aside>
<aside data-drawer="drawer-2" class="drawer is-opened">...</aside>
// If the current saved state in localStorage looks like this:
// {
// "drawer-1": "is-closed",
// "drawer-2": "is-closed"
// }
drawer.stateSet();
<!-- Output -->
<aside data-drawer="drawer-1" class="drawer is-closed">...</aside>
<aside data-drawer="drawer-2" class="drawer is-closed">...</aside>
drawer.stateSave(target)
Saves the current state of drawers to localStorage and drawer's drawer.state
object. This is useful when state becomes out of sync or the DOM is re-rendered in a way that breaks current state.
Parameters
HTML Element [Object]
(Default: null) A specific target to save state. If nothing is passed, all drawers in the DOM will have their state saved.<!-- Initial HTML -->
<aside data-drawer="drawer-1" class="drawer is-closed">...</aside>
<aside data-drawer="drawer-2" class="drawer is-opened">...</aside>
// If current saved state looks like:
console.log(drawer.state);
// {
// "drawer-1": "is-closed",
// "drawer-2": "is-closed"
// }
drawer.stateSave();
// Result
console.log(drawer.state);
// {
// "drawer-1": "is-closed",
// "drawer-2": "is-opened"
// }
drawer.stateClear()
Clears the existing saved states in both localStorage and drawer's drawer.state
object.
console.log(drawer.state);
// Returns: {
// "drawer-1": "is-closed",
// "drawer-2": "is-closed"
// }
drawer.stateClear();
console.log(drawer.state);
// Returns: Object { }
FAQs
A container component that slides in from the left or right. Typically containing menus, search or other content.
The npm package @vrembem/drawer receives a total of 326 weekly downloads. As such, @vrembem/drawer popularity was classified as not popular.
We found that @vrembem/drawer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Polyfill.io has been serving malware for months via its CDN, after the project's open source maintainer sold the service to a company based in China.
Security News
OpenSSF is warning open source maintainers to stay vigilant against reputation farming on GitHub, where users artificially inflate their status by manipulating interactions on closed issues and PRs.
Security News
A JavaScript library maintainer is under fire after merging a controversial PR to support legacy versions of Node.js.