@internetstiftelsen/styleguide 2.20.7 → 2.21.3-beta.0.1

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.
@@ -48,4 +48,6 @@ require('./molecules/glider/glider-single');
48
48
 
49
49
  require('./atoms/timeline/anchorScroll');
50
50
 
51
- require('./molecules/timeline-navigation/timeline-navigation');
51
+ require('./molecules/timeline-navigation/timeline-navigation');
52
+
53
+ require('./molecules/context-menu/context-menu');
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ var elements = document.querySelectorAll('[data-close-on-outside-click]');
4
+
5
+ function closeElement(element) {
6
+ document.addEventListener('mouseup', function (e) {
7
+ var childElement = element.nextElementSibling;
8
+
9
+ /* Close menu on all clicks except the trigger button,
10
+ the menu and it's child elements and if the menu is actually open. */
11
+ if (!element.contains(e.target) && !childElement.contains(e.target) && element.getAttribute('aria-expanded') === 'true') {
12
+ element.click();
13
+ }
14
+ });
15
+ }
16
+
17
+ if (elements) {
18
+ [].forEach.call(elements, closeElement);
19
+ }
@@ -9,6 +9,9 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
9
9
 
10
10
  var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
11
11
 
12
+ exports.onOpen = onOpen;
13
+ exports.onClose = onClose;
14
+
12
15
  var _focusTrap = require('../../focusTrap');
13
16
 
14
17
  var _focusTrap2 = _interopRequireDefault(_focusTrap);
@@ -51,6 +54,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
51
54
  */
52
55
 
53
56
  var queue = [];
57
+ var globalOnCloseCallbacks = [];
58
+ var globalOnOpenCallbacks = [];
54
59
  var active = null;
55
60
  var incrementId = 0;
56
61
  var modal = null;
@@ -138,6 +143,26 @@ function handleKeyUp(e) {
138
143
  });
139
144
  }
140
145
 
146
+ /**
147
+ * Global onOpen handler
148
+ *
149
+ * @param {Function} cb
150
+ * @returns {number}
151
+ */
152
+ function onOpen(cb) {
153
+ var index = globalOnOpenCallbacks.push(cb) - 1;
154
+
155
+ return function () {
156
+ globalOnOpenCallbacks.splice(index, 1);
157
+ };
158
+ }
159
+
160
+ function dispatchOnOpenHandlers(el, id) {
161
+ globalOnOpenCallbacks.forEach(function (cb) {
162
+ return cb(el, id);
163
+ });
164
+ }
165
+
141
166
  /**
142
167
  * Display the active modal.
143
168
  */
@@ -167,6 +192,8 @@ function display() {
167
192
  active.settings.onOpen(active.id, active.el);
168
193
  }
169
194
 
