From 5a058a8808b45f6c7a9ec310c26033e9337c6155 Mon Sep 17 00:00:00 2001 From: Lea Verou Date: Wed, 18 Dec 2024 08:11:10 -0500 Subject: [PATCH] Revamp dialog styles, port to Essentials Refactor dialog CSS Add native dialog stub --- src/components/dialog/dialog.css | 175 ++++--------------------------- src/components/dialog/dialog.ts | 42 +++----- src/styles/applied.css | 1 + src/styles/native/dialog.css | 141 +++++++++++++++++++++++++ 4 files changed, 178 insertions(+), 181 deletions(-) create mode 100644 src/styles/native/dialog.css diff --git a/src/components/dialog/dialog.css b/src/components/dialog/dialog.css index b4004d43b..2f852f3e9 100644 --- a/src/components/dialog/dialog.css +++ b/src/components/dialog/dialog.css @@ -1,89 +1,24 @@ :host { - --background-color: var(--wa-color-surface-raised); - --border-radius: var(--wa-panel-border-radius); - --box-shadow: var(--wa-shadow-l); - --width: 31rem; --spacing: var(--wa-space-xl); - --show-duration: 200ms; - --hide-duration: 200ms; + display: contents; +} + +:host(:not([open])) { display: none; } -:host([open]) { - display: block; -} - -.dialog { - display: flex; - flex-direction: column; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: var(--width); - max-width: calc(100% - var(--wa-space-2xl)); - max-height: calc(100% - var(--wa-space-2xl)); - background-color: var(--background-color); - border-radius: var(--border-radius); - border: none; - box-shadow: var(--box-shadow); - padding: 0; +dialog { + width: inherit; + max-width: inherit; + max-height: inherit; + background-color: inherit; + border-radius: inherit; + border: inherit; + box-shadow: inherit; + padding: inherit; margin: auto; - - &.show { - animation: show-dialog var(--show-duration) ease; - - &::backdrop { - animation: show-backdrop var(--show-duration, 200ms) ease; - } - } - - &.hide { - animation: show-dialog var(--hide-duration) ease reverse; - - &::backdrop { - animation: show-backdrop var(--hide-duration, 200ms) ease reverse; - } - } - - &.pulse { - animation: pulse 250ms ease; - } -} - -.dialog:focus { - outline: none; -} - -/* Ensure there's enough vertical padding for phones that don't update vh when chrome appears (e.g. iPhone) */ -@media screen and (max-width: 420px) { - .dialog { - max-height: 80vh; - } -} - -.dialog--open { - display: flex; - opacity: 1; -} - -.header { - flex: 0 0 auto; - display: flex; - flex-wrap: nowrap; - padding: var(--spacing); - padding-block-end: 0; -} - -.title { - align-self: center; - flex: 1 1 auto; - font-family: inherit; - font-size: var(--wa-font-size-l); - font-weight: var(--wa-font-weight-heading); - line-height: var(--wa-line-height-condensed); - margin: 0; + transition: inherit; } .header-actions { @@ -93,81 +28,13 @@ flex-wrap: wrap; justify-content: end; gap: var(--wa-space-2xs); - padding-inline-start: var(--spacing); -} + margin-inline-start: auto; -.header-actions wa-icon-button, -.header-actions ::slotted(wa-icon-button) { - flex: 0 0 auto; - display: flex; - align-items: center; - font-size: var(--wa-font-size-m); -} - -.body { - flex: 1 1 auto; - display: block; - padding: var(--spacing); - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -.footer { - flex: 0 0 auto; - display: flex; - flex-wrap: wrap; - gap: var(--wa-space-xs); - justify-content: end; - padding: var(--spacing); - padding-block-start: 0; -} - -.footer ::slotted(wa-button:not(:first-of-type)) { - margin-inline-start: var(--wa-spacing-xs); -} - -.dialog::backdrop { - /* - NOTE: the ::backdrop element doesn't inherit properly in Safari yet, but it will in 17.4! At that time, we can - remove the fallback values here. - */ - background-color: var(--wa-color-overlay-modal, rgb(0 0 0 / 0.25)); -} - -@keyframes pulse { - 0% { - scale: 1; - } - 50% { - scale: 1.02; - } - 100% { - scale: 1; - } -} - -@keyframes show-dialog { - from { - opacity: 0; - scale: 0.8; - } - to { - opacity: 1; - scale: 1; - } -} - -@keyframes show-backdrop { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@media (forced-colors: active) { - .dialog { - border: solid 1px white; + wa-icon-button, + ::slotted(wa-icon-button) { + flex: 0 0 auto; + display: flex; + align-items: center; + font-size: var(--wa-font-size-m); } } diff --git a/src/components/dialog/dialog.ts b/src/components/dialog/dialog.ts index 9fbefabf5..74857744a 100644 --- a/src/components/dialog/dialog.ts +++ b/src/components/dialog/dialog.ts @@ -1,6 +1,5 @@ import { html, isServer } from 'lit'; -import { customElement, property, query } from 'lit/decorators.js'; -import { classMap } from 'lit/directives/class-map.js'; +import { customElement, property, query, state } from 'lit/decorators.js'; import { WaAfterHideEvent } from '../../events/after-hide.js'; import { WaAfterShowEvent } from '../../events/after-show.js'; import { WaHideEvent } from '../../events/hide.js'; @@ -9,6 +8,7 @@ import { animateWithClass } from '../../internal/animate.js'; import { lockBodyScrolling, unlockBodyScrolling } from '../../internal/scroll.js'; import { watch } from '../../internal/watch.js'; import WebAwesomeElement from '../../internal/webawesome-element.js'; +import dialogStyles from '../../styles/native/dialog.css'; import { LocalizeController } from '../../utilities/localize.js'; import '../icon-button/icon-button.js'; import styles from './dialog.css'; @@ -35,6 +35,7 @@ import styles from './dialog.css'; * behavior such as data loss. * @event wa-after-hide - Emitted after the dialog closes and all animations are complete. * + * @csspart base - The inner `` used to render this component. * @csspart header - The dialog's header. This element wraps the title and header actions. * @csspart header-actions - Optional actions to add to the header. Works best with ``. * @csspart title - The dialog's title. @@ -43,23 +44,16 @@ import styles from './dialog.css'; * @csspart body - The dialog's body. * @csspart footer - The dialog's footer. * - * @cssproperty --background-color - The dialog's background color. - * @cssproperty --border-radius - The radius of the dialog's corners. - * @cssproperty --box-shadow - The shadow effects around the edges of the dialog. - * @cssproperty --spacing - The amount of space around and between the dialog's content. - * @cssproperty --width - The preferred width of the dialog. Note that the dialog will shrink to accommodate smaller screens. - * @cssproperty [--show-duration=200ms] - The animation duration when showing the dialog. - * @cssproperty [--hide-duration=200ms] - The animation duration when hiding the dialog. */ @customElement('wa-dialog') export default class WaDialog extends WebAwesomeElement { - static shadowStyle = styles; + static shadowStyle = [dialogStyles, styles]; private readonly localize = new LocalizeController(this); private originalTrigger: HTMLElement | null; private closeWatcher: CloseWatcher | null; - @query('.dialog') dialog: HTMLDialogElement; + @query('dialog') dialog: HTMLDialogElement; /** * Indicates whether or not the dialog is open. You can toggle this attribute to show and hide the dialog, or you can @@ -82,6 +76,9 @@ export default class WaDialog extends WebAwesomeElement { /** When enabled, the dialog will be closed when the user clicks outside of it. */ @property({ attribute: 'light-dismiss', type: Boolean }) lightDismiss = false; + @state() + hasOpened = this.open; + firstUpdated() { if (this.open) { this.addOpenListeners(); @@ -103,14 +100,12 @@ export default class WaDialog extends WebAwesomeElement { if (waHideEvent.defaultPrevented) { this.open = true; - animateWithClass(this.dialog, 'pulse'); + animateWithClass(this.dialog, 'wa-dialog-pulse'); return; } this.removeOpenListeners(); - await animateWithClass(this.dialog, 'hide'); - this.open = false; this.dialog.close(); unlockBodyScrolling(this); @@ -166,7 +161,7 @@ export default class WaDialog extends WebAwesomeElement { if (this.lightDismiss) { this.requestClose(this.dialog); } else { - await animateWithClass(this.dialog, 'pulse'); + await animateWithClass(this.dialog, 'wa-dialog-pulse'); } } } @@ -203,6 +198,7 @@ export default class WaDialog extends WebAwesomeElement { this.addOpenListeners(); this.originalTrigger = document.activeElement as HTMLElement; this.open = true; + this.hasOpened = true; this.dialog.showModal(); lockBodyScrolling(this); @@ -215,28 +211,20 @@ export default class WaDialog extends WebAwesomeElement { } }); - await animateWithClass(this.dialog, 'show'); - this.dispatchEvent(new WaAfterShowEvent()); } render() { return html` ${this.withHeader ? html` -
+

${this.label.length > 0 ? this.label : String.fromCharCode(65279)} @@ -258,11 +246,11 @@ export default class WaDialog extends WebAwesomeElement { ` : ''} -
+ ${this.withFooter ? html` -