@ecl/button 5.0.0-alpha.2 → 5.0.0-alpha.20

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/README.md CHANGED
@@ -9,7 +9,9 @@ npm install --save @ecl/button
9
9
  ### Parameters
10
10
 
11
11
  - **"label"** (string) (default: '')
12
- - **"variant"** (string) (default: 'primary'): variant of button (can be 'primary', 'secondary', 'cta', 'ghost', 'ghost-inverted', 'tertiary')
12
+ - **"size"** (string) (default: 'l'): button size
13
+ - **"variant"** (string) (default: 'primary'): can be 'primary', 'secondary', 'tertiary'
14
+ - **"style"** (string) (default: ''): can be 'highlight', 'neutral', 'inverted'. Not all styles are available for all variants
13
15
  - **"type"** (string) (default: 'submit'): can be the same type as HTML button - 'submit', 'reset', 'button'
14
16
  - **"disabled"** (bool) (default: false): define if button should be disabled (HTML disabled attribute)
15
17
  - **"hide_label"** (bool) (default: false): hide button label, for screen reader only. Note: requires to have an icon defined
@@ -30,7 +32,6 @@ npm install --save @ecl/button
30
32
  label: 'Example button',
31
33
  disabled: false,
32
34
  icon: {
33
- path: '/path-to-the-icon-file',
34
35
  type: 'ui',
35
36
  name: 'corner-arrow',
36
37
  size: 'xs,'
package/button-print.scss CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  @use 'sass:map';
7
+ @use '@ecl/mixins-typography/mixins';
7
8
 
8
9
  // Exposed variables
9
10
  $theme: null !default;
@@ -17,7 +18,6 @@ $button: null !default;
17
18
  border-width: 0;
18
19
  cursor: pointer;
19
20
  display: inline-block;
20
- font: map.get($theme, 'font-ui-print', 'm');
21
21
  margin: 0;
22
22
  text-decoration: none;
23
23
 
@@ -33,66 +33,161 @@ $button: null !default;
33
33
  display: flex;
34
34
  }
35
35
 
36
- .ecl-button__label {
37
- text-align: left;
38
- }
39
-
40
36
  .ecl-button__icon {
41
37
  flex-shrink: 0;
38
+ height: map.get($button, 'large', 'icon-size');
39
+ width: map.get($button, 'large', 'icon-size');
40
+
41
+ .ecl-button--s & {
42
+ height: map.get($button, 'small', 'icon-size');
43
+ width: map.get($button, 'small', 'icon-size');
44
+ }
45
+
46
+ .ecl-button--m & {
47
+ height: map.get($button, 'medium', 'icon-size');
48
+ width: map.get($button, 'medium', 'icon-size');
49
+ }
42
50
  }
43
51
 
