@bonniernews/dn-design-system-web 17.0.0 → 18.0.0-beta.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,17 @@ All changes to @bonniernews/dn-design-system-web will be documented in this file
4
4
 
5
5
 
6
6
 
7
+ ## [18.0.0-beta.0](https://github.com/BonnierNews/dn-design-system/compare/@bonniernews/dn-design-system-web@17.0.0...@bonniernews/dn-design-system-web@18.0.0-beta.0) (2024-08-13)
8
+
9
+
10
+ ### ⚠ BREAKING CHANGES
11
+
12
+ * list item design updates
13
+
14
+ ### Features
15
+
16
+ * list item design updates ([b281389](https://github.com/BonnierNews/dn-design-system/commit/b2813893022fc7d95ac070a85ee53db81a60b6a9))
17
+
7
18
  ## [17.0.0](https://github.com/BonnierNews/dn-design-system/compare/@bonniernews/dn-design-system-web@16.2.1...@bonniernews/dn-design-system-web@17.0.0) (2024-07-19)
8
19
 
9
20
 
@@ -85,7 +85,7 @@
85
85
  border-bottom-right-radius: ds-border-radius(x2);
86
86
  overflow: hidden;
87
87
  margin: 0;
88
- padding: 0;
88
+ padding: ds-spacing(0 $ds-s-100);
89
89
  }
90
90
 
91
91
  &.ds-force-px {
@@ -1,47 +1,11 @@
1
1
  {% from '@bonniernews/dn-design-system-web/njk-helpers/attributes.njk' import getAttributes %}
2
- {% from '@bonniernews/dn-design-system-web/components/icon-sprite/icon-sprite.njk' import IconUse %}
3
- {% from '@bonniernews/dn-design-system-web/components/button-toggle/button-toggle.njk' import ButtonToggle %}
2
+ {% from '@bonniernews/dn-design-system-web/components/list-item/list-item.njk' import ListItem %}
4
3
 
5
4
  {% macro Byline(params) %}
6
- {% set componentClassName = "ds-byline" %}
7
- <li class="{{ componentClassName + '__outer'}}">
8
- {% call BylineInner(params, componentClassName) %}
9
- <div class="{{ componentClassName + '__inner'}}">
10
- {% set componentClassName = componentClassName %}
11
- {% call BylineContent(params, componentClassName, useOuterAnchorElement) %}
12
- {% if params.bylineImage %}
13
- <span class="{{ componentClassName + '__image'}}">{{- params.bylineImage | safe -}}</span>
14
- {% endif %}
15
- <div class="{{ componentClassName + '__titles'}}">
16
- {% if params.authorName %}
17
- <span class="{{ componentClassName + '__title'}}">{{ params.authorName }}</span>
18
- {% endif %}
19
- {%- if subtitle %}
20
- <span class="{{ componentClassName + '__subtitle'}}">{{ subtitle }}</span>
21
- {% endif %}
22
- </div>
23
- {% endcall %}
24
- {% if useArrowIcon %}
25
- <span class="{{ componentClassName + '__icon-right'}}">{{- IconUse({ icon: 'arrow_forward' }) | safe -}}</span>
26
- {% elif useFollowButton %}
27
- {{ ButtonToggle({
28
- text: "Följ",
29
- selectedText: "Följer",
30
- selected: params.followed,
31
- variant: "secondary",
32
- size: "small",
33
- attributes: params.elementAttributes,
34
- classNames: elementClassNames | join(" "),
35
- forcePx: params.forcePx
36
- })}}
37
- {% endif %}
38
- </div>
39
- {% endcall %}
40
- </li>
41
- {% endmacro %}
5
+ {% set useOuterAnchorElement = params.authorPageUrl and not params.followable %}
6
+ {% set useArrowIcon = true if (useOuterAnchorElement and params.variant !== 'direkt') %}
7
+ {% set useFollowButton = true if (params.variant == 'follow' and params.followable) %}
42
8
 
43
- {# Internal helper macro - not intended for use outside of this file #}
44
- {% macro BylineContent(params, componentClassName, useOuterAnchorElement) %}
45
9
  {% if params.variant == 'link' %}
46
10
  {% set subtitle = params.role %}
47
11
  {% elif params.variant == 'follow' %}
@@ -50,54 +14,24 @@
50
14
  {% set subtitle = false %}
51
15
  {% endif %}
52
16
 
53
- {# This inner link can exist in combination with a button. It's been decided that it should only be used for authorPageUrls, not for email #}
54
- {% if not useOuterAnchorElement and params.authorPageUrl %}
55
- {% set linkAttributes = getAttributes(params.linkAttributes) %}
56
- {%- set ariaLabel = 'aria-label="Läs mer från ' + params.authorName + '"' %}
57
- <a href="{{params.authorPageUrl}}" {{- linkAttributes | safe }} {{ ariaLabel | safe if not params.email }} class="{{ componentClassName + '__content-wrapper'}}">
58
- {{ caller() if caller }}
59
- </a>
60
- {% else %}
61
- <div class="{{ componentClassName + '__content-wrapper'}}">
62
- {{ caller() if caller }}
63
- </div>
64
- {% endif %}
65
- {% endmacro %}
66
-
67
- {# Internal helper macro - not intended for use outside of this file #}
68
- {% macro BylineInner(params, componentClassName) %}
69
- {% set classNamePrefix = componentClassName + "--" %}
70
- {% set attributes = getAttributes(params.attributes) %}
71
-
72
- {% set useOuterAnchorElement = true if (params.authorPageUrl and not params.followable) %}
73
- {% set useArrowIcon = true if (useOuterAnchorElement and params.variant !== 'direkt') %}
74
- {% set useFollowButton = true if (params.variant == 'follow' and params.followable) %}
75
-
76
- {%- set classes = [
77
- componentClassName,
78
- "ds-force-px" if params.forcePx,
79
- classNamePrefix + "noninteractive" if not params.authorPageUrl,
80
- classNamePrefix + params.variant,
81
- params.classNames if params.classNames
82
- ] | join(" ") %}
83
-
84
- {% if params.bylineImage %}
85
- {% set bylineImage = params.bylineImage %}
86
- {% endif %}
87
-
88
- {% set elementClassNames = [ componentClassName + "__btn-toggle" ]%}
89
- {% if params.elementClassNames %}
90
- {% set elementClassNames = (elementClassNames.push(params.elementClassNames), elementClassNames) %}
91
- {% endif %}
92
-
93
- {% if useOuterAnchorElement %}
94
- {% set linkAttributes = getAttributes(params.linkAttributes) %}
95
- <a href="{{ params.authorPageUrl }}" aria-label="Läs mer från {{ params.authorName }}" class="{{ classes }}" {{- attributes | safe }} {{- linkAttributes | safe }}>
96
- {{ caller() if caller }}
97
- </a>
98
- {% else %}
99
- <div class="{{ classes }}" {{- attributes | safe }}>
100
- {{ caller() if caller }}
101
- </div>
102
- {% endif %}
17
+ {% set classNames = (params.classNames or '') + ' ds-byline--' + params.variant %}
18
+
19
+ {{ ListItem({
20
+ listItemType: 'byline',
21
+ title: params.authorName,
22
+ subtitle: subtitle,
23
+ mediaHtml: params.bylineImage,
24
+ trailingIcon: 'arrow_forward' if useArrowIcon,
25
+ toggleText: 'Följ' if useFollowButton,
26
+ toggleSelectedText: 'Följer' if useFollowButton,
27
+ selected: params.followed if useFollowButton,
28
+ href: params.authorPageUrl if useOuterAnchorElement,
29
+ titleHref: params.authorPageUrl if not useOuterAnchorElement,
30
+ linkAttributes: params.linkAttributes,
31
+ elementAttributes: params.elementAttributes,
32
+ elementClassNames: params.elementClassNames,
33
+ forcePx: params.forcePx,
34
+ classNames: classNames,
35
+ attributes: params.attributes
36
+ }) }}
103
37
  {% endmacro %}
@@ -1,187 +1 @@
1
- @use "../../foundations/helpers/forward.helpers.scss" as *;
2
- @use "../../components/icon-sprite/icon-sprite.scss";
3
- @use "../../components/button-toggle/button-toggle.scss" as *;
4
-
5
- $ds-byline__icon-size: 24px;
6
- $ds-byline__image-size: 44px;
7
- $ds-byline__image-size--direkt: 36px;
8
-
9
- .ds-byline__outer {
10
- list-style: none;
11
- line-height: 0;
12
- }
13
-
14
- .ds-byline {
15
- background-color: transparent;
16
- border: 0;
17
- display: inline-flex;
18
- align-items: center;
19
- justify-content: center;
20
- padding: 0;
21
- width: 100%;
22
- position: relative;
23
-
24
- &::after {
25
- content: "";
26
- height: ds-border-width(x1);
27
- width: calc(100% - ds-spacing($ds-s-200));
28
- background-color: $ds-color-border-primary;
29
- position: absolute;
30
- left: ds-spacing($ds-s-100);
31
- bottom: 0;
32
- }
33
-
34
- .ds-byline__inner {
35
- box-sizing: border-box;
36
- border-radius: 0;
37
- margin: 0;
38
- display: flex;
39
- align-items: center;
40
- justify-content: space-between;
41
- position: relative;
42
- padding: ds-spacing($ds-s-100 $ds-s-100);
43
- width: 100%;
44
-
45
- &::before {
46
- content: "";
47
- border-radius: inherit;
48
- pointer-events: none;
49
- position: absolute;
50
- top: 0;
51
- left: 0;
52
- bottom: 0;
53
- right: 0;
54
- }
55
- }
56
-
57
- .ds-byline__content-wrapper {
58
- display: flex;
59
- align-items: center;
60
- justify-content: space-between;
61
- flex-grow: 1;
62
- text-decoration: none;
63
-
64
- &:focus-visible {
65
- outline: ds-border-width(x2) solid $ds-color-border-focus-02;
66
- outline-offset: 2px;
67
- }
68
- }
69
-
70
- .ds-byline__image {
71
- height: $ds-byline__image-size;
72
- width: $ds-byline__image-size;
73
- border-radius: 50%;
74
- overflow: hidden;
75
- margin-right: ds-spacing($ds-s-100);
76
- background-color: $ds-color-component-primary-overlay;
77
- flex-shrink: 0;
78
- }
79
-
80
- .ds-byline__titles {
81
- display: flex;
82
- flex-grow: 1;
83
- flex-direction: column;
84
- align-items: flex-start;
85
- word-break: break-all;
86
-
87
- .ds-byline__title {
88
- @include ds-typography(
89
- $ds-typography-functionalheading01,
90
- $lineHeight: $ds-lineheight-m,
91
- $fontWeight: $ds-fontweight-semibold
92
- );
93
- @at-root .ds-force-px#{&} {
94
- @include ds-typography(
95
- $ds-typography-functionalheading01,
96
- $forcePx: true,
97
- $lineHeight: $ds-lineheight-m,
98
- $fontWeight: $ds-fontweight-semibold
99
- );
100
- }
101
- color: $ds-color-text-primary;
102
- text-align: left;
103
- }
104
-
105
- .ds-byline__subtitle {
106
- @include ds-typography($ds-typography-functionalbody02);
107
- @at-root .ds-force-px#{&} {
108
- @include ds-typography($ds-typography-functionalbody02, true);
109
- }
110
- color: $ds-color-text-primary-02;
111
- text-align: left;
112
- }
113
- }
114
-
115
- .ds-byline__icon-right {
116
- color: $ds-color-icon-primary;
117
- display: inline-flex;
118
- margin-left: ds-spacing($ds-s-100);
119
-
120
- .ds-icon {
121
- position: relative;
122
- display: flex;
123
- height: ds-px-to-rem($ds-byline__icon-size);
124
- width: ds-px-to-rem($ds-byline__icon-size);
125
- margin: 0;
126
- @at-root .ds-force-px#{&} {
127
- height: $ds-byline__icon-size;
128
- width: $ds-byline__icon-size;
129
- }
130
- svg {
131
- fill: currentColor;
132
- }
133
- }
134
- }
135
-
136
- .ds-byline__btn-toggle {
137
- margin-left: ds-spacing($ds-s-100);
138
- }
139
-
140
- @include ds-hover() {
141
- &:hover:not(.ds-byline--noninteractive) {
142
- cursor: pointer;
143
-
144
- .ds-byline__inner::before {
145
- background-color: $ds-color-component-primary-overlay;
146
- }
147
- }
148
- }
149
-
150
- &.ds-byline--direkt {
151
- .ds-byline__titles {
152
- .ds-byline__subtitle {
153
- line-height: ds-spacing($ds-s-100);
154
- }
155
- }
156
- .ds-byline__image {
157
- height: $ds-byline__image-size--direkt;
158
- width: $ds-byline__image-size--direkt;
159
- }
160
-
161
- .ds-byline__btn-toggle {
162
- min-height: $ds-byline__image-size--direkt;
163
- }
164
-
165
- .ds-byline__inner {
166
- padding-top: ds-spacing($ds-s-075);
167
- padding-bottom: ds-spacing($ds-s-075);
168
- }
169
- }
170
-
171
- &:active:not(.ds-byline--noninteractive) .ds-byline__inner::before {
172
- background-color: $ds-color-component-primary-overlay-02;
173
- }
174
- &:focus-visible {
175
- outline: none;
176
- .ds-byline__inner {
177
- outline: ds-border-width(x2) solid $ds-color-border-focus-02;
178
- outline-offset: -2px;
179
- }
180
- }
181
-
182
- @at-root a#{&} {
183
- box-sizing: border-box;
184
- text-align: center;
185
- text-decoration: none;
186
- }
187
- }
1
+ @use "../../components/list-item/list-item.scss";
@@ -28,6 +28,6 @@ function dsListItemToggle(toggleEl) {
28
28
  }
29
29
 
30
30
  function dsListItemAll() {
31
- const listElements = Array.from(document.getElementsByClassName("ds-list-item"));
31
+ const listElements = Array.from(document.getElementsByClassName("ds-list-item__content"));
32
32
  dsListItem(listElements);
33
33
  }
@@ -7,39 +7,40 @@
7
7
 
8
8
  {% macro ListItem(params) %}
9
9
  {% set componentClassName = "ds-list-item" %}
10
- <li class="{{ componentClassName + '__outer'}}">
10
+ <li class="{{ componentClassName }}{% if params.border %} {{componentClassName}}--border{% endif %}">
11
11
  {% call ListItemInner(params, componentClassName) %}
12
- <div class="{{ componentClassName + '__inner'}}">
13
- {% set componentClassName = componentClassName %}
14
- {% if iconLeftSvg %}
15
- <span class="{{ componentClassName + '__icon-left'}}">{{- iconLeftSvg | safe -}}</span>
16
- {% endif %}
17
- {% if params.listItemType == 'image' %}
18
- <div class="{{ componentClassName + '__image'}}">{{ params.mediaHtml }}</div>
19
- {% endif %}
20
- {% if params.title %}
21
- <div class="{{ componentClassName + '__titles'}}">
22
- {% if params.titleHref and not params.disabled %}
23
- {% set linkAttributes = getAttributes(params.linkAttributes) %}
24
- <a class="{{ componentClassName + '__title'}}" href="{{ params.titleHref }}" {{ linkAttributes | safe }}>{{ params.title }}</a>
25
- {% else %}
26
- <span class="{{ componentClassName + '__title'}}">{{ params.title }}</span>
27
- {% endif %}
28
- {%- if params.subtitle %}
29
- <span class="{{ componentClassName + '__subtitle'}}">{{ params.subtitle }}</span>
30
- {% endif %}
31
- </div>
32
- {% endif %}
33
- {% if params.meta %}
34
- <span class="{{ componentClassName + '__meta'}}">{{ params.meta }}</span>
35
- {% endif %}
36
- {% if iconRightSvg %}
37
- <span class="{{ componentClassName + '__icon-right'}}">{{- iconRightSvg | safe -}}</span>
38
- {% endif %}
39
- {% if elementRight %}
40
- {{- elementRight | safe -}}
41
- {% endif %}
42
- </div>
12
+ {% set componentClassName = componentClassName %}
13
+ {% if iconLeftSvg %}
14
+ <span class="{{ componentClassName + '__icon-left'}}">{{- iconLeftSvg | safe -}}</span>
15
+ {% endif %}
16
+ {% if params.listItemType == 'image' %}
17
+ <div class="{{ componentClassName + '__image'}}">{{ params.mediaHtml }}</div>
18
+ {% endif %}
19
+ {% if params.listItemType == 'byline' and params.mediaHtml %}
20
+ <div class="{{ componentClassName + '__portrait'}}">{{ params.mediaHtml }}</div>
21
+ {% endif %}
22
+ {% if params.title %}
23
+ <div class="{{ componentClassName + '__titles'}}">
24
+ {% if params.titleHref and not params.disabled %}
25
+ {% set linkAttributes = getAttributes(params.linkAttributes) %}
26
+ <a class="{{ componentClassName + '__title'}}" href="{{ params.titleHref }}" {{ linkAttributes | safe }}>{{ params.title }}</a>
27
+ {% else %}
28
+ <span class="{{ componentClassName + '__title'}}">{{ params.title }}</span>
29
+ {% endif %}
30
+ {%- if params.subtitle %}
31
+ <span class="{{ componentClassName + '__subtitle'}}">{{ params.subtitle }}</span>
32
+ {% endif %}
33
+ </div>
34
+ {% endif %}
35
+ {% if params.meta %}
36
+ <span class="{{ componentClassName + '__meta'}}">{{ params.meta }}</span>
37
+ {% endif %}
38
+ {% if iconRightSvg %}
39
+ <span class="{{ componentClassName + '__icon-right'}}">{{- iconRightSvg | safe -}}</span>
40
+ {% endif %}
41
+ {% if elementRight %}
42
+ {{- elementRight | safe -}}
43
+ {% endif %}
43
44
  {% endcall %}
44
45
  </li>
45
46
  {% endmacro %}
@@ -66,9 +67,8 @@
66
67
  {% endif %}
67
68
 
68
69
  {%- set classes = [
69
- componentClassName,
70
+ componentClassName + "__content",
70
71
  "ds-force-px" if params.forcePx,
71
- classNamePrefix + "border" if params.border,
72
72
  classNamePrefix + "disabled" if params.disabled,
73
73
  variantClass,
74
74
  params.classNames if params.classNames
@@ -83,8 +83,7 @@
83
83
  {{ caller() if caller }}
84
84
  </button>
85
85
  {% elif element == 'checkbox' %}
86
- <div class="{{ classes }}" {{- attributes | safe }}>
87
- <label class="{{ componentClassName + '__wrapping-label'}}" for="{{ params.name }}"></label>
86
+ <label class="{{ classes }}" for="{{ params.name }}" {{- attributes | safe }}>
88
87
  {% set iconLeftSvg %}
89
88
  {{ Checkbox({
90
89
  name: params.name,
@@ -93,28 +92,27 @@
93
92
  disabled: params.disabled,
94
93
  forcePx: params.forcePx,
95
94
  stripLabel: true,
96
- attributes: params.elementAttributes
95
+ attributes: params.elementAttributes,
96
+ classNames: params.elementClassNames
97
97
  })}}
98
98
  {% endset %}
99
99
  {{ caller() if caller }}
100
- </div>
100
+ </label>
101
101
  {% elif element == 'radio' %}
102
- <div class="{{ classes }}" {{- attributes | safe }}>
103
- <label class="{{ componentClassName + '__wrapping-label'}}" for="{{ params.id }}"></label>
102
+ <label class="{{ classes }}" for="{{ params.id }}" {{- attributes | safe }}>
104
103
  {% set iconLeftSvg %}
105
104
  {{ RadioButton({
106
105
  name: params.name,
107
106
  condensed: true,
108
107
  disabled: params.disabled,
109
108
  forcePx: params.forcePx,
110
- buttons: [{ id: params.id, checked: params.selected, attributes: params.elementAttributes }]
109
+ buttons: [{ id: params.id, checked: params.selected, attributes: params.elementAttributes, classNames: params.elementClassNames }]
111
110
  })}}
112
111
  {% endset %}
113
112
  {{ caller() if caller }}
114
- </div>
113
+ </label>
115
114
  {% elif element == 'switch' %}
116
- <div class="{{ classes }}" {{- attributes | safe }}>
117
- <label class="{{ componentClassName + '__wrapping-label'}}" for="{{ params.name }}"></label>
115
+ <label class="{{ classes }}" for="{{ params.name }}" {{- attributes | safe }} >
118
116
  {% set iconRightSvg %}
119
117
  {{ Switch({
120
118
  name: params.name,
@@ -124,11 +122,12 @@
124
122
  disabled: params.disabled,
125
123
  forcePx: params.forcePx,
126
124
  stripLabel: true,
127
- attributes: params.elementAttributes
125
+ attributes: params.elementAttributes,
126
+ classNames: params.elementClassNames
128
127
  })}}
129
128
  {% endset %}
130
129
  {{ caller() if caller }}
131
- </div>
130
+ </label>
132
131
  {% elif element == 'accordion' %}
133
132
  {% set iconRightSvg %}
134
133
  {{ IconUse({ icon: "expand_less" }) }}
@@ -151,11 +150,38 @@
151
150
  disabled: params.disabled,
152
151
  forcePx: params.forcePx,
153
152
  size: "small",
154
- attributes: params.elementAttributes
153
+ attributes: params.elementAttributes,
154
+ classNames: params.elementClassNames
155
155
  })}}
