@ons/design-system 53.1.0 → 54.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.
Files changed (48) hide show
  1. package/components/accordion/_macro.njk +2 -3
  2. package/components/accordion/_macro.spec.js +3 -40
  3. package/components/accordion/accordion.dom.js +19 -0
  4. package/components/{collapsible/collapsible.group.js → accordion/accordion.js} +12 -5
  5. package/components/accordion/accordion.spec.js +56 -51
  6. package/components/autosuggest/_autosuggest.scss +4 -4
  7. package/components/autosuggest/autosuggest.spec.js +12 -2
  8. package/components/autosuggest/autosuggest.ui.js +4 -7
  9. package/components/button/_button.scss +8 -1
  10. package/components/checkboxes/_checkbox.scss +7 -7
  11. package/components/checkboxes/_macro.njk +1 -1
  12. package/components/collapsible/_collapsible.scss +58 -85
  13. package/components/collapsible/_macro.njk +6 -39
  14. package/components/collapsible/_macro.spec.js +0 -53
  15. package/components/collapsible/collapsible.dom.js +3 -12
  16. package/components/collapsible/collapsible.js +3 -45
  17. package/components/collapsible/collapsible.spec.js +6 -139
  18. package/components/cookies-banner/_cookies-banner.scss +15 -7
  19. package/components/cookies-banner/_macro.njk +66 -22
  20. package/components/cookies-banner/_macro.spec.js +172 -114
  21. package/components/cookies-banner/cookies-banner.js +35 -13
  22. package/components/cookies-banner/cookies-banner.spec.js +58 -54
  23. package/components/duration/_macro.njk +1 -1
  24. package/components/duration/_macro.spec.js +1 -1
  25. package/components/fieldset/_fieldset.scss +3 -6
  26. package/components/input/_input-type.scss +34 -3
  27. package/components/input/_input.scss +16 -8
  28. package/components/input/_macro.njk +17 -14
  29. package/components/input/_macro.spec.js +56 -0
  30. package/components/label/_label.scss +1 -1
  31. package/components/mutually-exclusive/mutually-exclusive.duration.spec.js +2 -0
  32. package/components/mutually-exclusive/mutually-exclusive.number.spec.js +1 -0
  33. package/components/radios/_radio.scss +2 -2
  34. package/components/relationships/_relationships.scss +2 -2
  35. package/components/table/_table.scss +3 -2
  36. package/components/tabs/_tabs.scss +55 -34
  37. package/components/tabs/tabs.js +4 -2
  38. package/components/upload/_upload.scss +2 -2
  39. package/css/census.css +1 -1
  40. package/css/ids.css +1 -1
  41. package/css/main.css +1 -1
  42. package/js/main.js +1 -0
  43. package/package.json +1 -1
  44. package/scripts/main.es5.js +1 -1
  45. package/scripts/main.js +2 -2
  46. package/scss/objects/_page.scss +1 -1
  47. package/scss/patternlib.scss +0 -56
  48. package/scss/vars/_colors.scss +2 -1
@@ -1,10 +1,6 @@
1
1
  import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
2
2
 
3
- const EXAMPLE_COOKIES_BANNER_PAGE = renderComponent('cookies-banner', {
4
- statementTitle: 'Tell us whether you accept cookies',
5
- statementText: 'We use <a href="#0">cookies to collect information</a> about how you use census.gov.uk.',
6
- confirmationText: 'You’ve accepted all cookies. You can <a href="#0">change your cookie preferences</a> at any time.',
7
- });
3
+ const EXAMPLE_COOKIES_BANNER_PAGE = renderComponent('cookies-banner', {});
8
4
 