195
+ dispatchOnOpenHandlers(active.el, active.id);
196
+
170
197
  setTimeout(function () {
171
198
  if (active.el.focusTrap) {
172
199
  active.el.focusTrap.activate();
@@ -200,6 +227,26 @@ function dispatch() {
200
227
  display();
201
228
  }
202
229
 
230
+ /**
231
+ * Global onClose handler
232
+ *
233
+ * @param {Function} cb
234
+ * @returns {number}
235
+ */
236
+ function onClose(cb) {
237
+ var index = globalOnCloseCallbacks.push(cb) - 1;
238
+
239
+ return function () {
240
+ globalOnCloseCallbacks.splice(index, 1);
241
+ };
242
+ }
243
+
244
+ function dispatchOnCloseHandlers(el, id) {
245
+ globalOnCloseCallbacks.forEach(function (cb) {
246
+ return cb(el, id);
247
+ });
248
+ }
249
+
203
250
  /**
204
251
  * Close currently active modal
205
252
  * and dispatch next in queue.
@@ -212,6 +259,8 @@ function close() {
212
259
  active.settings.onClose(active.id);
213
260
  }
214
261
 
262
+ dispatchOnCloseHandlers(active.el, active.id);
263
+
215
264
  document.removeEventListener('keyup', handleKeyUp);
216
265
 
217
266
  if (active.el.focusTrap) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetstiftelsen/styleguide",
3
- "version": "2.20.7",
3
+ "version": "2.21.3-beta.0.1",
4
4
  "main": "dist/components.js",
5
5
  "ports": {
6
6
  "fractal": "3000"
package/src/app.js CHANGED
@@ -5,7 +5,7 @@ require('./atoms/grid-toggle/grid-toggle');
5
5
  require('./components');
6
6
 
7
7
  const Button = require('./atoms/button/Button');
8
- const { open } = require('./molecules/modal/modal');
8
+ const { open, onClose, onOpen } = require('./molecules/modal/modal');
9
9
 
10
10
  const demoButtons = document.querySelectorAll('button.a-button.has-loader');
11
11
 
@@ -59,3 +59,17 @@ if (demoModal) {
59
59
  });
60
60
  });
61
61
  }
62
+
63
+ // eslint-disable-next-line no-unused-vars
64
+ const unsubscribe = onClose((el, id) => {
65
+ console.log('Global onClose', el, id);
66
+ });
67
+
68
+ // Call unsubscribe to remove callback
69
+
70
+ // eslint-disable-next-line no-unused-vars
71
+ const unsubscribeOpen = onOpen((el, id) => {
72
+ console.log('Global onOpen', el, id);
73
+ });
74
+
75
+ // Call unsubscribe to remove callback
package/src/components.js CHANGED
@@ -23,3 +23,4 @@ import './molecules/glider/glider';
23
23
  import './molecules/glider/glider-single';
24
24
  import './atoms/timeline/anchorScroll';
25
25
  import './molecules/timeline-navigation/timeline-navigation';
26
+ import './molecules/context-menu/context-menu';
@@ -4,14 +4,24 @@ module.exports = {
4
4
  context: {
5
5
  name: 'Context menu',
6
6
  controls: 'contextMenu',
7
- focusTrap: true
7
+ focusTrap: true,
8
+ outsideClick: false
8
9
  },
9
10
  variants: [
10
11
  {
11
12
  name: 'No focus trap',
12
13
  context: {
13
14
  controls: 'contextMenu2',
14
- focusTrap: false
15
+ focusTrap: false,
16
+ outsideClick: false
17
+ }
18
+ },
19
+ {
20
+ name: 'Close on outside click',
21
+ context: {
22
+ controls: 'contextMenu3',
23
+ focusTrap: false,
24
+ outsideClick: true
15
25
  }
16
26
  }
17
27
  ]
@@ -1,5 +1,5 @@
1
1
  <nav class="m-context-menu js-context-menu">
2
- <button type="button" class="a-button a-button--icon a-button--transparent a-button--icon js-context-menu-btn" aria-expanded="false" data-a11y-toggle="{{controls}}" aria-controls="{{controls}}">
2
+ <button type="button" class="a-button a-button--icon a-button--transparent a-button--icon js-context-menu-btn" aria-expanded="false" data-a11y-toggle="{{controls}}" aria-controls="{{controls}}" {{#if outsideClick}}data-close-on-outside-click="true"{{/if}}>
3
3
  <span class="a-button__text">Exportera</span>
4
4
  <svg class="icon a-button__icon">
5
5
  <use xlink:href="#icon-download"></use>
@@ -0,0 +1,17 @@
1
+ const elements = document.querySelectorAll('[data-close-on-outside-click]');
2
+
3
+ function closeElement(element) {
4
+ document.addEventListener('mouseup', (e) => {
5
+ const childElement = element.nextElementSibling;
6
+
7
+ /* Close menu on all clicks except the trigger button,
8
+ the menu and it's child elements and if the menu is actually open. */
9
+ if (!element.contains(e.target) && !childElement.contains(e.target) && element.getAttribute('aria-expanded') === 'true') {
10
+ element.click();
11
+ }
12
+ });
13
+ }
14
+
15
+ if (elements) {
16
+ [].forEach.call(elements, closeElement);
17
+ }
@@ -67,7 +67,7 @@
67
67
  padding: rhythm(2) 0;
68
68
  overflow: hidden;
69
69
 
70
- img {
70
+ img:not([class]) {
71
71
  display: block;
72
72
  border-radius: $border-radius;
73
73
  width: 100%;
@@ -33,6 +33,8 @@ import className from '../../assets/js/className';
33
33
  */
34
34
 
35
35
  const queue = [];
36
+ const globalOnCloseCallbacks = [];
37
+ const globalOnOpenCallbacks = [];
36
38
  let active = null;
37
39
  let incrementId = 0;
38
40
  let modal = null;
@@ -117,6 +119,24 @@ function handleKeyUp(e) {
117
119
  });
118
120
  }
119
121
 