156
156
  {% endset %}
157
157
  {{ caller() if caller }}
158
158
  </div>
159
+ {% elif element == 'byline' %}
160
+ {% set elementRight %}
161
+ {% if params.toggleText %}
162
+ {{ ButtonToggle({
163
+ text: params.toggleText,
164
+ selected: params.selected,
165
+ selectedText: params.toggleSelectedText,
166
+ variant: params.variant | default("secondary"),
167
+ disabled: params.disabled,
168
+ forcePx: params.forcePx,
169
+ size: "small",
170
+ attributes: params.elementAttributes,
171
+ classNames: params.elementClassNames
172
+ })}}
173
+ {% endif %}
174
+ {% endset %}
175
+ {% if params.href %}
176
+ {% set linkAttributes = getAttributes(params.linkAttributes) %}
177
+ <a href="{{ params.href }}" class="{{ classes }}" {{- attributes | safe }} {{- linkAttributes | safe }}>
178
+ {{ caller() if caller }}
179
+ </a>
180
+ {% else %}
181
+ <div class="{{ classes }}" {{- attributes | safe }}>
182
+ {{ caller() if caller }}
183
+ </div>
184
+ {% endif %}
159
185
  {% else %}
160
186
  <div class="{{ classes }}" {{- attributes | safe }}>
