@ons/design-system 72.10.8 → 72.10.10
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 +9 -5
- package/components/accordion/accordion.js +3 -2
- package/components/announcement-banner/_announcement-banner.scss +24 -0
- package/components/announcement-banner/_macro.njk +33 -0
- package/components/announcement-banner/_macro.spec.js +106 -0
- package/components/announcement-banner/_test_examples.js +22 -0
- package/components/announcement-banner/example-banner-black.njk +12 -0
- package/components/announcement-banner/example-banner-red.njk +13 -0
- package/components/announcement-banner/example-banner-teal.njk +13 -0
- package/components/autosuggest/autosuggest.spec.js +2 -0
- package/components/autosuggest/autosuggest.ui.js +12 -7
- package/components/breadcrumbs/_breadcrumbs.scss +53 -0
- package/components/breadcrumbs/_macro.njk +33 -24
- package/components/breadcrumbs/_macro.spec.js +25 -0
- package/components/button/_button.scss +29 -1
- package/components/chart/_chart.scss +88 -0
- package/components/chart/_macro.njk +25 -6
- package/components/chart/_macro.spec.js +1178 -640
- package/components/chart/bar-chart.js +8 -1
- package/components/chart/chart-iframe-resize.js +2 -2
- package/components/chart/common-chart-options.js +9 -0
- package/components/chart/example-bar-chart-with-axis-min-and-max-values.njk +0 -1
- package/components/chart/example-bar-chart-with-point-range-and-reference-line-annotations.njk +4 -4
- package/components/chart/example-bar-chart.njk +0 -1
- package/components/chart/example-iframe-chart.njk +1 -1
- package/components/chart/range-annotations-options.js +1 -1
- package/components/download-resources/download-resources.spec.js +2 -0
- package/components/duration/example-duration-error-for-single-field.njk +0 -1
- package/components/duration/example-duration-error.njk +0 -1
- package/components/footer/_macro.spec.js +2 -2
- package/components/header/_macro.njk +5 -16
- package/components/header/example-header-button-and-navigation.njk +133 -0
- package/components/header/example-header-external-with-navigation-and-search.njk +1 -1
- package/components/hero/_hero.scss +17 -22
- package/components/hero/_macro.njk +1 -1
- package/components/hero/_macro.spec.js +1 -1
- package/components/hero/example-hero-dark-with-external-breadcrumbs.njk +194 -0
- package/components/hero/example-hero-default-with-external-breadcrumbs.njk +201 -0
- package/components/hero/example-hero-grey-with-external-breadcrumbs.njk +243 -0
- package/components/hero/example-hero-navy-blue-with-external-breadcrumbs.njk +200 -0
- package/components/hero/example-hero-pale-blue-with-external-breadcrumbs.njk +201 -0
- package/components/icon/_macro.njk +1 -1
- package/components/mutually-exclusive/mutually-exclusive.js +3 -1
- package/components/navigation/_macro.njk +11 -16
- package/components/navigation/_navigation.scss +24 -0
- package/components/radios/clear-radios.js +4 -2
- package/components/relationships/relationships.js +4 -2
- package/components/table/_macro.njk +107 -112
- package/components/table/_macro.spec.js +35 -44
- package/components/table/_table.scss +0 -12
- package/components/table/example-table-sortable.njk +1 -1
- package/components/tabs/example-tabs-details.njk +1 -1
- package/components/textarea/_macro.njk +1 -0
- package/components/textarea/_macro.spec.js +1 -0
- package/components/timeout-panel/timeout-panel.spec.js +1 -1
- package/components/video/video.js +2 -0
- package/css/main.css +1 -1
- package/js/timeout.js +9 -6
- package/layout/_template.njk +13 -0
- package/package.json +6 -6
- package/scripts/main.es5.js +4 -2
- package/scripts/main.js +4 -2
- package/scss/main.scss +1 -0
- package/scss/vars/_colors.scss +3 -0
- package/scss/vars/_forms.scss +11 -0
- package/components/table/example-table-scrollable.njk +0 -158
package/README.md
CHANGED
|
@@ -14,26 +14,30 @@ Nunjucks macros for components and templates are available from npm. Built CSS a
|
|
|
14
14
|
yarn add @ons/design-system
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Running the DS Locally
|
|
18
18
|
|
|
19
|
-
You'll need
|
|
19
|
+
You'll need to install:
|
|
20
|
+
|
|
21
|
+
- [Git](https://help.github.com/articles/set-up-git/)
|
|
22
|
+
- [Node.js](https://nodejs.org/en/)
|
|
23
|
+
- [Yarn](https://yarnpkg.com/en/docs/getting-started) (When installing yarn be sure to install yarn through brew using `brew install yarn` not using npm)
|
|
20
24
|
|
|
21
25
|
The version of node required is outlined in [.nvmrc](./.nvmrc).
|
|
22
26
|
|
|
23
|
-
### Using
|
|
27
|
+
### Using NVM
|
|
24
28
|
|
|
25
29
|
If you work across multiple Node.js projects there's a good chance they require different Node.js and npm versions.
|
|
26
30
|
|
|
27
31
|
To enable this we use [nvm (Node Version Manager)](https://github.com/creationix/nvm) to switch between versions easily.
|
|
28
32
|
|
|
29
33
|
1. [install nvm](https://github.com/creationix/nvm#installation)
|
|
30
|
-
2. Run nvm install in the project directory (this will use .nvmrc)
|
|
34
|
+
2. Run `nvm install` in the project directory (this will use .nvmrc)
|
|
31
35
|
|
|
32
36
|
### Install dependencies
|
|
33
37
|
|
|
34
38
|
```bash
|
|
35
39
|
yarn install
|
|
36
|
-
yarn husky
|
|
40
|
+
yarn husky
|
|
37
41
|
```
|
|
38
42
|
|
|
39
43
|
### Start a local server
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import DOMPurify from 'dompurify';
|
|
1
2
|
export default class Accordion {
|
|
2
3
|
constructor(button, detailsEls) {
|
|
3
4
|
this.openDetailsEls = 0;
|
|
@@ -52,11 +53,11 @@ export default class Accordion {
|
|
|
52
53
|
|
|
53
54
|
setButton() {
|
|
54
55
|
if (this.canClose()) {
|
|
55
|
-
this.buttonInner.innerHTML = this.closeButton;
|
|
56
|
+
this.buttonInner.innerHTML = DOMPurify.sanitize(this.closeButton);
|
|
56
57
|
this.button.setAttribute('data-ga-label', this.buttonOpen);
|
|
57
58
|
this.button.setAttribute('aria-expanded', 'true');
|
|
58
59
|
} else {
|
|
59
|
-
this.buttonInner.innerHTML = this.buttonOpen;
|
|
60
|
+
this.buttonInner.innerHTML = DOMPurify.sanitize(this.buttonOpen);
|
|
60
61
|
this.button.setAttribute('data-ga-label', this.closeButton);
|
|
61
62
|
this.button.setAttribute('aria-expanded', 'false');
|
|
62
63
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.ons-announcement-banner {
|
|
2
|
+
color: var(--ons-color-text-inverse);
|
|
3
|
+
padding: 1rem;
|
|
4
|
+
&--black {
|
|
5
|
+
background-color: var(--ons-color-gov-black);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
&--teal {
|
|
9
|
+
background-color: var(--ons-color-gov-teal);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
&--red {
|
|
13
|
+
background-color: var(--ons-color-gov-red);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&__link {
|
|
17
|
+
color: var(--ons-color-text-inverse);
|
|
18
|
+
|
|
19
|
+
&:hover {
|
|
20
|
+
color: var(--ons-color-text-inverse);
|
|
21
|
+
text-decoration: underline solid var(--ons-color-text-inverse) 2px;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{% macro onsAnnouncementBanner(params) %}
|
|
2
|
+
|
|
3
|
+
{% if params.variants %}
|
|
4
|
+
{% if 'wide' in params.variants %}
|
|
5
|
+
{% set width = "wide" %}
|
|
6
|
+
{% endif %}
|
|
7
|
+
{% endif %}
|
|
8
|
+
|
|
9
|
+
{% set content %}
|
|
10
|
+
<div
|
|
11
|
+
class="ons-announcement-banner{% if params.variants %}{% if params.variants == 'wide' or params.variants | length == 1 and 'wide' in params.variants %}{{ ' ' }}ons-announcement-banner--black{% elif params.variants is not string %}{% for variant in params.variants %}{{ ' ' }}ons-announcement-banner--{{ variant }}{% endfor %}{% else %}{{ ' ' }}ons-announcement-banner--{{ params.variants }}{% endif %}{% else %}{{ ' ' }}ons-announcement-banner--black{% endif %}"
|
|
12
|
+
>
|
|
13
|
+
<h2 class="ons-announcement-banner__title">{{ params.title }}</h2>
|
|
14
|
+
<p class="ons-announcement-banner__description">{{ params.description }}</p>
|
|
15
|
+
<a
|
|
16
|
+
class="ons-announcement-banner__link"
|
|
17
|
+
{% if params.link.attributes %}{% for attribute, value in (params.link.attributes.items() if params.link.attributes is mapping and params.link.attributes.items else params.link.attributes) %}{{ ' ' }}{{ attribute }}="{{ value }}"{% endfor %}{% endif %}
|
|
18
|
+
href="{{ params.link.url }}"
|
|
19
|
+
>{{ params.link.text }}</a
|
|
20
|
+
>
|
|
21
|
+
</div>
|
|
22
|
+
{% endset %}
|
|
23
|
+
|
|
24
|
+
{% if width != "wide" %}
|
|
25
|
+
<div
|
|
26
|
+
class="ons-announcement-banner__container{% if params.variants %}{% if params.variants is not string %}{% for variant in params.variants %}{{ ' ' }}ons-announcement-banner--{{ variant }}{% endfor %}{% else %}{{ ' ' }}ons-announcement-banner--{{ params.variants }}{% endif %}{% else %}{{ ' ' }}ons-announcement-banner--black{% endif %}"
|
|
27
|
+
>
|
|
28
|
+
<div class="ons-container">{{ content | safe }}</div>
|
|
29
|
+
</div>
|
|
30
|
+
{% else %}
|
|
31
|
+
{{ content | safe }}
|
|
32
|
+
{% endif %}
|
|
33
|
+
{% endmacro %}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/** @jest-environment jsdom */
|
|
2
|
+
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
|
|
5
|
+
import axe from '../../tests/helpers/axe';
|
|
6
|
+
import { renderComponent } from '../../tests/helpers/rendering';
|
|
7
|
+
import { EXAMPLE_FULL_ANNOUNCEMENT_BANNER, EXAMPLE_REQUIRED_ANNOUNCEMENT_BANNER } from './_test_examples';
|
|
8
|
+
|
|
9
|
+
describe('FOR: Macro: Announcement-banner', () => {
|
|
10
|
+
describe('GIVEN: Params: required', () => {
|
|
11
|
+
describe('WHEN: all required params are provided', () => {
|
|
12
|
+
const $ = cheerio.load(renderComponent('announcement-banner', EXAMPLE_REQUIRED_ANNOUNCEMENT_BANNER));
|
|
13
|
+
test('THEN: jest-axe checks pass', async () => {
|
|
14
|
+
const results = await axe($.html());
|
|
15
|
+
expect(results).toHaveNoViolations();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('THEN: the title has the provided text', async () => {
|
|
19
|
+
const title = $('.ons-announcement-banner__title');
|
|
20
|
+
expect(title.text().trim()).toBe('This is a black banner');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('THEN: the description has the provided text', async () => {
|
|
24
|
+
const description = $('.ons-announcement-banner__description');
|
|
25
|
+
expect(description.text().trim()).toBe('This is a description for the black banner');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('THEN: the link points to the provided URL', async () => {
|
|
29
|
+
const linkUrl = $('.ons-announcement-banner__link');
|
|
30
|
+
expect(linkUrl.attr('href')).toBe('http://example.com');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('THEN: the link has the provided link text', async () => {
|
|
34
|
+
const linkText = $('.ons-announcement-banner__link');
|
|
35
|
+
expect(linkText.text().trim()).toBe('Find out more');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('THEN: it defaults to the black variant', async () => {
|
|
39
|
+
const banner = $('.ons-announcement-banner');
|
|
40
|
+
expect(banner.hasClass('ons-announcement-banner--black')).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('THEN: containers are created', () => {
|
|
44
|
+
expect($('.ons-announcement-banner--black > .ons-container').length).toBe(1);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('GIVEN: Params: link attributes', () => {
|
|
50
|
+
const $ = cheerio.load(renderComponent('announcement-banner', EXAMPLE_FULL_ANNOUNCEMENT_BANNER));
|
|
51
|
+
describe('WHEN: link attributes are provided', () => {
|
|
52
|
+
test('THEN: the link has the provided attributes', async () => {
|
|
53
|
+
const link = $('.ons-announcement-banner__link');
|
|
54
|
+
expect(link.attr('abc')).toBe('123');
|
|
55
|
+
expect(link.attr('def')).toBe('456');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('GIVEN: Params: variants', () => {
|
|
61
|
+
describe('WHEN: variants is provided as a string', () => {
|
|
62
|
+
const $ = cheerio.load(renderComponent('announcement-banner', EXAMPLE_FULL_ANNOUNCEMENT_BANNER));
|
|
63
|
+
test('THEN: the banner has the correct variant class', async () => {
|
|
64
|
+
const banner = $('.ons-announcement-banner');
|
|
65
|
+
expect(banner.hasClass('ons-announcement-banner--red')).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('WHEN: wide is provided as one of the variants', () => {
|
|
69
|
+
const $ = cheerio.load(
|
|
70
|
+
renderComponent('announcement-banner', { ...EXAMPLE_REQUIRED_ANNOUNCEMENT_BANNER, variants: ['wide', 'red'] }),
|
|
71
|
+
);
|
|
72
|
+
test('THEN: containers are not created with the correct classes', () => {
|
|
73
|
+
expect($('.ons-announcement-banner--red > .ons-container').length).toBe(0);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('WHEN: red is provided alongside other variants', () => {
|
|
77
|
+
const $ = cheerio.load(
|
|
78
|
+
renderComponent('announcement-banner', { ...EXAMPLE_REQUIRED_ANNOUNCEMENT_BANNER, variants: ['wide', 'red'] }),
|
|
79
|
+
);
|
|
80
|
+
test('THEN: the banner has the correct variant class', async () => {
|
|
81
|
+
const banner = $('.ons-announcement-banner');
|
|
82
|
+
expect(banner.hasClass('ons-announcement-banner--red')).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('WHEN: wide is provided as the only variant as a string', () => {
|
|
86
|
+
const $ = cheerio.load(renderComponent('announcement-banner', { ...EXAMPLE_REQUIRED_ANNOUNCEMENT_BANNER, variants: 'wide' }));
|
|
87
|
+
test('THEN: it defaults to the black variant', async () => {
|
|
88
|
+
const banner = $('.ons-announcement-banner');
|
|
89
|
+
expect(banner.hasClass('ons-announcement-banner--black')).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
test('THEN: containers are not created with the correct classes', () => {
|
|
92
|
+
expect($('.ons-announcement-banner--black > .ons-container').length).toBe(0);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('WHEN: wide is provided as the only variant in an array', () => {
|
|
96
|
+
const $ = cheerio.load(renderComponent('announcement-banner', { ...EXAMPLE_REQUIRED_ANNOUNCEMENT_BANNER, variants: ['wide'] }));
|
|
97
|
+
test('THEN: it defaults to the black variant', async () => {
|
|
98
|
+
const banner = $('.ons-announcement-banner');
|
|
99
|
+
expect(banner.hasClass('ons-announcement-banner--black')).toBe(true);
|
|
100
|
+
});
|
|
101
|
+
test('THEN: containers are not created with the correct classes', () => {
|
|
102
|
+
expect($('.ons-announcement-banner--black > .ons-container').length).toBe(0);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const EXAMPLE_FULL_ANNOUNCEMENT_BANNER = {
|
|
2
|
+
variants: 'red',
|
|
3
|
+
title: 'This is a red banner',
|
|
4
|
+
description: 'This is a description for the red banner',
|
|
5
|
+
link: {
|
|
6
|
+
text: 'Find out more',
|
|
7
|
+
url: 'http://example.com',
|
|
8
|
+
attributes: {
|
|
9
|
+
abc: '123',
|
|
10
|
+
def: '456',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const EXAMPLE_REQUIRED_ANNOUNCEMENT_BANNER = {
|
|
16
|
+
title: 'This is a black banner',
|
|
17
|
+
description: 'This is a description for the black banner',
|
|
18
|
+
link: {
|
|
19
|
+
text: 'Find out more',
|
|
20
|
+
url: 'http://example.com',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{% from "components/announcement-banner/_macro.njk" import onsAnnouncementBanner %}
|
|
2
|
+
|
|
3
|
+
{{
|
|
4
|
+
onsAnnouncementBanner({
|
|
5
|
+
"title": 'His Royal Highness Henry VIII',
|
|
6
|
+
"description": '1491 to 1547',
|
|
7
|
+
"link": {
|
|
8
|
+
"text": 'Find out more',
|
|
9
|
+
"url": '#0'
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
}}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{% from "components/announcement-banner/_macro.njk" import onsAnnouncementBanner %}
|
|
2
|
+
|
|
3
|
+
{{
|
|
4
|
+
onsAnnouncementBanner({
|
|
5
|
+
"variants": ['red', 'wide'],
|
|
6
|
+
"title": 'National emergency',
|
|
7
|
+
"description": 'This is a level 1 incident',
|
|
8
|
+
"link": {
|
|
9
|
+
"text": 'More information',
|
|
10
|
+
"url": '#0'
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
}}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{% from "components/announcement-banner/_macro.njk" import onsAnnouncementBanner %}
|
|
2
|
+
|
|
3
|
+
{{
|
|
4
|
+
onsAnnouncementBanner({
|
|
5
|
+
"variants": 'teal',
|
|
6
|
+
"title": 'Local emergency',
|
|
7
|
+
"description": 'This is a level 2 incident',
|
|
8
|
+
"link": {
|
|
9
|
+
"text": 'More information',
|
|
10
|
+
"url": '#0'
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
}}
|
|
@@ -386,9 +386,11 @@ describe('script: autosuggest', () => {
|
|
|
386
386
|
describe('when the mouse moves over a result and a suggestion is focused', () => {
|
|
387
387
|
it('removes the focused class', async () => {
|
|
388
388
|
await setTestPage('/test', renderComponent('autosuggest', EXAMPLE_AUTOSUGGEST));
|
|
389
|
+
await page.mouse.move(0, 0); // move out of the component
|
|
389
390
|
|
|
390
391
|
await page.type('.ons-js-autosuggest-input', 'state', { delay: 20 });
|
|
391
392
|
await page.keyboard.press('ArrowDown');
|
|
393
|
+
|
|
392
394
|
await page.hover('.ons-autosuggest__option:nth-child(2)');
|
|
393
395
|
|
|
394
396
|
const focusedClassCount = await page.$$eval('.ons-autosuggest__option--focused', (nodes) => nodes.length);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import abortableFetch from '../../js/abortable-fetch';
|
|
2
2
|
import { sanitiseAutosuggestText } from './autosuggest.helpers';
|
|
3
3
|
import runFuse from './fuse-config';
|
|
4
|
+
import DOMPurify from 'dompurify';
|
|
4
5
|
|
|
5
6
|
export const baseClass = 'ons-js-autosuggest';
|
|
6
7
|
|
|
@@ -398,7 +399,7 @@ export default class AutosuggestUI {
|
|
|
398
399
|
const listElement = document.createElement('li');
|
|
399
400
|
listElement.className = `${classAutosuggestOption} ${classAutosuggestOptionMoreResults}`;
|
|
400
401
|
listElement.setAttribute('aria-hidden', 'true');
|
|
401
|
-
listElement.innerHTML = this.moreResults;
|
|
402
|
+
listElement.innerHTML = DOMPurify.sanitize(this.moreResults);
|
|
402
403
|
this.listbox.appendChild(listElement);
|
|
403
404
|
}
|
|
404
405
|
|
|
@@ -436,10 +437,12 @@ export default class AutosuggestUI {
|
|
|
436
437
|
if (status === 400 || status === false) {
|
|
437
438
|
message = this.typeMore;
|
|
438
439
|
this.setAriaStatus(message);
|
|
439
|
-
this.listbox.innerHTML =
|
|
440
|
+
this.listbox.innerHTML = DOMPurify.sanitize(
|
|
441
|
+
`<li class="${classAutosuggestOption} ${classAutosuggestOptionNoResults}">${message}</li>`,
|
|
442
|
+
);
|
|
440
443
|
} else if (status > 400 || status === '') {
|
|
441
|
-
|
|
442
|
-
|
|
444
|
+
const sanitizedHref = DOMPurify.sanitize(window.location.href);
|
|
445
|
+
message = this.errorAPI + (this.errorAPILinkText ? ' <a href="' + sanitizedHref + '">' + this.errorAPILinkText + '</a>.' : '');
|
|
443
446
|
let ariaMessage = this.errorAPI + (this.errorAPILinkText ? ' ' + this.errorAPILinkText : '');
|
|
444
447
|
|
|
445
448
|
this.input.setAttribute('disabled', true);
|
|
@@ -453,7 +456,9 @@ export default class AutosuggestUI {
|
|
|
453
456
|
this.resultsTitleContainer.remove();
|
|
454
457
|
} else {
|
|
455
458
|
message = this.noResults;
|
|
456
|
-
this.listbox.innerHTML =
|
|
459
|
+
this.listbox.innerHTML = DOMPurify.sanitize(
|
|
460
|
+
`<li class="${classAutosuggestOption} ${classAutosuggestOptionNoResults}">${message}</li>`,
|
|
461
|
+
);
|
|
457
462
|
}
|
|
458
463
|
}
|
|
459
464
|
|
|
@@ -503,7 +508,7 @@ export default class AutosuggestUI {
|
|
|
503
508
|
}
|
|
504
509
|
}
|
|
505
510
|
}
|
|
506
|
-
this.ariaStatus.innerHTML = content;
|
|
511
|
+
this.ariaStatus.innerHTML = DOMPurify.sanitize(content);
|
|
507
512
|
}
|
|
508
513
|
|
|
509
514
|
selectResult(index) {
|
|
@@ -548,7 +553,7 @@ export default class AutosuggestUI {
|
|
|
548
553
|
warningSpanElement.innerHTML = '!';
|
|
549
554
|
|
|
550
555
|
warningBodyElement.className = 'ons-panel__body';
|
|
551
|
-
warningBodyElement.innerHTML = content;
|
|
556
|
+
warningBodyElement.innerHTML = DOMPurify.sanitize(content);
|
|
552
557
|
|
|
553
558
|
warningElement.appendChild(warningSpanElement);
|
|
554
559
|
warningElement.appendChild(warningBodyElement);
|
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
$breadcrumb-chevron-height: 0.65rem;
|
|
2
2
|
|
|
3
|
+
.ons-breadcrumbs-wrapper {
|
|
4
|
+
position: relative;
|
|
5
|
+
z-index: 10;
|
|
6
|
+
margin-bottom: -2rem;
|
|
7
|
+
&--grey {
|
|
8
|
+
background-color: var(--ons-color-banner-bg);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&--dark {
|
|
12
|
+
background-color: var(--ons-color-hero-bg-dark);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
&--navy-blue {
|
|
16
|
+
background-color: var(--ons-color-navy-blue-light);
|
|
17
|
+
margin-bottom: -1.75rem;
|
|
18
|
+
@include mq(l) {
|
|
19
|
+
margin-bottom: -3.25rem;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&--dark,
|
|
24
|
+
&--navy-blue {
|
|
25
|
+
.ons-icon {
|
|
26
|
+
color: var(--ons-color-text-inverse);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.ons-breadcrumbs__link {
|
|
30
|
+
color: var(--ons-color-text-inverse);
|
|
31
|
+
text-decoration: underline;
|
|
32
|
+
|
|
33
|
+
&:hover {
|
|
34
|
+
color: var(--ons-color-text-inverse);
|
|
35
|
+
text-decoration: underline solid var(--ons-color-text-inverse) 2px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&:focus {
|
|
39
|
+
color: var(--ons-color-text);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&:focus:hover {
|
|
43
|
+
text-decoration: none;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&--pale-blue {
|
|
49
|
+
background-color: var(--ons-color-pale-blue);
|
|
50
|
+
}
|
|
51
|
+
.ons-breadcrumbs {
|
|
52
|
+
padding: 1rem;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
3
56
|
.ons-breadcrumbs {
|
|
4
57
|
align-items: center;
|
|
5
58
|
display: flex;
|
|
@@ -1,28 +1,37 @@
|
|
|
1
1
|
{% from "components/icon/_macro.njk" import onsIcon %}
|
|
2
|
-
|
|
3
2
|
{% macro onsBreadcrumbs(params) %}
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<
|
|
13
|
-
class="ons-
|
|
14
|
-
|
|
15
|
-
{% if item.id %}{{ ' ' }}id='{{ item.id }}'{% endif %}
|
|
16
|
-
{% if item.attributes %}{% for attribute, value in (item.attributes.items() if item.attributes is mapping and item.attributes.items else item.attributes) %}{{ ' ' }}{{ attribute }}="{{ value }}"{% endfor %}{% endif %}
|
|
17
|
-
>{{ item.text }}</a
|
|
3
|
+
{% set breadcrumbs %}
|
|
4
|
+
<nav
|
|
5
|
+
class="ons-breadcrumbs{{ ' ons-container' if params.variant }}{{ ' ' + params.classes if params.classes else '' }}"
|
|
6
|
+
aria-label="{{ params.ariaLabel | default('Breadcrumbs') }}"
|
|
7
|
+
{% if params.id %}id="{{ params.id }}"{% endif %}
|
|
8
|
+
>
|
|
9
|
+
<ol class="ons-breadcrumbs__items ons-u-fs-s">
|
|
10
|
+
{%- for item in params.itemsList -%}
|
|
11
|
+
<li
|
|
12
|
+
class="ons-breadcrumbs__item{{ ' ' + item.itemClasses if item.itemClasses else '' }}"
|
|
13
|
+
id="breadcrumb-{{ loop.index }}"
|
|
18
14
|
>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
<a
|
|
16
|
+
class="ons-breadcrumbs__link{{ ' ' + item.linkClasses if item.linkClasses else '' }}"
|
|
17
|
+
href="{% if not isDesignSystemExample %}{{ item.url }}{% else %}#0{% endif %}"
|
|
18
|
+
{% if item.id %}{{ ' ' }}id='{{ item.id }}'{% endif %}
|
|
19
|
+
{% if item.attributes %}{% for attribute, value in (item.attributes.items() if item.attributes is mapping and item.attributes.items else item.attributes) %}{{ ' ' }}{{ attribute }}="{{ value }}"{% endfor %}{% endif %}
|
|
20
|
+
>{{ item.text }}</a
|
|
21
|
+
>
|
|
22
|
+
{{-
|
|
23
|
+
onsIcon({
|
|
24
|
+
"iconType": "chevron"
|
|
25
|
+
})
|
|
26
|
+
-}}
|
|
27
|
+
</li>
|
|
28
|
+
{%- endfor -%}
|
|
29
|
+
</ol>
|
|
30
|
+
</nav>
|
|
31
|
+
{% endset %}
|
|
32
|
+
{% if params.variant %}
|
|
33
|
+
<div class="ons-breadcrumbs-wrapper ons-breadcrumbs-wrapper--{{ params.variant }}">{{ breadcrumbs | safe }}</div>
|
|
34
|
+
{% else %}
|
|
35
|
+
{{ breadcrumbs | safe }}
|
|
36
|
+
{% endif %}
|
|
28
37
|
{% endmacro %}
|
|
@@ -132,4 +132,29 @@ describe('FOR: Macro: Breadcrumbs', () => {
|
|
|
132
132
|
});
|
|
133
133
|
});
|
|
134
134
|
});
|
|
135
|
+
|
|
136
|
+
describe('GIVEN: Params: variant', () => {
|
|
137
|
+
describe('WHEN: variant is provided', () => {
|
|
138
|
+
const $ = cheerio.load(
|
|
139
|
+
renderComponent('breadcrumbs', {
|
|
140
|
+
...EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS,
|
|
141
|
+
variant: 'grey',
|
|
142
|
+
}),
|
|
143
|
+
);
|
|
144
|
+
test('THEN: renders breadcrumbs in a breadcrumbs-wrapper with correct modifier class', () => {
|
|
145
|
+
expect($('.ons-breadcrumbs-wrapper').hasClass('ons-breadcrumbs-wrapper--grey')).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('WHEN: variant is not provided', () => {
|
|
150
|
+
const $ = cheerio.load(
|
|
151
|
+
renderComponent('breadcrumbs', {
|
|
152
|
+
...EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS,
|
|
153
|
+
}),
|
|
154
|
+
);
|
|
155
|
+
test('THEN: does not render breadcrumbs-wrapper', () => {
|
|
156
|
+
expect($('.ons-breadcrumbs-wrapper').length).toBe(0);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
135
160
|
});
|
|
@@ -99,7 +99,7 @@ $button-shadow-size: 3px;
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
// When preceded by another button (for example
|
|
102
|
+
// When preceded by another button (for example in a group)
|
|
103
103
|
& + & {
|
|
104
104
|
margin-left: 0.5rem;
|
|
105
105
|
}
|
|
@@ -576,6 +576,34 @@ $button-shadow-size: 3px;
|
|
|
576
576
|
}
|
|
577
577
|
}
|
|
578
578
|
|
|
579
|
+
.ons-navigation--neutral &--dropdown {
|
|
580
|
+
.ons-btn__inner {
|
|
581
|
+
background: var(--ons-color-grey-15);
|
|
582
|
+
color: var(--ons-color-black);
|
|
583
|
+
.ons-icon {
|
|
584
|
+
fill: var(--ons-color-black);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
&:focus {
|
|
588
|
+
.ons-btn__inner {
|
|
589
|
+
background: var(--ons-color-focus);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.ons-navigation--neutral &--dropdown:active &,
|
|
595
|
+
.ons-navigation--neutral &--dropdown.active &,
|
|
596
|
+
.ons-navigation--neutral &--dropdown:active:focus &,
|
|
597
|
+
.ons-navigation--neutral &--dropdown.active:focus & {
|
|
598
|
+
&__inner {
|
|
599
|
+
background: var(--ons-color-grey-100);
|
|
600
|
+
color: var(--ons-color-white);
|
|
601
|
+
.ons-icon {
|
|
602
|
+
fill: var(--ons-color-white);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
579
607
|
&--neutral &,
|
|
580
608
|
&--neutral:hover &,
|
|
581
609
|
&--neutral:active &,
|