122
+ /**
123
+ * Global onOpen handler
124
+ *
125
+ * @param {Function} cb
126
+ * @returns {number}
127
+ */
128
+ export function onOpen(cb) {
129
+ const index = globalOnOpenCallbacks.push(cb) - 1;
130
+
131
+ return () => {
132
+ globalOnOpenCallbacks.splice(index, 1);
133
+ };
134
+ }
135
+
136
+ function dispatchOnOpenHandlers(el, id) {
137
+ globalOnOpenCallbacks.forEach((cb) => cb(el, id));
138
+ }
139
+
120
140
  /**
121
141
  * Display the active modal.
122
142
  */
@@ -149,6 +169,8 @@ function display() {
149
169
  active.settings.onOpen(active.id, active.el);
150
170
  }
151
171
 
172
+ dispatchOnOpenHandlers(active.el, active.id);
173
+
152
174
  setTimeout(() => {
153
175
  if (active.el.focusTrap) {
154
176
  active.el.focusTrap.activate();
@@ -182,6 +204,24 @@ function dispatch() {
182
204
  display();
183
205
  }
184
206
 
207
+ /**
208
+ * Global onClose handler
209
+ *
210
+ * @param {Function} cb
211
+ * @returns {number}
212
+ */
213
+ export function onClose(cb) {
214
+ const index = globalOnCloseCallbacks.push(cb) - 1;
215
+
216
+ return () => {
217
+ globalOnCloseCallbacks.splice(index, 1);
218
+ };
219
+ }
220
+
221
+ function dispatchOnCloseHandlers(el, id) {
222
+ globalOnCloseCallbacks.forEach((cb) => cb(el, id));
223
+ }
224
+
185
225
  /**
186
226
  * Close currently active modal
187
227
  * and dispatch next in queue.
@@ -194,6 +234,8 @@ function close() {
194
234
  active.settings.onClose(active.id);
195
235
  }
196
236
 
237
+ dispatchOnCloseHandlers(active.el, active.id);
238
+
197
239
  document.removeEventListener('keyup', handleKeyUp);
198
240
 
199
241
  if (active.el.focusTrap) {
@@ -349,6 +349,13 @@
349
349
  }
350
350
  }
351
351
  }
352
+
353
+ @include bp-only(xs) {
354
+ .wrapper {
355
+ padding-left: 0;
356
+ padding-right: 0;
357
+ }
358
+ }
352
359
  }
353
360
 
354
361
  // Hero with video
@@ -386,10 +393,10 @@
386
393
  }
387
394
 
388
395
  @include e(content) {
389
- padding: rhythm(2) rhythm(1);
396
+ padding: rhythm(2) 0;
390
397
 
391
398
  @include bp-up(sm) {
392
- padding: rhythm(4) rhythm(6);
399
+ padding: rhythm(4);
393
400
  }
394
401
 
395
402
  @include e(icon) {
@@ -19,6 +19,7 @@ module.exports = {
19
19
  has_radius: true,
20
20
  limited_width: true,
21
21
  has_radius: true,
22
+ has_buttons: false,
22
23
  text: 'Nästan alla i Sverige använder internet – men hur meningsfull är tiden vi spenderar där? I rapporten Svenskarna och internet 2019 frågar vi för första gången om meningsfullhet, och det syns stora skillnader mellan olika aktiviteter. Tid på sociala medier tycker bara var fjärde är meningsfull.',
23
24
  }
24
25
  },
@@ -27,6 +28,7 @@ module.exports = {
27
28
  context: {
28
29
  has_tags: false,
29
30
  has_buttons: true,
31
+ limited_width: false,
30
32
  text: 'Så gott som alla svenskar använder internet och digitala tjänster idag',
31
33
  },
32
34
  },
@@ -38,6 +40,7 @@ module.exports = {
38
40
  has_image: false,
39
41
  has_buttons: false,
40
42
  has_tags: true,
43
+ limited_width: false,
41
44
  text: 'Nästan alla i Sverige använder internet – men hur meningsfull är tiden vi spenderar där? I rapporten Svenskarna och internet 2019 frågar vi för första gången om meningsfullhet, och det syns stora skillnader mellan olika aktiviteter. Tid på sociala medier tycker bara var fjärde är meningsfull.',
42
45
  }
43
46
  },
@@ -49,7 +52,8 @@ module.exports = {
49
52
  video_class: 'o-hero--video',
50
53
  limited_width: true,
51
54
  has_video: true,
52
- has_image: false
55
+ has_image: false,
56
+ has_buttons: false,
53
57
  }
54
58
  },
55
59
  {
@@ -63,10 +67,11 @@ module.exports = {
63
67
  no_image_class: 'o-hero--no-image',
64
68
  icon_share: 'share',
65
69
  icon_export: 'external-link',
66
- limited_width: true,
70
+ limited_width: false,
67
71
  has_image: false,
68
72
  has_video: false,
69
73
  is_event: true,
74
+ has_buttons: false,
70
75
  background_color: 'background-peacock-light'
71
76
  }
72
77
  },
@@ -83,7 +88,7 @@ module.exports = {
83
88
  geometric_figures: false,
84
89
  icon_share: 'share',
85
90
  icon_export: 'external-link',
86
- limited_width: true,
91
+ limited_width: false,
87
92
  has_image: false,
88
93
  has_video: false,
89
94
  is_event: true,
@@ -96,12 +101,16 @@ module.exports = {
96
101
  name: 'Clean',
97
102
  context: {
98
103
  no_image_class: 'o-hero--clean',
104
+ limited_width: false,
105
+ has_buttons: false,
99
106
  }
100
107
  },
101
108
  {
102
109
  name: 'Early breakpoint',
103
110
  context: {
104
111
  no_image_class: 'o-hero--break-early o-hero--clean',
112
+ limited_width: false,
113
+ has_buttons: false,
105
114
  }
106
115
  },
107
116
  ]
@@ -1,5 +1,5 @@
1
1
  {{#if limited_width}}
2
- {{#unless is_event}}<div class="wrapper">{{/unless}}
2
+ <div class="wrapper">
3
3
  <div class="row">
4
4
  <div class="grid">
5
5
  {{/if}}
@@ -8,28 +8,25 @@
8
8
  {{#if has_video}}
9
9
  <iframe width="100%" height="100%" src="https://www.youtube-nocookie.com/embed/3RVcnx-hOk8?rel=0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
10
10
  {{else if is_event}}
11
- <div class="wrapper">
12
- <figcaption>
13
- <div class="o-hero__content">
14
- <p class="o-hero__text">{{event_text}} {{#if city}}<strong>{{city}}</strong>{{/if}}</p>
15
- <h1 class="supersize">{{event_title}}</h1>
16
- <p class="o-hero__text display-flex flex-wrap">
17
- <span class="meta u-m-y-0 u-p-y-0 u-p-r-1">{{time}}</span>
18
- <span class="o-hero__spacer">|</span>
19
- <span>Arrangör: <a href="#">{{organizer}}
20
- <svg class="icon o-mega-menu__link__icon">
21
- <use xlink:href="#icon-external-link"></use>
22
- </svg></a>
23
- </span>
24
- </p>
25
- {{#if has_button}}
26
- {{> @button el="a" modifiers="lemon a-button--inline u-m-y-2 u-m-r-2"}}
27
- {{/if}}
28
- {{> @share modifiers="inline"}}
29
-
11
+ <figcaption class="o-hero__content">
12
+ <div class="wrapper">
13
+ <p class="o-hero__text">{{event_text}} {{#if city}}<strong>{{city}}</strong>{{/if}}</p>
14
+ <h1 class="supersize">{{event_title}}</h1>
15
+ <p class="o-hero__text display-flex flex-wrap">
16
+ <span class="meta u-m-y-0 u-p-y-0 u-p-r-1">{{time}}</span>
17
+ <span class="o-hero__spacer">|</span>
18
+ <span>Arrangör: <a href="#">{{organizer}}
19
+ <svg class="icon o-mega-menu__link__icon">
20
+ <use xlink:href="#icon-external-link"></use>
21
+ </svg></a>
22
+ </span>
23
+ </p>
24
+ {{#if has_button}}
25
+ {{> @button el="a" modifiers="lemon a-button--inline u-m-y-2 u-m-r-2"}}
26
+ {{/if}}
27
+ {{> @share modifiers="inline"}}
30
28
  </div>
31
- </figcaption>
32
- </div>
29
+ </figcaption>
33
30
  {{else}}
34
31
  <figcaption class="o-hero__caption">
35
32
  <div class="wrapper">
@@ -56,5 +53,5 @@
56
53
  {{#if limited_width}}
57
54
  </div>
58
55
  </div>
59
- {{#unless is_event}}</div>{{/unless}}
56
+ </div>
60
57
  {{/if}}
@@ -11,6 +11,11 @@ $fill-color: $color-black;
11
11
  background-position: center center !important;
12
12
 
13
13
  // Sizes
14
+ @include m(smallest) {
15
+ width: $icon-size-smallest !important;
16
+ height: $icon-size-smallest !important;
17
+ }
18
+
14
19
  @include m(small) {
15
20
  width: $icon-size-small !important;
16
21
  height: $icon-size-small !important;