161
187
  {{ caller() if caller }}
@@ -6,59 +6,73 @@
6
6
  @use "../button-toggle/button-toggle.scss" as *;
7
7
 
8
8
  $ds-list-item__icon-size: 24px;
9
-
10
- .ds-list-item__outer {
11
- list-style: none;
12
- line-height: 0;
13
- position: relative;
14
- }
9
+ $ds-list-item__portrait-size: 44px;
10
+ $ds-list-item__portrait-size--small: 36px;
15
11
 
16
12
  .ds-list-item {
17
- cursor: pointer;
18
13
  background-color: transparent;
19
14
  border: 0;
20
- display: inline-flex;
15
+ display: flex;
16
+ flex-direction: column;
21
17
  align-items: center;
22
18
  justify-content: center;
23
- padding: 0;
24
19
  width: 100%;
20
+ list-style: none;
21
+ line-height: 0;
25
22
  position: relative;
26
23
 
27
- .ds-list-item__inner {
24
+ &.ds-list-item--border:not(:last-of-type)::after {
25
+ content: "";
26
+ width: 100%;
27
+ height: ds-border-width(x1);
28
+ background: $ds-color-border-primary;
29
+ position: absolute;
30
+ bottom: 0;
31
+ }
32
+
33
+ .ds-list-item__content {
28
34
  box-sizing: border-box;
29
35
  border-radius: 0;
30
36
  margin: 0;
31
37
  display: flex;
38
+ gap: ds-spacing($ds-s-100);
32
39
  align-items: center;
33
40
  justify-content: space-between;
34
- position: relative;
35
- padding: ds-spacing($ds-s-100 $ds-s-100);
41
+ padding: ds-spacing($ds-s-100 0);
36
42
  width: 100%;
43
+ border: none;
44
+ background: none;
37
45
 
38
- &::before {
39
- content: "";
40
- border-radius: inherit;
41
- pointer-events: none;
42
- position: absolute;
43
- top: 0;
44
- left: 0;
45
- bottom: 0;
46
- right: 0;
46
+ &:active {
47
+ opacity: 0.6;
47
48
  }
49
+ }
48
50
 
49
- .ds-icon {
50
- position: relative;
51
- display: flex;
52
- height: ds-px-to-rem($ds-list-item__icon-size);
53
- width: ds-px-to-rem($ds-list-item__icon-size);
54
- margin: 0;
55
- @at-root .ds-force-px#{&} {
56
- height: $ds-list-item__icon-size;
57
- width: $ds-list-item__icon-size;
58
- }
59
- svg {
60
- fill: currentColor;
61
- }
51
+ label.ds-list-item__content,
52
+ button.ds-list-item__content,
53
+ a.ds-list-item__content {
54
+ cursor: pointer;
55
+ @include ds-hover(true) {
56
+ opacity: 0.6;
57
+ }
58
+ }
59
+
60
+ a.ds-list-item__content {
61
+ text-decoration: none; /* full-element links are covered by the opacity hover effect - adding underlines makes it too busy */
62
+ }
63
+
64
+ .ds-icon {
65
+ position: relative;
66
+ display: flex;
67
+ height: ds-px-to-rem($ds-list-item__icon-size);
68
+ width: ds-px-to-rem($ds-list-item__icon-size);
69
+ margin: 0;
70
+ @at-root .ds-force-px#{&} {
71
+ height: $ds-list-item__icon-size;
72
+ width: $ds-list-item__icon-size;
73
+ }
74
+ svg {
75
+ fill: currentColor;
62
76
  }
63
77
  }
64
78
 
@@ -72,6 +86,7 @@ $ds-list-item__icon-size: 24px;
72
86
  flex-direction: column;
73
87
  flex-grow: 1;
74
88
  align-items: flex-start;
89
+ overflow-wrap: anywhere;
75
90
 
76
91
  .ds-list-item__title {
77
92
  @include ds-typography($ds-typography-functionalbody02);
@@ -82,12 +97,17 @@ $ds-list-item__icon-size: 24px;
82
97
  text-align: left;
83
98
  }
84
99
 
100
+ a.ds-list-item__title {
101
+ @include ds-link($ds-link-list);
102
+ }
103
+
85
104
  .ds-list-item__subtitle {
86
105
  @include ds-typography($ds-typography-functionalbody02);
87
106
  @at-root .ds-force-px#{&} {
88
107
  @include ds-typography($ds-typography-functionalbody02, true);
89
108
  }
90
109
  color: $ds-color-text-primary-02;
110
+ text-align: left;
91
111
  }
92
112
  }
