@ons/design-system 61.0.4 → 62.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.
@@ -159,13 +159,11 @@
159
159
  {% endif %}
160
160
  </li>
161
161
  {% endfor %}
162
- {% if params.language %}
163
- <div class="ons-u-d-no@xs">
164
- {% from "components/language-selector/_macro.njk" import onsLanguageSelector %}
165
- {{ onsLanguageSelector(params.language) }}
166
- </div>
167
- {% endif %}
168
162
  </ul>
163
+ {% if params.language %}
164
+ {% from "components/language-selector/_macro.njk" import onsLanguageSelector %}
165
+ {{ onsLanguageSelector(params.language) }}
166
+ {% endif %}
169
167
  </nav>
170
168
  {% endif %}
171
169
  </div>
@@ -5,7 +5,6 @@
5
5
  role="dialog"
6
6
  aria-labelledby="ons-modal-title"
7
7
  {% if params.attributes %}{% for attribute, value in (params.attributes.items() if params.attributes is mapping and params.attributes.items else params.attributes) %} {{attribute}}="{{value}}"{% endfor %}{% endif %}
8
- {% if params.enableGA == true %}data-enable-ga='true'{% endif %}
9
8
  >
10
9
  <div class="ons-modal__content">
11
10
  <h2 id="ons-modal-title" class="ons-modal__title">
@@ -1,5 +1,4 @@
1
1
  import dialogPolyfill from 'dialog-polyfill';
2
- import initAnalytics from '../../js/analytics';
3
2
 
4
3
  const overLayClass = 'ons-modal-overlay';
5
4
  const ie11Class = 'ons-modal-ie11';
@@ -9,7 +8,6 @@ export default class Modal {
9
8
  this.component = component;
10
9
  this.launcher = document.querySelector(`[data-modal-id=${component.id}]`);
11
10
  this.closeButton = component.querySelector('.ons-js-modal-btn');
12
- this.setGAAttributes = component.getAttribute('data-enable-ga');
13
11
  this.lastFocusedEl = null;
14
12
  this.dialogCSSSupported = true;
15
13
  this.modalType = this.component.classList.contains('ons-js-timeout-modal') ? 'Timeout' : 'Generic';
@@ -34,10 +32,6 @@ export default class Modal {
34
32
  if (this.modalType !== 'Timeout') {
35
33
  window.addEventListener('keydown', this.escToClose.bind(this));
36
34
  }
37
-
38
- if (this.setGAAttributes) {
39
- this.component.setAttribute('data-ga', `visible`);
40
- }
41
35
  }
42
36
 
43
37
  dialogSupported() {
@@ -72,17 +66,6 @@ export default class Modal {
72
66
  } else {
73
67
  this.component.showModal();
74
68
  }
75
-
76
- if (this.setGAAttributes) {
77
- if (event) {
78
- this.component.setAttribute('data-ga-action', `Modal opened by ${event.type} event`);
79
- } else {
80
- this.component.setAttribute('data-ga-action', 'Modal opened by timed event');
81
- }
82
- this.component.setAttribute('data-ga-label', `${this.modalType} modal opened`);
83
- this.component.setAttribute('data-ga-category', `${this.modalType} modal`);
84
- initAnalytics();
85
- }
86
69
  }
87
70
  }
88
71
 
@@ -119,17 +102,6 @@ export default class Modal {
119
102
 
120
103
  this.component.close();
121
104
  this.setFocusOnLastFocusedEl(this.lastFocusedEl);
122
-
123
- if (this.setGAAttributes) {
124
- if (event) {
125
- this.component.setAttribute('data-ga-action', `Modal closed by ${event.type} event`);
126
- } else {
127
- this.component.setAttribute('data-ga-action', 'Modal closed by timed event');
128
- }
129
- this.component.setAttribute('data-ga-label', `${this.modalType} modal closed`);
130
- this.component.setAttribute('data-ga-category', `${this.modalType} modal`);
131
- initAnalytics();
132
- }
133
105
  }
134
106
  }
135
107
 
