Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Dialog): add verticalAlignment property with top alignment support #4190

Merged
merged 2 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ export const DialogExampleHelpButton = () => (
</ComponentBox>
)

export const DialogExampleVerticalAlignment = () => (
<ComponentBox data-visual-test="dialog-vertical-alignment">
<Dialog
title="Vertical alignment top"
verticalAlignment="top"
triggerAttributes={{
text: 'Vertical alignment',
}}
modalContent="The Dialog component is a Modal aligned at the top of the screen. The Dialog has similar functionality to a traditional popup window and is mostly used for informational purposes."
/>
</ComponentBox>
)

export const DialogExampleFullscreen = () => (
<ComponentBox data-visual-test="dialog-fullscreen">
<Dialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
DialogExampleDefault,
DialogExampleHelpButton,
DialogExampleFullscreen,
DialogExampleVerticalAlignment,
DialogExampleDelayClose,
DialogExampleCustomTrigger,
DialogExampleProgressIndicator,
Expand All @@ -32,6 +33,10 @@ import {

<DialogExampleHelpButton />

### Top aligned Dialog

<DialogExampleVerticalAlignment />

### Dialog with custom trigger

<DialogExampleCustomTrigger />
Expand Down
Original file line number Diff line number Diff line change
@@ -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

<PropertiesTable props={DialogProperties} />
Original file line number Diff line number Diff line change
@@ -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`. |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
---
---

| Events | Description |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onOpen` | _(optional)_ This event gets triggered once the modal shows up. Returns the modal id: `{ id }`. |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
---
---

| Events | Description |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `onOpen` / `on_open` | _(optional)_ This event gets triggered once the modal shows up. Returns the modal id: `{ id }`. |
Expand Down
2 changes: 2 additions & 0 deletions packages/dnb-eufemia/src/components/dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ function Dialog(localProps: DialogProps & DialogContentProps) {
dialogTitle,
closeTitle,
spacing,
verticalAlignment,
noAnimation,
noAnimationOnMobile,
animationDuration,
Expand Down Expand Up @@ -100,6 +101,7 @@ function Dialog(localProps: DialogProps & DialogContentProps) {
labelledBy,
disabled,
spacing,
verticalAlignment,
openDelay,
contentId,
dialogTitle,
Expand Down
114 changes: 114 additions & 0 deletions packages/dnb-eufemia/src/components/dialog/DialogDocs.ts
Original file line number Diff line number Diff line change
@@ -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',
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@ describe('Dialog', () => {
)
})

it('will set correct class when verticalAlignment is set to top', () => {
render(<Dialog verticalAlignment="top" />)

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(
<Dialog {...props} openState={true}>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions packages/dnb-eufemia/src/components/modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand Down
2 changes: 2 additions & 0 deletions packages/dnb-eufemia/src/components/modal/ModalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions packages/dnb-eufemia/src/components/modal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
langz marked this conversation as resolved.
Show resolved Hide resolved

/**
* Give the content wrapper a custom class name (maps to `dnb-modal__content`).
*/
Expand Down
Loading