93
113
 
@@ -97,17 +117,15 @@ $ds-list-item__icon-size: 24px;
97
117
  @include ds-typography($ds-typography-functionalbody01, true);
98
118
  }
99
119
  color: $ds-color-text-primary-02;
100
- margin-left: ds-spacing($ds-s-100);
120
+ text-align: right;
101
121
  }
102
122
 
103
123
  .ds-list-item__icon-left {
104
124
  display: inline-flex;
105
- margin-right: ds-spacing($ds-s-100);
106
125
  }
107
126
 
108
127
  .ds-list-item__icon-right {
109
128
  display: inline-flex;
110
- margin-left: ds-spacing($ds-s-100);
111
129
  }
112
130
 
113
131
  .ds-list-item__image {
@@ -129,8 +147,6 @@ $ds-list-item__icon-size: 24px;
129
147
  }
130
148
 
131
149
  + .ds-list-item__titles {
132
- margin-left: ds-spacing($ds-s-100);
133
-
134
150
  .ds-list-item__title {
135
151
  @include ds-typography($ds-typography-functionalbody02, $fontWeight: $ds-fontweight-semibold);
136
152
 
@@ -141,15 +157,23 @@ $ds-list-item__icon-size: 24px;
141
157
  }
142
158
  }
143
159
 
