<duet-modal heading="Verkkopalvelun käyttöehdot" icon="messaging-success" active>
<duet-spacer size="large"></duet-spacer>
<duet-heading level="h4">Tervetuloa LähiTapiolan verkkopalveluun</duet-heading>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
<duet-link url="#">ullamco laboris nisi ut aliquip</duet-link> ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate.
</duet-paragraph>
<duet-heading level="h4">Käytön edellytykset</duet-heading>
<duet-paragraph
>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</duet-paragraph>
<duet-heading level="h4">Verkkopalvelun sisältö</duet-heading>
<duet-paragraph
>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
</duet-paragraph>
<duet-heading level="h4">Henkilötietojen käsittely</duet-heading>
<duet-paragraph
>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa.
</duet-paragraph>
<duet-spacer></duet-spacer>
<div class="duet-text-center">
<duet-button variation="primary" onclick="modal.hide()"> Hyväksyn verkkopalvelun käyttöehdot </duet-button>
</div>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
// Save reference to modal component to use in buttons
var modal = document.querySelector("duet-modal")
</script>
Modal Ready
Modals are used to display content that temporarily blocks interactions with the main view of an application. Modals should be used sparingly only when necessary.
Modal component is positioned over everything else in the application preventing scrolling of the main document, making only the modal’s content scrollable. Duet only supports one modal dialog at a time as nested modals are often a sign of bad user experience.
Examples #
<duet-modal
size="small"
heading="Onko matkapuhelimesi tai tablettisi rikkoutunut?"
icon="damage-breakage"
class="duet-text-center"
active
>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam quis nostrud.
</duet-paragraph>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.
</duet-paragraph>
<duet-button variation="primary" onclick="modal.hide()"> Jatka </duet-button>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
// Save reference to the modal component below
var modal = document.querySelector("duet-modal")
// Listen for open events
modal.addEventListener("duetOpen", function () {
// console.log("Modal opened")
})
// Listen for close events
modal.addEventListener("duetClose", function () {
// console.log("Modal closed")
})
// Listen for beforeClose events
modal.addEventListener("duetBeforeClose", function (e) {
var event = e.detail.originalEvent
if (!confirm("About to dismiss the modal, are you sure you want to continue?")) {
event.preventDefault()
// console.log("Modal not closed as user prevented it")
}
})
</script>
<duet-modal
size="small"
heading="Onko matkapuhelimesi tai tablettisi rikkoutunut?"
icon="damage-breakage"
class="duet-text-center"
active
heading-visual-level="h3"
heading-level="h1"
>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam quis nostrud.
</duet-paragraph>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.
</duet-paragraph>
<duet-button variation="primary" onclick="modal.hide()"> Jatka </duet-button>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
// Save reference to the modal component below
var modal = document.querySelector("duet-modal")
// Listen for open events
modal.addEventListener("duetOpen", function () {
// console.log("Modal opened")
})
// Listen for close events
modal.addEventListener("duetClose", function () {
// console.log("Modal closed")
})
// Listen for beforeClose events
modal.addEventListener("duetBeforeClose", function (e) {
var event = e.detail.originalEvent
if (!confirm("About to dismiss the modal, are you sure you want to continue?")) {
event.preventDefault()
// console.log("Modal not closed as user prevented it")
}
})
</script>
<duet-modal
heading="Oletko varma, että haluat poistua tältä sivulta?"
icon="messaging-alert"
color="warning"
size="small"
variation="dialog"
class="duet-text-center"
active
>
<duet-paragraph> Kaikki täyttämäsi tiedot poistetaan. </duet-paragraph>
<duet-button variation="primary" onclick="modal.hide()"> Kyllä </duet-button>
<duet-button onclick="modal.hide()"> Ei </duet-button>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
var modal = document.querySelector("duet-modal")
</script>
<duet-modal heading="Tarkista tietosi" icon="profile-personal-info" active>
<form novalidate action="#">
<duet-paragraph class="duet-text-center"> Kaikki kentät ovat pakollisia ellei muuten mainita. </duet-paragraph>
<duet-spacer size="large"></duet-spacer>
<duet-choice-group value="suomi" label="Asiointikieli" direction="horizontal" name="group" responsive>
<duet-choice label="Suomi" type="radio" value="suomi" expand></duet-choice>
<duet-choice label="Svenska" type="radio" value="svenska" expand></duet-choice>
<duet-choice label="English" type="radio" value="english" expand></duet-choice>
</duet-choice-group>
<duet-grid responsive>
<duet-input label="Etunimi" name="firstname" placeholder="Matti" expand></duet-input>
<duet-input label="Sukunimi" name="lastname" placeholder="Meikäläinen" expand></duet-input>
</duet-grid>
<duet-input label="Kansalaisuus" name="citizenship" icon="form-location" value="Suomi" expand></duet-input>
<duet-input label="Katuosoite" name="streetaddress" placeholder="Kotikatu 123" expand></duet-input>
<duet-grid responsive>
<duet-input label="Postinumero" name="zip" placeholder="00100"></duet-input>
<duet-input label="Kaupunki" name="city" placeholder="Helsinki" expand></duet-input>
</duet-grid>
<duet-input label="Maa" name="country" icon="form-location" value="Suomi" expand></duet-input>
<duet-input label="Tilinumero" name="bankaccount" placeholder="FI28 12345 67890" expand></duet-input>
<duet-spacer size="large"></duet-spacer>
<duet-button variation="primary" onclick="modal.hide()">Jatka</duet-button>
<duet-button onclick="modal.hide()">Peruuta</duet-button>
</form>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
var modal = document.querySelector("duet-modal")
</script>
<duet-modal size="large" heading="Verkkopalvelun käyttöehdot" icon="messaging-success" active>
<duet-spacer size="large"></duet-spacer>
<duet-heading level="h4">Tervetuloa LähiTapiolan verkkopalveluun</duet-heading>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
<duet-link url="#">ullamco laboris nisi ut aliquip</duet-link> ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate.
</duet-paragraph>
<duet-heading level="h4">Käytön edellytykset</duet-heading>
<duet-paragraph
>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</duet-paragraph>
<duet-heading level="h4">Verkkopalvelun sisältö</duet-heading>
<duet-paragraph
>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
</duet-paragraph>
<duet-heading level="h4">Henkilötietojen käsittely</duet-heading>
<duet-paragraph
>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa.
</duet-paragraph>
<duet-spacer></duet-spacer>
<div class="duet-text-center">
<duet-button variation="primary" onclick="modal.hide()"> Hyväksyn verkkopalvelun käyttöehdot </duet-button>
</div>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
// Save reference to modal component to use in buttons
var modal = document.querySelector("duet-modal")
</script>
<duet-modal
size="large"
gutter-size="small"
heading="Onko matkapuhelimesi tai tablettisi rikkoutunut?"
heading-level="h1"
class="duet-text-center"
active
>
<img src="https://cdn.duetds.com/api/assets/illustrations/lt-booking.png" slot="top" />
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam quis nostrud.
</duet-paragraph>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.
</duet-paragraph>
<duet-button variation="primary" onclick="modal.hide()"> Jatka </duet-button>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
// Save reference to the modal component below
var modal = document.querySelector("duet-modal")
// Listen for open events
modal.addEventListener("duetOpen", function () {
// console.log("Modal opened")
})
// Listen for close events
modal.addEventListener("duetClose", function () {
// console.log("Modal closed")
})
// Listen for beforeClose events
modal.addEventListener("duetBeforeClose", function (e) {
var event = e.detail.originalEvent
if (!confirm("About to dismiss the modal, are you sure you want to continue?")) {
event.preventDefault()
// console.log("Modal not closed as user prevented it")
}
})
</script>
<duet-modal
size="large"
gutter-size="medium"
heading="Onko matkapuhelimesi tai tablettisi rikkoutunut?"
heading-level="h1"
class="duet-text-center"
active
>
<img src="https://cdn.duetds.com/api/assets/illustrations/lt-booking.png" slot="top" />
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam quis nostrud.
</duet-paragraph>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.
</duet-paragraph>
<duet-button variation="primary" onclick="modal.hide()"> Jatka </duet-button>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
// Save reference to the modal component below
var modal = document.querySelector("duet-modal")
// Listen for open events
modal.addEventListener("duetOpen", function () {
// console.log("Modal opened")
})
// Listen for close events
modal.addEventListener("duetClose", function () {
// console.log("Modal closed")
})
// Listen for beforeClose events
modal.addEventListener("duetBeforeClose", function (e) {
var event = e.detail.originalEvent
if (!confirm("About to dismiss the modal, are you sure you want to continue?")) {
event.preventDefault()
// console.log("Modal not closed as user prevented it")
}
})
</script>
<duet-modal
size="large"
gutter-size="large"
heading="Onko matkapuhelimesi tai tablettisi rikkoutunut?"
heading-level="h1"
class="duet-text-center"
active
>
<img src="https://cdn.duetds.com/api/assets/illustrations/lt-booking.png" slot="top" />
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam quis nostrud.
</duet-paragraph>
<duet-paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.
</duet-paragraph>
<duet-button variation="primary" onclick="modal.hide()"> Jatka </duet-button>
</duet-modal>
<duet-button variation="primary" onclick="modal.show()"> Show modal </duet-button>
<script>
// Save reference to the modal component below
var modal = document.querySelector("duet-modal")
// Listen for open events
modal.addEventListener("duetOpen", function () {
// console.log("Modal opened")
})
// Listen for close events
modal.addEventListener("duetClose", function () {
// console.log("Modal closed")
})
// Listen for beforeClose events
modal.addEventListener("duetBeforeClose", function (e) {
var event = e.detail.originalEvent
if (!confirm("About to dismiss the modal, are you sure you want to continue?")) {
event.preventDefault()
// console.log("Modal not closed as user prevented it")
}
})
</script>
Properties #
Property | Attribute | Description | Type | Default |
---|---|---|---|---|
accessibleCloseLabel | accessible-close-label | Adds accessible label for the close icon that is only shown for screen readers. This property is always required to create an accessibly interface! Swedish translation for this property is “Stäng fönstret”. | string | getLocaleString( this.accessibleCloseLabelDefaults, this.language ) |
accessibleCloseLabelDefaults | accessible-close-label-default | Defaults for accessibleCloseLabel | DuetLangObject | string | { fi: "Sulje ikkuna", sv: "Stäng fönstret", en: "Close the dialog", } |
accessibleDescribedBy | accessible-described-by | Indicates the id or a string of space seperated ids of a component(s) that describes the input. | string | undefined |
accessibleDescription | accessible-description | Aria description the button | string | undefined |
accessibleDetails | accessible-details | Details of the component | string | undefined |
accessibleLabel | accessible-label | By default the heading is used as target for aria-labelledby, and it overrides this label. If you wish to skip the heading, you must set this label. | string | undefined |
accessibleLabelledBy | accessible-labelled-by | Indicates the id or a string of space seperated ids of a component(s) that labels the input. | string | undefined |
active | active | Use this property when you need to have the modal dialog initially active. | boolean | false |
closeOnBlur | close-on-blur | Use this property when you want the modal to close when clicked outside of modal. | boolean | false |
color | color | Custom color to be used for the icon, as a design token entered in camelCase or kebab-case. Example: "primary". | string | "" |
gutterSize | gutter-size | Size of the modal window's padding. | "large" | "medium" | "none" | "small" | "medium" |
heading | heading | Accessible heading displayed in the modal. The modal marks this as the label of the modal when used. This helps screen reader users which is why this is a required property. | string | "" |
headingLevel | heading-level | Accessible heading size | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "h3" |
headingVisualLevel | heading-visual-level | Makes the visual style mimic a specific heading level. This option allows you to make e.g. h1 visually look like h3, but still keep it h1 in the markup. | "h0" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | undefined |
icon | icon | Icon to display above the heading (from Duet’s icons). Example: "form-location" | string | "" |
language | language | [DEPRECATED] this is now handled via the html lang tag, and is no longer used - kept to avoid breaking changes and ease unit testing The currently active language. This setting also changes the logo to match the chosen language. | "en" | "fi" | "sv" | getLanguage() |
size | size | Size of the modal window. | "large" | "medium" | "small" | "medium" |
theme | theme | Theme of the modal. | "" | "default" | "turva" | "" |
Events #
Event | Description | Type |
---|---|---|
duetBeforeClose | Emitted before the modal is closed. To prevent the modal from actually closing, use ev.detail.originalEvent.preventDefault(). | CustomEvent<{ originalEvent: Event; component: "duet-modal"; }> |
duetClose | Emitted when the modal is closed. | CustomEvent<any> |
duetOpen | Emitted when the modal is opened. | CustomEvent<any> |
Methods #
hide() => Promise<void>
#
Hides the modal dialog and puts focus back to the original element
that triggered the modal (if we’re still in the same view).
Returns #
Type: Promise<void>
show() => Promise<void>
#
Shows the modal dialog. Additionally saves the element that triggered
the modal so that focus can be moved back to this specific element when
the modal dialog is closed.
Returns #
Type: Promise<void>
Slots #
Slot | Description |
---|---|
"top" | This is a slot that takes any content and will be displayed as the first thing in the hero area (typically an image) |
Usage #
This section includes guidelines for designers and developers about the usage of this component in different contexts.
When to use #
- When you need to display content that temporarily blocks interactions with the main view of an application.
- When you need to ask a confirmation from a user before proceeding.
- When the user is required to take an action.
- For important warnings, as a way to prevent or correct critical errors.
When not to use #
- For nonessential information that is not related to the current user flow.
- In the middle of a purchase flow to interrupt it.
- When the modal requires additional information for decision making that is unavailable in the modal itself.
Variations #
This section describes the different component variations, their purpose, and when to use each variation.
Name | Purpose |
---|---|
small | Small modal dialog variation is used for confirmation messages and similar. |
medium | Medium modal dialog should be always used when there’s more than just one paragraph of content. |
Accessibility #
This component has been validated to meet the WCAG 2.1 AA accessibility guidelines. You can find additional information regarding accessibility of this component below.
- Modal uses ARIA
role="dialog"
andaria-modal="true"
to convey to users of assistive technologies that it works like native dialog windows. - Modal contents are also wrapped in ARIA
role="document"
to inform assistive technologies to switch context to a reading mode. - After a modal is closed, the focus is moved back to the button that triggered the modal.
heading
property can be used to display a heading in the modal. The modal marks this as the label of the modal when used. This helps screen reader users which is why this is a required property.- Modal traps focus while it’s open and users can’t navigate out of the modal before the modal is closed.
- Pressing
esc
closes the modal window.
Additional considerations #
- When you have primary and secondary action buttons in modal, you should display primary on the left and secondary on the right. View an example.
- For
small
modal dialogs the action buttons are always centered. View an example. - For
medium
modal dialogs the action buttons are always left aligned. View an example. - Never have more than two buttons at the bottom of the modal.
Integration
For integration, event and theming guidelines, please see Using Components. This documentation explains how to implement and use Duet’s components across different technologies like Angular, React or Vanilla JavaScript.
Tutorials
Follow these practical tutorials to learn how to build simple page layouts using Duet’s CSS Framework, Web Components and other features:
Building Layouts
TutorialsUsing CLI Tools
TutorialsCreating Custom Patterns
TutorialsServer Side Rendering
TutorialsSharing Prototypes
TutorialsUsage With Markdown
Troubleshooting
If you experience any issues while using a component, please head over to the Support page for more guidelines and help.