diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/dialog/Examples.tsx b/packages/dnb-design-system-portal/src/docs/uilib/components/dialog/Examples.tsx index 319bf43f707..30e54ec3de9 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/components/dialog/Examples.tsx +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/dialog/Examples.tsx @@ -55,6 +55,19 @@ export const DialogExampleHelpButton = () => ( ) +export const DialogExampleVerticalAlignment = () => ( + + + +) + export const DialogExampleFullscreen = () => ( +### Top aligned Dialog + + + ### Dialog with custom trigger diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/dialog/prop-table.mdx b/packages/dnb-design-system-portal/src/docs/uilib/components/dialog/prop-table.mdx index cc7a2fdce9e..7064ba325b5 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/components/dialog/prop-table.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/dialog/prop-table.mdx @@ -1,23 +1,6 @@ -| Properties | Description | -| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `variant` | _(optional)_ The dialog variant. Can either be `information` or `confirmation`. Defaults to `information`. | -| `title` | _(optional)_ The dialog title. Displays on the very top of the content. | -| `minWidth` | _(optional)_ The minimum Dialog content width, defined by a CSS width value like `50vw` (50% of the viewport). Be careful on using fixed `minWidth` so you don't break responsiveness. Defaults to `30rem` (average width is set to `60vw`). | -| `maxWidth` | _(optional)_ The maximum Dialog content width, defined by a CSS width value like `20rem`. Defaults to `60rem` (average width is set to `60vw`). | -| `className` | _(optional)_ Give the Dialog content a class name (maps to `dnb-dialog`). | -| `spacing` | _(optional)_ If set to `false` then the dialog content will be shown without any spacing. Defaults to `true`. | -| `preventCoreStyle` | _(optional)_ By default the dialog content gets added the core style class `dnb-core-style`. Use `false` to disable this behavior. | -| `navContent` | _(optional)_ The content which will appear in the navigation, above the header, and side-by-side the close button. | -| `headerContent` | _(optional)_ The content which will appear in the header of the dialog. | -| `modalContent` | _(optional)_ The content which will appear when triggering the dialog. | -| `description` | _(optional)_ A description will be positioned below the title, but before the content. Used for Dialog variant `confirmation` to further describe what the actions will do. | -| `alignContent` | _(optional)_ Define the inner horizontal alignment of the content. Can be set to `left`, `center`, `right` and `centered`. If `centered`, then the content will also be centered vertically. Defaults to `left`. | -| `fullscreen` | _(optional)_ If set to `true` then the dialog content will be shown as fullscreen, without showing the original content behind. Can be set to `false` to omit the auto fullscreen. Defaults to `auto`. | -| `icon` | _(optional)_ An icon to display at the top of the component. Should be of size medium, so make sure you import the `_medium` version of the Eufemia icon. | -| `confirmType` | _(optional)_ For variant confirmation, the dialog is either an informational (`info`) or a warning (`warning`) message. Defaults to 'info'. | -| `declineText` | _(optional)_ For dialog actions, give a custom text for the decline button. | -| `confirmText` | _(optional)_ For dialog actions, give a custom text for the confirmation button. | -| `hideDecline` | _(optional)_ For variant confirmation, hide the default decline button and only show the confirmation button. | -| `hideConfirm` | _(optional)_ For variant confirmation, hide the default confirm button and only show the decline button. | -| `scrollRef` | _(optional)_ To get the scroll Element, pass in your own React ref. | -| `contentRef` | _(optional)_ To get the inner content Element, pass in your own React ref. | +import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable' +import { DialogProperties } from '@dnb/eufemia/src/components/dialog/DialogDocs' + +## Properties + + diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/drawer/prop-table.mdx b/packages/dnb-design-system-portal/src/docs/uilib/components/drawer/prop-table.mdx index 69a6fa3275a..24feda75c9a 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/components/drawer/prop-table.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/drawer/prop-table.mdx @@ -1,6 +1,3 @@ ---- ---- - | Properties | Description | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `containerPlacement` | _(optional)_ Defines on what side the Drawer should be opened. Can be set to `left`, `right`, `top` and `bottom`. Defaults to `right`. | diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/modal/event-table-camel-case.mdx b/packages/dnb-design-system-portal/src/docs/uilib/components/modal/event-table-camel-case.mdx index c19a6d1b87b..832c24b3260 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/components/modal/event-table-camel-case.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/modal/event-table-camel-case.mdx @@ -1,6 +1,3 @@ ---- ---- - | Events | Description | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `onOpen` | _(optional)_ This event gets triggered once the modal shows up. Returns the modal id: `{ id }`. | diff --git a/packages/dnb-design-system-portal/src/docs/uilib/components/modal/event-table.mdx b/packages/dnb-design-system-portal/src/docs/uilib/components/modal/event-table.mdx index d14e2fe5572..9f32d045fae 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/components/modal/event-table.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/components/modal/event-table.mdx @@ -1,6 +1,3 @@ ---- ---- - | Events | Description | | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `onOpen` / `on_open` | _(optional)_ This event gets triggered once the modal shows up. Returns the modal id: `{ id }`. | diff --git a/packages/dnb-eufemia/src/components/dialog/Dialog.tsx b/packages/dnb-eufemia/src/components/dialog/Dialog.tsx index db572c8c09c..8dd86795524 100644 --- a/packages/dnb-eufemia/src/components/dialog/Dialog.tsx +++ b/packages/dnb-eufemia/src/components/dialog/Dialog.tsx @@ -42,6 +42,7 @@ function Dialog(localProps: DialogProps & DialogContentProps) { dialogTitle, closeTitle, spacing, + verticalAlignment, noAnimation, noAnimationOnMobile, animationDuration, @@ -100,6 +101,7 @@ function Dialog(localProps: DialogProps & DialogContentProps) { labelledBy, disabled, spacing, + verticalAlignment, openDelay, contentId, dialogTitle, diff --git a/packages/dnb-eufemia/src/components/dialog/DialogDocs.ts b/packages/dnb-eufemia/src/components/dialog/DialogDocs.ts new file mode 100644 index 00000000000..9276a745d88 --- /dev/null +++ b/packages/dnb-eufemia/src/components/dialog/DialogDocs.ts @@ -0,0 +1,114 @@ +import { PropertiesTableProps } from '../../shared/types' + +export const DialogProperties: PropertiesTableProps = { + variant: { + doc: 'The dialog variant. Can either be `information` or `confirmation`. Defaults to `information`.', + type: 'string', + status: 'optional', + }, + title: { + doc: 'The dialog title. Displays on the very top of the content.', + type: 'string', + status: 'optional', + }, + minWidth: { + doc: "The minimum Dialog content width, defined by a CSS width value like `50vw` (50% of the viewport). Be careful on using fixed `minWidth` so you don't break responsiveness. Defaults to `30rem` (average width is set to `60vw`).", + type: 'string', + status: 'optional', + }, + maxWidth: { + doc: 'The maximum Dialog content width, defined by a CSS width value like `20rem`. Defaults to `60rem` (average width is set to `60vw`).', + type: 'string', + status: 'optional', + }, + className: { + doc: 'Give the Dialog content a class name (maps to `dnb-dialog`).', + type: 'string', + status: 'optional', + }, + spacing: { + doc: 'If set to `false` then the dialog content will be shown without any spacing. Defaults to `true`.', + type: 'boolean', + status: 'optional', + }, + preventCoreStyle: { + doc: 'By default the dialog content gets added the core style class `dnb-core-style`. Use `false` to disable this behavior.', + type: 'boolean', + status: 'optional', + }, + navContent: { + doc: 'The content which will appear in the navigation, above the header, and side-by-side the close button.', + type: 'React.Node', + status: 'optional', + }, + headerContent: { + doc: 'The content which will appear in the header of the dialog.', + type: 'React.Node', + status: 'optional', + }, + modalContent: { + doc: 'The content which will appear when triggering the dialog.', + type: 'React.Node', + status: 'optional', + }, + description: { + doc: 'A description will be positioned below the title, but before the content. Used for Dialog variant `confirmation` to further describe what the actions will do.', + type: 'string', + status: 'optional', + }, + verticalAlignment: { + doc: 'Define the vertical alignment of the container. Can be set to `top` or `center`. Defaults to `center`.', + type: 'string', + status: 'optional', + }, + alignContent: { + doc: 'Define the inner horizontal alignment of the content. Can be set to `left`, `center`, `right` and `centered`. If `centered`, then the content will also be centered vertically. Defaults to `left`.', + type: 'string', + status: 'optional', + }, + fullscreen: { + doc: 'If set to `true` then the dialog content will be shown as fullscreen, without showing the original content behind. Can be set to `false` to omit the auto fullscreen. Defaults to `auto`.', + type: 'boolean', + status: 'optional', + }, + icon: { + doc: 'An icon to display at the top of the component. Should be of size medium, so make sure you import the `_medium` version of the Eufemia icon.', + type: 'React.Node', + status: 'optional', + }, + confirmType: { + doc: 'For variant confirmation, the dialog is either an informational (`info`) or a warning (`warning`) message. Defaults to `info`.', + type: 'string', + status: 'optional', + }, + declineText: { + doc: 'For dialog actions, give a custom text for the decline button.', + type: 'string', + status: 'optional', + }, + confirmText: { + doc: 'For dialog actions, give a custom text for the confirmation button.', + type: 'string', + status: 'optional', + }, + hideDecline: { + doc: 'For variant confirmation, hide the default decline button and only show the confirmation button.', + type: 'boolean', + status: 'optional', + }, + hideConfirm: { + doc: 'For variant confirmation, hide the default confirm button and only show the decline button.', + type: 'boolean', + status: 'optional', + }, + scrollRef: { + doc: 'To get the scroll Element, pass in your own React ref.', + type: 'React.Ref', + status: 'optional', + }, + contentRef: { + doc: 'To get the inner content Element, pass in your own React ref.', + type: 'React.Ref', + status: 'optional', + }, +} diff --git a/packages/dnb-eufemia/src/components/dialog/__tests__/Dialog.screenshot.test.ts b/packages/dnb-eufemia/src/components/dialog/__tests__/Dialog.screenshot.test.ts index 3ad12488612..e891843b6d7 100644 --- a/packages/dnb-eufemia/src/components/dialog/__tests__/Dialog.screenshot.test.ts +++ b/packages/dnb-eufemia/src/components/dialog/__tests__/Dialog.screenshot.test.ts @@ -53,6 +53,19 @@ describe.each(['ui', 'sbanken'])('Dialog for %s', (themeName) => { expect(screenshot).toMatchImageSnapshot() }) + it('have to match a top aligned dialog', async () => { + const screenshot = await makeScreenshot({ + selector: 'div#dnb-modal-root', // only to make sure we have a valid selector + simulate: 'click', + simulateSelector: + '[data-visual-test="dialog-vertical-alignment"] button:first-of-type', + simulateAfter: { keypress: 'Escape' }, + screenshotSelector: '.dnb-modal__content', + rootClassName: 'hide-page-content', + }) + expect(screenshot).toMatchImageSnapshot() + }) + it('have to match the dialog fullscreen window', async () => { const screenshot = await makeScreenshot({ selector: 'div#dnb-modal-root', // only to make sure we have a valid selector diff --git a/packages/dnb-eufemia/src/components/dialog/__tests__/Dialog.test.tsx b/packages/dnb-eufemia/src/components/dialog/__tests__/Dialog.test.tsx index 7c7e7151225..9406daa9255 100644 --- a/packages/dnb-eufemia/src/components/dialog/__tests__/Dialog.test.tsx +++ b/packages/dnb-eufemia/src/components/dialog/__tests__/Dialog.test.tsx @@ -126,6 +126,16 @@ describe('Dialog', () => { ) }) + it('will set correct class when verticalAlignment is set to top', () => { + render() + + fireEvent.click(document.querySelector('button')) + + expect(document.querySelector('.dnb-modal__content')).toHaveClass( + 'dnb-modal__vertical-alignment--top' + ) + }) + it('has to have correct role', () => { const { rerender } = render( diff --git a/packages/dnb-eufemia/src/components/dialog/__tests__/__image_snapshots__/dialog-for-sbanken-have-to-match-a-top-aligned-dialog.snap.png b/packages/dnb-eufemia/src/components/dialog/__tests__/__image_snapshots__/dialog-for-sbanken-have-to-match-a-top-aligned-dialog.snap.png new file mode 100644 index 00000000000..22a5a6e4738 Binary files /dev/null and b/packages/dnb-eufemia/src/components/dialog/__tests__/__image_snapshots__/dialog-for-sbanken-have-to-match-a-top-aligned-dialog.snap.png differ diff --git a/packages/dnb-eufemia/src/components/dialog/__tests__/__image_snapshots__/dialog-for-ui-have-to-match-a-top-aligned-dialog.snap.png b/packages/dnb-eufemia/src/components/dialog/__tests__/__image_snapshots__/dialog-for-ui-have-to-match-a-top-aligned-dialog.snap.png new file mode 100644 index 00000000000..6c7de005b85 Binary files /dev/null and b/packages/dnb-eufemia/src/components/dialog/__tests__/__image_snapshots__/dialog-for-ui-have-to-match-a-top-aligned-dialog.snap.png differ diff --git a/packages/dnb-eufemia/src/components/dialog/__tests__/__snapshots__/Dialog.test.tsx.snap b/packages/dnb-eufemia/src/components/dialog/__tests__/__snapshots__/Dialog.test.tsx.snap index 9380bb5464e..0cda407e68f 100644 --- a/packages/dnb-eufemia/src/components/dialog/__tests__/__snapshots__/Dialog.test.tsx.snap +++ b/packages/dnb-eufemia/src/components/dialog/__tests__/__snapshots__/Dialog.test.tsx.snap @@ -740,6 +740,10 @@ html[data-dnb-modal-active] { align-items: flex-end; justify-content: flex-start; } +.dnb-modal__vertical-alignment--top { + padding-top: 5vh; + align-items: flex-start; +} .dnb-modal__overlay { position: fixed; z-index: var(--modal-z-index); diff --git a/packages/dnb-eufemia/src/components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap b/packages/dnb-eufemia/src/components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap index 10641a58d69..b4ea4a99c8d 100644 --- a/packages/dnb-eufemia/src/components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap +++ b/packages/dnb-eufemia/src/components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap @@ -741,6 +741,10 @@ html[data-dnb-modal-active] { align-items: flex-end; justify-content: flex-start; } +.dnb-modal__vertical-alignment--top { + padding-top: 5vh; + align-items: flex-start; +} .dnb-modal__overlay { position: fixed; z-index: var(--modal-z-index); diff --git a/packages/dnb-eufemia/src/components/modal/Modal.tsx b/packages/dnb-eufemia/src/components/modal/Modal.tsx index f06b334b075..22204aaa191 100644 --- a/packages/dnb-eufemia/src/components/modal/Modal.tsx +++ b/packages/dnb-eufemia/src/components/modal/Modal.tsx @@ -107,6 +107,7 @@ class Modal extends React.PureComponent< max_width: null, align_content: 'left', container_placement: null, + vertical_alignment: null, open_state: null, direct_dom_return: false, root_id: 'root', @@ -444,6 +445,7 @@ class Modal extends React.PureComponent< header_content = null, bar_content = null, bypass_invalidation_selectors = null, + vertical_alignment = 'center', id, // eslint-disable-line open_state, // eslint-disable-line @@ -526,6 +528,7 @@ class Modal extends React.PureComponent< focus_selector={focus_selector} modal_content={modal_content} header_content={header_content} + vertical_alignment={vertical_alignment} bar_content={bar_content} bypass_invalidation_selectors={bypass_invalidation_selectors} close={this.close} diff --git a/packages/dnb-eufemia/src/components/modal/ModalContent.tsx b/packages/dnb-eufemia/src/components/modal/ModalContent.tsx index 2e716a066c2..1dafece08ff 100644 --- a/packages/dnb-eufemia/src/components/modal/ModalContent.tsx +++ b/packages/dnb-eufemia/src/components/modal/ModalContent.tsx @@ -363,6 +363,7 @@ export default class ModalContent extends React.PureComponent< no_animation_on_mobile = false, fullscreen = 'auto', container_placement = 'right', + vertical_alignment = 'center', close, content_class, overlay_class, @@ -422,6 +423,7 @@ export default class ModalContent extends React.PureComponent< container_placement ? `dnb-modal__content--${container_placement || 'right'}` : null, + `dnb-modal__vertical-alignment--${vertical_alignment}`, getThemeClasses(this.context?.theme), content_class ), diff --git a/packages/dnb-eufemia/src/components/modal/__tests__/__snapshots__/Modal.test.tsx.snap b/packages/dnb-eufemia/src/components/modal/__tests__/__snapshots__/Modal.test.tsx.snap index 6a1fc79fe60..bf0217c5469 100644 --- a/packages/dnb-eufemia/src/components/modal/__tests__/__snapshots__/Modal.test.tsx.snap +++ b/packages/dnb-eufemia/src/components/modal/__tests__/__snapshots__/Modal.test.tsx.snap @@ -733,6 +733,10 @@ html[data-dnb-modal-active] { align-items: flex-end; justify-content: flex-start; } +.dnb-modal__vertical-alignment--top { + padding-top: 5vh; + align-items: flex-start; +} .dnb-modal__overlay { position: fixed; z-index: var(--modal-z-index); diff --git a/packages/dnb-eufemia/src/components/modal/style/dnb-modal.scss b/packages/dnb-eufemia/src/components/modal/style/dnb-modal.scss index a188072c94f..ccce22b454c 100644 --- a/packages/dnb-eufemia/src/components/modal/style/dnb-modal.scss +++ b/packages/dnb-eufemia/src/components/modal/style/dnb-modal.scss @@ -74,6 +74,11 @@ html[data-dnb-modal-active] { } } + &__vertical-alignment--top { + padding-top: 5vh; + align-items: flex-start; + } + &__overlay { position: fixed; z-index: var(--modal-z-index); diff --git a/packages/dnb-eufemia/src/components/modal/types.ts b/packages/dnb-eufemia/src/components/modal/types.ts index e74acbad21b..f13512208c1 100644 --- a/packages/dnb-eufemia/src/components/modal/types.ts +++ b/packages/dnb-eufemia/src/components/modal/types.ts @@ -254,6 +254,11 @@ export interface ModalContentProps { */ container_placement?: 'left' | 'right' | 'top' | 'bottom' + /** + * Define the vertical alignment of the container. Can be set to `top` or `center`. Defaults to `center`. + */ + vertical_alignment?: 'top' | 'center' + /** * Give the content wrapper a custom class name (maps to `dnb-modal__content`). */