-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat(web): Introduce Drawer component #DS-1580
- Loading branch information
Showing
14 changed files
with
455 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Drawer | ||
|
||
The Drawer component is a container that slides in from side of the screen. It can be used to display additional content or actions that are not part of the main view. | ||
|
||
The Drawer is a composition of several subcomponents: | ||
|
||
- [Drawer](#drawer) | ||
- [DrawerCloseButton](#drawerclosebutton) | ||
- [DrawerPanel](#drawerpanel) | ||
|
||
👉 The animation effect of this component is dependent on the | ||
`prefers-reduced-motion` media query. | ||
|
||
## Drawer | ||
|
||
```html | ||
<dialog id="my-drawer-dialog" class="Drawer Drawer--right"> | ||
<!-- Drawer panel goes here --> | ||
</dialog> | ||
``` | ||
|
||
### Alignment | ||
|
||
The `Drawer` component allows aligning the content panel horizontally to the left or right side of the screen using `--left` or `--right` modifier. The default alignment of the drawer content panel is to the right. | ||
|
||
```html | ||
<dialog id="my-drawer-dialog" class="Drawer Drawer--left"> | ||
<!-- Drawer panel goes here --> | ||
</dialog> | ||
``` | ||
|
||
## DrawerCloseButton | ||
|
||
The `DrawerCloseButton` component is a button that closes the drawer when clicked. | ||
|
||
```html | ||
<button | ||
type="button" | ||
class="Button Button--tertiary Button--medium Button--symmetrical DrawerCloseButton" | ||
data-spirit-dismiss="offcanvas" | ||
data-spirit-target="#my-drawer-dialog" | ||
aria-controls="my-drawer-dialog" | ||
aria-expanded="false" | ||
> | ||
<svg width="24" height="24" aria-hidden="true"> | ||
<use xlink:href="/icons/svg/sprite.svg#close" /> | ||
</svg> | ||
<span class="accessibility-hidden">Close</span> | ||
</button> | ||
``` | ||
|
||
## DrawerPanel | ||
|
||
The `DrawerPanel` component is a container for the content that will be displayed in the drawer. | ||
|
||
```html | ||
<div class="DrawerPanel"> | ||
<div class="DrawerPanel__content"> | ||
<!-- Drawer content goes here --> | ||
</div> | ||
</div> | ||
``` | ||
|
||
## Full Example | ||
|
||
```html | ||
<dialog id="drawer-example" class="Drawer Drawer--right"> | ||
<div class="DrawerPanel"> | ||
<div class="DrawerPanel__content"> | ||
<button | ||
type="button" | ||
aria-expanded="false" | ||
class="Button Button--tertiary Button--medium Button--symmetrical DrawerCloseButton" | ||
data-spirit-dismiss="offcanvas" | ||
data-spirit-target="#drawer-example" | ||
aria-controls="drawer-example" | ||
> | ||
<svg width="24" height="24" aria-hidden="true"> | ||
<use xlink:href="/icons/svg/sprite.svg#close" /> | ||
</svg> | ||
<span class="accessibility-hidden">Close</span> | ||
</button> | ||
<!-- Drawer content goes here --> | ||
</div> | ||
</div> | ||
</dialog> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
@use '../../tools/typography'; | ||
@use '@tokens' as tokens; | ||
@use 'theme'; | ||
|
||
.Drawer { | ||
@include typography.generate(theme.$drawer-typography); | ||
|
||
--#{tokens.$css-variable-prefix}drawer-translate-x: 0%; | ||
|
||
all: unset; | ||
position: fixed; | ||
inset: 0; | ||
z-index: 1; | ||
display: flex; | ||
width: 100%; | ||
max-width: none; | ||
height: 100%; | ||
max-height: none; | ||
border: none; | ||
background-color: theme.$drawer-backdrop-background-color; | ||
visibility: hidden; | ||
|
||
&::backdrop { | ||
background-color: transparent; | ||
} | ||
|
||
@media (prefers-reduced-motion: no-preference) { | ||
transition-property: visibility, opacity; | ||
transition-duration: theme.$drawer-transition-duration; | ||
} | ||
} | ||
|
||
.Drawer--left { | ||
--#{tokens.$css-variable-prefix}drawer-translate-x: -100%; | ||
|
||
justify-content: start; | ||
} | ||
|
||
.Drawer--right { | ||
--#{tokens.$css-variable-prefix}drawer-translate-x: 100%; | ||
|
||
justify-content: end; | ||
} | ||
|
||
.Drawer[open] { | ||
--#{tokens.$css-variable-prefix}drawer-translate-x: 0%; | ||
|
||
visibility: visible; | ||
} |
11 changes: 11 additions & 0 deletions
11
packages/web/src/scss/components/Drawer/_DrawerCloseButton.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
@use '../../tools/accessibility'; | ||
@use '../../tools/reset'; | ||
@use 'theme'; | ||
|
||
.DrawerCloseButton { | ||
@include accessibility.min-tap-target(theme.$drawer-close-button-size); | ||
|
||
align-self: flex-end; | ||
margin-inline-end: theme.$drawer-close-button-padding-x; | ||
margin-block-start: theme.$drawer-close-button-padding-y; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
@use '@tokens' as tokens; | ||
@use 'theme'; | ||
|
||
.DrawerPanel { | ||
display: flex; | ||
flex-direction: column; | ||
box-sizing: border-box; | ||
width: var(--#{tokens.$css-variable-prefix}drawer-panel-width, #{theme.$drawer-panel-width}); | ||
height: theme.$drawer-panel-height; | ||
max-height: theme.$drawer-panel-max-height; | ||
color: theme.$drawer-panel-text-color; | ||
background-color: theme.$drawer-panel-background-color; | ||
box-shadow: theme.$drawer-panel-shadow; | ||
transform: translateX(var(--#{tokens.$css-variable-prefix}drawer-translate-x)); | ||
|
||
@media (prefers-reduced-motion: no-preference) { | ||
transition-property: transform; | ||
transition-duration: theme.$drawer-transition-duration; | ||
transition-timing-function: theme.$drawer-transition-timing; | ||
} | ||
} | ||
|
||
.DrawerPanel__content { | ||
display: flex; | ||
flex-grow: 1; | ||
flex-direction: column; | ||
overflow-y: auto; | ||
overscroll-behavior: contain; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
@use '@tokens' as tokens; | ||
@use '../../settings/transitions'; | ||
|
||
$drawer-typography: tokens.$body-medium-semibold; | ||
|
||
// Transition | ||
$drawer-transition-duration: transitions.$duration-200; | ||
$drawer-transition-timing: transitions.$timing-eased-in-out; | ||
$drawer-backdrop-background-color: tokens.$background-backdrop; | ||
|
||
// DrawerPanel | ||
$drawer-panel-width: 288px; | ||
$drawer-panel-height: auto; | ||
$drawer-panel-max-height: none; | ||
$drawer-panel-text-color: tokens.$text-primary; | ||
$drawer-panel-background-color: tokens.$background-primary; | ||
$drawer-panel-shadow: tokens.$shadow-400; | ||
|
||
// DrawerCloseButton | ||
$drawer-close-button-size: tokens.$space-1200; | ||
$drawer-close-button-padding-x: tokens.$space-900; | ||
$drawer-close-button-padding-y: tokens.$space-700; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
{{#> web/layout/default title="Drawer" parentPageName="Components" }} | ||
|
||
<script> | ||
document.addEventListener("DOMContentLoaded", () => { | ||
const radios = document.querySelectorAll('input[name="drawer-alignment"]'); | ||
const drawer = document.getElementById("drawer-example"); | ||
const backdropCheckbox = document.getElementById("drawer-is-closable-on-backdrop-click"); | ||
const escapeKeyCheckbox = document.getElementById("drawer-is-closable-on-escape-key"); | ||
const contentTextArea = document.getElementById("drawer-content"); | ||
const drawerContentDiv = drawer.querySelector("[data-drawer-demo-content]"); | ||
|
||
let isClosableOnBackdropClick = backdropCheckbox.checked; | ||
let isClosableOnEscapeKey = escapeKeyCheckbox.checked; | ||
|
||
radios.forEach(radio => { | ||
radio.addEventListener("change", () => { | ||
if (radio.checked) { | ||
if (radio.value === "left") { | ||
drawer.classList.replace("Drawer--right", "Drawer--left"); | ||
} else if (radio.value === "right") { | ||
drawer.classList.replace("Drawer--left", "Drawer--right"); | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
backdropCheckbox.addEventListener("change", () => { | ||
isClosableOnBackdropClick = backdropCheckbox.checked; | ||
}); | ||
|
||
escapeKeyCheckbox.addEventListener("change", () => { | ||
isClosableOnEscapeKey = escapeKeyCheckbox.checked; | ||
}); | ||
|
||
contentTextArea.addEventListener("input", () => { | ||
drawerContentDiv.textContent = contentTextArea.value; | ||
}); | ||
|
||
const closeDrawer = () => { | ||
drawer.close(); | ||
drawer.setAttribute("aria-expanded", "false"); | ||
}; | ||
|
||
const openDrawerButton = document.querySelector('button[data-testid="drawer-open-button"]'); | ||
openDrawerButton.addEventListener("click", () => { | ||
drawer.show(); | ||
drawer.setAttribute("aria-expanded", "true"); | ||
|
||
drawer.addEventListener("click", (event) => { | ||
if (isClosableOnBackdropClick && event.target === drawer) { | ||
closeDrawer(); | ||
} | ||
}); | ||
|
||
document.addEventListener("keydown", (event) => { | ||
if (isClosableOnEscapeKey && event.key === "Escape") { | ||
closeDrawer(); | ||
} | ||
}); | ||
}); | ||
|
||
const closeButton = drawer.querySelector(".DrawerCloseButton"); | ||
closeButton.addEventListener("click", closeDrawer); | ||
}); | ||
</script> | ||
|
||
|
||
<section class="UNSTABLE_Section"> | ||
|
||
<div class="Container"> | ||
<h2 class="docs-Heading">Drawer</h2> | ||
|
||
<div class="docs-Stack docs-Stack--start"> | ||
|
||
<form class="mb-600"> | ||
<fieldset class="border-0"> | ||
<legend>Drawer alignment:</legend> | ||
<label for="drawer-alignment-left" class="Radio mr-600"> | ||
<input name="drawer-alignment" autocomplete="off" aria-describedby="drawer-alignment-left__helperText" type="radio" id="drawer-alignment-left" class="Radio__input" value="left"> | ||
<span class="Radio__text"> | ||
<span class="Radio__label"> | ||
Left | ||
</span> | ||
</span> | ||
</label> | ||
<label for="drawer-alignment-right" class="Radio"> | ||
<input name="drawer-alignment" autocomplete="off" aria-describedby="drawer-alignment-right__helperText" type="radio" id="drawer-alignment-right" class="Radio__input" value="right" checked=""> | ||
<span class="Radio__text"> | ||
<span class="Radio__label"> | ||
Right | ||
</span> | ||
</span> | ||
</label> | ||
</fieldset> | ||
<fieldset class="border-0"> | ||
<div class="Stack Stack--hasSpacing"> | ||
<label class="Checkbox" for="drawer-is-closable-on-backdrop-click"> | ||
<input name="is-closable-on-backdrop-click" aria-describedby="drawer-is-closable-on-backdrop-click__helperText" type="checkbox" id="drawer-is-closable-on-backdrop-click" class="Checkbox__input" value="" checked=""> | ||
<span class="Checkbox__text"> | ||
<span class="Checkbox__label"> | ||
Closable on Backdrop Click | ||
</span> | ||
</span> | ||
</label> | ||
<label class="Checkbox" for="drawer-is-closable-on-escape-key"> | ||
<input name="is-closable-on-escape-key" aria-describedby="drawer-is-closable-on-escape-key__helperText" type="checkbox" id="drawer-is-closable-on-escape-key" class="Checkbox__input" value="" checked=""> | ||
<span class="Checkbox__text"> | ||
<span class="Checkbox__label"> | ||
Closable on Escape Key Down | ||
</span> | ||
</span> | ||
</label> | ||
<div class="TextArea"> | ||
<label for="drawer-content" class="TextArea__label">Drawer content</label> | ||
<textarea aria-describedby="drawer-content__helperText" name="content" class="TextArea__input" id="drawer-content">This is a Drawer content.</textarea> | ||
<div class="TextArea__helperText" id="drawer-content__helperText"> | ||
Can contain HTML. | ||
</div> | ||
</div> | ||
</div> | ||
</fieldset> | ||
</form> | ||
|
||
<button | ||
type="button" | ||
data-testid="drawer-open-button" | ||
class="Button Button--primary Button--medium" | ||
data-spirit-toggle="offcanvas" | ||
data-spirit-target="#drawer-example" | ||
aria-controls="drawer-example" | ||
aria-expanded="false" | ||
> | ||
Open Drawer | ||
</button> | ||
|
||
<!-- Drawer: start --> | ||
<dialog id="drawer-example" class="Drawer Drawer--right" aria-label="example-basic__title"> | ||
<div class="DrawerPanel" data-testid="drawer-panel"> | ||
<div class="DrawerPanel__content"> | ||
<button | ||
type="button" | ||
aria-expanded="false" | ||
class="Button Button--tertiary Button--medium Button--symmetrical DrawerCloseButton" | ||
data-spirit-dismiss="offcanvas" | ||
data-spirit-target="#drawer-example" | ||
aria-controls="drawer-example" | ||
> | ||
<svg width="24" height="24" aria-hidden="true"> | ||
<use xlink:href="/assets/icons/svg/sprite.svg#close" /> | ||
</svg> | ||
<span class="accessibility-hidden">Close</span> | ||
</button> | ||
<div class="p-800" data-drawer-demo-content>This is a Drawer content.</div> | ||
</div> | ||
</div> | ||
</dialog> | ||
<!-- Drawer: end --> | ||
|
||
</div> | ||
</div> | ||
</section> | ||
|
||
{{/web/layout/default }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
@forward 'Drawer'; | ||
@forward 'DrawerPanel'; | ||
@forward 'DrawerCloseButton'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.