44
- .ecl-button__icon ~ .ecl-button__label,
45
- .ecl-button__icon-container ~ .ecl-button__label,
46
- .ecl-button__label ~ .ecl-button__icon,
47
- .ecl-button__label ~ .ecl-button__icon-container {
48
- margin-inline-end: map.get($theme, 'spacing-print', 'xs');
52
+ .ecl-button__icon-container {
53
+ display: flex;
54
+ position: relative;
49
55
  }
50
56
 
51
57
  .ecl-button__indicator {
52
58
  display: none;
53
59
  }
54
60
 
55
- /**
56
- * Button styles
57
- */
61
+ // Icon only
62
+ .ecl-button--icon-only {
63
+ align-items: center;
64
+ display: flex;
65
+ justify-content: center;
66
+ padding: 0 !important;
67
+
68
+ .ecl-button__label {
69
+ display: none;
70
+ }
71
+
72
+ .ecl-button__icon {
73
+ height: map.get($button, 'large', 'icon-only-size');
74
+ width: map.get($button, 'large', 'icon-only-size');
75
+ }
76
+
77
+ &.ecl-button--s .ecl-button__icon {
78
+ height: map.get($button, 'small', 'icon-only-size');
79
+ width: map.get($button, 'small', 'icon-only-size');
80
+ }
81
+
82
+ &.ecl-button--m .ecl-button__icon {
83
+ height: map.get($button, 'medium', 'icon-only-size');
84
+ width: map.get($button, 'medium', 'icon-only-size');
85
+ }
86
+ }
87
+
88
+ .ecl-button:not(.ecl-button--icon-only) {
89
+ .ecl-button__icon ~ .ecl-button__label,
90
+ .ecl-button__icon-container ~ .ecl-button__label,
91
+ .ecl-button__label ~ .ecl-button__icon,
92
+ .ecl-button__label ~ .ecl-button__icon-container {
93
+ margin-inline-start: map.get($button, 'large', 'icon-spacing');
94
+
95
+ .ecl-button--s & {
96
+ margin-inline-start: map.get($button, 'small', 'icon-spacing');
97
+ }
98
+
99
+ .ecl-button--m & {
100
+ margin-inline-start: map.get($button, 'medium', 'icon-spacing');
101
+ }
102
+ }
103
+ }
104
+
105
+ // Button styles
106
+ // stylelint-disable nesting-selector-no-missing-scoping-root
58
107
  @mixin button($variant: null) {
59
108
  background-color: map.get($button, #{$variant}, 'background');
60
109
  border: map.get($button, #{$variant}, 'border-width') solid
61
110
  map.get($button, #{$variant}, 'border-color');
62
111
  color: map.get($button, #{$variant}, 'color');
112
+ min-height: map.get($button, 'large', 'size');
113
+ min-width: map.get($button, 'large', 'size');
63
114
  padding: calc(
64
- #{map.get($button, 'padding-vertical')} -
115
+ #{map.get($button, 'large', 'padding-vertical')} -
65
116
  #{map.get($button, #{$variant}, 'border-width')}
66
117
  )
67
118
  calc(
68
- #{map.get($button, 'padding-horizontal')} -
119
+ #{map.get($button, 'large', 'padding-horizontal')} -
69
120
  #{map.get($button, #{$variant}, 'border-width')}
70
121
  );
122
+
123
+ @include mixins.responsive-font(map.get($button, 'large', 'font'));
124
+
125
+ &.ecl-button--s {
126
+ min-height: map.get($button, 'small', 'size');
127
+ min-width: map.get($button, 'small', 'size');
128
+ padding: calc(
129
+ #{map.get($button, 'small', 'padding-vertical')} -
130
+ #{map.get($button, #{$variant}, 'border-width')}
131
+ )
132
+ calc(
133
+ #{map.get($button, 'small', 'padding-horizontal')} -
134
+ #{map.get($button, #{$variant}, 'border-width')}
135
+ );
136
+
137
+ @include mixins.responsive-font(map.get($button, 'small', 'font'));
138
+ }
139
+
140
+ &.ecl-button--m {
141
+ min-height: map.get($button, 'medium', 'size');
142
+ min-width: map.get($button, 'medium', 'size');
143
+ padding: calc(
144
+ #{map.get($button, 'medium', 'padding-vertical')} -
145
+ #{map.get($button, #{$variant}, 'border-width')}
146
+ )
147
+ calc(
148
+ #{map.get($button, 'medium', 'padding-horizontal')} -
149
+ #{map.get($button, #{$variant}, 'border-width')}
150
+ );
151
+
152
+ @include mixins.responsive-font(map.get($button, 'medium', 'font'));
153
+ }
71
154
  }
155
+ // stylelint-enable nesting-selector-no-missing-scoping-root
72
156
 
157
+ // Primary
73
158
  .ecl-button--primary {
74
159
  @include button(primary);
160
+
161
+ &.ecl-button--highlight {
162
+ @include button(primary-highlight);
163
+ }
164
+
165
+ &.ecl-button--inverted {
166
+ @include button(primary-inverted);
167
+ }
75
168
  }
76
169
 
77
- // stylelint-disable plugin/selector-bem-pattern
78
170
  .ecl-button--secondary,
79
171
  %ecl-button {
80
172
  @include button(secondary);
173
+
174
+ &.ecl-button--neutral {
175
+ @include button(secondary-neutral);
176
+ }
177
+
178
+ &.ecl-button--inverted {
179
+ @include button(secondary-inverted);
180
+ }
81
181
  }
82
- // stylelint-enable plugin/selector-bem-pattern
83
182
 
84
183
  .ecl-button--tertiary {
85
184
  @include button(tertiary);
86
- }
87
185
 
88
- .ecl-button--cta {
89
- @include button(cta);
90
- }
91
-
92
- .ecl-button--ghost {
93
- @include button(ghost);
94
- }
186
+ &.ecl-button--neutral {
187
+ @include button(tertiary-neutral);
188
+ }
95
189
 
96
- .ecl-button--ghost-inverted {
97
- @include button(ghost-inverted);
190
+ &.ecl-button--inverted {
191
+ @include button(tertiary-inverted);
192
+ }
98
193
  }
package/button.html.twig CHANGED
@@ -4,7 +4,9 @@
4
4
  {#
5
5
  Parameters:
6
6
  - "label" (string) (default: '')
7
- - "variant" (string) (default: 'primary'): can be 'primary', 'secondary', 'cta', 'ghost', 'ghost-inverted', 'tertiaty'
7
+ - "size" (string) (default: 'l'): button size
8
+ - "variant" (string) (default: 'primary'): can be 'primary', 'secondary', 'tertiary'
9
+ - "style" (string) (default: ''): can be 'highlight', 'neutral', 'inverted'. Not all styles are available for all variants
8
10
  - "type" (string) (default: 'submit'): can be the same type as HTML button - 'submit', 'reset', 'button'
9
11
  - "icon" (associative array) OR (array) of associative arrays : format
10
12
  {
@@ -43,23 +45,32 @@
43
45
  {% set _css_class = 'ecl-button' %}
44
46
  {% set _extra_attributes = '' %}
45
47
  {% set _label = label|default('') %}
48
+ {% set _size = size|default('l') %}
46
49
  {% set _variant = variant|default('primary') %}
50
+ {% set _style = style|default('') %}
47
51
  {% set _type = type|default('submit') %}
48
52
  {% set _icon_position = icon_position|default('after') %}
49
53
  {% set _disabled = disabled|default(false) %}
50
54
  {% set _hide_label = hide_label|default(false) %}
51
- {% set _icon = {
55
+ {% set _icon = icon|default({
52
56
  name: '',
53
- path: '',
54
57
  size: '',
55
58
  title: ''
56
- } %}
59
+ }) %}
57
60
  {% set _indicator = indicator|default({}) %}
58
61
 
59
62
  {# Internal logic - Process properties #}
60
63
 
61
64
  {% set _css_class = _css_class ~ ' ecl-button--' ~ _variant %}
62
65
 
66
+ {% if _size != 'l' %}
67
+ {% set _css_class = _css_class ~ ' ecl-button--' ~ _size %}
68
+ {% endif %}
69
+
70
+ {% if _style is not empty %}
71
+ {% set _css_class = _css_class ~ ' ecl-button--' ~ _style %}
72
+ {% endif %}
73
+
63
74
  {% if extra_classes is defined and extra_classes is not empty %}
64
75
  {% set _css_class = _css_class ~ ' ' ~ extra_classes %}
65
76
  {% endif %}
@@ -74,10 +85,10 @@
74
85
  {% endfor %}
75
86
  {% endif %}
76
87
 
77
- {% if icon.name is defined and icon.name is not empty %}
78
- {% set _icons = [icon] %}
79
- {% elseif icon[1] is defined and icon[1] is not empty %}
80
- {% set _icons = icon %}
88
+ {% if _icon.name is defined and _icon.name is not empty %}
89
+ {% set _icons = [_icon] %}
90
+ {% elseif _icon[1] is defined and _icon[1] is not empty %}
91
+ {% set _icons = _icon %}
81
92
  {% endif %}
82
93
 
83
94
  {% if _hide_label and _icon is not empty %}
package/button.scss CHANGED
@@ -5,14 +5,12 @@
5
5
 
6
6
  @use 'sass:map';
7
7
  @use '@ecl/utility-screen-reader/screen-reader';
8
+ @use '@ecl/mixins-typography/mixins';
8
9
 
9
10
  // Exposed variables
10
11
  $theme: null !default;
11
12
  $button: null !default;
12
13
 
13
- // Internal variables
14
- $min-width: 44px; // According to COMM every interactive element should be at least 44px large
15
-
16
14
  .ecl-button,
17
15
  %ecl-button {
18
16
  appearance: none;
@@ -22,10 +20,7 @@ $min-width: 44px; // According to COMM every interactive element should be at le
22
20
  box-sizing: border-box;
23
21
  cursor: pointer;
24
22
  display: inline-block;
25
- font: map.get($button, 'font');
26
23
  margin: 0;
27
- min-height: map.get($button, 'min-height');
28
- min-width: $min-width;
29
24
  text-decoration: none;
30
25
 
31
26
  &:hover {
@@ -56,6 +51,18 @@ $min-width: 44px; // According to COMM every interactive element should be at le
56
51
 
57
52
  .ecl-button__icon {
58
53
  flex-shrink: 0;
54
+ height: map.get($button, 'large', 'icon-size');
55
+ width: map.get($button, 'large', 'icon-size');
56
+
57
+ .ecl-button--s & {
58
+ height: map.get($button, 'small', 'icon-size');
59
+ width: map.get($button, 'small', 'icon-size');
60
+ }
61
+
62
+ .ecl-button--m & {
63
+ height: map.get($button, 'medium', 'icon-size');
64
+ width: map.get($button, 'medium', 'icon-size');
65
+ }
59
66
  }
60
67
 
61
68
  .ecl-button__icon-container {
@@ -67,13 +74,6 @@ $min-width: 44px; // According to COMM every interactive element should be at le
67
74
  display: none;
68
75
  }
69
76
 
70
- .ecl-button__icon ~ .ecl-button__label,
71
- .ecl-button__icon-container ~ .ecl-button__label,
72
- .ecl-button__label ~ .ecl-button__icon,
73
- .ecl-button__label ~ .ecl-button__icon-container {
74
- margin-inline-start: var(--s-xs);
75
- }
76
-
77
77
  // Icon only
78
78
  .ecl-button--icon-only {
79
79
  align-items: center;
@@ -85,34 +85,89 @@ $min-width: 44px; // According to COMM every interactive element should be at le
85
85
  @include screen-reader.sr-only;
86
86
  }
87
87
 
88
- .ecl-button__icon,
89
- .ecl-button__icon-container {
90
- margin: 0;
88
+ .ecl-button__icon {
89
+ height: map.get($button, 'large', 'icon-only-size');
90
+ width: map.get($button, 'large', 'icon-only-size');
91
91
  }
92
92
 
93
- .ecl-button__icon {
94
- height: map.get($theme, 'icon', 'm');
95
- width: map.get($theme, 'icon', 'm');
93
+ &.ecl-button--s .ecl-button__icon {
94
+ height: map.get($button, 'small', 'icon-only-size');
95
+ width: map.get($button, 'small', 'icon-only-size');
96
+ }
97
+
98
+ &.ecl-button--m .ecl-button__icon {
99
+ height: map.get($button, 'medium', 'icon-only-size');
100
+ width: map.get($button, 'medium', 'icon-only-size');
96
101
  }
97
102
  }
98
103
 
99
- /**
100
- * Button styles
101
- */
104
+ .ecl-button:not(.ecl-button--icon-only) {
105
+ .ecl-button__icon ~ .ecl-button__label,
106
+ .ecl-button__icon-container ~ .ecl-button__label,
107
+ .ecl-button__label ~ .ecl-button__icon,
108
+ .ecl-button__label ~ .ecl-button__icon-container {
109
+ margin-inline-start: map.get($button, 'large', 'icon-spacing');
110
+
111
+ .ecl-button--s & {
112
+ margin-inline-start: map.get($button, 'small', 'icon-spacing');
113
+ }
114
+
115
+ .ecl-button--m & {
116
+ margin-inline-start: map.get($button, 'medium', 'icon-spacing');
117
+ }
118
+ }
119
+ }
120
+
121
+ // Button styles
122
+ // stylelint-disable nesting-selector-no-missing-scoping-root
102
123
  @mixin button($variant: null) {
103
124
  background-color: map.get($button, #{$variant}, 'background');
104
125
  border: map.get($button, #{$variant}, 'border-width') solid
105
126
  map.get($button, #{$variant}, 'border-color');
106
127
  color: map.get($button, #{$variant}, 'color');
128
+ min-height: map.get($button, 'large', 'size');
129
+ min-width: map.get($button, 'large', 'size');
107
130
  padding: calc(
108
- #{map.get($button, 'padding-vertical')} -
131
+ #{map.get($button, 'large', 'padding-vertical')} -
109
132
  #{map.get($button, #{$variant}, 'border-width')}
110
133
  )
111
134
  calc(
112
- #{map.get($button, 'padding-horizontal')} -
135
+ #{map.get($button, 'large', 'padding-horizontal')} -
113
136
  #{map.get($button, #{$variant}, 'border-width')}
114
137
  );
115
138
 
139
+ @include mixins.responsive-font(map.get($button, 'large', 'font'));
140
+
141
+ &.ecl-button--s {
142
+ min-height: map.get($button, 'small', 'size');
143
+ min-width: map.get($button, 'small', 'size');
144
+ padding: calc(
145
+ #{map.get($button, 'small', 'padding-vertical')} -
146
+ #{map.get($button, #{$variant}, 'border-width')}
147
+ )
148
+ calc(
149
+ #{map.get($button, 'small', 'padding-horizontal')} -
150
+ #{map.get($button, #{$variant}, 'border-width')}
151
+ );
152
+
153
+ @include mixins.responsive-font(map.get($button, 'small', 'font'));
154
+ }
155
+
156
+ &.ecl-button--m {
157
+ min-height: map.get($button, 'medium', 'size');
158
+ min-width: map.get($button, 'medium', 'size');
159
+ padding: calc(
160
+ #{map.get($button, 'medium', 'padding-vertical')} -
161
+ #{map.get($button, #{$variant}, 'border-width')}
162
+ )
163
+ calc(
164
+ #{map.get($button, 'medium', 'padding-horizontal')} -
165
+ #{map.get($button, #{$variant}, 'border-width')}
166
+ );
167
+
168
+ @include mixins.responsive-font(map.get($button, 'medium', 'font'));
169
+ }
170
+
116
171
  &:hover {
117
172
  background-color: map.get($button, #{$variant}, 'background-hover');
118
173
  border-color: map.get($button, #{$variant}, 'border-color-hover');
@@ -126,6 +181,46 @@ $min-width: 44px; // According to COMM every interactive element should be at le
126
181
  outline: #{map.get($button, #{$variant}, 'outline-width')} solid
127
182
  #{map.get($button, #{$variant}, 'outline-color')};
128
183
  outline-offset: map.get($button, #{$variant}, 'outline-offset');
184
+
185
+ @if map.has-key($button, #{$variant}, 'shadow-focus') {
186
+ box-shadow: map.get($button, #{$variant}, 'shadow-focus');
187
+ }
188
+ }
189
+
190
+ @if map.has-key($button, #{$variant}, 'border-width-focus') {
191
+ &:focus-visible {
192
+ border-width: map.get($button, #{$variant}, 'border-width-focus');
193
+ padding: calc(
194
+ #{map.get($button, 'large', 'padding-vertical')} -
195
+ #{map.get($button, #{$variant}, 'border-width-focus')}
196
+ )
197
+ calc(
198
+ #{map.get($button, 'large', 'padding-horizontal')} -
199
+ #{map.get($button, #{$variant}, 'border-width-focus')}
200
+ );
201
+ }
202
+
203
+ &.ecl-button--s:focus-visible {
204
+ padding: calc(
205
+ #{map.get($button, 'small', 'padding-vertical')} -
206
+ #{map.get($button, #{$variant}, 'border-width-focus')}
207
+ )
208
+ calc(
209
+ #{map.get($button, 'small', 'padding-horizontal')} -
210
+ #{map.get($button, #{$variant}, 'border-width-focus')}
211
+ );
212
+ }
213
+
214
+ &.ecl-button--m:focus-visible {
215
+ padding: calc(
216
+ #{map.get($button, 'medium', 'padding-vertical')} -
217
+ #{map.get($button, #{$variant}, 'border-width-focus')}
218
+ )
219
+ calc(
220
+ #{map.get($button, 'medium', 'padding-horizontal')} -
221
+ #{map.get($button, #{$variant}, 'border-width-focus')}
222
+ );
223
+ }
129
224
  }
130
225
 
131
226
  &:active {
@@ -134,34 +229,42 @@ $min-width: 44px; // According to COMM every interactive element should be at le
134
229
  color: map.get($button, #{$variant}, 'color-active');
135
230
  }
136
231
  }
232
+ // stylelint-enable nesting-selector-no-missing-scoping-root
137
233
 
234
+ // Primary
138
235
  .ecl-button--primary {
139
236
  @include button(primary);
237
+
238
+ &.ecl-button--highlight {
239
+ @include button(primary-highlight);
240
+ }
241
+
242
+ &.ecl-button--inverted {
243
+ @include button(primary-inverted);
244
+ }
140
245
  }
141
246
 
142
- // stylelint-disable plugin/selector-bem-pattern
143
247
  .ecl-button--secondary,
144
248
  %ecl-button {
145
249
  @include button(secondary);
146
250
 
147
- &:focus-visible {
148
- box-shadow: map.get($button, 'secondary', 'focus-shadow');
251
+ &.ecl-button--neutral {
252
+ @include button(secondary-neutral);
253
+ }
254
+
255
+ &.ecl-button--inverted {
256
+ @include button(secondary-inverted);
149
257
  }
150
258
  }
151
- // stylelint-enable plugin/selector-bem-pattern
152
259
 
153
260
  .ecl-button--tertiary {
154
261
  @include button(tertiary);
155
- }
156
262
 
157
- .ecl-button--cta {
158
- @include button(cta);
159
- }
160
-
161
- .ecl-button--ghost {
162
- @include button(ghost);
163
- }
263
+ &.ecl-button--neutral {
264
+ @include button(tertiary-neutral);
265
+ }
164
266
 
165
- .ecl-button--ghost-inverted {
166
- @include button(ghost-inverted);
267
+ &.ecl-button--inverted {
268
+ @include button(tertiary-inverted);
269
+ }
167
270
  }
package/package.json CHANGED
@@ -2,15 +2,20 @@
2
2
  "name": "@ecl/button",
3
3
  "author": "European Commission",
4
4
  "license": "EUPL-1.2",
5
- "version": "5.0.0-alpha.2",
5
+ "version": "5.0.0-alpha.20",
6
6
  "description": "ECL Button",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
10
10
  "style": "button.scss",
11
11
  "dependencies": {
12
- "@ecl/icon": "5.0.0-alpha.2",
13
- "@ecl/indicator": "5.0.0-alpha.2"
12
+ "@ecl/icon": "5.0.0-alpha.20",
13
+ "@ecl/indicator": "5.0.0-alpha.20"
14
+ },
15
+ "devDependencies": {
16
+ "@ecl/mixins-typography": "5.0.0-alpha.20",
17
+ "@ecl/resources-icons": "5.0.0-alpha.20",
18
+ "@ecl/utility-screen-reader": "5.0.0-alpha.20"
14
19
  },
15
20
  "repository": {
16
21
  "type": "git",
@@ -26,5 +31,5 @@
26
31
  "design-system",
27
32
  "twig"
28
33
  ],
29
- "gitHead": "3c10f74e78b7c3891917c075fa3868eb7c4f3d7a"
34
+ "gitHead": "47aedb8e6c7b15ce6acc9cbd2284c4a52ba1014b"
30
35
  }