@@ -69,67 +69,4 @@ describe('script: modal', () => {
69
69
  });
70
70
  });
71
71
  });
72
-
73
- describe('when GA tracking is enabled', () => {
74
- beforeEach(async () => {
75
- const component = renderComponent('modal', { ...EXAMPLE_MODAL, enableGA: true });
76
- const template = `
77
- <div class="ons-page">
78
- <button id="launcher" data-modal-id="dialog">Launcher</button>
79
- ${component}
80
- </div>
81
- `;
82
- await setTestPage('/test', template);
83
- });
84
-
85
- describe('when the modal is launched by a click event', () => {
86
- beforeEach(async () => {
87
- await page.focus('#launcher');
88
- await page.keyboard.press('Enter');
89
- });
90
-
91
- it('has the correct attributes set on the modal', async () => {
92
- const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
93
- const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
94
- const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
95
- expect(gaLabel).toBe('Generic modal opened');
96
- expect(gaAction).toBe('Modal opened by click event');
97
- expect(gaCategory).toBe('Generic modal');
98
- });
99
- });
100
-
101
- describe('when the modal is closed by a click event', () => {
102
- beforeEach(async () => {
103
- await page.focus('#launcher');
104
- await page.keyboard.press('Enter');
105
- await page.click('.ons-js-modal-btn');
106
- });
107
-
108
- it('has the correct attributes set on the modal', async () => {
109
- const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
110
- const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
111
- const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
112
- expect(gaLabel).toBe('Generic modal closed');
113
- expect(gaAction).toBe('Modal closed by click event');
114
- expect(gaCategory).toBe('Generic modal');
115
- });
116
- });
117
-
118
- describe('when the modal is closed by `escape` keypress event', () => {
119
- beforeEach(async () => {
120
- await page.focus('#launcher');
121
- await page.keyboard.press('Enter');
122
- await page.keyboard.press('Escape');
123
- });
124
-
125
- it('has the correct attributes set on the modal', async () => {
126
- const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
127
- const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
128
- const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
129
- expect(gaLabel).toBe('Generic modal closed');
130
- expect(gaAction).toBe('Modal closed by keydown event');
131
- expect(gaCategory).toBe('Generic modal');
132
- });
133
- });
134
- });
135
72
  });
@@ -5,36 +5,32 @@
5
5
  {% endif %}
6
6
 
7
7
  <aside class="ons-related-content{{ classes }}" aria-label="{{ params.ariaLabel | default("Related content") }}">
8
-
9
- <div class="ons-related-content__body">
10
- {% if params.rows %}
11
- {% for row in params.rows %}
12
- {% from "components/related-content/_section-macro.njk" import onsRelatedContentSection %}
13
- {% call onsRelatedContentSection(
14
- {
15
- "title": row.title,
16
- "id": row.id
17
- }
18
- ) %}
19
- <nav class="ons-related-content__navigation" aria-labelledby="{{ row.id }}">
20
- {% from "components/lists/_macro.njk" import onsList %}
21
- {{
22
- onsList({
23
- "variants": 'bare',
24
- "iconType": row.iconType,
25
- "iconPosition": row.iconPosition,
26
- "iconSize": row.iconSize,
27
- "itemsList": row.itemsList
28
- })
29
- }}
30
- </nav>
31
- {% endcall %}
32
- {% endfor %}
33
- {% else %}
34
- {{ caller() if caller }}
35
- {% endif %}
36
- </div>
37
-
8
+ {% if params.rows %}
9
+ {% for row in params.rows %}
10
+ {% from "components/related-content/_section-macro.njk" import onsRelatedContentSection %}
11
+ {% call onsRelatedContentSection(
12
+ {
13
+ "title": row.title,
14
+ "id": row.id
15
+ }
16
+ ) %}
17
+ <nav class="ons-related-content__navigation" aria-labelledby="{{ row.id }}">
18
+ {% from "components/lists/_macro.njk" import onsList %}
19
+ {{
20
+ onsList({
21
+ "variants": 'bare',
22
+ "iconType": row.iconType,
23
+ "iconPosition": row.iconPosition,
24
+ "iconSize": row.iconSize,
25
+ "itemsList": row.itemsList
26
+ })
27
+ }}
28
+ </nav>
29
+ {% endcall %}
30
+ {% endfor %}
31
+ {% else %}
32
+ {{ caller() if caller }}
33
+ {% endif %}
38
34
  </aside>
