@bonniernews/dn-design-system-web 9.0.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@ All changes to @bonniernews/dn-design-system-web will be documented in this file
4
4
 
5
5
 
6
6
 
7
+ ## [9.1.0](https://github.com/BonnierNews/dn-design-system/compare/@bonniernews/dn-design-system-web@9.0.0...@bonniernews/dn-design-system-web@9.1.0) (2024-01-04)
8
+
9
+
10
+ ### Features
11
+
12
+ * **web:** modal component ([#1150](https://github.com/BonnierNews/dn-design-system/issues/1150)) ([a0a70ec](https://github.com/BonnierNews/dn-design-system/commit/a0a70ec4d431b6b38738a70468e60ed9cc9e93ef))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **app:** pressable remove hitslop ([#1146](https://github.com/BonnierNews/dn-design-system/issues/1146)) ([4f59509](https://github.com/BonnierNews/dn-design-system/commit/4f59509cc3c29bd1f66c7d064b0fb5e25451b07c))
18
+
19
+
20
+ ### Maintenance
21
+
22
+ * **foundations:** update tokens from Figma ([#1142](https://github.com/BonnierNews/dn-design-system/issues/1142)) ([66cc18e](https://github.com/BonnierNews/dn-design-system/commit/66cc18e2bd91337d5ffd8b38e76f9230ba5d3610))
23
+ * prerelease packages ([d6f9f31](https://github.com/BonnierNews/dn-design-system/commit/d6f9f31c313028d1e3b192a8b4b2dd59732ef192))
24
+ * prerelease packages ([49b5357](https://github.com/BonnierNews/dn-design-system/commit/49b53574003a03a233b63f467a69d9ea55d9b852))
25
+
7
26
  ## [9.0.0](https://github.com/BonnierNews/dn-design-system/compare/@bonniernews/dn-design-system-web@8.9.8...@bonniernews/dn-design-system-web@9.0.0) (2023-12-08)
8
27
 
9
28
 
@@ -0,0 +1,52 @@
1
+ - GitHub: [BonnierNews/dn-design-system/../web/src/components/modal](https://github.com/BonnierNews/dn-design-system/tree/main/web/src/components/modal)
2
+ - Storybook: [Modal](https://designsystem.dn.se/?path=/docs/basic-modal--docs)
3
+ - Storybook (Latest): [Modal](https://designsystem-latest.dn.se/?path=/docs/basic-modal--docs)
4
+
5
+ ----
6
+
7
+ # Modal
8
+
9
+
10
+ ## Parameters
11
+
12
+ |parameter | type | required | options | default | description |
13
+ |:--- | :--- | :--- | :--- | :--- | :--- |
14
+ | title | String | yes | | | Title in modal |
15
+ | bodyText | String | yes | text | | Text in modal |
16
+ | primaryButton | Object | no | text | | Object with text, href (optional), classNames (optional) and attributes (optional) |
17
+ | secondaryButton | Object | no | text | | Object with text, href (optional), classNames (optional) and attributes (optional). Set isCloseButton to true if you wanna close modal with this button |
18
+ | classNames | String | no | | | Ex. "my-special-class" |
19
+ | attributes | Object | no | | | Ex. { data-prop: value } |
20
+ | forcePx | bool | no | true, false | false | Fixed pixel value is used for typography to prevent scaling based on html font-size
21
+
22
+ ## Minimum requirement example
23
+
24
+ These are copy paste friendly examples to quickliy get started using a component.
25
+
26
+ ### Nunjucks
27
+
28
+ ```javascript
29
+ {% from '@bonniernews/dn-design-system-web/components/modal/modal.njk' import Modal %}
30
+
31
+ {{ Modal({
32
+ title: "Rubrik",
33
+ bodyText: "Text i modalen",
34
+ primaryButton: "Text i knapp",
35
+ secondaryButton: "Text i knapp",
36
+ })}}
37
+ ```
38
+
39
+ ### Scss
40
+
41
+ ```scss
42
+ @use "@bonniernews/dn-design-system-web/components/modal/modal";
43
+ ```
44
+
45
+ ### Javascript
46
+
47
+ ```javascript
48
+ import { initModal, openModal } from '@bonniernews/dn-design-system-web/components/modal/modal.js'
49
+ const modalEl = document.querySelector(".ds-modal");
50
+ initModal(modalEl);
51
+ openModal(modalEl);
52
+ ```
@@ -0,0 +1,59 @@
1
+ export {
2
+ initModal,
3
+ openModal,
4
+ initModalStorybook
5
+ }
6
+
7
+ function initModal(modalEl) {
8
+ const isDialogSupported = typeof HTMLDialogElement === "function";
9
+ let modalWrapper = modalEl.querySelector(".ds-modal__inner");
10
+ if (!isDialogSupported) {
11
+ modalWrapper = modalEl;
12
+ const modalElInner = document.querySelector(".ds-modal__inner");
13
+ const modalAttributes = Array.from(modalElInner.attributes);
14
+ const fallbackDiv = document.createElement("div");
15
+ modalEl.classList.add("ds-modal--hidden", "ds-modal--fallback");
16
+ modalAttributes.forEach((attr) => {
17
+ fallbackDiv.setAttribute(attr.name, attr.value);
18
+ });
19
+ fallbackDiv.setAttribute("role", "dialog");
20
+ fallbackDiv.setAttribute("aria-modal", "true");
21
+ fallbackDiv.innerHTML = modalElInner.innerHTML;
22
+ modalEl.replaceChild(fallbackDiv, modalElInner);
23
+ }
24
+
25
+ modalEl.addEventListener("click", (e) => {
26
+ if (e.target === modalWrapper) closeModal(modalEl, isDialogSupported);
27
+ });
28
+
29
+ const closeButtons = Array.from(modalEl.getElementsByClassName("ds-modal__close"));
30
+ closeButtons.forEach((button) => {
31
+ button.addEventListener("click", () => {
32
+ closeModal(modalEl, isDialogSupported);
33
+ });
34
+ });
35
+ }
36
+
37
+ function openModal(modalEl) {
38
+ if (typeof HTMLDialogElement === "function") {
39
+ const modalElInner = modalEl.querySelector(".ds-modal__inner");
40
+ modalElInner.showModal();
41
+ } else {
42
+ modalEl.classList.remove("ds-modal--hidden");
43
+ }
44
+ }
45
+
46
+ function closeModal(modalEl, isDialogSupported) {
47
+ if (isDialogSupported) {
48
+ const modalElInner = modalEl.querySelector(".ds-modal__inner");
49
+ modalElInner.close();
50
+ } else {
51
+ modalEl.classList.add("ds-modal--hidden");
52
+ }
53
+ }
54
+
55
+ function initModalStorybook() {
56
+ const modalEl = document.querySelector(".ds-modal");
57
+ initModal(modalEl);
58
+ openModal(modalEl);
59
+ }
@@ -0,0 +1,66 @@
1
+ {% from '@bonniernews/dn-design-system-web/components/icon-sprite/icon-sprite.njk' import IconUse %}
2
+ {% from '@bonniernews/dn-design-system-web/components/button/button.njk' import Button %}
3
+ {% from '@bonniernews/dn-design-system-web/components/icon-button/icon-button.njk' import IconButton %}
4
+ {% from '@bonniernews/dn-design-system-web/njk-helpers/attributes.njk' import getAttributes %}
5
+
6
+ {% macro Modal(params) %}
7
+ {% set componentClassName = "ds-modal" %}
8
+
9
+ {%- set classes = [
10
+ componentClassName,
11
+ "ds-force-px" if params.forcePx,
12
+ params.classNames if params.classNames
13
+ ] | join(" ") %}
14
+ {% set attributes = getAttributes(params.attributes) %}
15
+
16
+ <div class="{{ classes }}">
17
+ <dialog class="{{ componentClassName + '__inner' }}" {{- attributes | safe }}>
18
+ <div class="{{ componentClassName + '__content' }}">
19
+ {{ IconButton({
20
+ variant: "transparent",
21
+ size: "small",
22
+ iconName: "close",
23
+ classNames: "ds-modal__close"
24
+ })}}
25
+ <h2>{{ params.title }}</h2>
26
+ <p>{{ params.bodyText }}</p>
27
+
28
+ {% if params.primaryButton or params.secondaryButton %}
29
+ <div class="ds-modal__buttons">
30
+ {% if params.secondaryButton %}
31
+ {%- set secondaryButtonClasses = [
32
+ "ds-modal__close" if params.secondaryButton.isCloseButton,
33
+ params.secondaryButton.classNames if params.secondaryButton.classNames
34
+ ] | join(" ") %}
35
+ {{ Button({
36
+ text: params.secondaryButton.text,
37
+ variant: "secondaryOutlined",
38
+ href: params.secondaryButton.href,
39
+ classNames: secondaryButtonClasses,
40
+ attributes: params.secondaryButton.attributes,
41
+ forcePx: params.forcePx,
42
+ mobile: {
43
+ fullWidth: true
44
+ }
45
+ })}}
46
+ {% endif %}
47
+
48
+ {% if params.primaryButton %}
49
+ {{ Button({
50
+ text: params.primaryButton.text,
51
+ variant: "primary",
52
+ href: params.primaryButton.href,
53
+ classNames: params.primaryButton.classNames,
54
+ attributes: params.primaryButton.attributes,
55
+ forcePx: params.forcePx,
56
+ mobile: {
57
+ fullWidth: true
58
+ }
59
+ })}}
60
+ {% endif %}
61
+ </div>
62
+ {% endif %}
63
+ </div>
64
+ </dialog>
65
+ </div>
66
+ {% endmacro %}
@@ -0,0 +1,115 @@
1
+ @use "../../foundations/helpers/forward.helpers.scss" as *;
2
+ @use "../../components/icon-sprite/icon-sprite.scss";
3
+ @use "../../components/button/button.scss";
4
+ @use "../../components/icon-button/icon-button.scss";
5
+
6
+ .ds-modal {
7
+ &--fallback.ds-modal--hidden {
8
+ display: none;
9
+ }
10
+
11
+ &--fallback {
12
+ display: flex;
13
+ position: fixed;
14
+ top: 0;
15
+ bottom: 0;
16
+ right: 0;
17
+ left: 0;
18
+ z-index: 999;
19
+ background-color: $ds-color-surface-overlay;
20
+
21
+ @include ds-mq-only-breakpoint(mobile) {
22
+ align-items: flex-end;
23
+ }
24
+
25
+ @include ds-mq-smallest-breakpoint(tablet) {
26
+ align-items: center;
27
+ justify-content: center;
28
+ }
29
+
30
+ .ds-modal__inner {
31
+ position: relative;
32
+ }
33
+
34
+ .ds-modal__content {
35
+ @include ds-mq-only-breakpoint(mobile) {
36
+ border-radius: 16px 16px 0 0;
37
+ }
38
+
39
+ @include ds-mq-smallest-breakpoint(tablet) {
40
+ border-radius: ds-border-radius(x1);
41
+ }
42
+ }
43
+ }
44
+
45
+ .ds-modal__inner {
46
+ max-width: 700px;
47
+ border: none;
48
+ padding: 0;
49
+
50
+ @include ds-mq-only-breakpoint(mobile) {
51
+ margin-bottom: 0;
52
+ border-radius: 16px 16px 0 0;
53
+ }
54
+
55
+ @include ds-mq-smallest-breakpoint(tablet) {
56
+ border-radius: ds-border-radius(x1);
57
+ }
58
+
59
+ &::backdrop {
60
+ background-color: $ds-color-surface-overlay;
61
+ }
62
+ }
63
+
64
+ .ds-modal__content {
65
+ padding: ds-spacing($ds-s-400 $ds-s-300 $ds-s-300);
66
+ background-color: $ds-color-surface-background;
67
+
68
+ .ds-icon-btn.ds-modal__close {
69
+ position: absolute;
70
+ top: ds-spacing($ds-s-100);
71
+ right: ds-spacing($ds-s-100);
72
+ }
73
+
74
+ > h2 {
75
+ @include ds-typography($ds-typography-functional-heading03bold);
76
+ margin: ds-spacing(0 0 $ds-s-200);
77
+ color: $ds-color-text-primary;
78
+ text-align: center;
79
+ }
80
+
81
+ > p {
82
+ @include ds-typography($ds-typography-functional-body02regular);
83
+ margin: 0;
84
+ text-align: center;
85
+ color: $ds-color-text-primary;
86
+ }
87
+
88
+ > .ds-modal__buttons {
89
+ margin: ds-spacing($ds-s-200 0 0);
90
+
91
+ @include ds-mq-only-breakpoint(mobile) {
92
+ display: flex;
93
+ flex-wrap: wrap;
94
+
95
+ .ds-btn--primary:not(:only-child) {
96
+ order: 1;
97
+ margin-bottom: ds-spacing($ds-s-100);
98
+ }
99
+
100
+ .ds-btn--secondaryOutlined:not(:only-child) {
101
+ order: 2;
102
+ }
103
+ }
104
+
105
+ @include ds-mq-smallest-breakpoint(tablet) {
106
+ display: flex;
107
+ justify-content: center;
108
+
109
+ .ds-btn--secondaryOutlined:not(:only-child) {
110
+ margin-right: ds-spacing($ds-s-100);
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
@@ -5,6 +5,7 @@
5
5
  @use "./helpers/colors.scss" as *;
6
6
 
7
7
  html,
8
+ ::backdrop, //backdrop can't handle variables in html element. It needs to be defined here
8
9
  .ds-light {
9
10
  @each $name, $value in meta.module-variables("colorsDnLightTokens") {
10
11
  --ds-color-#{string.slice($name, 8)}: #{$value};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonniernews/dn-design-system-web",
3
- "version": "9.0.0",
3
+ "version": "9.1.0",
4
4
  "description": "DN design system for web.",
5
5
  "main": "index.js",
6
6
  "homepage": "https://github.com/BonnierNews/dn-design-system/tree/main/web/src#readme",