144
- @include ds-hover() {
145
- &:hover:not(.ds-list-item--disabled) .ds-list-item__inner::before {
146
- background-color: $ds-color-component-primary-overlay;
160
+ .ds-list-item__portrait {
161
+ border-radius: 50%;
162
+ overflow: hidden;
163
+ background-color: $ds-color-component-primary-overlay;
164
+ flex-shrink: 0;
165
+
166
+ .picture,
167
+ img {
168
+ width: ds-px-to-rem($ds-list-item__portrait-size);
169
+ height: ds-px-to-rem($ds-list-item__portrait-size);
147
170
  }
148
171
  }
149
172
 
150
173
  &:active:not(.ds-list-item--disabled) .ds-list-item__inner::before {
151
174
  background-color: $ds-color-component-primary-overlay;
152
175
  }
176
+
153
177
  &:focus-visible {
154
178
  outline: none;
155
179
  .ds-list-item__inner {
@@ -165,34 +189,15 @@ $ds-list-item__icon-size: 24px;
165
189
  }
166
190
  }
167
191
 
168
- .ds-list-item--border {
169
- position: relative;
170
-
171
- &::after,
172
- &.ds-list-item--accordion-active + .ds-list-item__accordion-inner::after {
173
- content: "";
174
- height: ds-border-width(x1);
175
- width: calc(100% - (ds-spacing($ds-s-100) * 2));
176
- background-color: $ds-color-border-primary;
177
- position: absolute;
178
- left: ds-spacing($ds-s-100);
179
- bottom: 0;
180
- }
181
-
182
- &.ds-list-item--accordion-active {
183
- &::after {
184
- background-color: transparent;
185
- }
186
- }
187
- }
188
-
189
192
  .ds-list-item--accordion {
190
- .ds-list-item__inner .ds-icon--expand_less {
193
+ .ds-icon--expand_less {
191
194
  display: none;
192
195
  }
193
196
 
194
197
  @at-root .ds-list-item__accordion-inner {
195
198
  display: none;
199
+ padding: ds-spacing(0 $ds-s-050);
200
+ border-top: ds-border-width(x1) solid $ds-color-border-primary;
196
201
  ul {
197
202
  margin: 0;
198
203
  padding: 0;
@@ -200,40 +205,22 @@ $ds-list-item__icon-size: 24px;
200
205
  }
201
206
 
202
207
  &.ds-list-item--accordion-active {
203
- .ds-list-item__inner .ds-icon--expand_less {
208
+ .ds-icon--expand_less {
204
209
  display: flex;
205
210
  }
206
- .ds-list-item__inner .ds-icon--expand_more {
211
+ .ds-icon--expand_more {
207
212
  display: none;
208
213
  }
209
214
 
210
215
  & + .ds-list-item__accordion-inner {
211
216
  display: block;
212
- position: relative;
213
217
  }
214
218
  }
215
219
  }
216
220
 
217
221
  .ds-list-item--disabled {
218
222
  cursor: not-allowed;
219
- .ds-list-item__titles .ds-list-item__title,
220
- .ds-list-item__titles .ds-list-item__subtitle {
221
- color: $ds-color-text-disabled;
222
- }
223
- .ds-list-item__icon-left,
224
- .ds-list-item__icon-right {
225
- color: $ds-color-icon-disabled;
226
- }
227
-
228
- .ds-list-item__wrapping-label::after {
229
- cursor: not-allowed;
230
- }
231
- .ds-list-item__inner {
232
- color: $ds-color-icon-disabled;
233
- &::before {
234
- background-color: unset;
235
- }
236
- }
223
+ opacity: 0.5;
237
224
  }
238
225
 
239
226
  .ds-list-item--accordion .ds-checkbox__accordion,
@@ -252,34 +239,42 @@ $ds-list-item__icon-size: 24px;
252
239
  }
253
240
  }
254
241
 
255
- .ds-list-item__wrapping-label {
256
- &::after {
257
- content: "";
242
+ .ds-list-item--toggle {
243
+ a {
244
+ @include ds-link($ds-link-list);
245
+ display: block;
258
246
  width: 100%;
259
- height: 100%;
260
- position: absolute;
261
- top: 0;
262
- left: 0;
263
- z-index: 1;
264
- cursor: pointer;
265
247
  }
266
248
  }
267
249
 
268
- .ds-list-item--toggle {
269
- cursor: default;
270
- .ds-list-item__inner {
271
- display: flex;
272
- padding: ds-spacing(0 0 0 $ds-s-100);
273
- }
250
+ .ds-list-item--byline {
274
251
  .ds-list-item__titles {
275
- padding: ds-spacing($ds-s-100) 0;
276
- }
277
- .ds-btn--toggle {
278
- margin: ds-spacing(0 $ds-s-100 0 $ds-s-100);
252
+ .ds-list-item__title {
253
+ @include ds-typography(
254
+ $ds-typography-functionalheading01,
255
+ $lineHeight: $ds-lineheight-m,
256
+ $fontWeight: $ds-fontweight-semibold
257
+ );
258
+ @at-root .ds-force-px#{&} {
259
+ @include ds-typography(
260
+ $ds-typography-functionalheading01,
261
+ $forcePx: true,
262
+ $lineHeight: $ds-lineheight-m,
263
+ $fontWeight: $ds-fontweight-semibold
264
+ );
265
+ }
266
+ }
279
267
  }
280
- a {
281
- @include ds-link($ds-link-list);
282
- display: block;
283
- width: 100%;
268
+
269
+ &.ds-byline--direkt {
270
+ padding: ds-spacing($ds-s-075 0);
271
+
272
+ .ds-list-item__portrait {
273
+ .picture,
274
+ img {
275
+ width: ds-px-to-rem($ds-list-item__portrait-size--small);
276
+ height: ds-px-to-rem($ds-list-item__portrait-size--small);
277
+ }
278
+ }
284
279
  }
285
280
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonniernews/dn-design-system-web",
3
- "version": "17.0.0",
3
+ "version": "18.0.0-beta.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",