mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-19 15:34:15 +00:00
Compare commits
6 Commits
kj/pattern
...
remove-slo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e9223953e | ||
|
|
cf9044d826 | ||
|
|
252d710175 | ||
|
|
58d14ed1d2 | ||
|
|
879e912a5c | ||
|
|
c69e98cd7f |
@@ -1,7 +1,7 @@
|
||||
import * as path from 'node:path';
|
||||
import * as url from 'node:url';
|
||||
import { defineConfig } from 'astro/config';
|
||||
import starlight from '@astrojs/starlight';
|
||||
import * as url from 'node:url';
|
||||
import * as path from 'node:path';
|
||||
// const __filename = url.fileURLToPath(import.meta.url);
|
||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
@@ -9,9 +9,9 @@ import FullReload from 'vite-plugin-full-reload';
|
||||
|
||||
import { customElementsManifest } from './src/js/cem.js';
|
||||
import { RemarkPluginFindAndReplace } from 'remark-plugin-find-and-replace';
|
||||
import GithubAutolink from './src/plugins/github-autolink.ts';
|
||||
import rehypeExternalLinks from 'rehype-external-links';
|
||||
import remarkCodeHighlighter from './src/plugins/prism';
|
||||
import GithubAutolink from './src/plugins/github-autolink.ts';
|
||||
|
||||
const version = customElementsManifest().package.version;
|
||||
const cdndir = 'cdn';
|
||||
@@ -126,7 +126,6 @@ export default defineConfig({
|
||||
label: 'Components',
|
||||
autogenerate: { directory: 'components' }
|
||||
},
|
||||
{ label: 'Patterns', autogenerate: { directory: 'patterns' } },
|
||||
{
|
||||
label: 'Design Tokens',
|
||||
autogenerate: { directory: 'tokens' }
|
||||
|
||||
@@ -328,7 +328,7 @@ wa-select[label="Signet"]::part(form-control-help-text) {
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<wa-dialog id="icon-chooser" label="Browse Icons">
|
||||
<wa-dialog id="icon-chooser" label="Browse Icons" with-header>
|
||||
<div style="display: grid; grid-template-rows: minmax(0, auto) minmax(0, 1fr); height: 100%; gap: 1rem;">
|
||||
<div style="display: flex; gap: 1.25rem;">
|
||||
<wa-input name="icon-search" placeholder="Search Icons" clearable style="flex: 1 1 auto;">
|
||||
|
||||
@@ -9,6 +9,15 @@ layout: ../../../layouts/ComponentLayout.astro
|
||||
<wa-icon slot="icon" name="circle-info" variant="regular"></wa-icon>
|
||||
This is a standard alert. You can customize its content and even the icon.
|
||||
</wa-alert>
|
||||
|
||||
<wa-alert open>
|
||||
<wa-icon slot="icon" name="circle-info" variant="regular"></wa-icon>
|
||||
<div style="border: solid 2px tomato; height: 2rem;"></div>
|
||||
</wa-alert>
|
||||
|
||||
<wa-alert open>
|
||||
<div style="border: solid 2px tomato; height: 2rem;"></div>
|
||||
</wa-alert>
|
||||
```
|
||||
|
||||
```jsx:react
|
||||
|
||||
@@ -5,7 +5,7 @@ layout: ../../../layouts/ComponentLayout.astro
|
||||
---
|
||||
|
||||
```html:preview
|
||||
<wa-card class="card-overview">
|
||||
<wa-card with-image with-footer class="card-overview">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
@@ -62,7 +62,7 @@ const css = `
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<WaCard className="card-overview">
|
||||
<WaCard with-image with-footer className="card-overview">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
@@ -129,7 +129,7 @@ const App = () => (
|
||||
Headers can be used to display titles and more.
|
||||
|
||||
```html:preview
|
||||
<wa-card class="card-header">
|
||||
<wa-card with-header class="card-header">
|
||||
<div slot="header">
|
||||
Header Title
|
||||
<wa-icon-button name="gear" variant="solid" label="Settings"></wa-icon-button>
|
||||
@@ -185,7 +185,7 @@ const css = `
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<WaCard className="card-header">
|
||||
<WaCard with-header className="card-header">
|
||||
<div slot="header">
|
||||
Header Title
|
||||
<WaIconButton name="gear" variant="solid"></WaIconButton>
|
||||
@@ -203,7 +203,7 @@ const App = () => (
|
||||
Footers can be used to display actions, summaries, or other relevant content.
|
||||
|
||||
```html:preview
|
||||
<wa-card class="card-footer">
|
||||
<wa-card with-footer class="card-footer">
|
||||
This card has a footer. You can put all sorts of things in it!
|
||||
|
||||
<div slot="footer">
|
||||
@@ -244,7 +244,7 @@ const css = `
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<WaCard className="card-footer">
|
||||
<WaCard with-footer className="card-footer">
|
||||
This card has a footer. You can put all sorts of things in it!
|
||||
<div slot="footer">
|
||||
<WaRating></WaRating>
|
||||
@@ -264,7 +264,7 @@ const App = () => (
|
||||
Cards accept an `image` slot. The image is displayed atop the card and stretches to fit.
|
||||
|
||||
```html:preview
|
||||
<wa-card class="card-image">
|
||||
<wa-card with-image class="card-image">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1547191783-94d5f8f6d8b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80"
|
||||
@@ -291,7 +291,7 @@ const css = `
|
||||
|
||||
const App = () => (
|
||||
<>
|
||||
<WaCard className="card-image">
|
||||
<WaCard with-image className="card-image">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1547191783-94d5f8f6d8b1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80"
|
||||
|
||||
@@ -7,7 +7,7 @@ layout: ../../../layouts/ComponentLayout.astro
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
|
||||
```html:preview
|
||||
<wa-dialog label="Dialog" class="dialog-overview">
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -34,7 +34,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDialog label="Dialog" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDialog label="Dialog" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -54,7 +54,7 @@ const App = () => {
|
||||
Use the `--width` custom property to set the dialog's width.
|
||||
|
||||
```html:preview
|
||||
<wa-dialog label="Dialog" class="dialog-width" style="--width: 50vw;">
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-width" style="--width: 50vw;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -81,7 +81,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDialog label="Dialog" open={open} style={{ '--width': '50vw' }} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDialog label="Dialog" with-header with-footer open={open} style={{ '--width': '50vw' }} onWaAfterHide={() => setOpen(false)}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -99,7 +99,7 @@ const App = () => {
|
||||
By design, a dialog's height will never exceed that of the viewport. As such, dialogs will not scroll with the page ensuring the header and footer are always accessible to the user.
|
||||
|
||||
```html:preview
|
||||
<wa-dialog label="Dialog" class="dialog-scrolling">
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-scrolling">
|
||||
<div style="height: 150vh; border: dashed 2px var(--wa-color-surface-border); padding: 0 1rem;">
|
||||
<p>Scroll down and give it a try! 👇</p>
|
||||
</div>
|
||||
@@ -128,7 +128,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDialog label="Dialog" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDialog label="Dialog" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<div
|
||||
style={{
|
||||
height: '150vh',
|
||||
@@ -155,7 +155,7 @@ const App = () => {
|
||||
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/components/icon-button) if needed.
|
||||
|
||||
```html:preview
|
||||
<wa-dialog label="Dialog" class="dialog-header-actions">
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-header-actions">
|
||||
<wa-icon-button class="new-window" slot="header-actions" name="arrow-up-right-from-square" variant="solid"></wa-icon-button>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
@@ -186,7 +186,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDialog label="Dialog" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDialog label="Dialog" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaIconButton
|
||||
class="new-window"
|
||||
slot="header-actions"
|
||||
@@ -214,7 +214,7 @@ To keep the dialog open in such cases, you can cancel the `wa-request-close` eve
|
||||
You can use `event.detail.source` to determine what triggered the request to close. This example prevents the dialog from closing when the overlay is clicked, but allows the close button or [[Escape]] to dismiss it.
|
||||
|
||||
```html:preview
|
||||
<wa-dialog label="Dialog" class="dialog-deny-close">
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-deny-close">
|
||||
This dialog will not close when you click on the overlay.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -255,7 +255,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDialog label="Dialog" open={open} onWaRequestClose={handleRequestClose} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDialog label="Dialog" with-header with-footer open={open} onWaRequestClose={handleRequestClose} onWaAfterHide={() => setOpen(false)}>
|
||||
This dialog will not close when you click on the overlay.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -273,7 +273,7 @@ const App = () => {
|
||||
By default, the dialog's panel will gain focus when opened. This allows a subsequent tab press to focus on the first tabbable element in the dialog. If you want a different element to have focus, add the `autofocus` attribute to it as shown below.
|
||||
|
||||
```html:preview
|
||||
<wa-dialog label="Dialog" class="dialog-focus">
|
||||
<wa-dialog label="Dialog" with-header with-footer class="dialog-focus">
|
||||
<wa-input autofocus placeholder="I will have focus when the dialog is opened"></wa-input>
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-dialog>
|
||||
@@ -302,7 +302,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDialog label="Dialog" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDialog label="Dialog" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaInput autofocus placeholder="I will have focus when the dialog is opened" />
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
|
||||
@@ -7,7 +7,7 @@ layout: ../../../layouts/ComponentLayout.astro
|
||||
<!-- cspell:dictionaries lorem-ipsum -->
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" class="drawer-overview">
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -34,7 +34,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDrawer label="Drawer" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -54,7 +54,7 @@ const App = () => {
|
||||
By default, drawers slide in from the end. To make the drawer slide in from the start, set the `placement` attribute to `start`.
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" placement="start" class="drawer-placement-start">
|
||||
<wa-drawer label="Drawer" placement="start" with-header with-footer class="drawer-placement-start">
|
||||
This drawer slides in from the start.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -81,7 +81,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" placement="start" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDrawer label="Drawer" placement="start" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
This drawer slides in from the start.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -99,7 +99,7 @@ const App = () => {
|
||||
To make the drawer slide in from the top, set the `placement` attribute to `top`.
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" placement="top" class="drawer-placement-top">
|
||||
<wa-drawer label="Drawer" placement="top" with-header with-footer class="drawer-placement-top">
|
||||
This drawer slides in from the top.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -126,7 +126,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" placement="top" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDrawer label="Drawer" placement="top" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
This drawer slides in from the top.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -144,7 +144,7 @@ const App = () => {
|
||||
To make the drawer slide in from the bottom, set the `placement` attribute to `bottom`.
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" placement="bottom" class="drawer-placement-bottom">
|
||||
<wa-drawer label="Drawer" placement="bottom" with-header with-footer class="drawer-placement-bottom">
|
||||
This drawer slides in from the bottom.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -171,7 +171,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" placement="bottom" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDrawer label="Drawer" placement="bottom" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
This drawer slides in from the bottom.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -184,84 +184,12 @@ const App = () => {
|
||||
};
|
||||
```
|
||||
|
||||
### Contained to an Element
|
||||
|
||||
By default, drawers slide out of their [containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#Identifying_the_containing_block), which is usually the viewport. To make a drawer slide out of a parent element, add the `contained` attribute to the drawer and apply `position: relative` to its parent.
|
||||
|
||||
Unlike normal drawers, contained drawers are not modal. This means they do not show an overlay, they do not trap focus, and they are not dismissible with [[Escape]]. This is intentional to allow users to interact with elements outside of the drawer.
|
||||
|
||||
```html:preview
|
||||
<div
|
||||
style="position: relative; border: solid 2px var(--wa-color-surface-border); height: 300px; padding: 1rem; margin-bottom: 1rem;"
|
||||
>
|
||||
The drawer will be contained to this box. This content won't shift or be affected in any way when the drawer opens.
|
||||
|
||||
<wa-drawer label="Drawer" contained class="drawer-contained" style="--size: 50%;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-drawer>
|
||||
</div>
|
||||
|
||||
<wa-button>Toggle Drawer</wa-button>
|
||||
|
||||
<script>
|
||||
const drawer = document.querySelector('.drawer-contained');
|
||||
const openButton = drawer.parentElement.nextElementSibling;
|
||||
const closeButton = drawer.querySelector('wa-button[variant="brand"]');
|
||||
|
||||
openButton.addEventListener('click', () => (drawer.open = !drawer.open));
|
||||
closeButton.addEventListener('click', () => drawer.hide());
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx:react
|
||||
import { useState } from 'react';
|
||||
import WaButton from '@shoelace-style/shoelace/dist/react/button';
|
||||
import WaDrawer from '@shoelace-style/shoelace/dist/react/drawer';
|
||||
|
||||
const App = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
border: 'solid 2px var(--wa-color-surface-border)',
|
||||
height: '300px',
|
||||
padding: '1rem',
|
||||
marginBottom: '1rem'
|
||||
}}
|
||||
>
|
||||
The drawer will be contained to this box. This content won't shift or be affected in any way when the drawer
|
||||
opens.
|
||||
<WaDrawer
|
||||
label="Drawer"
|
||||
contained
|
||||
no-modal
|
||||
open={open}
|
||||
onWaAfterHide={() => setOpen(false)}
|
||||
style={{ '--size': '50%' }}
|
||||
>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
</WaButton>
|
||||
</WaDrawer>
|
||||
</div>
|
||||
|
||||
<WaButton onClick={() => setOpen(true)}>Open Drawer</WaButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Size
|
||||
|
||||
Use the `--size` custom property to set the drawer's size. This will be applied to the drawer's width or height depending on its `placement`.
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" class="drawer-custom-size" style="--size: 50vw;">
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-custom-size" style="--size: 50vw;">
|
||||
This drawer is always 50% of the viewport.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -288,7 +216,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" open={open} onWaAfterHide={() => setOpen(false)} style={{ '--size': '50vw' }}>
|
||||
<WaDrawer label="Drawer" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)} style={{ '--size': '50vw' }}>
|
||||
This drawer is always 50% of the viewport.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
@@ -306,7 +234,7 @@ const App = () => {
|
||||
By design, a drawer's height will never exceed 100% of its container. As such, drawers will not scroll with the page to ensure the header and footer are always accessible to the user.
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" class="drawer-scrolling">
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-scrolling">
|
||||
<div style="height: 150vh; border: dashed 2px var(--wa-color-surface-border); padding: 0 1rem;">
|
||||
<p>Scroll down and give it a try! 👇</p>
|
||||
</div>
|
||||
@@ -335,7 +263,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDrawer label="Drawer" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<div
|
||||
style={{
|
||||
height: '150vh',
|
||||
@@ -361,7 +289,7 @@ const App = () => {
|
||||
The header shows a functional close button by default. You can use the `header-actions` slot to add additional [icon buttons](/components/icon-button) if needed.
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" class="drawer-header-actions">
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-header-actions">
|
||||
<wa-icon-button class="new-window" slot="header-actions" name="arrow-up-right-from-square" variant="solid"></wa-icon-button>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
@@ -392,7 +320,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDrawer label="Drawer" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaIconButton slot="header-actions" name="arrow-up-right-from-square" onClick={() => window.open(location.href)} />
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
@@ -415,7 +343,7 @@ To keep the drawer open in such cases, you can cancel the `wa-request-close` eve
|
||||
You can use `event.detail.source` to determine what triggered the request to close. This example prevents the drawer from closing when the overlay is clicked, but allows the close button or [[Escape]] to dismiss it.
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" class="drawer-deny-close">
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-deny-close">
|
||||
This drawer will not close when you click on the overlay.
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -456,7 +384,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" open={open} onWaRequestClose={handleRequestClose} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDrawer label="Drawer" with-header with-footer open={open} onWaRequestClose={handleRequestClose} onWaAfterHide={() => setOpen(false)}>
|
||||
This drawer will not close when you click on the overlay.
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Save & Close
|
||||
@@ -474,7 +402,7 @@ const App = () => {
|
||||
By default, the drawer's panel will gain focus when opened. This allows a subsequent tab press to focus on the first tabbable element in the drawer. If you want a different element to have focus, add the `autofocus` attribute to it as shown below.
|
||||
|
||||
```html:preview
|
||||
<wa-drawer label="Drawer" class="drawer-focus">
|
||||
<wa-drawer label="Drawer" with-header with-footer class="drawer-focus">
|
||||
<wa-input autofocus placeholder="I will have focus when the drawer is opened"></wa-input>
|
||||
<wa-button slot="footer" variant="brand">Close</wa-button>
|
||||
</wa-drawer>
|
||||
@@ -503,7 +431,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<WaDrawer label="Drawer" open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaDrawer label="Drawer" with-header with-footer open={open} onWaAfterHide={() => setOpen(false)}>
|
||||
<WaInput autofocus placeholder="I will have focus when the drawer is opened" />
|
||||
<WaButton slot="footer" variant="brand" onClick={() => setOpen(false)}>
|
||||
Close
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Patterns
|
||||
description: TODO
|
||||
---
|
||||
@@ -6,7 +6,7 @@ description: TODO
|
||||
## Card
|
||||
|
||||
```html:preview
|
||||
<wa-card class="card-overview">
|
||||
<wa-card with-image class="card-overview">
|
||||
<img
|
||||
slot="image"
|
||||
src="https://images.unsplash.com/photo-1559209172-0ff8f6d49ff7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80"
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: App
|
||||
description: TODO
|
||||
---
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Blog
|
||||
description: TODO
|
||||
---
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Business
|
||||
description: TODO
|
||||
---
|
||||
@@ -1,716 +0,0 @@
|
||||
---
|
||||
title: E-commerce
|
||||
description: TODO
|
||||
---
|
||||
|
||||
TODO Page Description
|
||||
|
||||
## Examples
|
||||
|
||||
### Slide Over
|
||||
|
||||
```html:preview
|
||||
<wa-card class="card-header" style="width: 500px;">
|
||||
<div slot="header">
|
||||
<strong>Shopping Cart</strong>
|
||||
<wa-icon-button name="close" variant="solid" label="Settings"></wa-icon-button>
|
||||
</div>
|
||||
<section class="cart-item">
|
||||
<img src="https://source.unsplash.com/white-and-red-nike-air-force-1-high--iJgjj33eEk" alt="" width="300">
|
||||
<div>
|
||||
<div style="display:flex; justify-content: space-between; font-weight: 600;">
|
||||
<span>AJ1</span>
|
||||
<span>$170.00</span>
|
||||
</div>
|
||||
<div style="font-size: small;">Off-white Jordan One</div>
|
||||
<div style="display:flex; justify-content: space-between; align-items: center;">
|
||||
<span>Qty: 1</span>
|
||||
<wa-button variant="text" size="small">Remove</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="cart-item">
|
||||
<img src="https://source.unsplash.com/smiling-woman-in-black-and-white-print-t-shirt-VW5VjskNXZ8" alt="" width="300">
|
||||
<div>
|
||||
<div style="display:flex; justify-content: space-between; font-weight: 600;">
|
||||
<span>The Trails</span>
|
||||
<span>$35.00</span>
|
||||
</div>
|
||||
<div style="font-size: small;">50/50 Cotton Poly Blend</div>
|
||||
<div style="display:flex; justify-content: space-between; align-items: center;">
|
||||
<span>Qty: 1</span>
|
||||
<wa-button variant="text" size="small">Remove</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="cart-item">
|
||||
<img src="https://source.unsplash.com/man-standing-in-front-of-door-dG4Eb_oC5iM" alt="" width="300">
|
||||
<div>
|
||||
<div style="display:flex; justify-content: space-between; font-weight: 600;">
|
||||
<span>Outcast</span>
|
||||
<span>$27.00</span>
|
||||
</div>
|
||||
<div style="font-size: small;">100% Cotton</div>
|
||||
<div style="display:flex; justify-content: space-between; align-items: center;">
|
||||
<span>Qty: 1</span>
|
||||
<wa-button variant="text" size="small">Remove</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div slot="footer">
|
||||
<div style="display:flex; justify-content: space-between; font-weight: 600;">
|
||||
<span>Subtotal</span>
|
||||
<span>$232.00</span>
|
||||
</div>
|
||||
<div style="font-size: small; margin-bottom: 1rem;">Shipping and taxes calculated at checkout.</div>
|
||||
<wa-button size="medium" variant="brand" style="width: 100%; margin-bottom: 1rem;">Medium</wa-button>
|
||||
or <a href="#">Continue shopping <wa-icon-button name="arrow-right" variant="solid" label="Settings"></wa-icon-button></a>
|
||||
</div>
|
||||
|
||||
</wa-card>
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
.card-header [slot='header'] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-header h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.card-header wa-icon-button {
|
||||
font-size: var(--wa-font-size-m);
|
||||
}
|
||||
|
||||
.cart-item {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
width: 6rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
div {
|
||||
flex-grow: 11;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
```
|
||||
|
||||
### Two Column Cart
|
||||
|
||||
```html:preview
|
||||
<div class="two-column">
|
||||
<h1>Shopping Cart</h1>
|
||||
<div class="first-column">
|
||||
<section class="cart-item">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/white-crew-neck-t-shirt-acn5ERAeSb4" alt="" width="300">
|
||||
<div class="cart-item-info">
|
||||
<div class="cart-item-meta">
|
||||
<div>
|
||||
<span style="font-size: larger">Classic</span>
|
||||
<div>White - L</div>
|
||||
<span style="font-size: larger">$15.00</span>
|
||||
</div>
|
||||
|
||||
<wa-select placeholder="1">
|
||||
<wa-option value="option-1">1</wa-option>
|
||||
<wa-option value="option-2">2</wa-option>
|
||||
<wa-option value="option-3">3</wa-option>
|
||||
</wa-select>
|
||||
<wa-icon-button name="close" variant="solid" label="Settings"></wa-icon-button>
|
||||
|
||||
</div>
|
||||
<div style="display: flex;justify-content: flex-start;align-items: baseline;">
|
||||
<wa-icon name="check" style="color: green; margin-right: 0.5rem;"></wa-icon> In Stock
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<section class="cart-item">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/blue-and-white-checkered-dress-shirt-RqYTuWkTdEs" alt="" width="300">
|
||||
<div class="cart-item-info">
|
||||
<div class="cart-item-meta">
|
||||
<div>
|
||||
<span style="font-size: larger">Button Up</span>
|
||||
<div>Blue - L</div>
|
||||
<span style="font-size: larger">$20.00</span>
|
||||
</div>
|
||||
|
||||
<wa-select placeholder="1">
|
||||
<wa-option value="option-1">1</wa-option>
|
||||
<wa-option value="option-2">2</wa-option>
|
||||
<wa-option value="option-3">3</wa-option>
|
||||
</wa-select>
|
||||
<wa-icon-button name="close" variant="solid" label="Settings"></wa-icon-button>
|
||||
|
||||
</div>
|
||||
<div style="display: flex;justify-content: flex-start;align-items: baseline;">
|
||||
<wa-icon name="check" style="color: green; margin-right: 0.5rem;"></wa-icon> In Stock
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<section class="cart-item">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/white-and-blue-cat-printed-crew-neck-t-shirt-fEt6Wd4t4j0" alt="" width="300">
|
||||
<div class="cart-item-info">
|
||||
<div class="cart-item-meta">
|
||||
<div>
|
||||
<span style="font-size: larger">Kitten</span>
|
||||
<div>Egg - L</div>
|
||||
<span style="font-size: larger">$20.00</span>
|
||||
</div>
|
||||
|
||||
<wa-select placeholder="1">
|
||||
<wa-option value="option-1">1</wa-option>
|
||||
<wa-option value="option-2">2</wa-option>
|
||||
<wa-option value="option-3">3</wa-option>
|
||||
</wa-select>
|
||||
<wa-icon-button name="close" variant="solid" label="Settings"></wa-icon-button>
|
||||
|
||||
</div>
|
||||
<div style="display: flex;justify-content: flex-start;align-items: baseline;">
|
||||
<wa-icon name="check" style="color: green; margin-right: 0.5rem;"></wa-icon> In Stock
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
<wa-card class="card-header second-column">
|
||||
<div slot="header">
|
||||
Order Summary
|
||||
|
||||
</div>
|
||||
<div style="display:flex; justify-content: space-between; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem;">
|
||||
<span>Subtotal</span>
|
||||
<span>$55.00</span>
|
||||
</div>
|
||||
<div style="display:flex; justify-content: space-between; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem;">
|
||||
<span>Shipping</span>
|
||||
<span>$5.00</span>
|
||||
</div>
|
||||
<div style="display:flex; justify-content: space-between; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem;">
|
||||
<span>Tax</span>
|
||||
<span>$5.50</span>
|
||||
</div>
|
||||
<div style="display:flex; justify-content: space-between; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem;">
|
||||
<span>Order Total</span>
|
||||
<span>$65.50</span>
|
||||
</div>
|
||||
|
||||
<wa-button size="medium" variant="brand" style="width: 100%; margin-bottom: 1rem;">Checkout</wa-button>
|
||||
|
||||
|
||||
|
||||
|
||||
</wa-card>
|
||||
|
||||
<style>
|
||||
.two-column {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
column-gap: 1rem;
|
||||
|
||||
.first-column {
|
||||
grid-column: 1/8;
|
||||
}
|
||||
|
||||
.second-column {
|
||||
grid-column: 8/14
|
||||
}
|
||||
|
||||
.cart-item {
|
||||
display: grid;
|
||||
grid-template-columns: 30% 61%;
|
||||
column-gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid rgb(48, 50, 59);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.cart-item-meta {
|
||||
display: grid;
|
||||
grid-template-columns: 45% 35% 20%;
|
||||
column-gap: 1rem;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
width: 100%;
|
||||
grid-column: 1 / end;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Single Column Cart
|
||||
|
||||
```html:preview
|
||||
<div class="single-column">
|
||||
<h1>Shopping Cart</h1>
|
||||
<div class="first-half half">
|
||||
<section class="cart-item">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/black-convertible-coupe-0CZwuZhiC84" alt="" >
|
||||
<div>
|
||||
<span style="display: flex;justify-content: space-between;">
|
||||
<span><strong>Convertible</strong></span>
|
||||
<span>$32.00</span>
|
||||
</span>
|
||||
<div>Eggplant</div>
|
||||
|
||||
<div style="display: flex;justify-content: space-between;align-items: baseline;">
|
||||
<span><wa-icon name="check" style="color: green; margin-right: 0.5rem;"></wa-icon> In Stock</span>
|
||||
<wa-button variant="text" size="small">Remove</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
<section class="cart-item">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/blue-open-door-pickup-truck-BCKgFzJbwz4" alt="" >
|
||||
<div>
|
||||
<span style="display: flex;justify-content: space-between;">
|
||||
<span><strong>Pickup</strong></span>
|
||||
<span>$32.00</span>
|
||||
</span>
|
||||
<div>Sky Blue</div>
|
||||
|
||||
<div style="display: flex;justify-content: space-between;align-items: baseline;">
|
||||
<span><wa-icon name="check" style="color: green; margin-right: 0.5rem;"></wa-icon> In Stock</span>
|
||||
<wa-button variant="text" size="small">Remove</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
<section class="cart-item">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/red-and-white-volkswagen-t-2-scale-model-GlDRYsruYJ8" alt="" >
|
||||
<div>
|
||||
<span style="display: flex;justify-content: space-between;">
|
||||
<span><strong>Volkswagon T2</strong></span>
|
||||
<span>$32.00</span>
|
||||
</span>
|
||||
<div>Red/White</div>
|
||||
|
||||
<div style="display: flex;justify-content: space-between;align-items: baseline;">
|
||||
<span><wa-icon name="check" style="color: green; margin-right: 0.5rem;"></wa-icon> In Stock</span>
|
||||
<wa-button variant="text" size="small">Remove</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
<div slot="footer">
|
||||
<div style="display:flex; justify-content: space-between; font-weight: 600;">
|
||||
<span>Subtotal</span>
|
||||
<span>$96.00</span>
|
||||
</div>
|
||||
<div style="font-size: small; margin-bottom: 1rem;">Shipping and taxes calculated at checkout.</div>
|
||||
<wa-button size="medium" variant="brand" style="width: 100%; margin-bottom: 1rem;">Medium</wa-button>
|
||||
or <a href="#">Continue shopping <wa-icon-button name="arrow-right" variant="solid" label="Settings"></wa-icon-button></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.single-column {
|
||||
.cart-item {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
column-gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid rgb(48, 50, 59);
|
||||
}
|
||||
|
||||
img {
|
||||
grid-column: 1/4;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
div {
|
||||
grid-column: 4/-1;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### Product Quickview
|
||||
|
||||
```html:preview
|
||||
<wa-card class="card-header">
|
||||
<div slot="header">
|
||||
<strong>Quickview</strong>
|
||||
<wa-icon-button name="close" variant="solid" label="Settings"></wa-icon-button>
|
||||
</div>
|
||||
<div style="
|
||||
display: grid;
|
||||
grid-template-columns: 35% 65%;
|
||||
grid-column-gap: 1rem;
|
||||
">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/white-crew-neck-t-shirt-acn5ERAeSb4" alt="" width="300">
|
||||
<div>
|
||||
<h3>Quality Cotton Tee</h3>
|
||||
<span>$45.00</span>
|
||||
<div style="display: flex;justify-content: space-between;">
|
||||
<wa-rating label="Rating" precision="0.5" value="2.5"></wa-rating>
|
||||
<a href="#">See all ratings</a>
|
||||
</div>
|
||||
<wa-radio-group label="Color" name="a" value="1" style="margin-bottom: 1rem">
|
||||
<wa-radio-button value="1">White</wa-radio-button>
|
||||
<wa-radio-button value="2">Gray</wa-radio-button>
|
||||
<wa-radio-button value="3">Black</wa-radio-button>
|
||||
</wa-radio-group>
|
||||
<wa-radio-group label="Size" name="a" value="1" style="margin-bottom: 1rem">
|
||||
<wa-radio-button value="1">Small</wa-radio-button>
|
||||
<wa-radio-button value="2">Medium</wa-radio-button>
|
||||
<wa-radio-button value="3">Large</wa-radio-button>
|
||||
</wa-radio-group>
|
||||
<wa-button size="medium" variant="brand" style="width: 100%; margin: 1rem 0;">Add to Cart</wa-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</wa-card>
|
||||
```
|
||||
|
||||
### Product Review
|
||||
|
||||
```html:preview
|
||||
<div>
|
||||
<div>
|
||||
<h2>Customer Reviews</h2>
|
||||
<div>
|
||||
<wa-rating label="Rating" precision="0.5" value="2.5"></wa-rating> Based on 1624 reviews
|
||||
</div>
|
||||
<div style="margin-bottom: 2rem;">
|
||||
<span><wa-progress-bar value="50"></wa-progress-bar></span>
|
||||
<h3>Share your Thoughts</h3>
|
||||
<p>If you’ve used this product, share your thoughts with other customers</p>
|
||||
<wa-button size="medium">Write a Review</wa-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 1rem;">
|
||||
<div>
|
||||
<div style="border-bottom: 1px solid #eee; margin-bottom: 1rem;">
|
||||
<span style="display: flex; align-items: center;">
|
||||
<wa-avatar image="https://source.unsplash.com/bman-wearing-henley-top-portrait-7YVZYZeITc8" label="man-wearing-henley" style="margin-right: 1rem;"></wa-avatar>
|
||||
<span style="display: flex; flex-direction: column">Mark Henry <wa-rating label="Rating" precision="0.5" value="2.5"></wa-rating></span>
|
||||
</span>
|
||||
<p><em>I initially had my doubts, but once I got the widgets and played around with them, I became a believer.</em></p>
|
||||
</div>
|
||||
<div style="border-bottom: 1px solid #eee; margin-bottom: 1rem;">
|
||||
<span style="display: flex; align-items: center;">
|
||||
<wa-avatar image="https://source.unsplash.com/woman-wearing-black-crew-neck-shirt-3TLl_97HNJo" label="lady-in-turtleneck" style="margin-right: 1rem;"></wa-avatar>
|
||||
<span style="display: flex; flex-direction: column">Liz Michaels <wa-rating label="Rating" precision="0.5" value="2.5"></wa-rating></span>
|
||||
</span>
|
||||
<p><em>I'd definitely but these again.</em></p>
|
||||
</div>
|
||||
<div style="border-bottom: 1px solid #eee; margin-bottom: 1rem;">
|
||||
<span style="display: flex; align-items: center;">
|
||||
<wa-avatar image="https://source.unsplash.com/man-with-index-finger-on-lips-RukI4qZGlQs" label="man-with-hair" style="margin-right: 1rem;"></wa-avatar>
|
||||
<span style="display: flex; flex-direction: column">Todd Smith <wa-rating label="Rating" precision="0.5" value="2.5"></wa-rating></span>
|
||||
</span>
|
||||
<p><em>It was everything I wanted and more, would totally recommend.</em></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Order History
|
||||
|
||||
```html:preview
|
||||
<div>
|
||||
<h2>Order History</h2>
|
||||
<p>Check the status of recent orders, manage returns, and download invoices.</p>
|
||||
<div class="order-history-meta">
|
||||
<span class="order-history-meta-item">
|
||||
<strong>Order number</strong>
|
||||
<span>WU88191111</span>
|
||||
</span>
|
||||
<span class="order-history-meta-item">
|
||||
<strong>Date placed</strong>
|
||||
<span>January 22, 2021</span>
|
||||
</span>
|
||||
<span class="order-history-meta-item">
|
||||
<strong>Total amount</strong>
|
||||
<span>$95.00</span>
|
||||
</span>
|
||||
<span style="display: grid;grid-template-columns: 1fr 1fr;column-gap: 1rem;">
|
||||
<wa-button variant="neutral" outline>View Order</wa-button>
|
||||
<wa-button variant="neutral" outline>View Invoice</wa-button>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="order-history-list-item" style="align-items: center;">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/beige-wooden-bar-stool-4kTbAMRAHtQ" alt="">
|
||||
<div>
|
||||
<span style="display: flex;justify-content: space-between;">
|
||||
<span><strong>Kitchen Stool</strong></span>
|
||||
<span><strong>$55.00</strong></span>
|
||||
</span>
|
||||
<p>TODO: add a description</p>
|
||||
<span>
|
||||
<a href="#">View Product</a> | <a href="#">Buy Again</a>
|
||||
</span>
|
||||
<br/>
|
||||
<span>Out for Delivery</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-history-list-item" style="margin-top: 1rem; align-items: center;">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/green-succulent-in-teal-ceramic-vase-miziNqvJx5M" alt="">
|
||||
<div>
|
||||
<span style="display: flex;justify-content: space-between;">
|
||||
<span><strong>Succulent</strong></span>
|
||||
<span><strong>$5.00</strong></span>
|
||||
</span>
|
||||
<p>TODO: add a description</p>
|
||||
<span>
|
||||
<a href="#">View Product</a> | <a href="#">Buy Again</a>
|
||||
</span>
|
||||
<br/>
|
||||
<span>Out for Delivery</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-history-list-item" style="margin-top: 1rem; align-items: center;">
|
||||
<img class="cart-item-image" src="https://source.unsplash.com/battercreek-coffee-pack-rsnzc-8dVs0" alt="">
|
||||
<div>
|
||||
<span style="display: flex;justify-content: space-between;">
|
||||
<span><strong>French Roast</strong></span>
|
||||
<span><strong>$35.00</strong></span>
|
||||
</span>
|
||||
<p>TODO: add a description</p>
|
||||
<span>
|
||||
<a href="#">View Product</a> | <a href="#">Buy Again</a>
|
||||
</span>
|
||||
<br/>
|
||||
<span>Out for Delivery</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.order-history-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1.5rem;
|
||||
|
||||
.order-history-meta-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.order-history-list-item {
|
||||
display: grid;
|
||||
grid-template-columns: 18% 79%;
|
||||
column-gap: 1rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### Checkout
|
||||
|
||||
```html:preview
|
||||
<div class="checkout-form">
|
||||
<div class="checkout-form-inputs">
|
||||
<h4 class="full-row" style="margin-top: 0.5rem;">Contact Info</h4>
|
||||
<wa-input type="email" label="Email Address" class="full-row"></wa-input>
|
||||
<hr class="full-row" />
|
||||
<h4 class="full-row" style="margin-top: 0.5rem;">Shipping Information</h4>
|
||||
<wa-input label="First Name" class="first-half"></wa-input>
|
||||
<wa-input label="Last Name" class="second-half" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-input label="Company" class="full-row" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-input label="Address" class="full-row" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-input label="City" class="first-half" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-select label="Country" placeholder="Country" class="second-half" style="margin-top: 1.5rem;">
|
||||
<wa-option value="option-1">Option 1</wa-option>
|
||||
<wa-option value="option-2">Option 2</wa-option>
|
||||
<wa-option value="option-3">Option 3</wa-option>
|
||||
</wa-select>
|
||||
<wa-input label="State" class="first-half" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-input label="Postal Code" class="second-half" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-input label="Phone" class=" full-row" style="margin-top: 1.5rem;"></wa-input>
|
||||
<hr class="full-row" />
|
||||
<wa-radio-group label="Delivery Method" help-text="Select an option that makes you proud." name="a" value="1" class="full-row" style="margin-top: 1.5rem;">
|
||||
<wa-radio-button value="1">Standard</wa-radio-button>
|
||||
<wa-radio-button value="2">Express</wa-radio-button>
|
||||
</wa-radio-group>
|
||||
<hr class="full-row" />
|
||||
<h4 class="full-row" style="margin-top: 0.5rem;">Payment</h4>
|
||||
<wa-radio-group label="Select an option" name="a" value="1" class="full-row" style="margin-top: 1.5rem;">
|
||||
<wa-radio value="1">Credit Card</wa-radio>
|
||||
<wa-radio value="3">Paypal</wa-radio>
|
||||
</wa-radio-group>
|
||||
<wa-input label="Card Number" class="full-row" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-input label="Name on Card" class="full-row" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-input label="Expiration Date" class="first-half" style="margin-top: 1.5rem;"></wa-input>
|
||||
<wa-input label="CVC" class="second-half" style="margin-top: 1.5rem;"></wa-input>
|
||||
</div>
|
||||
<div class="checkout-form-summary">
|
||||
<h4>Order Summary</h4>
|
||||
<wa-card class="card-basic">
|
||||
<div class="summary-item">
|
||||
<img src="https://source.unsplash.com/pair-of-white-and-orange-athletic-shoes-on-white-box-dwKiHoqqxk8">
|
||||
<div class="summary-item-info">
|
||||
<span style="display: flex; justify-content: space-between;">
|
||||
<span class="item-heading">Dolce Runners</span>
|
||||
<wa-icon-button name="trash" variant="solid" label="Settings"></wa-icon-button>
|
||||
</span>
|
||||
<span class="subtle">Cream/Seafoam</span>
|
||||
<br />
|
||||
<span class="subtle">12.5</span>
|
||||
<span style="display:flex;justify-content: space-between; width: 100%;margin: 1rem 0 2rem;">
|
||||
<span class="item-price">$0.00</span>
|
||||
<wa-select placeholder="1" style="width: 70px; margin-left: auto">
|
||||
<wa-option value="option-1">1</wa-option>
|
||||
<wa-option value="option-2">2</wa-option>
|
||||
<wa-option value="option-3">3</wa-option>
|
||||
</wa-select>
|
||||
</span>
|
||||
</div>
|
||||
<hr style="grid-column: 1 / -1;">
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<img src="https://source.unsplash.com/white-and-brown-nike-sneaker-LV_4qM5Gf9c">
|
||||
<div class="summary-item-info">
|
||||
<span style="display: flex; justify-content: space-between;">
|
||||
<span class="item-heading">Dunk High</span>
|
||||
<wa-icon-button name="trash" variant="solid" label="Settings"></wa-icon-button>
|
||||
</span>
|
||||
<span class="subtle">Sand/Amber/Black</span>
|
||||
<br />
|
||||
<span class="subtle">12.5</span>
|
||||
<span style="display:flex;justify-content: space-between; width: 100%;margin: 1rem 0 2rem;">
|
||||
<span class="item-price">$180.00</span>
|
||||
<wa-select placeholder="1" style="width: 70px; margin-left: auto">
|
||||
<wa-option value="option-1">1</wa-option>
|
||||
<wa-option value="option-2">2</wa-option>
|
||||
<wa-option value="option-3">3</wa-option>
|
||||
</wa-select>
|
||||
</span>
|
||||
</div>
|
||||
<hr style="grid-column: 1 / -1;">
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<img src="https://source.unsplash.com/black-and-white-new-balance-low-top-sneaker-6zO5VKogoZE">
|
||||
<div class="summary-item-info">
|
||||
<span style="display: flex; justify-content: space-between;">
|
||||
<span class="item-heading">NB Runner</span>
|
||||
<wa-icon-button name="trash" variant="solid" label="Settings"></wa-icon-button>
|
||||
</span>
|
||||
<span class="subtle">Forrest Green</span>
|
||||
<br />
|
||||
<span class="subtle">12.5</span>
|
||||
<span style="display:flex;justify-content: space-between; width: 100%;margin: 1rem 0 2rem;">
|
||||
<span class="item-price">$48.99</span>
|
||||
<wa-select placeholder="1" style="width: 70px; margin-left: auto">
|
||||
<wa-option value="option-1">1</wa-option>
|
||||
<wa-option value="option-2">2</wa-option>
|
||||
<wa-option value="option-3">3</wa-option>
|
||||
</wa-select>
|
||||
</span>
|
||||
</div>
|
||||
<hr style="grid-column: 1 / -1;">
|
||||
</div>
|
||||
<wa-button size="medium" variant="brand" style="width: 100%; margin-bottom: 1rem;">Confirm Order</wa-button>
|
||||
</wa-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.checkout-form {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-column-gap: 1rem;
|
||||
|
||||
.checkout-form-inputs {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
grid-column-gap: 1rem;
|
||||
}
|
||||
.summary-item {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
grid-column-gap: 1rem;
|
||||
|
||||
img {
|
||||
grid-column: 1/4;
|
||||
}
|
||||
|
||||
.summary-item-info {
|
||||
grid-column: 4/12;
|
||||
}
|
||||
}
|
||||
/* & hr {
|
||||
border-width: 1px;
|
||||
margin: 1rem 0;
|
||||
} */
|
||||
.subtle {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.item-heading {
|
||||
font-size: large:
|
||||
}
|
||||
|
||||
/* Grid utilities */
|
||||
|
||||
.full-row {
|
||||
grid-column: 1/-1
|
||||
}
|
||||
|
||||
.first-half {
|
||||
grid-column: 1/4
|
||||
}
|
||||
|
||||
.second-half {
|
||||
grid-column: 4/7
|
||||
}
|
||||
|
||||
.first-third {
|
||||
rid-column: 1/3
|
||||
}
|
||||
.second-third {
|
||||
rid-column: 3/5
|
||||
}
|
||||
.last-third {
|
||||
rid-column: 5/7
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Entertainment
|
||||
description: TODO
|
||||
---
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Membership
|
||||
description: TODO
|
||||
---
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: News
|
||||
description: TODO
|
||||
---
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Non-profit
|
||||
description: TODO
|
||||
---
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Portfolio
|
||||
description: TODO
|
||||
---
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Product Landing
|
||||
description: TODO
|
||||
---
|
||||
@@ -281,7 +281,7 @@ Internally, each component uses the [BEM methodology](http://getbem.com/) for cl
|
||||
|
||||
### Boolean Props
|
||||
|
||||
Boolean props should _always_ default to `false`, otherwise there's no way for the user to unset them using only attributes. To keep the API as friendly and consistent as possible, use a property such as `noHeader` and a corresponding kebab-case attribute such as `no-header`.
|
||||
Boolean props should _always_ default to `false`, otherwise there's no way for the user to unset them using only attributes. To keep the API as friendly and consistent as possible, use a property such as `noValue` and a corresponding kebab-case attribute such as `no-value`.
|
||||
|
||||
When naming boolean props that hide or disable things, prefix them with `no-`, e.g. `no-spin-buttons` and avoid using other verbs such as `hide-` and `disable-` for consistency.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
fun.
|
||||
</p>
|
||||
|
||||
<wa-dialog id="dialog"> I'm just a lowly dialog. </wa-dialog>
|
||||
<wa-dialog id="dialog" label="Dialog" with-header> I'm just a lowly dialog. </wa-dialog>
|
||||
|
||||
<wa-button>Open Dialog</wa-button>
|
||||
</wa-page>
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
text-align: center;
|
||||
"
|
||||
>
|
||||
<wa-card class="wa-card--muted" style="--padding: 8px">
|
||||
<wa-card with-header class="wa-card--muted" style="--padding: 8px">
|
||||
<h3 slot="header">Total listening time</h3>
|
||||
|
||||
<p>
|
||||
@@ -146,7 +146,7 @@
|
||||
</p>
|
||||
</wa-card>
|
||||
|
||||
<wa-card class="wa-card--muted" style="--padding: 8px">
|
||||
<wa-card with-header class="wa-card--muted" style="--padding: 8px">
|
||||
<h3 slot="header">Total songs played</h3>
|
||||
|
||||
<p>
|
||||
@@ -160,7 +160,7 @@
|
||||
</p>
|
||||
</wa-card>
|
||||
|
||||
<wa-card class="wa-card--muted" style="--padding: 8px">
|
||||
<wa-card with-header class="wa-card--muted" style="--padding: 8px">
|
||||
<h3 slot="header">Average listening session</h3>
|
||||
|
||||
<p>
|
||||
@@ -174,7 +174,7 @@
|
||||
</p>
|
||||
</wa-card>
|
||||
|
||||
<wa-card class="wa-card--muted" style="--padding: 8px">
|
||||
<wa-card with-header class="wa-card--muted" style="--padding: 8px">
|
||||
<h3 slot="header">Average track listening time</h3>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { animateTo, stopAnimations } from '../../internal/animate.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { getAnimation, setDefaultAnimation } from '../../utilities/animation-registry.js';
|
||||
import { HasSlotController } from '../../internal/slot.js';
|
||||
import { html } from 'lit';
|
||||
import { LocalizeController } from '../../utilities/localize.js';
|
||||
import { property, query } from 'lit/decorators.js';
|
||||
@@ -55,7 +54,6 @@ export default class WaAlert extends WebAwesomeElement {
|
||||
static dependencies = { 'wa-icon-button': WaIconButton };
|
||||
|
||||
private autoHideTimeout: number;
|
||||
private readonly hasSlotController = new HasSlotController(this, 'icon', 'suffix');
|
||||
private readonly localize = new LocalizeController(this);
|
||||
|
||||
@query('[part~="base"]') base: HTMLElement;
|
||||
@@ -198,7 +196,6 @@ export default class WaAlert extends WebAwesomeElement {
|
||||
alert: true,
|
||||
'alert--open': this.open,
|
||||
'alert--closable': this.closable,
|
||||
'alert--has-icon': this.hasSlotController.test('icon'),
|
||||
'alert--brand': this.variant === 'brand',
|
||||
'alert--success': this.variant === 'success',
|
||||
'alert--neutral': this.variant === 'neutral',
|
||||
|
||||
@@ -56,10 +56,10 @@ export default css`
|
||||
border-width: var(--border-width);
|
||||
color: var(--content-color);
|
||||
font: inherit;
|
||||
padding: var(--padding);
|
||||
margin: inherit;
|
||||
}
|
||||
|
||||
.alert:not(.alert--has-icon) .alert__icon,
|
||||
.alert:not(.alert--closable) .alert__close-button {
|
||||
display: none;
|
||||
}
|
||||
@@ -70,13 +70,15 @@ export default css`
|
||||
align-items: center;
|
||||
color: var(--icon-color);
|
||||
font-size: var(--icon-size);
|
||||
padding-inline-start: var(--padding);
|
||||
}
|
||||
|
||||
.alert__icon ::slotted(*) {
|
||||
margin-inline-end: var(--padding) !important;
|
||||
}
|
||||
|
||||
.alert__message {
|
||||
flex: 1 1 auto;
|
||||
display: block;
|
||||
padding: var(--padding);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ export default css`
|
||||
align-items: center;
|
||||
color: currentColor;
|
||||
font-size: var(--wa-font-size-m);
|
||||
padding-inline-end: var(--padding);
|
||||
padding-inline-start: var(--padding);
|
||||
}
|
||||
|
||||
.alert__close-button:hover::part(base) {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { HasSlotController } from '../../internal/slot.js';
|
||||
import { html } from 'lit';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { property } from 'lit/decorators.js';
|
||||
@@ -29,8 +27,6 @@ import type { CSSResultGroup } from 'lit';
|
||||
export default class WaBreadcrumbItem extends WebAwesomeElement {
|
||||
static styles: CSSResultGroup = [componentStyles, styles];
|
||||
|
||||
private readonly hasSlotController = new HasSlotController(this, 'prefix', 'suffix');
|
||||
|
||||
/**
|
||||
* Optional URL to direct the user to when the breadcrumb item is activated. When set, a link will be rendered
|
||||
* internally. When unset, a button will be rendered instead.
|
||||
@@ -47,14 +43,7 @@ export default class WaBreadcrumbItem extends WebAwesomeElement {
|
||||
const isLink = this.href ? true : false;
|
||||
|
||||
return html`
|
||||
<div
|
||||
part="base"
|
||||
class=${classMap({
|
||||
'breadcrumb-item': true,
|
||||
'breadcrumb-item--has-prefix': this.hasSlotController.test('prefix'),
|
||||
'breadcrumb-item--has-suffix': this.hasSlotController.test('suffix')
|
||||
})}
|
||||
>
|
||||
<div part="base" class="breadcrumb-item">
|
||||
<span part="prefix" class="breadcrumb-item__prefix">
|
||||
<slot name="prefix"></slot>
|
||||
</span>
|
||||
|
||||
@@ -58,14 +58,13 @@ export default css`
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.breadcrumb-item--has-prefix .breadcrumb-item__prefix {
|
||||
.breadcrumb-item__prefix,
|
||||
.breadcrumb-item__suffix {
|
||||
display: inline-flex;
|
||||
margin-inline-end: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.breadcrumb-item--has-suffix .breadcrumb-item__suffix {
|
||||
display: inline-flex;
|
||||
margin-inline-start: var(--wa-space-s);
|
||||
::slotted(*) {
|
||||
margin-inline-end: var(--wa-space-s) !important;
|
||||
}
|
||||
}
|
||||
|
||||
:host(:last-of-type) .breadcrumb-item__separator {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { FormControlController, validValidityState } from '../../internal/form.js';
|
||||
import { HasSlotController } from '../../internal/slot.js';
|
||||
import { html, literal } from 'lit/static-html.js';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { LocalizeController } from '../../utilities/localize.js';
|
||||
@@ -63,7 +62,6 @@ export default class WaButton extends WebAwesomeElement implements WebAwesomeFor
|
||||
private readonly formControlController = new FormControlController(this, {
|
||||
assumeInteractionOn: ['click']
|
||||
});
|
||||
private readonly hasSlotController = new HasSlotController(this, '[default]', 'prefix', 'suffix');
|
||||
private readonly localize = new LocalizeController(this);
|
||||
|
||||
@query('.button') button: HTMLButtonElement | HTMLLinkElement;
|
||||
@@ -288,10 +286,7 @@ export default class WaButton extends WebAwesomeElement implements WebAwesomeFor
|
||||
'button--standard': !this.outline,
|
||||
'button--outline': this.outline,
|
||||
'button--pill': this.pill,
|
||||
'button--rtl': this.localize.dir() === 'rtl',
|
||||
'button--has-label': this.hasSlotController.test('[default]'),
|
||||
'button--has-prefix': this.hasSlotController.test('prefix'),
|
||||
'button--has-suffix': this.hasSlotController.test('suffix')
|
||||
'button--rtl': this.localize.dir() === 'rtl'
|
||||
})}
|
||||
?disabled=${ifDefined(isLink ? undefined : this.disabled)}
|
||||
type=${ifDefined(isLink ? undefined : this.type)}
|
||||
|
||||
@@ -213,13 +213,13 @@ export default css`
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.button:hover:not(.button--disabled) {
|
||||
.button:hover:not(.button--disabled, .button--loading) {
|
||||
background: var(--background-hover, var(--background, none));
|
||||
border-color: var(--border-color-hover, var(--border-color, transparent));
|
||||
color: var(--label-color-hover, var(--label-color));
|
||||
}
|
||||
|
||||
.button:active:not(.button--disabled) {
|
||||
.button:active:not(.button--disabled, .button--loading) {
|
||||
background: var(--background-active, var(--background, none));
|
||||
border-color: var(--border-color-active, var(--border-color, transparent));
|
||||
color: var(--label-color-active, var(--label-color));
|
||||
@@ -300,6 +300,21 @@ export default css`
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button--small .button__caret {
|
||||
margin-inline-start: calc(-0.5 * var(--wa-space-xs));
|
||||
margin-inline-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.button--medium .button__caret {
|
||||
margin-inline-start: calc(-0.5 * var(--wa-space-s));
|
||||
margin-inline-end: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.button--large .button__caret {
|
||||
margin-inline-start: calc(-0.5 * var(--wa-space-m));
|
||||
margin-inline-end: var(--wa-space-m);
|
||||
}
|
||||
|
||||
.button--caret .button__caret::part(svg) {
|
||||
width: 0.875em;
|
||||
height: 0.875em;
|
||||
@@ -354,70 +369,46 @@ export default css`
|
||||
* Button spacing
|
||||
*/
|
||||
|
||||
.button--has-label.button--small .button__label {
|
||||
padding: 0 var(--wa-space-s);
|
||||
.button--small {
|
||||
::slotted([slot='prefix']) {
|
||||
margin-inline-start: var(--wa-space-xs) !important;
|
||||
}
|
||||
|
||||
::slotted([slot='suffix']) {
|
||||
margin-inline-end: var(--wa-space-xs) !important;
|
||||
}
|
||||
|
||||
.button__label {
|
||||
padding: 0 var(--wa-space-s);
|
||||
}
|
||||
}
|
||||
|
||||
.button--has-label.button--medium .button__label {
|
||||
padding: 0 var(--wa-space-m);
|
||||
.button--medium {
|
||||
::slotted([slot='prefix']) {
|
||||
margin-inline-start: var(--wa-space-s) !important;
|
||||
}
|
||||
|
||||
::slotted([slot='suffix']) {
|
||||
margin-inline-end: var(--wa-space-s) !important;
|
||||
}
|
||||
|
||||
.button__label {
|
||||
padding: 0 var(--wa-space-m);
|
||||
}
|
||||
}
|
||||
|
||||
.button--has-label.button--large .button__label {
|
||||
padding: 0 var(--wa-space-l);
|
||||
}
|
||||
.button--large {
|
||||
::slotted([slot='prefix']) {
|
||||
margin-inline-start: var(--wa-space-m) !important;
|
||||
}
|
||||
|
||||
.button--has-prefix.button--small {
|
||||
padding-inline-start: var(--wa-space-xs);
|
||||
}
|
||||
::slotted([slot='suffix']) {
|
||||
margin-inline-end: var(--wa-space-m) !important;
|
||||
}
|
||||
|
||||
.button--has-prefix.button--small .button__label {
|
||||
padding-inline-start: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.button--has-prefix.button--medium {
|
||||
padding-inline-start: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.button--has-prefix.button--medium .button__label {
|
||||
padding-inline-start: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.button--has-prefix.button--large {
|
||||
padding-inline-start: var(--wa-space-m);
|
||||
}
|
||||
|
||||
.button--has-prefix.button--large .button__label {
|
||||
padding-inline-start: var(--wa-space-m);
|
||||
}
|
||||
|
||||
.button--has-suffix.button--small,
|
||||
.button--caret.button--small {
|
||||
padding-inline-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.button--has-suffix.button--small .button__label,
|
||||
.button--caret.button--small .button__label {
|
||||
padding-inline-end: var(--wa-space-xs);
|
||||
}
|
||||
|
||||
.button--has-suffix.button--medium,
|
||||
.button--caret.button--medium {
|
||||
padding-inline-end: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.button--has-suffix.button--medium .button__label,
|
||||
.button--caret.button--medium .button__label {
|
||||
padding-inline-end: var(--wa-space-s);
|
||||
}
|
||||
|
||||
.button--has-suffix.button--large,
|
||||
.button--caret.button--large {
|
||||
padding-inline-end: var(--wa-space-m);
|
||||
}
|
||||
|
||||
.button--has-suffix.button--large .button__label,
|
||||
.button--caret.button--large .button__label {
|
||||
padding-inline-end: var(--wa-space-m);
|
||||
.button__label {
|
||||
padding: 0 var(--wa-space-l);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { HasSlotController } from '../../internal/slot.js';
|
||||
import { html } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import componentStyles from '../../styles/component.styles.js';
|
||||
import styles from './card.styles.js';
|
||||
import WebAwesomeElement from '../../internal/webawesome-element.js';
|
||||
@@ -34,7 +34,14 @@ import type { CSSResultGroup } from 'lit';
|
||||
export default class WaCard extends WebAwesomeElement {
|
||||
static styles: CSSResultGroup = [componentStyles, styles];
|
||||
|
||||
private readonly hasSlotController = new HasSlotController(this, 'footer', 'header', 'image');
|
||||
/** Renders the card with a header */
|
||||
@property({ attribute: 'with-header', type: Boolean }) withHeader = false;
|
||||
|
||||
/** Renders the card with an image */
|
||||
@property({ attribute: 'with-image', type: Boolean }) withImage = false;
|
||||
|
||||
/** Renders the card with a footer */
|
||||
@property({ attribute: 'with-footer', type: Boolean }) withFooter = false;
|
||||
|
||||
render() {
|
||||
return html`
|
||||
@@ -42,9 +49,9 @@ export default class WaCard extends WebAwesomeElement {
|
||||
part="base"
|
||||
class=${classMap({
|
||||
card: true,
|
||||
'card--has-footer': this.hasSlotController.test('footer'),
|
||||
'card--has-image': this.hasSlotController.test('image'),
|
||||
'card--has-header': this.hasSlotController.test('header')
|
||||
'card--has-footer': this.withFooter,
|
||||
'card--has-image': this.withImage,
|
||||
'card--has-header': this.withHeader
|
||||
})}
|
||||
>
|
||||
<slot name="image" part="image" class="card__image"></slot>
|
||||
|
||||
@@ -37,6 +37,8 @@ export default css`
|
||||
.card__image::slotted(img) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||
|
||||
.card:not(.card--has-image) .card__image {
|
||||
|
||||
@@ -29,7 +29,7 @@ describe('<wa-card>', () => {
|
||||
describe('when provided an element in the slot "header" to render a header', () => {
|
||||
before(async () => {
|
||||
el = await fixture<WaCard>(
|
||||
html`<wa-card>
|
||||
html`<wa-card with-header>
|
||||
<div slot="header">Header Title</div>
|
||||
This card has a header. You can put all sorts of things in it!
|
||||
</wa-card>`
|
||||
@@ -65,7 +65,7 @@ describe('<wa-card>', () => {
|
||||
describe('when provided an element in the slot "footer" to render a footer', () => {
|
||||
before(async () => {
|
||||
el = await fixture<WaCard>(
|
||||
html`<wa-card>
|
||||
html`<wa-card with-footer>
|
||||
This card has a footer. You can put all sorts of things in it!
|
||||
|
||||
<div slot="footer">Footer Content</div>
|
||||
@@ -102,7 +102,7 @@ describe('<wa-card>', () => {
|
||||
describe('when provided an element in the slot "image" to render a image', () => {
|
||||
before(async () => {
|
||||
el = await fixture<WaCard>(
|
||||
html`<wa-card>
|
||||
html`<wa-card with-image>
|
||||
<img
|
||||
slot="image"
|
||||
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { animateTo, stopAnimations } from '../../internal/animate.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { getAnimation, setDefaultAnimation } from '../../utilities/animation-registry.js';
|
||||
import { HasSlotController } from '../../internal/slot.js';
|
||||
import { html } from 'lit';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { LocalizeController } from '../../utilities/localize.js';
|
||||
@@ -71,7 +70,6 @@ export default class WaDialog extends WebAwesomeElement {
|
||||
'wa-icon-button': WaIconButton
|
||||
};
|
||||
|
||||
private readonly hasSlotController = new HasSlotController(this, 'footer');
|
||||
private readonly localize = new LocalizeController(this);
|
||||
private originalTrigger: HTMLElement | null;
|
||||
public modal = new Modal(this);
|
||||
@@ -88,16 +86,16 @@ export default class WaDialog extends WebAwesomeElement {
|
||||
@property({ type: Boolean, reflect: true }) open = false;
|
||||
|
||||
/**
|
||||
* The dialog's label as displayed in the header. You should always include a relevant label even when using
|
||||
* `no-header`, as it is required for proper accessibility. If you need to display HTML, use the `label` slot instead.
|
||||
* The dialog's label as displayed in the header. You should always include a relevant label, as it is required for
|
||||
* proper accessibility. If you need to display HTML, use the `label` slot instead.
|
||||
*/
|
||||
@property({ reflect: true }) label = '';
|
||||
|
||||
/**
|
||||
* Disables the header. This will also remove the default close button, so please ensure you provide an easy,
|
||||
* accessible way for users to dismiss the dialog.
|
||||
*/
|
||||
@property({ attribute: 'no-header', type: Boolean, reflect: true }) noHeader = false;
|
||||
/** Renders the dialog with a header. */
|
||||
@property({ attribute: 'with-header', type: Boolean, reflect: true }) withHeader = false;
|
||||
|
||||
/** Renders the dialog with a footer. */
|
||||
@property({ attribute: 'with-footer', type: Boolean, reflect: true }) withFooter = false;
|
||||
|
||||
firstUpdated() {
|
||||
this.dialog.hidden = !this.open;
|
||||
@@ -272,7 +270,8 @@ export default class WaDialog extends WebAwesomeElement {
|
||||
class=${classMap({
|
||||
dialog: true,
|
||||
'dialog--open': this.open,
|
||||
'dialog--has-footer': this.hasSlotController.test('footer')
|
||||
'dialog--with-header': this.withHeader,
|
||||
'dialog--with-footer': this.withFooter
|
||||
})}
|
||||
>
|
||||
<div part="overlay" class="dialog__overlay" @click=${() => this.requestClose('overlay')} tabindex="-1"></div>
|
||||
@@ -283,11 +282,11 @@ export default class WaDialog extends WebAwesomeElement {
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-hidden=${this.open ? 'false' : 'true'}
|
||||
aria-label=${ifDefined(this.noHeader ? this.label : undefined)}
|
||||
aria-labelledby=${ifDefined(!this.noHeader ? 'title' : undefined)}
|
||||
aria-label=${ifDefined(this.withHeader ? undefined : this.label)}
|
||||
aria-labelledby=${ifDefined(this.withHeader ? 'title' : undefined)}
|
||||
tabindex="-1"
|
||||
>
|
||||
${!this.noHeader
|
||||
${this.withHeader
|
||||
? html`
|
||||
<header part="header" class="dialog__header">
|
||||
<h2 part="title" class="dialog__title" id="title">
|
||||
@@ -314,9 +313,13 @@ export default class WaDialog extends WebAwesomeElement {
|
||||
}
|
||||
<div part="body" class="dialog__body" tabindex="-1"><slot></slot></div>
|
||||
|
||||
<footer part="footer" class="dialog__footer">
|
||||
<slot name="footer"></slot>
|
||||
</footer>
|
||||
${this.withFooter
|
||||
? html`
|
||||
<footer part="footer" class="dialog__footer">
|
||||
<slot name="footer"></slot>
|
||||
</footer>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -99,10 +99,6 @@ export default css`
|
||||
margin-inline-start: var(--wa-spacing-xs);
|
||||
}
|
||||
|
||||
.dialog:not(.dialog--has-footer) .dialog__footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dialog__overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
||||
@@ -6,10 +6,10 @@ import { sendKeys } from '@web/test-runner-commands';
|
||||
import sinon from 'sinon';
|
||||
import type WaDialog from './dialog.js';
|
||||
|
||||
describe('<wa-dialog>', () => {
|
||||
describe('<wa-dialog with-header>', () => {
|
||||
it('should be visible with the open attribute', async () => {
|
||||
const el = await fixture<WaDialog>(html`
|
||||
<wa-dialog open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
<wa-dialog with-header open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
`);
|
||||
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('<wa-dialog>', () => {
|
||||
|
||||
it('should not be visible without the open attribute', async () => {
|
||||
const el = await fixture<WaDialog>(html`
|
||||
<wa-dialog>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
<wa-dialog with-header>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
`);
|
||||
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('<wa-dialog>', () => {
|
||||
|
||||
it('should emit wa-show and wa-after-show when calling show()', async () => {
|
||||
const el = await fixture<WaDialog>(html`
|
||||
<wa-dialog>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
<wa-dialog with-header>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
`);
|
||||
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
|
||||
const showHandler = sinon.spy();
|
||||
@@ -47,7 +47,7 @@ describe('<wa-dialog>', () => {
|
||||
|
||||
it('should emit wa-hide and wa-after-hide when calling hide()', async () => {
|
||||
const el = await fixture<WaDialog>(html`
|
||||
<wa-dialog open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
<wa-dialog with-header open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
`);
|
||||
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
|
||||
const hideHandler = sinon.spy();
|
||||
@@ -67,7 +67,7 @@ describe('<wa-dialog>', () => {
|
||||
|
||||
it('should emit wa-show and wa-after-show when setting open = true', async () => {
|
||||
const el = await fixture<WaDialog>(html`
|
||||
<wa-dialog>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
<wa-dialog with-header>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
`);
|
||||
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
|
||||
const showHandler = sinon.spy();
|
||||
@@ -87,7 +87,7 @@ describe('<wa-dialog>', () => {
|
||||
|
||||
it('should emit wa-hide and wa-after-hide when setting open = false', async () => {
|
||||
const el = await fixture<WaDialog>(html`
|
||||
<wa-dialog open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
<wa-dialog with-header open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
`);
|
||||
const base = el.shadowRoot!.querySelector<HTMLElement>('[part~="base"]')!;
|
||||
const hideHandler = sinon.spy();
|
||||
@@ -107,7 +107,7 @@ describe('<wa-dialog>', () => {
|
||||
|
||||
it('should not close when wa-request-close is prevented', async () => {
|
||||
const el = await fixture<WaDialog>(html`
|
||||
<wa-dialog open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
<wa-dialog with-header open>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</wa-dialog>
|
||||
`);
|
||||
const overlay = el.shadowRoot!.querySelector<HTMLElement>('[part~="overlay"]')!;
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('<wa-dialog>', () => {
|
||||
});
|
||||
|
||||
it('should allow initial focus to be set', async () => {
|
||||
const el = await fixture<WaDialog>(html` <wa-dialog><input /></wa-dialog> `);
|
||||
const el = await fixture<WaDialog>(html` <wa-dialog with-header><input /></wa-dialog> `);
|
||||
const input = el.querySelector('input')!;
|
||||
const initialFocusHandler = sinon.spy((event: Event) => {
|
||||
event.preventDefault();
|
||||
@@ -137,7 +137,7 @@ describe('<wa-dialog>', () => {
|
||||
});
|
||||
|
||||
it('should close when pressing Escape', async () => {
|
||||
const el = await fixture<WaDialog>(html` <wa-dialog open></wa-dialog> `);
|
||||
const el = await fixture<WaDialog>(html` <wa-dialog with-header open></wa-dialog> `);
|
||||
const hideHandler = sinon.spy();
|
||||
|
||||
el.addEventListener('wa-hide', hideHandler);
|
||||
@@ -162,7 +162,7 @@ describe('<wa-dialog>', () => {
|
||||
render() {
|
||||
return html`
|
||||
<h1>Dialog Example</h1>
|
||||
<wa-dialog label="Dialog" class="dialog-overview">
|
||||
<wa-dialog with-header label="Dialog" class="dialog-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<br />
|
||||
<label><input type="checkbox" />A</label>
|
||||
@@ -200,7 +200,7 @@ describe('<wa-dialog>', () => {
|
||||
const dialog = container.shadowRoot?.querySelector('wa-dialog');
|
||||
|
||||
if (!dialog) {
|
||||
throw Error('Could not find <wa-dialog> element.');
|
||||
throw Error('Could not find <wa-dialog with-header> element.');
|
||||
}
|
||||
|
||||
const closeButton = dialog.shadowRoot?.querySelector('wa-icon-button');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { animateTo, stopAnimations } from '../../internal/animate.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { getAnimation, setDefaultAnimation } from '../../utilities/animation-registry.js';
|
||||
import { HasSlotController } from '../../internal/slot.js';
|
||||
import { html } from 'lit';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { LocalizeController } from '../../utilities/localize.js';
|
||||
@@ -78,7 +77,6 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
static styles: CSSResultGroup = [componentStyles, styles];
|
||||
static dependencies = { 'wa-icon-button': WaIconButton };
|
||||
|
||||
private readonly hasSlotController = new HasSlotController(this, 'footer');
|
||||
private readonly localize = new LocalizeController(this);
|
||||
private originalTrigger: HTMLElement | null;
|
||||
public modal = new Modal(this);
|
||||
@@ -95,36 +93,27 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
@property({ type: Boolean, reflect: true }) open = false;
|
||||
|
||||
/**
|
||||
* The drawer's label as displayed in the header. You should always include a relevant label even when using
|
||||
* `no-header`, as it is required for proper accessibility. If you need to display HTML, use the `label` slot instead.
|
||||
* The drawer's label as displayed in the header. You should always include a relevant label, as it is required for
|
||||
* proper accessibility. If you need to display HTML, use the `label` slot instead.
|
||||
*/
|
||||
@property({ reflect: true }) label = '';
|
||||
|
||||
/** The direction from which the drawer will open. */
|
||||
@property({ reflect: true }) placement: 'top' | 'end' | 'bottom' | 'start' = 'end';
|
||||
|
||||
/**
|
||||
* By default, the drawer slides out of its containing block (usually the viewport). To make the drawer slide out of
|
||||
* its parent element, set this attribute and add `position: relative` to the parent.
|
||||
*/
|
||||
@property({ type: Boolean, reflect: true }) contained = false;
|
||||
/** Renders the drawer with a header. */
|
||||
@property({ attribute: 'with-header', type: Boolean, reflect: true }) withHeader = false;
|
||||
|
||||
/**
|
||||
* Removes the header. This will also remove the default close button, so please ensure you provide an easy,
|
||||
* accessible way for users to dismiss the drawer.
|
||||
*/
|
||||
@property({ attribute: 'no-header', type: Boolean, reflect: true }) noHeader = false;
|
||||
/** Renders the drawer with a footer. */
|
||||
@property({ attribute: 'with-footer', type: Boolean, reflect: true }) withFooter = false;
|
||||
|
||||
firstUpdated() {
|
||||
this.drawer.hidden = !this.open;
|
||||
|
||||
if (this.open) {
|
||||
this.addOpenListeners();
|
||||
|
||||
if (!this.contained) {
|
||||
this.modal.activate();
|
||||
lockBodyScrolling(this);
|
||||
}
|
||||
this.modal.activate();
|
||||
lockBodyScrolling(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,10 +141,8 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
private addOpenListeners() {
|
||||
if ('CloseWatcher' in window) {
|
||||
this.closeWatcher?.destroy();
|
||||
if (!this.contained) {
|
||||
this.closeWatcher = new CloseWatcher();
|
||||
this.closeWatcher.onclose = () => this.requestClose('keyboard');
|
||||
}
|
||||
this.closeWatcher = new CloseWatcher();
|
||||
this.closeWatcher.onclose = () => this.requestClose('keyboard');
|
||||
} else {
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
this.closeWatcher?.destroy();
|
||||
@@ -167,11 +154,6 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
}
|
||||
|
||||
private handleDocumentKeyDown = (event: KeyboardEvent) => {
|
||||
// Contained drawers aren't modal and don't response to the escape key
|
||||
if (this.contained) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === 'Escape' && this.modal.isActive() && this.open) {
|
||||
event.stopImmediatePropagation();
|
||||
this.requestClose('keyboard');
|
||||
@@ -185,12 +167,8 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
this.emit('wa-show');
|
||||
this.addOpenListeners();
|
||||
this.originalTrigger = document.activeElement as HTMLElement;
|
||||
|
||||
// Lock body scrolling only if the drawer isn't contained
|
||||
if (!this.contained) {
|
||||
this.modal.activate();
|
||||
lockBodyScrolling(this);
|
||||
}
|
||||
this.modal.activate();
|
||||
lockBodyScrolling(this);
|
||||
|
||||
// When the drawer is shown, Safari will attempt to set focus on whatever element has autofocus. This causes the
|
||||
// drawer's animation to jitter, so we'll temporarily remove the attribute, call `focus({ preventScroll: true })`
|
||||
@@ -239,11 +217,8 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
// Hide
|
||||
this.emit('wa-hide');
|
||||
this.removeOpenListeners();
|
||||
|
||||
if (!this.contained) {
|
||||
this.modal.deactivate();
|
||||
unlockBodyScrolling(this);
|
||||
}
|
||||
this.modal.deactivate();
|
||||
unlockBodyScrolling(this);
|
||||
|
||||
await Promise.all([stopAnimations(this.drawer), stopAnimations(this.overlay)]);
|
||||
const panelAnimation = getAnimation(this, `drawer.hide${uppercaseFirstLetter(this.placement)}`, {
|
||||
@@ -279,19 +254,6 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
}
|
||||
}
|
||||
|
||||
@watch('contained', { waitUntilFirstUpdate: true })
|
||||
handleNoModalChange() {
|
||||
if (this.open && !this.contained) {
|
||||
this.modal.activate();
|
||||
lockBodyScrolling(this);
|
||||
}
|
||||
|
||||
if (this.open && this.contained) {
|
||||
this.modal.deactivate();
|
||||
unlockBodyScrolling(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Shows the drawer. */
|
||||
async show() {
|
||||
if (this.open) {
|
||||
@@ -323,10 +285,9 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
'drawer--end': this.placement === 'end',
|
||||
'drawer--bottom': this.placement === 'bottom',
|
||||
'drawer--start': this.placement === 'start',
|
||||
'drawer--contained': this.contained,
|
||||
'drawer--fixed': !this.contained,
|
||||
'drawer--rtl': this.localize.dir() === 'rtl',
|
||||
'drawer--has-footer': this.hasSlotController.test('footer')
|
||||
'drawer--with-header': this.withHeader,
|
||||
'drawer--with-footer': this.withFooter
|
||||
})}
|
||||
>
|
||||
<div part="overlay" class="drawer__overlay" @click=${() => this.requestClose('overlay')} tabindex="-1"></div>
|
||||
@@ -337,11 +298,11 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-hidden=${this.open ? 'false' : 'true'}
|
||||
aria-label=${ifDefined(this.noHeader ? this.label : undefined)}
|
||||
aria-labelledby=${ifDefined(!this.noHeader ? 'title' : undefined)}
|
||||
aria-label=${ifDefined(this.withHeader ? undefined : this.label)}
|
||||
aria-labelledby=${ifDefined(this.withHeader ? 'title' : undefined)}
|
||||
tabindex="0"
|
||||
>
|
||||
${!this.noHeader
|
||||
${this.withHeader
|
||||
? html`
|
||||
<header part="header" class="drawer__header">
|
||||
<h2 part="title" class="drawer__title" id="title">
|
||||
@@ -367,9 +328,13 @@ export default class WaDrawer extends WebAwesomeElement {
|
||||
|
||||
<slot part="body" class="drawer__body"></slot>
|
||||
|
||||
<footer part="footer" class="drawer__footer">
|
||||
<slot name="footer"></slot>
|
||||
</footer>
|
||||
${this.withFooter
|
||||
? html`
|
||||
<footer part="footer" class="drawer__footer">
|
||||
<slot name="footer"></slot>
|
||||
</footer>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -11,6 +11,8 @@ export default css`
|
||||
}
|
||||
|
||||
.drawer {
|
||||
position: fixed;
|
||||
z-index: var(--wa-z-index-drawer);
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
@@ -19,16 +21,6 @@ export default css`
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.drawer--contained {
|
||||
position: absolute;
|
||||
z-index: initial;
|
||||
}
|
||||
|
||||
.drawer--fixed {
|
||||
position: fixed;
|
||||
z-index: var(--wa-z-index-drawer);
|
||||
}
|
||||
|
||||
.drawer__panel {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
@@ -129,10 +121,6 @@ export default css`
|
||||
margin-inline-end: var(--wa-spacing-xs);
|
||||
}
|
||||
|
||||
.drawer:not(.drawer--has-footer) .drawer__footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.drawer__overlay {
|
||||
display: block;
|
||||
position: fixed;
|
||||
@@ -144,10 +132,6 @@ export default css`
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.drawer--contained .drawer__overlay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.drawer__panel {
|
||||
border: solid 1px white;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { getTextContent, HasSlotController } from '../../internal/slot.js';
|
||||
import { getTextContent } from '../../internal/slot.js';
|
||||
import { html } from 'lit';
|
||||
import { LocalizeController } from '../../utilities/localize.js';
|
||||
import { property, query } from 'lit/decorators.js';
|
||||
@@ -67,8 +67,7 @@ export default class WaMenuItem extends WebAwesomeElement {
|
||||
@property({ type: Boolean, reflect: true }) disabled = false;
|
||||
|
||||
private readonly localize = new LocalizeController(this);
|
||||
private readonly hasSlotController = new HasSlotController(this, 'submenu');
|
||||
private submenuController: SubmenuController = new SubmenuController(this, this.hasSlotController, this.localize);
|
||||
private submenuController: SubmenuController = new SubmenuController(this, this.localize);
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
@@ -150,7 +149,7 @@ export default class WaMenuItem extends WebAwesomeElement {
|
||||
}
|
||||
|
||||
isSubmenu() {
|
||||
return this.hasSlotController.test('submenu');
|
||||
return this.querySelector(`:scope > [slot="submenu"]`) !== null;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { createRef, ref, type Ref } from 'lit/directives/ref.js';
|
||||
import { type HasSlotController } from '../../internal/slot.js';
|
||||
import { html } from 'lit';
|
||||
import { type LocalizeController } from '../../utilities/localize.js';
|
||||
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
||||
@@ -14,22 +13,20 @@ export class SubmenuController implements ReactiveController {
|
||||
private isConnected = false;
|
||||
private isPopupConnected = false;
|
||||
private skidding = 0;
|
||||
private readonly hasSlotController: HasSlotController;
|
||||
private readonly localize: LocalizeController;
|
||||
private readonly submenuOpenDelay = 100;
|
||||
|
||||
constructor(
|
||||
host: ReactiveControllerHost & WaMenuItem,
|
||||
hasSlotController: HasSlotController,
|
||||
localize: LocalizeController
|
||||
) {
|
||||
constructor(host: ReactiveControllerHost & WaMenuItem, localize: LocalizeController) {
|
||||
(this.host = host).addController(this);
|
||||
this.hasSlotController = hasSlotController;
|
||||
this.localize = localize;
|
||||
}
|
||||
|
||||
private hasSubmenu() {
|
||||
return this.host.querySelector(`:scope > [slot="submenu"]`) !== null;
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
if (this.hasSlotController.test('submenu') && !this.host.disabled) {
|
||||
if (this.hasSubmenu() && !this.host.disabled) {
|
||||
this.addListeners();
|
||||
}
|
||||
}
|
||||
@@ -39,7 +36,7 @@ export class SubmenuController implements ReactiveController {
|
||||
}
|
||||
|
||||
hostUpdated() {
|
||||
if (this.hasSlotController.test('submenu') && !this.host.disabled) {
|
||||
if (this.hasSubmenu() && !this.host.disabled) {
|
||||
this.addListeners();
|
||||
this.updateSkidding();
|
||||
} else {
|
||||
@@ -93,7 +90,7 @@ export class SubmenuController implements ReactiveController {
|
||||
};
|
||||
|
||||
private handleMouseOver = () => {
|
||||
if (this.hasSlotController.test('submenu')) {
|
||||
if (this.hasSubmenu()) {
|
||||
this.enableSubmenu();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -147,7 +147,7 @@ it('Should allow tabbing to slotted elements', async () => {
|
||||
|
||||
it('Should account for when focus is changed from outside sources (like clicking)', async () => {
|
||||
const dialog = await fixture(html`
|
||||
<wa-dialog open="" label="Dialog" class="dialog-overview">
|
||||
<wa-dialog open="" label="Dialog" with-header with-footer class="dialog-overview">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
<wa-input placeholder="tab to me"></wa-input>
|
||||
<wa-button slot="footer" variant="primary">Close</wa-button>
|
||||
@@ -188,12 +188,12 @@ it('Should respect nested modal instances', async () => {
|
||||
await fixture(html`
|
||||
<div>
|
||||
<wa-button id="open-dialog-1" @click=${() => dialogOne().show()}></wa-button>
|
||||
<wa-dialog id="dialog-1" label="Dialog 1">
|
||||
<wa-dialog id="dialog-1" label="Dialog 1" with-header with-footer>
|
||||
<wa-button @click=${() => dialogTwo().show()} id="open-dialog-2">Open Dialog 2</wa-button>
|
||||
<wa-button slot="footer" variant="primary">Close</wa-button>
|
||||
</wa-dialog>
|
||||
|
||||
<wa-dialog id="dialog-2" label="Dialog 2">
|
||||
<wa-dialog id="dialog-2" label="Dialog 2" with-header with-footer>
|
||||
<wa-input id="focus-1" autofocus="" placeholder="I will have focus when the dialog is opened"></wa-input>
|
||||
<wa-input id="focus-2" placeholder="Second input"></wa-input>
|
||||
<wa-button slot="footer" variant="primary" class="close-2">Close</wa-button>
|
||||
|
||||
Reference in New Issue
Block a user