39
35
 
40
36
  {% endmacro %}
@@ -82,7 +82,7 @@ describe('macro: related-content', () => {
82
82
  it('calls with content', () => {
83
83
  const $ = cheerio.load(renderComponent('related-content', { EXAMPLE_RELATED_CONTENT_GENERAL }, 'Example content...'));
84
84
 
85
- const content = $('.ons-related-content__body')
85
+ const content = $('.ons-related-content')
86
86
  .text()
87
87
  .trim();
88
88
  expect(content).toEqual(expect.stringContaining('Example content...'));
@@ -16,7 +16,7 @@
16
16
  <tr class="ons-table__row">
17
17
  {% for th in params.ths %}
18
18
  <th scope="col" class="ons-table__header{{ ' ' + th.thClasses if th.thClasses }}{{ " ons-table__header--numeric" if th.numeric }}"{% if 'sortable' in variants %} aria-sort="{{- th.ariaSort | default('none') -}}"{% endif %}>
19
- <span>{{- th.value -}}</span>
19
+ <span class="ons-table__header-text">{{- th.value -}}</span>
20
20
  {% if 'sortable' in variants %}
21
21
  {{
22
22
  onsIcon({
@@ -27,24 +27,24 @@ export default class TableSort {
27
27
 
28
28
  createHeadingButtons(heading, i) {
29
29
  const text = heading.textContent.trim();
30
- heading.childNodes[1].remove();
31
- heading.childNodes[2].classList.remove('ons-u-d-no');
30
+ heading.querySelector('.ons-table__header-text').remove();
31
+ heading.querySelector('.ons-svg-icon').classList.remove('ons-u-d-no');
32
32
  const button = document.createElement('button');
33
33
  button.setAttribute('aria-label', this.table.getAttribute('data-aria-sort') + ' ' + text);
34
34
  button.setAttribute('type', 'button');
35
35
  button.setAttribute('data-index', i);
36
36
  button.setAttribute('class', 'ons-table__sort-button');
37
37
  button.textContent = text;
38
- button.addEventListener('click', this.sortButtonClicked.bind(this));
39
38
  let sortSprite = document.getElementById('sort-sprite-' + text.toLowerCase());
40
39
  const sortSpriteParent = sortSprite.parentNode;
41
40
  sortSpriteParent.replaceChild(button, sortSprite);
42
41
  button.appendChild(sortSprite);
42
+ button.addEventListener('click', this.sortButtonClicked.bind(this));
43
43
  }
44
44
 
45
45
  sortButtonClicked(event) {
46
- const columnNumber = event.target.getAttribute('data-index');
47
- const sortDirection = event.target.parentElement.getAttribute('aria-sort');
46
+ const columnNumber = event.target.closest('[data-index]').getAttribute('data-index');
47
+ const sortDirection = event.target.closest('[aria-sort]').getAttribute('aria-sort');
48
48
  let newSortDirection;
49
49
 
50
50
  if (sortDirection === 'none' || sortDirection === 'ascending') {
@@ -63,7 +63,7 @@ export default class TableSort {
63
63
  });
64
64
 
65
65
  this.removeButtonStates();
66
- this.updateButtonState(event.target, newSortDirection);
66
+ this.updateButtonState(event.target.closest('[aria-sort]'), newSortDirection);
67
67
  }
68
68
 
69
69
  getTableRowsArray(tbody) {
@@ -109,6 +109,10 @@ export default class TableSort {
109
109
  }
110
110
 
111
111
  getCellValue(cell) {
112
+ if (!cell) {
113
+ return undefined;
114
+ }
115
+
112
116
  let cellValue = cell.getAttribute('data-sort-value') || cell.textContent;
113
117
  cellValue = parseFloat(cellValue) || cellValue;
114
118
 
@@ -130,7 +134,7 @@ export default class TableSort {
130
134
  }
131
135
 
132
136
  updateButtonState(button, direction) {
133
- button.parentElement.setAttribute('aria-sort', direction);
137
+ button.setAttribute('aria-sort', direction);
134
138
  let message = this.options.statusMessage;
135
139
  message = message + ' ' + button.textContent.replace(/^\s+|\s+$/g, '');
136
140
  message = message + ' (' + direction + ')';
@@ -14,9 +14,9 @@
14
14
  <{{ titleTag }} class="ons-tabs__title ons-u-fs-r--b ons-u-mt-no">{{ params.title }}</{{ titleTag }}>
15
15
 
16
16
  <ul class="ons-tabs__list">
17
- {% for tab in params.tabs %}
17
+ {%- for tab in params.tabs -%}
18
18
  <li class="ons-tab__list-item"><a href="#{{ tab.id if tab.id else 'tabId' ~ loop.index }}" class="ons-tab" data-ga="click" data-ga-category="tabs" data-ga-action="Show: {{ tab.title }}" data-ga-label="Show: {{ tab.title }}">{{ tab.title }}</a></li>
19
- {% endfor %}
19
+ {%- endfor -%}
20
20
  </ul>
21
21
 
22
22
  {% for tab in params.tabs %}
@@ -50,13 +50,13 @@
50
50
  display: inline-block;
51
51
  height: 2.55rem;
52
52
  line-height: 2.3rem;
53
- margin: 0 0.1rem 0 0;
53
+ margin: 0 0.4rem 0 0;
54
54
  overflow: visible;
55
55
  padding: 0 1rem;
56
56
  position: relative;
57
57
  text-decoration: underline;
58
58
 
59
- &:hover {
59
+ &:hover:not(:focus) {
60
60
  background-color: var(--ons-color-button-secondary-hover);
61
61
  border-color: var(--ons-color-button-secondary-hover);
62
62
  color: var(--ons-color-text);
@@ -4,7 +4,6 @@
4
4
  "title": params.title,
5
5
  "btnText": params.btnText,
6
6
  "classes": "ons-js-timeout-modal",
7
- "enableGA": params.enableGA,
8
7
  "attributes": {
9
8
  "data-redirect-url": params.redirectUrl,
10
9
  "data-server-session-expires-at": params.sessionExpiresAt,
@@ -167,7 +167,6 @@ describe('script: timeout modal', () => {
167
167
  ...EXAMPLE_TIMEOUT_MODAL_BASIC,
168
168
  showModalTimeInSeconds: 1,
169
169
  sessionExpiresAt: expiryTimeInISOFormat,
170
- enableGA: true,
171
170
  });
172
171
 
173
172
  const template = `
@@ -187,15 +186,6 @@ describe('script: timeout modal', () => {
187
186
  await page.waitForTimeout(2000);
188
187
  expect(page.url()).toContain('#!');
189
188
  });
190
-
191
- it('and GA tracking is enabled it has the correct attributes set on the modal', async () => {
192
- const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
193
- const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
194
- const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
195
- expect(gaLabel).toBe('Timeout modal closed');
196
- expect(gaAction).toBe('Modal closed by timed event');
197
- expect(gaCategory).toBe('Timeout modal');
198
- });
199
189
  });
200
190
  });
201
191
 
@@ -233,77 +223,4 @@ describe('script: timeout modal', () => {
233
223
  });
234
224
  });
235
225
  });
236
-
237
- describe('when GA tracking is enabled', () => {
238
- beforeEach(async () => {
239
- const component = renderComponent('timeout-modal', {
240
- ...EXAMPLE_TIMEOUT_MODAL_BASIC,
241
- showModalTimeInSeconds: 59,
242
- enableGA: true,
243
- });
244
-
245
- const template = `
246
- <div class="ons-page">
247
- ${component}
248
- </div>
249
- `;
250
-
251
- await setTestPage('/test', template);
252
- });
253
-
254
- it('has ga initialise attribute set', async () => {
255
- const gaInitialise = await page.$eval('.ons-modal', node => node.getAttribute('data-ga'));
256
- expect(gaInitialise).toBe('visible');
257
- });
258
-
259
- describe('when the modal is open', () => {
260
- beforeEach(async () => {
261
- await page.waitForSelector('.ons-modal');
262
- await page.waitForTimeout(1000);
263
- });
264
-
265
- it('has the correct attributes set on the modal', async () => {
266
- const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
267
- const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
268
- const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
269
- expect(gaLabel).toBe('Timeout modal opened');
270
- expect(gaAction).toBe('Modal opened by timed event');
271
- expect(gaCategory).toBe('Timeout modal');
272
- });
273
- });
274
-
275
- describe('when the modal is closed by a click event', () => {
276
- beforeEach(async () => {
277
- await page.waitForSelector('.ons-modal');
278
- await page.waitForTimeout(1000);
279
- await page.click('.ons-js-modal-btn');
280
- });
281
-
282
- it('has the correct attributes set on the modal', async () => {
283
- const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
284
- const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
285
- const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
286
- expect(gaLabel).toBe('Timeout modal closed');
287
- expect(gaAction).toBe('Modal closed by click event');
288
- expect(gaCategory).toBe('Timeout modal');
289
- });
290
- });
291
-
292
- describe('when the modal is closed by `escape` keypress event', () => {
293
- beforeEach(async () => {
294
- await page.waitForSelector('.ons-modal');
295
- await page.waitForTimeout(1000);
296
- await page.keyboard.press('Escape');
297
- });
298
-
299
- it('has the correct attributes set on the modal', async () => {
300
- const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
301
- const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
302
- const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
303
- expect(gaLabel).toBe('Timeout modal closed');
304
- expect(gaAction).toBe('Modal closed by keydown event');
305
- expect(gaCategory).toBe('Timeout modal');
306
- });
307
- });
308
- });
309
226
  });
@@ -1,9 +1,11 @@
1
1
  .ons-video {
2
2
  @extend .ons-u-mb-m;
3
3
 
4
- height: 0;
5
- padding-bottom: 56.25%; /* 16:9 */
6
- position: relative;
4
+ &--hasIframe {
5
+ height: 0;
6
+ padding-bottom: 56.25%; /* 16:9 */
7
+ position: relative;
8
+ }
7
9
 
8
10
  &__iframe {
9
11
  height: 100%;
@@ -25,6 +25,7 @@ export default class Video {
25
25
  const src = this.iframe.getAttribute('data-src');
26
26
  this.iframe.src = src;
27
27
  this.iframe.classList.remove('ons-u-d-no');
28
+ this.component.classList.add('ons-video--hasIframe');
28
29
  this.placeholder.classList.add('ons-u-d-no');
29
30
  }
30
31
  }
@@ -47,6 +47,11 @@ describe('script: video', () => {
47
47
  const displayStyle = await page.$eval('.ons-js-video-iframe', node => window.getComputedStyle(node).getPropertyValue('display'));
48
48
  expect(displayStyle).toBe('block');
49
49
  }, 10000);
50
+
51
+ it('should add the correct modifier class', async () => {
52
+ const hasClass = await page.$eval('.ons-js-video', node => node.classList.contains('ons-video--hasIframe'));
53
+ expect(hasClass).toBe(true);
54
+ }, 10000);
50
55
  });
51
56
 
52
57
  describe('when cookies are accepted via banner', () => {
@@ -68,5 +73,10 @@ describe('script: video', () => {
68
73
  const displayStyle = await page.$eval('.ons-js-video-iframe', node => window.getComputedStyle(node).getPropertyValue('display'));
69
74
  expect(displayStyle).toBe('block');
70
75
  });
76
+
77
+ it('should add the correct modifier class', async () => {
78
+ const hasClass = await page.$eval('.ons-js-video', node => node.classList.contains('ons-video--hasIframe'));
79
+ expect(hasClass).toBe(true);
80
+ }, 10000);
71
81
  });
72
82
  });