From 4351f35b7c8ed21ff4d6c4035738877be81cc72a Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Thu, 29 Feb 2024 14:52:20 +0100 Subject: [PATCH 01/23] feat(dialog): adds styling and docs This is WIP --- .../stories/components/dialog/dialog.docs.mdx | 17 ++ .../components/dialog/dialog.stories.ts | 202 ++++++++++++++++++ packages/styles/src/components/_index.scss | 1 + packages/styles/src/components/dialog.scss | 175 +++++++++++++++ 4 files changed, 395 insertions(+) create mode 100644 packages/documentation/src/stories/components/dialog/dialog.docs.mdx create mode 100644 packages/documentation/src/stories/components/dialog/dialog.stories.ts create mode 100644 packages/styles/src/components/dialog.scss diff --git a/packages/documentation/src/stories/components/dialog/dialog.docs.mdx b/packages/documentation/src/stories/components/dialog/dialog.docs.mdx new file mode 100644 index 0000000000..672113b8a9 --- /dev/null +++ b/packages/documentation/src/stories/components/dialog/dialog.docs.mdx @@ -0,0 +1,17 @@ +import { Canvas, Controls, Meta } from '@storybook/blocks'; +import * as DialogStories from './dialog.stories'; + + + +# Dialog + + +
+ +
+ +## Form dialog + + +## Cookie banner + \ No newline at end of file diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts new file mode 100644 index 0000000000..7ebb6d8608 --- /dev/null +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -0,0 +1,202 @@ +import { BADGE } from '@geometricpanda/storybook-addon-badges'; +import { background } from '@storybook/theming'; +import { Args, Meta, StoryObj } from '@storybook/web-components'; +import { TemplateResult, html, nothing } from 'lit-html'; + +const meta: Meta = { + id: '562eac2b-6dc1-4007-ba8e-4e981cef0cbc', + title: 'Components/Dialog', + parameters: { + badges: [BADGE.NEEDS_REVISION], + design: { + type: 'figma', + }, + }, + args: { + variant: 'standard', + notificationType: 'general', + title: 'Dialog', + content: 'This is a dialog', + size: 'medium', + closeButton: true, + }, + argTypes: { + variant: { + name: 'Variant', + description: 'Choose which dialog variant to display', + control: 'radio', + options: ['standard', 'notification', 'cookie'], + table: { category: 'Variant' }, + }, + notificationType: { + name: 'Notification type', + description: 'Choose the type of notification to display', + control: 'select', + options: ['general', 'error', 'warning', 'success', 'brand'], + if: { + arg: 'variant', + eq: 'notification', + }, + table: { category: 'Variant' }, + }, + title: { + name: 'Title', + description: 'Optional title', + control: 'text', + table: { category: 'Content' }, + }, + content: { + name: 'Content', + description: 'Dialog text', + control: 'text', + table: { category: 'Content' }, + }, + size: { + name: 'Size', + description: 'Max width of the dialog.', + control: { + type: 'select', + }, + options: ['small', 'medium', 'large'], + table: { category: 'Variant' }, + }, + closeButton: { + name: 'Close button', + description: 'Show a close button to dismiss the dialog', + control: 'boolean', + table: { category: 'Content' }, + }, + }, + decorators: [ + (story: Function) => + html`
+ ${story()} +
`, + ], +}; + +export default meta; + +const notificationTypeIconMap: { [key: string]: { icon: number; color: string } } = { + general: { icon: 1034, color: 'bg-info' }, + error: { icon: 2104, color: 'bg-danger' }, + warning: { icon: 2106, color: 'bg-warning' }, + success: { icon: 2105, color: 'bg-success' }, + brand: { icon: 1034, color: 'bg-yellow' }, +}; + +const getHeader = (text: string) => { + return html`

${text}

`; +}; + +const getCloseButton = () => { + return html``; +}; + +const getControls = () => { + return html`
+ + +
`; +}; + +const Template = { + render: (args: Args) => { + let variant = nothing; + let notificationType: symbol | string = nothing; + let backgroundColor: string | symbol = nothing; + + let icon: symbol | TemplateResult = nothing; + let header = getHeader(args.title); + let body = html`${args.content}`; + const controls = getControls(); + const closeButton = args.closeButton ? getCloseButton() : nothing; + + if (args.variant === 'notification') { + variant = args.variant; + const { icon: iconNr, color } = notificationTypeIconMap[args.notificationType]; + notificationType = args.notificationType as string; + icon = html``; + header = getHeader(args.title, color); + } + if (args.variant === 'cookie') { + backgroundColor = 'bg-light'; + icon = html``; + variant = args.variant; + } + return html` + +
+ ${icon} ${header} +
${body}
+ ${controls} ${closeButton} +
+
+ `; + }, +}; + +const FormTemplate = { + render: (args: Args) => { + return html` + +
+

Form example

+
+ + +
+ Hintus textus elare volare cantare hendrerit in vulputate velit esse molestie + consequat, vel illum dolore eu feugiat nulla facilisis. +
+
+
+ + +
+
+
+ `; + }, +}; + +const CookieTemplate = { + ...Template, + args: { + variant: 'cookie', + closeButton: false, + size: 'large', + }, +}; + +type Story = StoryObj; + +export const Default: Story = { + ...Template, +}; + +export const Form: Story = { + ...FormTemplate, +}; + +export const Cookie: Story = { + ...CookieTemplate, +}; diff --git a/packages/styles/src/components/_index.scss b/packages/styles/src/components/_index.scss index 988eb30500..8153959a83 100644 --- a/packages/styles/src/components/_index.scss +++ b/packages/styles/src/components/_index.scss @@ -17,6 +17,7 @@ @use 'form-select'; @use 'form-textarea'; @use 'datatable'; +@use 'dialog'; @use 'form-check'; @use 'forms'; @use 'grid'; diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss new file mode 100644 index 0000000000..0a41aeb3fd --- /dev/null +++ b/packages/styles/src/components/dialog.scss @@ -0,0 +1,175 @@ +@use '../mixins/elevation'; +@use '../variables/spacing'; +@use '../variables/color'; + +@use './../themes/bootstrap/core' as *; + +dialog { + @include elevation.elevation('elevation-3'); + + padding: spacing.$size-regular spacing.$size-regular 0; + max-height: 90vh; + overflow: auto; + overscroll-behavior: contain; + + // [size="medium"] is the standard case + min-width: min(389px, 90vw); + max-width: 590px; + + &::backdrop { + background-color: rgba(0, 0, 0, 0.8); + } + + > form { + display: grid; + column-gap: spacing.$size-regular; + grid-template-columns: 1fr auto; + grid-template-areas: + 'header close-button' + 'body close-button' + 'controls controls'; + + // Propagate bg color to the controls + background-color: inherit; + } + + &[size='small'] { + min-width: 296px; + max-width: 388px; + } + + &[size='large'] { + min-width: min(600px, 90vw); + max-width: 792px; + } + + &[variant='notification'] { + padding: 0; + + > form { + grid-template-columns: 1fr; + grid-template-areas: + 'close-button' + 'icon' + 'header' + 'body' + 'controls'; + } + + &[type='general'] { + --post-dialog-background-color: #{color.$info}; + } + &[type='warning'] { + --post-dialog-background-color: #{color.$warning}; + } + &[type='error'] { + --post-dialog-background-color: #{color.$error}; + } + &[type='success'] { + --post-dialog-background-color: #{color.$success}; + } + + > form::before { + content: ''; + grid-area: close-button / close-button / header / header; + background-color: var(--post-dialog-background-color); + } + + .dialog--header, + .dialog--icon { + justify-self: center; + } + + .dialog--header, + .dialog--body, + .dialog--controls { + padding-inline: spacing.$size-regular; + } + + .dialog--close { + margin-right: spacing.$size-regular; + } + + .dialog--header, + .dialog--controls { + padding-bottom: spacing.$size-regular; + } + } + + &[variant='cookie'] { + top: auto; + bottom: 2rem; + + > form { + grid-template-columns: auto 1fr auto; + grid-template-areas: + 'icon header close-button' + 'icon body close-button' + 'controls controls controls'; + } + + .dialog--icon { + align-self: flex-start; + } + } +} + +.dialog--icon { + grid-area: icon; + display: block; + width: spacing.$size-big; + height: spacing.$size-big; + + // Larger icon for bigger notification dialogs + dialog:not([size='small']) & { + @include media-breakpoint-up(rg) { + width: spacing.$size-small-huge; + height: spacing.$size-small-huge; + } + } +} + +.dialog--header { + grid-area: header; + + & > *:first-child { + margin-top: 0; + } +} + +.dialog--body { + grid-area: body; + margin-bottom: 0; + + & > *:last-child { + margin-bottom: 0; + } +} + +.dialog--controls { + grid-area: controls; + position: sticky; + bottom: 0; + padding-block: spacing.$size-regular; + display: flex; + flex-wrap: wrap; + flex-direction: row-reverse; + gap: spacing.$size-regular; + background-color: inherit; + + button { + @include media-breakpoint-down(sm) { + width: 100%; + } + } +} + +.dialog--close { + position: sticky; + top: 0; + grid-area: close-button; + width: spacing.$size-large; + height: spacing.$size-large; + min-height: 0; + margin-left: auto; +} From 3fe243d453e17cc2a9ed5ef9af4d4cd063741dfc Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Thu, 7 Mar 2024 16:16:09 +0100 Subject: [PATCH 02/23] refactor: animations and dialog part names --- .../components/dialog/dialog.stories.ts | 35 ++-- packages/styles/src/components/dialog.scss | 190 +++++++++++++++--- 2 files changed, 177 insertions(+), 48 deletions(-) diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index 7ebb6d8608..b45f378dd6 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -18,6 +18,7 @@ const meta: Meta = { title: 'Dialog', content: 'This is a dialog', size: 'medium', + open: true, closeButton: true, }, argTypes: { @@ -92,20 +93,18 @@ const notificationTypeIconMap: { [key: string]: { icon: number; color: string } }; const getHeader = (text: string) => { - return html`