9
5
  describe('script: cookies-banner', () => {
10
6
  beforeEach(async () => {
@@ -18,73 +14,81 @@ describe('script: cookies-banner', () => {
18
14
  const displayStyle = await page.$eval('.ons-cookies-banner', node => window.getComputedStyle(node).getPropertyValue('display'));
19
15
  expect(displayStyle).toBe('block');
20
16
  });
17
+ describe.each([
18
+ ['accepting cookies', 'accept', true],
19
+ ['rejecting cookies', 'reject', false],
20
+ ])('action: %s', (_, action, value) => {
21
+ it(`sets all cookies to ${value} when ${_}`, async () => {
22
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
23
+
24
+ await page.click(`.ons-js-${action}-cookies`);
25
+
26
+ const cookies = await page.cookies();
27
+ const ons_cookie_policy = cookies.find(cookie => cookie.name === 'ons_cookie_policy');
28
+ const policy = JSON.parse(ons_cookie_policy.value.replace(/'/g, '"'));
29
+
30
+ expect(policy).toEqual({
31
+ essential: true,
32
+ settings: value,
33
+ usage: value,
34
+ campaigns: value,
35
+ });
36
+ });
21
37
 
22
- it('sets all cookies to true when accepting cookies', async () => {
23
- await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
38
+ it(`sets seen cookie message when ${_}`, async () => {
39
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
24
40
 
25
- await page.click('.ons-js-accept-cookies');
41
+ await page.click(`.ons-js-${action}-cookies`);
26
42
 
27
- const cookies = await page.cookies();
28
- const ons_cookie_policy = cookies.find(cookie => cookie.name === 'ons_cookie_policy');
29
- const policy = JSON.parse(ons_cookie_policy.value.replace(/'/g, '"'));
43
+ const cookies = await page.cookies();
44
+ const ons_cookie_message_displayed = cookies.find(cookie => cookie.name === 'ons_cookie_message_displayed');
30
45
 
31
- expect(policy).toEqual({
32
- essential: true,
33
- settings: true,
34
- usage: true,
35
- campaigns: true,
46
+ expect(ons_cookie_message_displayed.value).toBe('true');
36
47
  });
37
- });
38
-
39
- it('sets seen cookie message when accepting cookies', async () => {
40
- await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
41
48
 
42
- await page.click('.ons-js-accept-cookies');
49
+ it(`should hide the primary message when pressing the ${action} button`, async () => {
50
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
43
51
 
44
- const cookies = await page.cookies();
45
- const ons_cookie_message_displayed = cookies.find(cookie => cookie.name === 'ons_cookie_message_displayed');
52
+ await page.click(`.ons-js-${action}-cookies`);
46
53
 
47
- expect(ons_cookie_message_displayed.value).toBe('true');
48
- });
54
+ const displayStyle = await page.$eval('.ons-cookies-banner__primary', node =>
55
+ window.getComputedStyle(node).getPropertyValue('display'),
56
+ );
57
+ expect(displayStyle).toBe('none');
58
+ });
49
59
 
50
- it('should hide the primary message when pressing the accept button', async () => {
51
- await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
60
+ it(`should show the secondary message when pressing the ${action} button`, async () => {
61
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
52
62
 
53
- await page.click('.ons-js-accept-cookies');
63
+ await page.click(`.ons-js-${action}-cookies`);
54
64
 
55
- const displayStyle = await page.$eval('.ons-cookies-banner__primary', node =>
56
- window.getComputedStyle(node).getPropertyValue('display'),
57
- );
58
- expect(displayStyle).toBe('none');
65
+ const displayStyle = await page.$eval('.ons-cookies-banner__confirmation', node =>
66
+ window.getComputedStyle(node).getPropertyValue('display'),
67
+ );
68
+ expect(displayStyle).not.toBe('none');
69
+ });
59
70
  });
60
71
 
61
- it('should show the secondary message when pressing the accept button', async () => {
62
- await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
63
-
64
- await page.click('.ons-js-accept-cookies');
65
-
66
- const displayStyle = await page.$eval('.ons-cookies-banner__confirmation', node =>
67
- window.getComputedStyle(node).getPropertyValue('display'),
68
- );
69
- expect(displayStyle).not.toBe('none');
70
- });
71
- //...
72
- it('should hide the secondary message when pressing the hide button', async () => {
73
- await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
72
+ describe('confirmation banner', () => {
73
+ it('should hide the confirmation message when pressing the hide button', async () => {
74
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
74
75
 
75
- await page.click('.ons-js-accept-cookies');
76
- await page.click('.ons-js-hide-button');
76
+ await page.click('.ons-js-accept-cookies');
77
+ await page.click('.ons-js-hide-button');
77
78
 
78
- const displayStyle = await page.$eval('.ons-cookies-banner', node => window.getComputedStyle(node).getPropertyValue('display'));
79
- expect(displayStyle).toBe('none');
79
+ const displayStyle = await page.$eval('.ons-cookies-banner', node => window.getComputedStyle(node).getPropertyValue('display'));
80
+ expect(displayStyle).toBe('none');
81
+ });
80
82
  });
81
83
 
82
- it('does not show the banner if user has acknowledged the banner previously and consent cookie is present', async () => {
83
- await page.setCookie({ name: 'ons_cookie_message_displayed', value: 'true' });
84
+ describe('cookie preferences confirmed', () => {
85
+ it('does not show the banner if user has acknowledged the banner previously and consent cookie is present', async () => {
86
+ await page.setCookie({ name: 'ons_cookie_message_displayed', value: 'true' });
84
87
 
85
- await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
88
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
86
89
 
87
- const displayStyle = await page.$eval('.ons-cookies-banner', node => window.getComputedStyle(node).getPropertyValue('display'));
88
- expect(displayStyle).toBe('none');
90
+ const displayStyle = await page.$eval('.ons-cookies-banner', node => window.getComputedStyle(node).getPropertyValue('display'));
91
+ expect(displayStyle).toBe('none');
92
+ });
89
93
  });
90
94
  });
@@ -84,7 +84,7 @@
84
84
  "id": params.id,
85
85
  "legend": params.legendOrLabel,
86
86
  "description": params.description,
87
- "legendClasses": 'ons-u-mb-xs ' + (params.legendClasses if params.legendClasses else ''),
87
+ "legendClasses": params.legendClasses,
88
88
  "error": params.error,
89
89
  "legendIsQuestionTitle": params.legendIsQuestionTitle,
90
90
  "dontWrap": params.dontWrap
@@ -127,7 +127,7 @@ describe('macro: duration', () => {
127
127
  id: 'duration',
128
128
  legend: 'How long have you lived at this address?',
129
129
  description: 'Enter “0” into the years field if you have lived at this address for less than a year',
130
- legendClasses: 'ons-u-mb-xs custom-legend-class',
130
+ legendClasses: 'custom-legend-class',
131
131
  dontWrap: true,
132
132
  legendIsQuestionTitle: true,
133
133
  error: false,
@@ -1,6 +1,7 @@
1
1
  .ons-fieldset {
2
2
  &__legend {
3
- @extend .ons-label;
3
+ font-weight: $font-weight-bold;
4
+ margin: 0 0 0.6rem;
4
5
  }
5
6
 
6
7
  &__description:not(&__description--title) {
@@ -11,14 +12,10 @@
11
12
  font-weight: normal;
12
13
  }
13
14
 
14
- .ons-fieldset {
15
- &__legend {
16
- margin: 0 0 0.6rem;
17
- }
15
+ > * .ons-fieldset {
18
16
  .ons-fieldset {
19
17
  &__legend {
20
18
  font-weight: normal;
21
- margin: 0;
22
19
  }
23
20
  }
24
21
  }
@@ -14,7 +14,14 @@
14
14
  z-index: 1;
15
15
 
16
16
  &:focus {
17
- box-shadow: inset 0 0 0 1px $color-input;
17
+ // Overide default input focus so it can wrap prefix/suffix too
18
+ box-shadow: none;
19
+ }
20
+
21
+ // Overide default input error style so it can wrap prefix/suffix too
22
+ &.ons-input--error:not(:focus) {
23
+ border-right: $input-border-width solid $color-input-border;
24
+ box-shadow: none;
18
25
  }
19
26
  }
20
27
 
@@ -36,13 +43,15 @@
36
43
 
37
44
  &__type,
38
45
  &__type[title] {
39
- border: 1px solid $color-input;
46
+ border: 1px solid $color-input-border;
40
47
  }
41
48
 
42
49
  &__input:focus + &__type::after {
50
+ // Style input + prefix/suffix on focus
51
+ @extend %ons-input-focus;
52
+
43
53
  border-radius: $input-radius;
44
54
  bottom: 0;
45
- box-shadow: 0 0 0 3px $color-focus;
46
55
  content: '';
47
56
  display: block;
48
57
  left: 0;
@@ -75,3 +84,25 @@
75
84
  }
76
85
  }
77
86
  }
87
+
88
+ // Errors
89
+ .ons-input--error:not(:focus) {
90
+ & + .ons-input-type__type,
91
+ & + .ons-input-type__type[title] {
92
+ border-color: $color-errors;
93
+ }
94
+
95
+ & + .ons-input-type__type::after {
96
+ border-radius: $input-radius;
97
+ bottom: 0;
98
+
99
+ // Style input + prefix/suffix for errors
100
+ box-shadow: 0 0 0 1px $color-errors;
101
+ content: '';
102
+ display: block;
103
+ left: 0;
104
+ position: absolute;
105
+ right: 0;
106
+ top: 0;
107
+ }
108
+ }
@@ -1,10 +1,10 @@
1
1
  %ons-input-focus {
2
- box-shadow: 0 0 0 3px $color-focus, inset 0 0 0 1px $color-input;
2
+ box-shadow: 0 0 0 $input-border-width $color-input-border, 0 0 0 4px $color-focus;
3
3
  outline: none;
4
4
  }
5
5
 
6
6
  .ons-input {
7
- border: $input-border-width solid $color-input;
7
+ border: $input-border-width solid $color-input-border;
8
8
  border-radius: $input-radius;
9
9
  color: inherit;
10
10
  display: block;
@@ -45,8 +45,8 @@
45
45
  }
46
46
 
47
47
  &--error:not(:focus) {
48
- border: 1px solid $color-errors;
49
- box-shadow: inset 0 0 0 1px $color-errors;
48
+ border: $input-border-width solid $color-errors;
49
+ box-shadow: 0 0 0 $input-border-width $color-errors;
50
50
  }
51
51
 
52
52
  &--with-description {
@@ -73,7 +73,7 @@
73
73
 
74
74
  .ons-input--select {
75
75
  appearance: none;
76
- background: $color-white url('#{$static}/img/icons--chevron-down.svg') no-repeat center right 10px;
76
+ background: $color-input-bg url('#{$static}/img/icons--chevron-down.svg') no-repeat center right 10px;
77
77
  background-size: 1rem;
78
78
  line-height: 1.3rem;
79
79
  padding: 0.39rem 2rem 0.39rem $input-padding-horizontal;
@@ -100,10 +100,10 @@
100
100
  color: transparent;
101
101
  }
102
102
  &:valid:not(:placeholder-shown) {
103
- background-color: $color-white;
103
+ background-color: $color-input-bg;
104
104
  }
105
105
  &:focus {
106
- background-color: $color-white;
106
+ background-color: $color-input-bg;
107
107
  }
108
108
  }
109
109
 
@@ -122,7 +122,7 @@
122
122
  .ons-input--ghost {
123
123
  border: 2px solid rgba(255, 255, 255, 0.6);
124
124
  &:focus {
125
- border: 2px solid $color-input;
125
+ border: 2px solid $color-input-border;
126
126
  }
127
127
  }
128
128
 
@@ -156,3 +156,11 @@
156
156
  }
157
157
  }
158
158
  }
159
+
160
+ // Search type inputs - removes the 'X' clear button from webkit browsers
161
+ input[type='search']::-webkit-search-decoration,
162
+ input[type='search']::-webkit-search-cancel-button,
163
+ input[type='search']::-webkit-search-results-button,
164
+ input[type='search']::-webkit-search-results-decoration {
165
+ display: none;
166
+ }
@@ -27,7 +27,7 @@
27
27
  type="{{ type }}"
28
28
  id="{{ params.id }}"
29
29
  class="ons-input ons-input--text ons-input-type__input{% if params.error is defined and params.error %} ons-input--error{% endif %}{% if params.searchButton is defined and params.searchButton %} ons-search__input{% endif %}{% if params.classes is defined and params.classes %} {{ params.classes }}{% endif %}{% if params.width is defined and params.width %} ons-input{% if params.type is defined and (params.type == 'number' or params.type == 'tel') %}-number{% endif %}--w-{{ params.width }}{% endif %}{{ exclusiveClass }}{{ inputPlaceholder }}"
30
- {% if params.prefix is defined and params.prefix or params.suffix is defined and params.suffix %}aria-labelledby="{{ params.prefix.id if params.prefix }}{{ params.suffix.id if params.suffix }}"{% endif %}
30
+ {% if params.prefix is defined and params.prefix and params.prefix.id is defined and params.prefix.id %}aria-labelledby="{{ params.prefix.id }}"{% elif params.suffix is defined and params.suffix and params.suffix.id is defined and params.suffix.id %}aria-labelledby="{{ params.suffix.id }}"{% endif %}
31
31
  {% if params.name is defined and params.name %}name="{{ params.name }}"{% endif %}
32
32
  {% if params.value is defined and params.value %}value="{{ params.value }}"{% endif %}
33
33
  {% if params.accept is defined and params.accept %}accept="{{ params.accept }}"{% endif %}
@@ -71,21 +71,24 @@
71
71
  {% endif %}
72
72
 
73
73
  {% if params.prefix is defined and params.prefix or params.suffix is defined and params.suffix %}
74
- {% if params.prefix is defined and params.prefix %}
75
- {% set prefixClass = " ons-input-type--prefix" %}
76
- {% endif %}
74
+ {% if (params.prefix is defined and params.prefix and params.prefix.id is defined and params.prefix.id and params.prefix.title is defined and params.prefix.title) or (params.suffix is defined and params.suffix and params.suffix.id is defined and params.suffix.id and params.suffix.title is defined and params.suffix.title) %}
75
+ {% if params.prefix is defined and params.prefix %}
76
+ {% set prefixClass = " ons-input-type--prefix" %}
77
+ {% endif %}
77
78
 
78
- <span class="ons-input-type{{ prefixClass }}">
79
- <span class="ons-input-type__inner">
80
- {{ input | safe }}
81
- {% set abbr = params.prefix or params.suffix %}
82
- <abbr
83
- {% if abbr.id is defined and abbr.id %}id="{{ abbr.id }}" {% endif %}
84
- class="ons-input-type__type ons-js-input-abbr"
85
- title="{{ abbr.title }}"
86
- >{{ abbr.text or abbr.title }}</abbr>
79
+ <span class="ons-input-type{{ prefixClass }}">
80
+ <span class="ons-input-type__inner">
81
+ {{ input | safe }}
82
+
83
+ {% set abbr = params.prefix or params.suffix %}
84
+ <abbr
85
+ id="{{ abbr.id }}"
86
+ class="ons-input-type__type ons-js-input-abbr"
87
+ title="{{ abbr.title }}"
88
+ >{{ abbr.text or abbr.title }}</abbr>
89
+ </span>
87
90
  </span>
88
- </span>
91
+ {% endif %}
89
92
  {% elif params.searchButton is defined and params.searchButton %}
90
93
  <span class="ons-grid--flex ons-search">
91
94
  {% call onsSearch({
@@ -429,6 +429,34 @@ describe('macro: input', () => {
429
429
  ).toBe('Example prefix text');
430
430
  });
431
431
 
432
+ it('does not render prefix element when `prefix.id` not set', () => {
433
+ const $ = cheerio.load(
434
+ renderComponent('input', {
435
+ ...EXAMPLE_INPUT_MINIMAL,
436
+ prefix: {
437
+ title: 'Example prefix title',
438
+ text: 'Example prefix text',
439
+ },
440
+ }),
441
+ );
442
+
443
+ expect($('.ons-input-type--prefix').length).toBe(0);
444
+ });
445
+
446
+ it('does not render prefix element when `prefix.title` not set', () => {
447
+ const $ = cheerio.load(
448
+ renderComponent('input', {
449
+ ...EXAMPLE_INPUT_MINIMAL,
450
+ prefix: {
451
+ text: 'Example prefix text',
452
+ id: 'example-prefix-id',
453
+ },
454
+ }),
455
+ );
456
+
457
+ expect($('.ons-input-type--prefix').length).toBe(0);
458
+ });
459
+
432
460
  it('adds `aria-labelledby` attribute when `suffix` is provided', () => {
433
461
  const $ = cheerio.load(
434
462
  renderComponent('input', {
@@ -485,6 +513,34 @@ describe('macro: input', () => {
485
513
  });
486
514
  });
487
515
 
516
+ it('does not render suffix element when `suffix.id` not set', () => {
517
+ const $ = cheerio.load(
518
+ renderComponent('input', {
519
+ ...EXAMPLE_INPUT_MINIMAL,
520
+ suffix: {
521
+ title: 'Example suffix title',
522
+ text: 'Example suffix text',
523
+ },
524
+ }),
525
+ );
526
+
527
+ expect($('.ons-input').length).toBe(0);
528
+ });
529
+
530
+ it('does not render suffix element when `suffix.title` not set', () => {
531
+ const $ = cheerio.load(
532
+ renderComponent('input', {
533
+ ...EXAMPLE_INPUT_MINIMAL,
534
+ suffix: {
535
+ text: 'Example suffix text',
536
+ id: 'example-suffix-id',
537
+ },
538
+ }),
539
+ );
540
+
541
+ expect($('.ons-input').length).toBe(0);
542
+ });
543
+
488
544
  describe('search', () => {
489
545
  it('renders `search` component', () => {
490
546
  const faker = templateFaker();
@@ -2,7 +2,7 @@
2
2
  color: inherit;
3
3
  display: block;
4
4
  font-weight: $font-weight-bold;
5
- margin-bottom: 0.4rem;
5
+ margin: 0 0 0.6rem;
6
6
 
7
7
  &__description {
8
8
  @extend .ons-u-fs-s;
@@ -11,6 +11,7 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_PARAMS = {
11
11
  name: 'address-duration-years',
12
12
  suffix: {
13
13
  text: 'Years',
14
+ id: 'address-duration-years-suffix',
14
15
  },
15
16
  attributes: {
16
17
  min: 0,
@@ -22,6 +23,7 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_PARAMS = {
22
23
  name: 'address-duration-months',
23
24
  suffix: {
24
25
  text: 'Months',
26
+ id: 'address-duration-months-suffix',
25
27
  },
26
28
  attributes: {
27
29
  min: 0,
@@ -16,6 +16,7 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_NUMBER_INPUT_PARAMS = {
16
16
  prefix: {
17
17
  title: 'Pounds',
18
18
  text: '£',
19
+ id: 'currency-prefix',
19
20
  },
20
21
  mutuallyExclusive: {
21
22
  or: 'Or',
@@ -9,7 +9,7 @@
9
9
  box-shadow: inset 0 0 0 3px $color-white;
10
10
 
11
11
  &:checked {
12
- background: $color-input;
12
+ background: $color-input-border;
13
13
  }
14
14
  }
15
15
 
@@ -27,7 +27,7 @@
27
27
  }
28
28
 
29
29
  &:focus {
30
- box-shadow: 0 0 0 3px $color-focus, inset 0 0 0 3px $color-white;
30
+ box-shadow: inset 0 0 0 3px $color-input-bg, 0 0 0 $input-border-width $color-input-border, 0 0 0 4px $color-focus;
31
31
  }
32
32
  }
33
33
  }
@@ -1,7 +1,7 @@
1
1
  .ons-relationships {
2
2
  &__playback {
3
- border-bottom: 1px solid $color-input;
4
- border-top: 1px solid $color-input;
3
+ border-bottom: 1px solid $color-input-border;
4
+ border-top: 1px solid $color-input-border;
5
5
  margin: 2rem 0 0;
6
6
  padding: 1rem 0;
7
7
 
@@ -107,8 +107,8 @@
107
107
  overflow-x: scroll;
108
108
  width: 100%;
109
109
  &:focus {
110
- outline: 3px solid $color-focus;
111
- outline-offset: 3px;
110
+ box-shadow: 0 0 0 3px $color-page-light, 0 0 0 5px $color-text-link-focus, 0 0 0 8px $color-focus;
111
+ outline: none;
112
112
  }
113
113
  .ons-table__header,
114
114
  .ons-table__cell {
@@ -119,6 +119,7 @@
119
119
  .ons-table__right-shadow,
120
120
  .ons-table__left-shadow {
121
121
  height: 100%;
122
+ padding: 2px;
122
123
  position: absolute;
123
124
  top: 0;
124
125
  width: 5px;
@@ -1,17 +1,33 @@
1
1
  .ons-tabs {
2
2
  margin-bottom: 1rem;
3
- }
4
3
 
5
- // Tabs - list
6
- .ons-tabs__list {
7
- border-bottom: 0;
8
- margin: 0 0 1rem;
9
- overflow: visible;
10
- padding: 0;
4
+ &__title {
5
+ @extend .ons-u-fs-r--b;
6
+ }
11
7
 
12
- &--row {
13
- border-bottom: 1px solid $color-borders;
14
- margin: 0;
8
+ // Anchor links list
9
+ &__list {
10
+ border-bottom: 0;
11
+ margin: 0 0 1rem;
12
+ overflow: visible;
13
+ padding: 0;
14
+
15
+ // Tabs
16
+ &--row {
17
+ margin: 0;
18
+ position: relative;
19
+
20
+ &::after {
21
+ background: $color-borders;
22
+ bottom: 0;
23
+ box-shadow: 0 1px 0 0 $color-page-light;
24
+ content: '';
25
+ height: 1px;
26
+ left: 0;
27
+ position: absolute;
28
+ width: 100%;
29
+ }
30
+ }
15
31
  }
16
32
  }
17
33
 
@@ -32,7 +48,7 @@
32
48
  border-radius: 3px 3px 0 0;
33
49
  color: $color-text;
34
50
  display: inline-block;
35
- height: 2.5rem;
51
+ height: 2.55rem;
36
52
  line-height: 2.3rem;
37
53
  margin: 0 0.1rem 0 0;
38
54
  overflow: visible;
@@ -47,47 +63,52 @@
47
63
  text-decoration: underline solid $color-text 2px;
48
64
  }
49
65
 
66
+ &:focus {
67
+ background-color: $color-focus;
68
+ border-bottom: 1px solid $color-borders;
69
+ box-shadow: inset 0 0 0 9px $color-button-secondary,
70
+ inset 17px 0 0 0 $color-button-secondary,
71
+ inset -17px 0 0 0 $color-button-secondary,
72
+ inset 0 -13px 0 0 $color-text-link-focus;
73
+ color: $color-text-link-focus;
74
+ outline: none;
75
+ text-decoration: underline solid $color-text 2px;
76
+ }
77
+
78
+ // Tab when selected
50
79
  &[aria-selected='true'] {
51
- background-color: $color-white;
80
+ background-color: $color-page-light;
81
+ border-bottom: none;
52
82
  border-color: $color-borders;
53
- // Tab when selected
54
83
  border-radius: 3px 3px 0 0;
55
- font-weight: 700;
56
84
  text-decoration: none;
85
+ z-index: 1;
57
86
 
58
- &::after {
59
- background: $color-white;
60
- bottom: -2px;
61
- box-shadow: none;
62
- content: '';
63
- height: 0.09rem;
64
- left: 0;
65
- // hides the lower border of the active tab.
66
- position: absolute;
67
- right: 0;
68
- z-index: 3;
87
+ &:focus {
88
+ background-color: $color-focus;
89
+ border-bottom: 1px solid $color-page-light;
90
+ box-shadow: inset 0 0 0 9px $color-page-light,
91
+ inset 17px 0 0 0 $color-page-light,
92
+ inset -17px 0 0 0 $color-page-light,
93
+ inset 0 -13px 0 0 $color-text-link-focus;
94
+ text-decoration: none;
69
95
  }
70
96
  }
71
-
72
- &:focus {
73
- background-color: $color-focus;
74
- color: $color-text-link-focus;
75
- outline: none;
76
- }
77
97
  }
78
98
 
79
99
  // Tabs - Panels
80
100
  .ons-tabs__panel {
81
- margin-bottom: 1rem;
101
+ padding-bottom: 1rem;
82
102
  padding-top: 1rem;
83
103
  position: relative;
84
- z-index: 10;
85
104
 
86
105
  &--hidden {
87
106
  display: none;
88
107
  }
89
108
 
90
109
  &:focus {
91
- outline: 4px solid $color-focus;
110
+ box-shadow: 0 0 0 3px $color-page-light, 0 0 0 5px $color-text-link-focus, 0 0 0 8px $color-focus;
111
+ outline: none;
112
+ z-index: 1;
92
113
  }
93
114
  }
@@ -30,8 +30,6 @@ export default class Tabs {
30
30
  this.jsTabItemAsRowClass = 'ons-tab__list-item--row';
31
31
  this.jsTabAsListClass = 'ons-tab--row';
32
32
 
33
- this.tabsTitle.classList.add('ons-u-vh');
34
-
35
33
  if (matchMediaUtil.hasMatchMedia()) {
36
34
  this.setupViewportChecks();
37
35
  } else {
@@ -61,6 +59,8 @@ export default class Tabs {
61
59
  this.tabList[0].setAttribute('role', 'tablist');
62
60
  this.tabList[0].classList.add(this.jsTabListAsRowClass);
63
61
 
62
+ this.tabsTitle.classList.add('ons-u-vh');
63
+
64
64
  this.tabPanels.forEach(panel => {
65
65
  panel.setAttribute('tabindex', '0');
66
66
  });
@@ -90,6 +90,8 @@ export default class Tabs {
90
90
  this.tabList[0].removeAttribute('role');
91
91
  this.tabList[0].classList.remove(this.jsTabListAsRowClass);
92
92
 
93
+ this.tabsTitle.classList.remove('ons-u-vh');
94
+
93
95
  this.tabPanels.forEach(panel => {
94
96
  panel.removeAttribute('tabindex', '0');
95
97
  });