${text}

`; + return html`

${text}

`; }; const getCloseButton = () => { - return html``; }; const getControls = () => { - return html`
- - -
`; + return html` + `; }; const Template = { @@ -122,27 +121,31 @@ const Template = { if (args.variant === 'notification') { variant = args.variant; - const { icon: iconNr, color } = notificationTypeIconMap[args.notificationType]; + const { icon: iconNr } = notificationTypeIconMap[args.notificationType]; notificationType = args.notificationType as string; - icon = html``; - header = getHeader(args.title, color); + icon = html``; + header = getHeader(args.title); } if (args.variant === 'cookie') { backgroundColor = 'bg-light'; - icon = html``; + icon = html``; variant = args.variant; } return html`
- ${icon} ${header} -
${body}
- ${controls} ${closeButton} + ${icon} + ${header} + ${body} + ${controls} + ${args.closeButton + ? html`${closeButton}` + : nothing}
`; diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index 0a41aeb3fd..6153141f36 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -4,6 +4,12 @@ @use './../themes/bootstrap/core' as *; +// Prevent page from scrolling while a dialog is open +// Missing support for has is negligible, it's progressive enhancement. It will magically work some day +html:has(dialog[open]) { + overflow: hidden; +} + dialog { @include elevation.elevation('elevation-3'); @@ -11,13 +17,35 @@ dialog { max-height: 90vh; overflow: auto; overscroll-behavior: contain; + border-width: 0; + + @media (forced-colors: active) { + border-width: 2px; + } - // [size="medium"] is the standard case min-width: min(389px, 90vw); max-width: 590px; &::backdrop { background-color: rgba(0, 0, 0, 0.8); + backdrop-filter: blur(0); + + @media (forced-colors: active) { + background-image: linear-gradient( + 135deg, + CanvasText 4.55%, + transparent 4.55%, + transparent 50%, + CanvasText 50%, + CanvasText 54.55%, + transparent 54.55%, + transparent 100% + ); + background-size: 22px 22px; + backdrop-filter: none; + background-color: transparent; + forced-color-adjust: none; + } } > form { @@ -33,17 +61,19 @@ dialog { background-color: inherit; } - &[size='small'] { + &[data-size='small'] { min-width: 296px; max-width: 388px; } - &[size='large'] { + // [size="medium"] is the standard case + + &[data-size='large'] { min-width: min(600px, 90vw); max-width: 792px; } - &[variant='notification'] { + &[data-variant='notification'] { padding: 0; > form { @@ -56,16 +86,16 @@ dialog { 'controls'; } - &[type='general'] { + &[data-type='general'] { --post-dialog-background-color: #{color.$info}; } - &[type='warning'] { + &[data-type='warning'] { --post-dialog-background-color: #{color.$warning}; } - &[type='error'] { + &[data-type='error'] { --post-dialog-background-color: #{color.$error}; } - &[type='success'] { + &[data-type='success'] { --post-dialog-background-color: #{color.$success}; } @@ -75,61 +105,81 @@ dialog { background-color: var(--post-dialog-background-color); } - .dialog--header, - .dialog--icon { + post-dialog-close, + post-dialog-icon, + post-dialog-header, + post-dialog-body { + margin-top: spacing.$size-regular; + } + + post-dialog-header, + post-dialog-icon { justify-self: center; } - .dialog--header, - .dialog--body, - .dialog--controls { + post-dialog-header, + post-dialog-body, + post-dialog-controls { padding-inline: spacing.$size-regular; } - .dialog--close { + post-dialog-close { margin-right: spacing.$size-regular; } - .dialog--header, - .dialog--controls { + post-dialog-header, + post-dialog-controls { padding-bottom: spacing.$size-regular; } } - &[variant='cookie'] { + &[data-variant='cookie'] { top: auto; bottom: 2rem; > form { grid-template-columns: auto 1fr auto; grid-template-areas: - 'icon header close-button' - 'icon body close-button' + 'icon header close-button' + 'icon body close-button' 'controls controls controls'; } - .dialog--icon { + post-dialog-icon { align-self: flex-start; } } } -.dialog--icon { +post-dialog-icon, +post-dialog-header, +post-dialog-body, +post-dialog-controls, +post-dialog-close { + &:empty { + display: none; + } +} + +post-dialog-icon { grid-area: icon; display: block; - width: spacing.$size-big; - height: spacing.$size-big; - // Larger icon for bigger notification dialogs - dialog:not([size='small']) & { - @include media-breakpoint-up(rg) { - width: spacing.$size-small-huge; - height: spacing.$size-small-huge; + > post-icon { + width: spacing.$size-big; + height: spacing.$size-big; + + // Larger icon for bigger notification dialogs + dialog:not([size='small']) & { + @include media-breakpoint-up(rg) { + width: spacing.$size-small-huge; + height: spacing.$size-small-huge; + } } } } -.dialog--header { +post-dialog-header { grid-area: header; & > *:first-child { @@ -137,7 +187,7 @@ dialog { } } -.dialog--body { +post-dialog-body { grid-area: body; margin-bottom: 0; @@ -146,7 +196,7 @@ dialog { } } -.dialog--controls { +post-dialog-controls { grid-area: controls; position: sticky; bottom: 0; @@ -164,7 +214,7 @@ dialog { } } -.dialog--close { +post-dialog-close { position: sticky; top: 0; grid-area: close-button; @@ -173,3 +223,79 @@ dialog { min-height: 0; margin-left: auto; } + +// Animations +dialog:not([data-animation='none']) { + --_dialog-transition-duration: var(--dialog-transition-duration, 0.5s); + + transform: scale(0.8); + opacity: 0; + transition-property: transform, opacity, overlay, display; + transition-behavior: allow-discrete; + transition-duration: var(--_dialog-transition-duration); + transition-timing-function: linear( + 0, + 0.007, + 0.029 2.2%, + 0.118 4.7%, + 0.625 14.4%, + 0.826 19%, + 0.902, + 0.962, + 1.008 26.1%, + 1.041 28.7%, + 1.064 32.1%, + 1.07 36%, + 1.061 40.5%, + 1.015 53.4%, + 0.999 61.6%, + 0.995 71.2%, + 1 + ); + + &::backdrop { + opacity: 0; + transition: + backdrop-filter var(--_dialog-transition-duration), + opacity var(--_dialog-transition-duration), + overlay var(--_dialog-transition-duration) allow-discrete, + display var(--_dialog-transition-duration) allow-discrete; + } + + &[open] { + transform: scale(1); + opacity: 1; + + @starting-style { + opacity: 0; + transform: scale(0.8); + } + + &::backdrop { + opacity: 1; + backdrop-filter: blur(10px); + + @starting-style { + opacity: 0; + backdrop-filter: blur(0); + } + + @media (forced-colors: active) { + backdrop-filter: none; + } + } + } + + &[data-variant='cookie'] { + opacity: 1; // Reset default + transform: translateY(calc(100% + 3rem)); + + &[open] { + transform: translateY(0); + + @starting-style { + transform: translateY(calc(100% + 3rem)); + } + } + } +} From c9a03dba2a846a295e28fddf4ab404f2aa9a38e9 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Thu, 21 Mar 2024 08:08:21 +0100 Subject: [PATCH 03/23] chore: deprecating modal and notification overlay --- .../documentation/src/stories/components/modal/modal.docs.mdx | 4 ++++ .../src/stories/components/modal/modal.stories.ts | 2 +- .../notification-overlay/notification-overlay.docs.mdx | 4 ++++ .../notification-overlay/notification-overlay.stories.ts | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/documentation/src/stories/components/modal/modal.docs.mdx b/packages/documentation/src/stories/components/modal/modal.docs.mdx index 2db36b70a0..e04deaa053 100644 --- a/packages/documentation/src/stories/components/modal/modal.docs.mdx +++ b/packages/documentation/src/stories/components/modal/modal.docs.mdx @@ -21,6 +21,10 @@ import modalBlocking from './modal-blocking.sample?raw'; +
+ This component is deprecated in favor of the dialog component. +
+
  • Component Import diff --git a/packages/documentation/src/stories/components/modal/modal.stories.ts b/packages/documentation/src/stories/components/modal/modal.stories.ts index 6f5f0c470b..f69f7d8600 100644 --- a/packages/documentation/src/stories/components/modal/modal.stories.ts +++ b/packages/documentation/src/stories/components/modal/modal.stories.ts @@ -4,7 +4,7 @@ import { MetaComponent } from '../../../../types'; const meta: MetaComponent = { id: '9a512414-84c5-473c-a7c8-a434eda9578d', - title: 'Components/Modal', + title: 'Components/Modal (deprecated)', tags: ['package:Angular'], parameters: { badges: [], diff --git a/packages/documentation/src/stories/components/notification-overlay/notification-overlay.docs.mdx b/packages/documentation/src/stories/components/notification-overlay/notification-overlay.docs.mdx index 407600f74a..307a06069c 100644 --- a/packages/documentation/src/stories/components/notification-overlay/notification-overlay.docs.mdx +++ b/packages/documentation/src/stories/components/notification-overlay/notification-overlay.docs.mdx @@ -17,6 +17,10 @@ import basicExampleAngular from './notification-overlay.sample.ts?raw';

    Present the user with important information or a decision before continuing the workflow.

    +
    + This component is deprecated in favor of the dialog component. +
    +
    • Component Import diff --git a/packages/documentation/src/stories/components/notification-overlay/notification-overlay.stories.ts b/packages/documentation/src/stories/components/notification-overlay/notification-overlay.stories.ts index c3ae11ff76..74101a5b5e 100644 --- a/packages/documentation/src/stories/components/notification-overlay/notification-overlay.stories.ts +++ b/packages/documentation/src/stories/components/notification-overlay/notification-overlay.stories.ts @@ -3,7 +3,7 @@ import { MetaComponent } from '../../../../types'; const meta: MetaComponent = { id: 'aab3f0df-08ca-4e33-90eb-77ffda6528db', - title: 'Components/Notification Overlay', + title: 'Components/Notification Overlay (deprecated)', tags: ['package:Angular'], parameters: { badges: [], From f796576fedc7e926d508133fa734248ede367d15 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Thu, 21 Mar 2024 08:10:44 +0100 Subject: [PATCH 04/23] chore: add changesets --- .changeset/kind-buses-trade.md | 6 ++++++ .changeset/popular-games-rush.md | 5 +++++ 2 files changed, 11 insertions(+) create mode 100644 .changeset/kind-buses-trade.md create mode 100644 .changeset/popular-games-rush.md diff --git a/.changeset/kind-buses-trade.md b/.changeset/kind-buses-trade.md new file mode 100644 index 0000000000..03a0351ecb --- /dev/null +++ b/.changeset/kind-buses-trade.md @@ -0,0 +1,6 @@ +--- +'@swisspost/design-system-documentation': minor +'@swisspost/design-system-styles': minor +--- + +Added styling support and documentation for the `` element. The dialog will replace the current modal and notification overlay components coming from ng-bootstrap. diff --git a/.changeset/popular-games-rush.md b/.changeset/popular-games-rush.md new file mode 100644 index 0000000000..f4710296da --- /dev/null +++ b/.changeset/popular-games-rush.md @@ -0,0 +1,5 @@ +--- +'@swisspost/design-system-styles': patch +--- + +Deprecated the ngBootstrap components Modal and Notification overlay in favor of the new Dialog component. The styles for these ngBootstrap components will be removed in a future major version. From f29cf71a1910e79adee16cdb11b8ac9ecafcb49a Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Thu, 21 Mar 2024 08:11:09 +0100 Subject: [PATCH 05/23] chore: added code samples --- .../stories/components/dialog/dialog.docs.mdx | 32 ++++++- .../components/dialog/dialog.stories.ts | 66 +++++++++---- .../dialog/samples/angular-form-data.ts | 1 + .../components/dialog/samples/js-form-data.ts | 4 + packages/styles/src/components/dialog.scss | 70 ++++++++++---- packages/styles/src/variables/_animation.scss | 19 ++++ pnpm-lock.yaml | 92 +++---------------- 7 files changed, 163 insertions(+), 121 deletions(-) create mode 100644 packages/documentation/src/stories/components/dialog/samples/angular-form-data.ts create mode 100644 packages/documentation/src/stories/components/dialog/samples/js-form-data.ts diff --git a/packages/documentation/src/stories/components/dialog/dialog.docs.mdx b/packages/documentation/src/stories/components/dialog/dialog.docs.mdx index 672113b8a9..530ba4df9a 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.docs.mdx +++ b/packages/documentation/src/stories/components/dialog/dialog.docs.mdx @@ -1,5 +1,7 @@ -import { Canvas, Controls, Meta } from '@storybook/blocks'; +import { Canvas, Controls, Meta, Source } from '@storybook/blocks'; import * as DialogStories from './dialog.stories'; +import JSFormData from './samples/js-form-data?raw'; +import AngularFormData from './samples/angular-form-data?raw'; @@ -13,5 +15,31 @@ import * as DialogStories from './dialog.stories'; ## Form dialog +### Using form data + + + HTML & CSS + Angular + + + Register a `submit` event listener on the form. In the event handler, you have access to all the form field values inside the dialog. The dialog box closes when the form gets submitted. + + + + + + + + + ## Cookie banner - \ No newline at end of file + + +## Custom content banner + \ No newline at end of file diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index b45f378dd6..89f6e709f7 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -1,5 +1,4 @@ import { BADGE } from '@geometricpanda/storybook-addon-badges'; -import { background } from '@storybook/theming'; import { Args, Meta, StoryObj } from '@storybook/web-components'; import { TemplateResult, html, nothing } from 'lit-html'; @@ -18,7 +17,6 @@ const meta: Meta = { title: 'Dialog', content: 'This is a dialog', size: 'medium', - open: true, closeButton: true, }, argTypes: { @@ -138,7 +136,7 @@ const Template = { data-type="${notificationType}" class="${backgroundColor}" > -
      + ${icon} ${header} ${body} @@ -153,28 +151,54 @@ const Template = { }; const FormTemplate = { + ...Template, render: (args: Args) => { return html` - -

      Form example

      -
      - - -
      - Hintus textus elare volare cantare hendrerit in vulputate velit esse molestie - consequat, vel illum dolore eu feugiat nulla facilisis. + +

      Form example

      + +
      + + +
      + Hintus textus elare volare cantare hendrerit in vulputate velit esse molestie + consequat, vel illum dolore eu feugiat nulla facilisis. +
      -
      -
      + + + -
      + + +
      + `; + }, +}; + +const CustomContentTemplate = { + ...Template, + render: (args: Args) => { + return html` + +
      +

      Custom content

      +

      This is some other content, just placed inside the dialog.

      +
      `; @@ -203,3 +227,7 @@ export const Form: Story = { export const Cookie: Story = { ...CookieTemplate, }; + +export const Custom: Story = { + ...CustomContentTemplate, +}; diff --git a/packages/documentation/src/stories/components/dialog/samples/angular-form-data.ts b/packages/documentation/src/stories/components/dialog/samples/angular-form-data.ts new file mode 100644 index 0000000000..954ddd236b --- /dev/null +++ b/packages/documentation/src/stories/components/dialog/samples/angular-form-data.ts @@ -0,0 +1 @@ +// TBD diff --git a/packages/documentation/src/stories/components/dialog/samples/js-form-data.ts b/packages/documentation/src/stories/components/dialog/samples/js-form-data.ts new file mode 100644 index 0000000000..ea8983bea8 --- /dev/null +++ b/packages/documentation/src/stories/components/dialog/samples/js-form-data.ts @@ -0,0 +1,4 @@ +document.querySelector('#example-dialog-form')?.addEventListener('submit', event => { + if (!event.target) return; + const formData = Object.fromEntries(new FormData(event.target as HTMLFormElement)); // Object containing your form data +}); diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index 6153141f36..2f94cee125 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -1,6 +1,7 @@ @use '../mixins/elevation'; @use '../variables/spacing'; @use '../variables/color'; +@use '../variables/animation'; @use './../themes/bootstrap/core' as *; @@ -11,14 +12,16 @@ html:has(dialog[open]) { } dialog { - @include elevation.elevation('elevation-3'); + @include elevation.elevation('elevation-5'); padding: spacing.$size-regular spacing.$size-regular 0; + max-width: calc(100vw - 2rem); max-height: 90vh; overflow: auto; overscroll-behavior: contain; border-width: 0; + // Show the border in HCM @media (forced-colors: active) { border-width: 2px; } @@ -48,7 +51,7 @@ dialog { } } - > form { + > .dialog-grid { display: grid; column-gap: spacing.$size-regular; grid-template-columns: 1fr auto; @@ -76,7 +79,7 @@ dialog { &[data-variant='notification'] { padding: 0; - > form { + > .dialog-grid { grid-template-columns: 1fr; grid-template-areas: 'close-button' @@ -89,17 +92,20 @@ dialog { &[data-type='general'] { --post-dialog-background-color: #{color.$info}; } + &[data-type='warning'] { --post-dialog-background-color: #{color.$warning}; } + &[data-type='error'] { --post-dialog-background-color: #{color.$error}; } + &[data-type='success'] { --post-dialog-background-color: #{color.$success}; } - > form::before { + > .dialog-grid::before { content: ''; grid-area: close-button / close-button / header / header; background-color: var(--post-dialog-background-color); @@ -137,7 +143,7 @@ dialog { top: auto; bottom: 2rem; - > form { + > .dialog-grid { grid-template-columns: auto 1fr auto; grid-template-areas: 'icon header close-button' @@ -151,14 +157,14 @@ dialog { } } -post-dialog-icon, -post-dialog-header, -post-dialog-body, -post-dialog-controls, -post-dialog-close { - &:empty { - display: none; - } +:where( + post-dialog-icon, + post-dialog-header, + post-dialog-body, + post-dialog-controls, + post-dialog-close + ):empty { + display: none; } post-dialog-icon { @@ -182,7 +188,7 @@ post-dialog-icon { post-dialog-header { grid-area: header; - & > *:first-child { + > *:first-child { margin-top: 0; } } @@ -191,7 +197,7 @@ post-dialog-body { grid-area: body; margin-bottom: 0; - & > *:last-child { + > *:last-child { margin-bottom: 0; } } @@ -218,13 +224,16 @@ post-dialog-close { position: sticky; top: 0; grid-area: close-button; - width: spacing.$size-large; - height: spacing.$size-large; - min-height: 0; - margin-left: auto; + + > .btn-close { + width: spacing.$size-large; + height: spacing.$size-large; + min-height: 0; + } } // Animations +// Progressively enhanced with currently experimental @starting-style which allows to animate stuff appearing in the top layer dialog:not([data-animation='none']) { --_dialog-transition-duration: var(--dialog-transition-duration, 0.5s); @@ -299,3 +308,26 @@ dialog:not([data-animation='none']) { } } } + +// Animations + +dialog { + &[effect="bump-in"] { + --dialog-effect-closed-transform: + } + &[effect] { + transition-behavior: allow-discrete; + transition-duration: animation.$transition-time-default; + transition-timing-function: animation.$transition-easing-bump-in; + + // Closed state + transform: var(--dialog-effect-closed-transform); + opacity: var(--dialog-effect-closed-opacity); + + // Open state + &[open] { + transform: translate(0, 0); + opacity: 1; + } + } +} diff --git a/packages/styles/src/variables/_animation.scss b/packages/styles/src/variables/_animation.scss index c657c0e69d..48df5ee979 100644 --- a/packages/styles/src/variables/_animation.scss +++ b/packages/styles/src/variables/_animation.scss @@ -21,6 +21,25 @@ $transition-time-area-large: 500ms !default; $transition-easing-default: cubic-bezier(0.4, 0, 0.2, 1) !default; $transition-easing-decelerate: cubic-bezier(0, 0, 0.2, 1) !default; $transition-easing-accelerate: cubic-bezier(0.4, 0, 1, 1) !default; +$transition-easing-bump-in: linear( + 0, + 0.007, + 0.029 2.2%, + 0.118 4.7%, + 0.625 14.4%, + 0.826 19%, + 0.902, + 0.962, + 1.008 26.1%, + 1.041 28.7%, + 1.064 32.1%, + 1.07 36%, + 1.061 40.5%, + 1.015 53.4%, + 0.999 61.6%, + 0.995 71.2%, + 1 +); // Distances $transition-distance-xsmall: map.get(spacing.$post-sizes, 'micro') !default; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5244c06a2f..121d0c94c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -506,7 +506,7 @@ importers: devDependencies: '@geometricpanda/storybook-addon-badges': specifier: 2.0.2 - version: 2.0.2(@storybook/blocks@7.6.17)(@storybook/components@7.6.17)(@storybook/core-events@7.6.17)(@storybook/manager-api@7.6.17)(@storybook/preview-api@7.6.17)(@storybook/theming@7.6.17)(@storybook/types@7.6.12)(react-dom@18.2.0)(react@18.2.0) + version: 2.0.2(@storybook/blocks@7.6.17)(@storybook/components@7.6.17)(@storybook/core-events@7.6.17)(@storybook/manager-api@7.6.17)(@storybook/preview-api@7.6.17)(@storybook/theming@7.6.17)(@storybook/types@7.6.17)(react-dom@18.2.0)(react@18.2.0) '@lit/task': specifier: 1.0.0 version: 1.0.0 @@ -563,7 +563,7 @@ importers: version: 7.6.17(lit@3.1.2)(react-dom@18.2.0)(react@18.2.0) '@storybook/web-components-vite': specifier: 7.6.17 - version: 7.6.17(lit@3.1.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.6)(vite@5.0.12) + version: 7.6.17(lit@3.1.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.6)(vite@5.1.5) '@types/css-modules': specifier: 1.0.5 version: 1.0.5 @@ -4380,7 +4380,7 @@ packages: /@floating-ui/utils@0.2.1: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} - /@geometricpanda/storybook-addon-badges@2.0.2(@storybook/blocks@7.6.17)(@storybook/components@7.6.17)(@storybook/core-events@7.6.17)(@storybook/manager-api@7.6.17)(@storybook/preview-api@7.6.17)(@storybook/theming@7.6.17)(@storybook/types@7.6.12)(react-dom@18.2.0)(react@18.2.0): + /@geometricpanda/storybook-addon-badges@2.0.2(@storybook/blocks@7.6.17)(@storybook/components@7.6.17)(@storybook/core-events@7.6.17)(@storybook/manager-api@7.6.17)(@storybook/preview-api@7.6.17)(@storybook/theming@7.6.17)(@storybook/types@7.6.17)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-RlJvQcSSXwwrN+ABc+2s1UDatWSUsba9TPX/TyNVyobuZZPvu+Bx1d2HVDCIVtXwhlrSvgVB2yr+nVa18edOgw==} peerDependencies: '@storybook/blocks': ^7.0.0 @@ -4404,7 +4404,7 @@ packages: '@storybook/manager-api': 7.6.17(react-dom@18.2.0)(react@18.2.0) '@storybook/preview-api': 7.6.17 '@storybook/theming': 7.6.17(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.6.12 + '@storybook/types': 7.6.17 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true @@ -6593,7 +6593,7 @@ packages: - supports-color dev: true - /@storybook/builder-vite@7.6.17(typescript@5.1.6)(vite@5.0.12): + /@storybook/builder-vite@7.6.17(typescript@5.1.6)(vite@5.1.5): resolution: {integrity: sha512-2Q32qalI401EsKKr9Hkk8TAOcHEerqwsjCpQgTNJnCu6GgCVKoVUcb99oRbR9Vyg0xh+jb19XiWqqQujFtLYlQ==} peerDependencies: '@preact/preset-vite': '*' @@ -6625,7 +6625,7 @@ packages: magic-string: 0.30.7 rollup: 3.29.4 typescript: 5.1.6 - vite: 5.0.12(sass@1.72.0) + vite: 5.1.5(@types/node@18.17.19)(less@4.2.0)(sass@1.72.0) transitivePeerDependencies: - encoding - supports-color @@ -6639,17 +6639,6 @@ packages: util-deprecate: 1.0.2 dev: true - /@storybook/channels@7.6.12: - resolution: {integrity: sha512-TaPl5Y3lOoVi5kTLgKNRX8xh2sUPekH0Id1l4Ymw+lpgriEY6r60bmkZLysLG1GhlskpQ/da2+S2ap2ht8P2TQ==} - dependencies: - '@storybook/client-logger': 7.6.12 - '@storybook/core-events': 7.6.12 - '@storybook/global': 5.0.0 - qs: 6.11.2 - telejson: 7.2.0 - tiny-invariant: 1.3.1 - dev: true - /@storybook/channels@7.6.17: resolution: {integrity: sha512-GFG40pzaSxk1hUr/J/TMqW5AFDDPUSu+HkeE/oqSWJbOodBOLJzHN6CReJS6y1DjYSZLNFt1jftPWZZInG/XUA==} dependencies: @@ -6719,12 +6708,6 @@ packages: global: 4.4.0 dev: true - /@storybook/client-logger@7.6.12: - resolution: {integrity: sha512-hiRv6dXsOttMPqm9SxEuFoAtDe9rs7TUS8XcO5rmJ9BgfwBJsYlHzAxXkazxmvlyZtKL7gMx6m8OYbCdZgUqtA==} - dependencies: - '@storybook/global': 5.0.0 - dev: true - /@storybook/client-logger@7.6.17: resolution: {integrity: sha512-6WBYqixAXNAXlSaBWwgljWpAu10tPRBJrcFvx2gPUne58EeMM20Gi/iHYBz2kMCY+JLAgeIH7ZxInqwO8vDwiQ==} dependencies: @@ -6819,12 +6802,6 @@ packages: core-js: 3.36.0 dev: true - /@storybook/core-events@7.6.12: - resolution: {integrity: sha512-IO4cwk7bBCKH6lLnnIlHO9FwQXt/9CzLUAoZSY9msWsdPppCdKlw8ynJI5YarSNKDBUn8ArIfnRf0Mve0KQr9Q==} - dependencies: - ts-dedent: 2.2.0 - dev: true - /@storybook/core-events@7.6.17: resolution: {integrity: sha512-AriWMCm/k1cxlv10f+jZ1wavThTRpLaN3kY019kHWbYT9XgaSuLU67G7GPr3cGnJ6HuA6uhbzu8qtqVCd6OfXA==} dependencies: @@ -7097,15 +7074,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/types@7.6.12: - resolution: {integrity: sha512-Wsbd+NS10/2yMHQ/26rXHflXam0hm2qufTFiHOX6VXZWxij3slRU88Fnwzp+1QSyjXb0qkEr8dOx7aG00+ItVw==} - dependencies: - '@storybook/channels': 7.6.12 - '@types/babel__core': 7.20.5 - '@types/express': 4.17.17 - file-system-cache: 2.3.0 - dev: true - /@storybook/types@7.6.17: resolution: {integrity: sha512-GRY0xEJQ0PrL7DY2qCNUdIfUOE0Gsue6N+GBJw9ku1IUDFLJRDOF+4Dx2BvYcVCPI5XPqdWKlEyZdMdKjiQN7Q==} dependencies: @@ -7115,11 +7083,11 @@ packages: file-system-cache: 2.3.0 dev: true - /@storybook/web-components-vite@7.6.17(lit@3.1.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.6)(vite@5.0.12): + /@storybook/web-components-vite@7.6.17(lit@3.1.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.6)(vite@5.1.5): resolution: {integrity: sha512-luBXrRP1OS9QfB+Sw7hcP0cktqQmbF41+m2R/3C56DjBckoh8ojw0CUIpNIktkN4rS9cB/NUGHvaeZSWuDtuFw==} engines: {node: ^14.18 || >=16} dependencies: - '@storybook/builder-vite': 7.6.17(typescript@5.1.6)(vite@5.0.12) + '@storybook/builder-vite': 7.6.17(typescript@5.1.6)(vite@5.1.5) '@storybook/core-server': 7.6.17 '@storybook/node-logger': 7.6.17 '@storybook/web-components': 7.6.17(lit@3.1.2)(react-dom@18.2.0)(react@18.2.0) @@ -11687,7 +11655,6 @@ packages: '@esbuild/win32-ia32': 0.20.1 '@esbuild/win32-x64': 0.20.1 dev: true - optional: true /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -15907,8 +15874,6 @@ packages: peerDependenciesMeta: webpack: optional: true - webpack-sources: - optional: true dependencies: webpack: 5.90.3(esbuild@0.20.1) webpack-sources: 3.2.3 @@ -20748,7 +20713,7 @@ packages: engines: {node: '>=8'} dev: true - /terser-webpack-plugin@5.3.10(webpack@5.90.3): + /terser-webpack-plugin@5.3.10(esbuild@0.20.1)(webpack@5.90.3): resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -20765,6 +20730,7 @@ packages: optional: true dependencies: '@jridgewell/trace-mapping': 0.3.22 + esbuild: 0.20.1 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.1 @@ -21885,42 +21851,6 @@ packages: replace-ext: 1.0.1 dev: true - /vite@5.0.12(sass@1.72.0): - resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.19.12 - postcss: 8.4.35 - rollup: 4.13.0 - sass: 1.72.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - /vite@5.1.5(@types/node@18.17.19)(less@4.2.0)(sass@1.72.0): resolution: {integrity: sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==} engines: {node: ^18.0.0 || >=20.0.0} @@ -22218,7 +22148,7 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.90.3) + terser-webpack-plugin: 5.3.10(esbuild@0.20.1)(webpack@5.90.3) watchpack: 2.4.0 webpack-sources: 3.2.3 transitivePeerDependencies: From 1dfcead84b3de2500087558c451f180b6aba8f54 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Thu, 21 Mar 2024 08:14:00 +0100 Subject: [PATCH 06/23] chore: fix styles typo --- packages/styles/src/components/dialog.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index 2f94cee125..7f495357d3 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -312,8 +312,8 @@ dialog:not([data-animation='none']) { // Animations dialog { - &[effect="bump-in"] { - --dialog-effect-closed-transform: + &[effect='bump-in'] { + --dialog-effect-closed-transform: translateY(-100%); } &[effect] { transition-behavior: allow-discrete; From b19cd2f89c985a431effc45c63b5049a6798b436 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Mon, 15 Apr 2024 11:36:06 +0200 Subject: [PATCH 07/23] refactor: split dialog up into variants --- .../components/dialog/dialog.stories.ts | 102 ++++++++----- .../styles/src/components/dialog-cookie.scss | 13 ++ .../src/components/dialog-notification.scss | 62 ++++++++ packages/styles/src/components/dialog.scss | 138 +++++------------- 4 files changed, 176 insertions(+), 139 deletions(-) create mode 100644 packages/styles/src/components/dialog-cookie.scss create mode 100644 packages/styles/src/components/dialog-notification.scss diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index 89f6e709f7..1354250aee 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -12,21 +12,16 @@ const meta: Meta = { }, }, args: { - variant: 'standard', notificationType: 'general', title: 'Dialog', content: 'This is a dialog', size: 'medium', + position: 'center', + backgroundColor: 'bg-white', + animation: 'pop-in', closeButton: true, }, argTypes: { - variant: { - name: 'Variant', - description: 'Choose which dialog variant to display', - control: 'radio', - options: ['standard', 'notification', 'cookie'], - table: { category: 'Variant' }, - }, notificationType: { name: 'Notification type', description: 'Choose the type of notification to display', @@ -54,11 +49,51 @@ const meta: Meta = { name: 'Size', description: 'Max width of the dialog.', control: { - type: 'select', + type: 'radio', }, options: ['small', 'medium', 'large'], table: { category: 'Variant' }, }, + position: { + name: 'Position', + description: 'Position of the dialog on the screen', + control: { + type: 'radio', + }, + options: ['top', 'center', 'bottom'], + table: { category: 'Variant' }, + }, + animation: { + name: 'Animation', + description: 'Choose an animation effect for showing and hidding the dialog.', + control: 'radio', + options: ['pop-in', 'slide-in', 'none'], + table: { category: 'Variant' }, + }, + icon: { + name: 'Icon', + description: 'Display an icon in the dialog.', + control: { + type: 'select', + labels: { + none: 'None', + 1034: '1034 (Info)', + 2104: '2104 (Danger)', + 2106: '2106 (Warning)', + 2105: '2105 (Success)', + }, + }, + options: ['none', '1034', '2105', '2104', '2106'], + }, + backgroundColor: { + name: 'Background color', + description: 'The background color of the dialog field', + control: { + type: 'select', + }, + options: ['bg-white', 'bg-light', 'bg-primary'], + table: { category: 'Variant' }, + }, closeButton: { name: 'Close button', description: 'Show a close button to dismiss the dialog', @@ -107,43 +142,36 @@ const getControls = () => { const Template = { render: (args: Args) => { - let variant = nothing; - let notificationType: symbol | string = nothing; - let backgroundColor: string | symbol = nothing; - - let icon: symbol | TemplateResult = nothing; - let header = getHeader(args.title); - let body = html`${args.content}`; + const header = getHeader(args.title); + const body = html`${args.content}`; const controls = getControls(); - const closeButton = args.closeButton ? getCloseButton() : nothing; - - if (args.variant === 'notification') { - variant = args.variant; - const { icon: iconNr } = notificationTypeIconMap[args.notificationType]; - notificationType = args.notificationType as string; - icon = html``; - header = getHeader(args.title); - } - if (args.variant === 'cookie') { - backgroundColor = 'bg-light'; - icon = html``; - variant = args.variant; - } + const postDialogIcon = + args.icon && args.icon !== 'none' + ? html`` + : nothing; + const postDialogCloseButton = args.closeButton + ? html`${getCloseButton()}` + : nothing; + + // Don't declare default values or show empty containers + if (args.backgroundColor === 'bg-white') args.backgroundColor = nothing; + if (args.animation === 'pop-in') args.animation = nothing; + if (args.position === 'center') args.position = nothing; + if (args.size === 'medium') args.size = nothing; + return html`
      - ${icon} + ${postDialogIcon} ${header} ${body} ${controls} - ${args.closeButton - ? html`${closeButton}` - : nothing} + ${postDialogCloseButton}
      `; diff --git a/packages/styles/src/components/dialog-cookie.scss b/packages/styles/src/components/dialog-cookie.scss new file mode 100644 index 0000000000..eb0d7f9baa --- /dev/null +++ b/packages/styles/src/components/dialog-cookie.scss @@ -0,0 +1,13 @@ +dialog[data-variant='cookie'] { + > .dialog-grid { + grid-template-columns: auto 1fr auto; + grid-template-areas: + 'icon header close-button' + 'icon body close-button' + 'controls controls controls'; + } + + post-dialog-icon { + align-self: flex-start; + } +} diff --git a/packages/styles/src/components/dialog-notification.scss b/packages/styles/src/components/dialog-notification.scss new file mode 100644 index 0000000000..2c43b4c7c0 --- /dev/null +++ b/packages/styles/src/components/dialog-notification.scss @@ -0,0 +1,62 @@ +dialog[data-variant='notification'] { + padding: 0; + + > .dialog-grid { + grid-template-columns: 1fr; + grid-template-areas: + 'close-button' + 'icon' + 'header' + 'body' + 'controls'; + } + + &[data-type='general'] { + --post-dialog-background-color: #{color.$info}; + } + + &[data-type='warning'] { + --post-dialog-background-color: #{color.$warning}; + } + + &[data-type='error'] { + --post-dialog-background-color: #{color.$error}; + } + + &[data-type='success'] { + --post-dialog-background-color: #{color.$success}; + } + + > .dialog-grid::before { + content: ''; + grid-area: close-button / close-button / header / header; + background-color: var(--post-dialog-background-color); + } + + post-dialog-close, + post-dialog-icon, + post-dialog-header, + post-dialog-body { + margin-top: spacing.$size-regular; + } + + post-dialog-header, + post-dialog-icon { + justify-self: center; + } + + post-dialog-header, + post-dialog-body, + post-dialog-controls { + padding-inline: spacing.$size-regular; + } + + post-dialog-close { + margin-right: spacing.$size-regular; + } + + post-dialog-header, + post-dialog-controls { + padding-bottom: spacing.$size-regular; + } +} diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index 7f495357d3..6018a81a33 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -1,4 +1,5 @@ @use '../mixins/elevation'; +@use '../mixins/utilities'; @use '../variables/spacing'; @use '../variables/color'; @use '../variables/animation'; @@ -6,7 +7,7 @@ @use './../themes/bootstrap/core' as *; // Prevent page from scrolling while a dialog is open -// Missing support for has is negligible, it's progressive enhancement. It will magically work some day +// Missing support for :has is negligible, it's progressive enhancement. It will magically work some day html:has(dialog[open]) { overflow: hidden; } @@ -14,26 +15,25 @@ html:has(dialog[open]) { dialog { @include elevation.elevation('elevation-5'); - padding: spacing.$size-regular spacing.$size-regular 0; - max-width: calc(100vw - 2rem); + padding: 0; + min-width: min(389px, 90vw); + max-width: 590px; max-height: 90vh; overflow: auto; overscroll-behavior: contain; - border-width: 0; - - // Show the border in HCM - @media (forced-colors: active) { - border-width: 2px; - } - - min-width: min(389px, 90vw); - max-width: 590px; + border: 2px solid var(--post-contrast-color); &::backdrop { background-color: rgba(0, 0, 0, 0.8); backdrop-filter: blur(0); + } + + @include utilities.high-contrast-mode { + // Show the border in HCM + border-width: 2px; - @media (forced-colors: active) { + // Mark the backdrop as inactive in HCM + &::backdrop { background-image: linear-gradient( 135deg, CanvasText 4.55%, @@ -51,112 +51,45 @@ dialog { } } - > .dialog-grid { - display: grid; - column-gap: spacing.$size-regular; - grid-template-columns: 1fr auto; - grid-template-areas: - 'header close-button' - 'body close-button' - 'controls controls'; - - // Propagate bg color to the controls - background-color: inherit; - } - + // Sizes + // [small, medium (default), large] &[data-size='small'] { min-width: 296px; max-width: 388px; } - // [size="medium"] is the standard case - &[data-size='large'] { min-width: min(600px, 90vw); max-width: 792px; } - &[data-variant='notification'] { - padding: 0; - - > .dialog-grid { - grid-template-columns: 1fr; - grid-template-areas: - 'close-button' - 'icon' - 'header' - 'body' - 'controls'; - } - - &[data-type='general'] { - --post-dialog-background-color: #{color.$info}; - } - - &[data-type='warning'] { - --post-dialog-background-color: #{color.$warning}; - } - - &[data-type='error'] { - --post-dialog-background-color: #{color.$error}; - } - - &[data-type='success'] { - --post-dialog-background-color: #{color.$success}; - } - - > .dialog-grid::before { - content: ''; - grid-area: close-button / close-button / header / header; - background-color: var(--post-dialog-background-color); - } - - post-dialog-close, - post-dialog-icon, - post-dialog-header, - post-dialog-body { - margin-top: spacing.$size-regular; - } - - post-dialog-header, - post-dialog-icon { - justify-self: center; - } - - post-dialog-header, - post-dialog-body, - post-dialog-controls { - padding-inline: spacing.$size-regular; - } - - post-dialog-close { - margin-right: spacing.$size-regular; - } - - post-dialog-header, - post-dialog-controls { - padding-bottom: spacing.$size-regular; - } + // Positioning + // [top, center (default), bottom] + &[data-position='top'] { + top: 2rem; + bottom: auto; } - &[data-variant='cookie'] { + &[data-position='bottom'] { top: auto; bottom: 2rem; - - > .dialog-grid { - grid-template-columns: auto 1fr auto; - grid-template-areas: - 'icon header close-button' - 'icon body close-button' - 'controls controls controls'; - } - - post-dialog-icon { - align-self: flex-start; - } } } +dialog > .dialog-grid { + margin: spacing.$size-regular spacing.$size-regular 0 spacing.$size-regular; + display: grid; + column-gap: spacing.$size-regular; + grid-template-columns: auto 1fr auto; + grid-template-areas: + 'icon header close-button' + 'icon body close-button' + 'controls controls controls'; + + // Propagate bg color to the controls + background-color: inherit; +} + :where( post-dialog-icon, post-dialog-header, @@ -233,6 +166,7 @@ post-dialog-close { } // Animations +// [slide-in, pop-in, none] // Progressively enhanced with currently experimental @starting-style which allows to animate stuff appearing in the top layer dialog:not([data-animation='none']) { --_dialog-transition-duration: var(--dialog-transition-duration, 0.5s); From 49b38758fa05325336439a4978d90bcdb3cfe06c Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Wed, 29 May 2024 21:20:20 +0200 Subject: [PATCH 08/23] fix: animations --- packages/styles/src/components/dialog.scss | 40 +++++++--------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index 6018a81a33..d3bb186795 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -21,7 +21,7 @@ dialog { max-height: 90vh; overflow: auto; overscroll-behavior: contain; - border: 2px solid var(--post-contrast-color); + border: 2px solid var(--post-contrast-color); // Ensures good contrast when bg is dark against dark backdrop &::backdrop { background-color: rgba(0, 0, 0, 0.8); @@ -168,6 +168,7 @@ post-dialog-close { // Animations // [slide-in, pop-in, none] // Progressively enhanced with currently experimental @starting-style which allows to animate stuff appearing in the top layer +// https://developer.mozilla.org/en-US/docs/Web/CSS/@starting-style dialog:not([data-animation='none']) { --_dialog-transition-duration: var(--dialog-transition-duration, 0.5s); @@ -229,39 +230,22 @@ dialog:not([data-animation='none']) { } } - &[data-variant='cookie'] { - opacity: 1; // Reset default - transform: translateY(calc(100% + 3rem)); + &[data-animation='slide-in'] { + &[data-position='top'] { + --_dialog-slide-in-offset: -3rem; + } + &[data-position='bottom'] { + --_dialog-slide-in-offset: 3rem; + } + + transform: translateY(calc(var(--_dialog-slide-in-offset))); &[open] { transform: translateY(0); @starting-style { - transform: translateY(calc(100% + 3rem)); + transform: translateY(calc(var(--_dialog-slide-in-offset))); } } } } - -// Animations - -dialog { - &[effect='bump-in'] { - --dialog-effect-closed-transform: translateY(-100%); - } - &[effect] { - transition-behavior: allow-discrete; - transition-duration: animation.$transition-time-default; - transition-timing-function: animation.$transition-easing-bump-in; - - // Closed state - transform: var(--dialog-effect-closed-transform); - opacity: var(--dialog-effect-closed-opacity); - - // Open state - &[open] { - transform: translate(0, 0); - opacity: 1; - } - } -} From beed7259d1007f50e638feba2ddd239d2c1f9431 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Fri, 9 Aug 2024 14:08:49 +0200 Subject: [PATCH 09/23] chore: clean up and scope down to just dialog --- .../stories/components/dialog/dialog.docs.mdx | 9 +-- .../components/dialog/dialog.stories.ts | 20 +----- .../styles/src/components/dialog-cookie.scss | 13 ---- .../src/components/dialog-notification.scss | 62 ------------------- 4 files changed, 6 insertions(+), 98 deletions(-) delete mode 100644 packages/styles/src/components/dialog-cookie.scss delete mode 100644 packages/styles/src/components/dialog-notification.scss diff --git a/packages/documentation/src/stories/components/dialog/dialog.docs.mdx b/packages/documentation/src/stories/components/dialog/dialog.docs.mdx index 530ba4df9a..d6b002f1de 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.docs.mdx +++ b/packages/documentation/src/stories/components/dialog/dialog.docs.mdx @@ -37,9 +37,6 @@ import AngularFormData from './samples/angular-form-data?raw'; - -## Cookie banner - - -## Custom content banner - \ No newline at end of file +## Custom content dialog +The dialog can also contain arbitrary content. + diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index 1354250aee..8a8c5fd8bf 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -1,12 +1,10 @@ -import { BADGE } from '@geometricpanda/storybook-addon-badges'; import { Args, Meta, StoryObj } from '@storybook/web-components'; -import { TemplateResult, html, nothing } from 'lit-html'; +import { html, nothing } from 'lit-html'; const meta: Meta = { id: '562eac2b-6dc1-4007-ba8e-4e981cef0cbc', title: 'Components/Dialog', parameters: { - badges: [BADGE.NEEDS_REVISION], design: { type: 'figma', }, @@ -84,6 +82,7 @@ const meta: Meta = { }, }, options: ['none', '1034', '2105', '2104', '2106'], + table: { category: 'Content' }, }, backgroundColor: { name: 'Background color', @@ -223,7 +222,7 @@ const CustomContentTemplate = { render: (args: Args) => { return html` -
      +

      Custom content

      This is some other content, just placed inside the dialog.

      @@ -233,15 +232,6 @@ const CustomContentTemplate = { }, }; -const CookieTemplate = { - ...Template, - args: { - variant: 'cookie', - closeButton: false, - size: 'large', - }, -}; - type Story = StoryObj; export const Default: Story = { @@ -252,10 +242,6 @@ export const Form: Story = { ...FormTemplate, }; -export const Cookie: Story = { - ...CookieTemplate, -}; - export const Custom: Story = { ...CustomContentTemplate, }; diff --git a/packages/styles/src/components/dialog-cookie.scss b/packages/styles/src/components/dialog-cookie.scss deleted file mode 100644 index eb0d7f9baa..0000000000 --- a/packages/styles/src/components/dialog-cookie.scss +++ /dev/null @@ -1,13 +0,0 @@ -dialog[data-variant='cookie'] { - > .dialog-grid { - grid-template-columns: auto 1fr auto; - grid-template-areas: - 'icon header close-button' - 'icon body close-button' - 'controls controls controls'; - } - - post-dialog-icon { - align-self: flex-start; - } -} diff --git a/packages/styles/src/components/dialog-notification.scss b/packages/styles/src/components/dialog-notification.scss deleted file mode 100644 index 2c43b4c7c0..0000000000 --- a/packages/styles/src/components/dialog-notification.scss +++ /dev/null @@ -1,62 +0,0 @@ -dialog[data-variant='notification'] { - padding: 0; - - > .dialog-grid { - grid-template-columns: 1fr; - grid-template-areas: - 'close-button' - 'icon' - 'header' - 'body' - 'controls'; - } - - &[data-type='general'] { - --post-dialog-background-color: #{color.$info}; - } - - &[data-type='warning'] { - --post-dialog-background-color: #{color.$warning}; - } - - &[data-type='error'] { - --post-dialog-background-color: #{color.$error}; - } - - &[data-type='success'] { - --post-dialog-background-color: #{color.$success}; - } - - > .dialog-grid::before { - content: ''; - grid-area: close-button / close-button / header / header; - background-color: var(--post-dialog-background-color); - } - - post-dialog-close, - post-dialog-icon, - post-dialog-header, - post-dialog-body { - margin-top: spacing.$size-regular; - } - - post-dialog-header, - post-dialog-icon { - justify-self: center; - } - - post-dialog-header, - post-dialog-body, - post-dialog-controls { - padding-inline: spacing.$size-regular; - } - - post-dialog-close { - margin-right: spacing.$size-regular; - } - - post-dialog-header, - post-dialog-controls { - padding-bottom: spacing.$size-regular; - } -} From f023e4f5ddb3821e647733885382a19216df7e98 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Fri, 9 Aug 2024 14:09:13 +0200 Subject: [PATCH 10/23] chore: deprecate notification without replacement There will be a new notification concept for Design v2 --- .../notification-overlay/notification-overlay.docs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/documentation/src/stories/components/notification-overlay/notification-overlay.docs.mdx b/packages/documentation/src/stories/components/notification-overlay/notification-overlay.docs.mdx index a36b189d9e..910ea235e7 100644 --- a/packages/documentation/src/stories/components/notification-overlay/notification-overlay.docs.mdx +++ b/packages/documentation/src/stories/components/notification-overlay/notification-overlay.docs.mdx @@ -21,7 +21,7 @@ import basicExampleAngular from './notification-overlay.sample.ts?raw';

      Present the user with important information or a decision before continuing the workflow.

      - This component is deprecated in favor of the dialog component. + This component is deprecated and will be removed in a future major version.
        From fd8c570df6a37a23354b8ed43ba5b37186bb9c87 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Fri, 9 Aug 2024 14:12:09 +0200 Subject: [PATCH 11/23] fix: linting --- packages/documentation/package.json | 2 +- packages/migrations/package.json | 2 +- packages/styles/src/components/dialog.scss | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/documentation/package.json b/packages/documentation/package.json index 6e308b332a..ff879ebe9d 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -25,7 +25,7 @@ "e2e:watch": "cypress open", "doctor": "storybook doctor", "snapshots": "percy exec -- cypress run --config-file ./cypress.snapshot.config.js --record --key 0995e768-43ec-42bd-a127-ff944a2ad8c9", - "lint": "eslint **/*.{js,ts,tsx,mdx}" + "lint": "eslint **/*.{ts,tsx,mdx}" }, "dependencies": { "@swisspost/design-system-components": "workspace:8.1.0", diff --git a/packages/migrations/package.json b/packages/migrations/package.json index 436b38f4fb..c5dca9d8fd 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -18,7 +18,7 @@ "copy-files": "copyfiles -f LICENSE README.md package.json CONTRIBUTING.md CHANGELOG.md src/migrations.json dist", "build": "tsc -p tsconfig.json && pnpm copy-files", "clean": "rimraf dist", - "lint": "eslint **/*.{js,ts}" + "lint": "eslint **/*.ts" }, "dependencies": { "@angular-devkit/core": "=15.0.4", diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index d3bb186795..29848e7fa1 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -234,6 +234,7 @@ dialog:not([data-animation='none']) { &[data-position='top'] { --_dialog-slide-in-offset: -3rem; } + &[data-position='bottom'] { --_dialog-slide-in-offset: 3rem; } From dac7bb577625f968a3f40f4cdd331bc83a2e1c33 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Fri, 9 Aug 2024 15:06:15 +0200 Subject: [PATCH 12/23] fix: disable this behavior, does not work with non-modal dialogs --- packages/styles/src/components/dialog.scss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index 29848e7fa1..41cb97a825 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -6,12 +6,6 @@ @use './../themes/bootstrap/core' as *; -// Prevent page from scrolling while a dialog is open -// Missing support for :has is negligible, it's progressive enhancement. It will magically work some day -html:has(dialog[open]) { - overflow: hidden; -} - dialog { @include elevation.elevation('elevation-5'); From e30517673108399a33441cffa7f7ff78adf9c511 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Fri, 9 Aug 2024 15:07:30 +0200 Subject: [PATCH 13/23] chore: add snapshot tests --- .../snapshots/components/dialog.snapshot.ts | 7 ++++ packages/documentation/package.json | 2 +- .../dialog/dialog.snapshot.stories.ts | 40 +++++++++++++++++++ .../components/dialog/dialog.stories.ts | 32 +++++---------- 4 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 packages/documentation/cypress/snapshots/components/dialog.snapshot.ts create mode 100644 packages/documentation/src/stories/components/dialog/dialog.snapshot.stories.ts diff --git a/packages/documentation/cypress/snapshots/components/dialog.snapshot.ts b/packages/documentation/cypress/snapshots/components/dialog.snapshot.ts new file mode 100644 index 0000000000..7ec2745610 --- /dev/null +++ b/packages/documentation/cypress/snapshots/components/dialog.snapshot.ts @@ -0,0 +1,7 @@ +describe('Dialog', () => { + it('default', () => { + cy.visit('/iframe.html?id=snapshots--dialog'); + cy.get('dialog[open]', { timeout: 30000 }).should('be.visible'); + cy.percySnapshot('Dialog', { widths: [1440] }); + }); +}); diff --git a/packages/documentation/package.json b/packages/documentation/package.json index ff879ebe9d..aa293a8634 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -16,7 +16,7 @@ "private": true, "scripts": { "prebuild:managerui": "sass --update --load-path=node_modules .storybook/styles/manager.scss public/manager/ui.css", - "start": "pnpm clean && pnpm prebuild:managerui --style=expanded & storybook dev -p 9000 --quiet --docs", + "start": "pnpm clean && pnpm prebuild:managerui --style=expanded & storybook dev -p 9000 --quiet", "start:headless": "pnpm clean && pnpm prebuild:managerui --style=expanded && storybook dev -p 9001 --quiet --no-open --docs", "build": "pnpm clean && pnpm prebuild:managerui --style=compressed --no-source-map & storybook build --quiet --docs", "clean": "rimraf storybook-static public/manager", diff --git a/packages/documentation/src/stories/components/dialog/dialog.snapshot.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.snapshot.stories.ts new file mode 100644 index 0000000000..0351c31a40 --- /dev/null +++ b/packages/documentation/src/stories/components/dialog/dialog.snapshot.stories.ts @@ -0,0 +1,40 @@ +import meta, { Default } from './dialog.stories'; +import { html } from 'lit'; +import { bombArgs } from '@root/src/utils'; +import type { Args, StoryContext, StoryObj } from '@storybook/web-components'; + +const { id, ...metaWithoutId } = meta; + +export default { + ...metaWithoutId, + title: 'Snapshots', +}; + +type Story = StoryObj; + +export const Dialog: Story = { + render: (_args: Args, context: StoryContext) => { + return html` + +
        + ${bombArgs({ + backgroundColor: ['bg-white', 'bg-primary'], + size: context.argTypes.size.options, + icon: ['none', '1034'], + closeButton: [true, false], + content: [ + 'Content', + 'Contentus momentus vero siteos et accusam iretea et justo. Contentus momentus vero siteos et accusam iretea et justo.', + ], + open: [true], + }).map((args: Args) => Default.render?.({ ...context.args, ...args }, context))} +
        + `; + }, +}; diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index 8a8c5fd8bf..5334a8e81e 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -10,7 +10,6 @@ const meta: Meta = { }, }, args: { - notificationType: 'general', title: 'Dialog', content: 'This is a dialog', size: 'medium', @@ -18,19 +17,9 @@ const meta: Meta = { backgroundColor: 'bg-white', animation: 'pop-in', closeButton: true, + open: false, }, argTypes: { - notificationType: { - name: 'Notification type', - description: 'Choose the type of notification to display', - control: 'select', - options: ['general', 'error', 'warning', 'success', 'brand'], - if: { - arg: 'variant', - eq: 'notification', - }, - table: { category: 'Variant' }, - }, title: { name: 'Title', description: 'Optional title', @@ -99,6 +88,12 @@ const meta: Meta = { control: 'boolean', table: { category: 'Content' }, }, + open: { + name: 'Default open', + description: 'Test property for snapshots', + control: 'boolean', + table: { disable: true }, + }, }, decorators: [ (story: Function) => @@ -116,14 +111,6 @@ const meta: Meta = { export default meta; -const notificationTypeIconMap: { [key: string]: { icon: number; color: string } } = { - general: { icon: 1034, color: 'bg-info' }, - error: { icon: 2104, color: 'bg-danger' }, - warning: { icon: 2106, color: 'bg-warning' }, - success: { icon: 2105, color: 'bg-success' }, - brand: { icon: 1034, color: 'bg-yellow' }, -}; - const getHeader = (text: string) => { return html`

        ${text}

        `; }; @@ -164,6 +151,7 @@ const Template = { data-size="${args.size}" data-position="${args.position}" data-animation="${args.animation}" + open="${args.open || nothing}" > ${postDialogIcon} @@ -219,9 +207,9 @@ const FormTemplate = { const CustomContentTemplate = { ...Template, - render: (args: Args) => { + render: () => { return html` - +

        Custom content

        This is some other content, just placed inside the dialog.

        From 5da958c2339e053a92ca6d4a101e226438a4e1a9 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Fri, 9 Aug 2024 15:22:29 +0200 Subject: [PATCH 14/23] fix: linting errors --- .../src/stories/components/dialog/dialog.stories.ts | 2 +- .../src/stories/components/dialog/samples/js-form-data.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index 5334a8e81e..4e2237fb74 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -96,7 +96,7 @@ const meta: Meta = { }, }, decorators: [ - (story: Function) => + story => html`
        + + +## Examples + ### Form dialog -### Using form data +#### Using form data HTML & CSS @@ -39,6 +44,6 @@ import AngularFormData from './samples/angular-form-data?raw'; -## Custom content dialog +### Custom content dialog The dialog can also contain arbitrary content. diff --git a/packages/documentation/src/stories/components/dialog/dialog.snapshot.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.snapshot.stories.ts index 0351c31a40..9160ab7f2d 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.snapshot.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.snapshot.stories.ts @@ -1,6 +1,6 @@ import meta, { Default } from './dialog.stories'; import { html } from 'lit'; -import { bombArgs } from '@root/src/utils'; +import { bombArgs } from '@/utils'; import type { Args, StoryContext, StoryObj } from '@storybook/web-components'; const { id, ...metaWithoutId } = meta; diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index 4e2237fb74..950f469721 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -7,6 +7,7 @@ const meta: Meta = { parameters: { design: { type: 'figma', + url: 'https://www.figma.com/design/xZ0IW0MJO0vnFicmrHiKaY/Components-Post?node-id=20215-22938&m=dev', }, }, args: { @@ -14,6 +15,7 @@ const meta: Meta = { content: 'This is a dialog', size: 'medium', position: 'center', + icon: 'none', backgroundColor: 'bg-white', animation: 'pop-in', closeButton: true, From 55b3f024ef6fdacb19c2f3dd088c16e71b3622bb Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Tue, 10 Sep 2024 10:00:34 +0200 Subject: [PATCH 20/23] update docs and styles to use classes instead of custom elements --- .../components/dialog/dialog.stories.ts | 22 ++++----- packages/styles/src/components/dialog.scss | 48 +++++++------------ 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index 950f469721..10c5adb5f8 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -135,11 +135,9 @@ const Template = { const controls = getControls(); const postDialogIcon = args.icon && args.icon !== 'none' - ? html`` + ? html`` : nothing; - const postDialogCloseButton = args.closeButton - ? html`${getCloseButton()}` - : nothing; + const postDialogCloseButton = args.closeButton ? getCloseButton() : nothing; // Don't declare default values or show empty containers if (args.backgroundColor === 'bg-white') args.backgroundColor = nothing; @@ -157,9 +155,9 @@ const Template = { > ${postDialogIcon} - ${header} - ${body} - ${controls} +

        ${header}

        +
        ${body}
        +
        ${controls}
        ${postDialogCloseButton}
        @@ -178,8 +176,8 @@ const FormTemplate = { class="dialog-grid" onsubmit="console.log(Object.fromEntries(new FormData(event.target)))" > -

        Form example

        - +

        Form example

        +
        - +
        - +
        - +
        `; diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index 41cb97a825..434982e190 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -84,43 +84,32 @@ dialog > .dialog-grid { background-color: inherit; } -:where( - post-dialog-icon, - post-dialog-header, - post-dialog-body, - post-dialog-controls, - post-dialog-close - ):empty { +:where(.dialog-icon, .dialog-header, .dialog-body, .dialog-controls, .dialog-close):empty { display: none; } -post-dialog-icon { +.dialog-grid > post-icon { grid-area: icon; display: block; - > post-icon { - width: spacing.$size-big; - height: spacing.$size-big; + width: spacing.$size-big; + height: spacing.$size-big; - // Larger icon for bigger notification dialogs - dialog:not([size='small']) & { - @include media-breakpoint-up(rg) { - width: spacing.$size-small-huge; - height: spacing.$size-small-huge; - } + // Larger icon for bigger notification dialogs + dialog:not([size='small']) & { + @include media-breakpoint-up(rg) { + width: spacing.$size-small-huge; + height: spacing.$size-small-huge; } } } -post-dialog-header { +.dialog-header { grid-area: header; - - > *:first-child { - margin-top: 0; - } + margin-top: 0; } -post-dialog-body { +.dialog-body { grid-area: body; margin-bottom: 0; @@ -129,7 +118,7 @@ post-dialog-body { } } -post-dialog-controls { +.dialog-controls { grid-area: controls; position: sticky; bottom: 0; @@ -147,16 +136,13 @@ post-dialog-controls { } } -post-dialog-close { +.dialog-grid > .btn-close { position: sticky; top: 0; grid-area: close-button; - - > .btn-close { - width: spacing.$size-large; - height: spacing.$size-large; - min-height: 0; - } + width: spacing.$size-large; + height: spacing.$size-large; + min-height: 0; } // Animations From 8f38ff749cdf3675f57ad6e0f1bcce3d8344c15d Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Tue, 10 Sep 2024 10:02:37 +0200 Subject: [PATCH 21/23] removed angular form data example --- .../stories/components/dialog/dialog.docs.mdx | 26 +++++-------------- .../dialog/samples/angular-form-data.ts | 1 - 2 files changed, 6 insertions(+), 21 deletions(-) delete mode 100644 packages/documentation/src/stories/components/dialog/samples/angular-form-data.ts diff --git a/packages/documentation/src/stories/components/dialog/dialog.docs.mdx b/packages/documentation/src/stories/components/dialog/dialog.docs.mdx index 57eb024cee..91ab622432 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.docs.mdx +++ b/packages/documentation/src/stories/components/dialog/dialog.docs.mdx @@ -1,7 +1,6 @@ import { Canvas, Controls, Meta, Source } from '@storybook/blocks'; import * as DialogStories from './dialog.stories'; import JSFormData from './samples/js-form-data?raw'; -import AngularFormData from './samples/angular-form-data?raw'; import StylesPackageImport from '@/shared/styles-package-import.mdx'; @@ -24,25 +23,12 @@ import StylesPackageImport from '@/shared/styles-package-import.mdx'; #### Using form data - - HTML & CSS - Angular - - - Register a `submit` event listener on the form. In the event handler, you have access to all the form field values inside the dialog. The dialog box closes when the form gets submitted. - - - - - - - +Register a `submit` event listener on the form. In the event handler, you have access to all the form field values inside the dialog. The dialog box closes when the form gets submitted. + + ### Custom content dialog The dialog can also contain arbitrary content. diff --git a/packages/documentation/src/stories/components/dialog/samples/angular-form-data.ts b/packages/documentation/src/stories/components/dialog/samples/angular-form-data.ts deleted file mode 100644 index 954ddd236b..0000000000 --- a/packages/documentation/src/stories/components/dialog/samples/angular-form-data.ts +++ /dev/null @@ -1 +0,0 @@ -// TBD From df30dca6777710db73bd0c62760d7df17aa46f74 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Mon, 7 Oct 2024 12:15:04 +0200 Subject: [PATCH 22/23] chore: fix dialog display --- .../src/stories/components/dialog/dialog.stories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/documentation/src/stories/components/dialog/dialog.stories.ts b/packages/documentation/src/stories/components/dialog/dialog.stories.ts index 10c5adb5f8..24569321fe 100644 --- a/packages/documentation/src/stories/components/dialog/dialog.stories.ts +++ b/packages/documentation/src/stories/components/dialog/dialog.stories.ts @@ -209,7 +209,7 @@ const CustomContentTemplate = { ...Template, render: () => { return html` - +

        Custom content

        This is some other content, just placed inside the dialog.

        From 3021bb0492c46cdb42a34d5c13ae5c30ce13ed19 Mon Sep 17 00:00:00 2001 From: Philipp Gfeller Date: Tue, 8 Oct 2024 16:28:38 +0200 Subject: [PATCH 23/23] revert margins for the dialog --- packages/styles/src/components/dialog.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/styles/src/components/dialog.scss b/packages/styles/src/components/dialog.scss index 434982e190..f3bf5211df 100644 --- a/packages/styles/src/components/dialog.scss +++ b/packages/styles/src/components/dialog.scss @@ -14,6 +14,7 @@ dialog { max-width: 590px; max-height: 90vh; overflow: auto; + margin: revert; overscroll-behavior: contain; border: 2px solid var(--post-contrast-color); // Ensures good contrast when bg is dark against dark backdrop