@ministryofjustice/frontend 3.3.0 → 3.4.0

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 (87) hide show
  1. package/README.md +4 -10
  2. package/govuk-prototype-kit.config.json +5 -16
  3. package/moj/all.jquery.min.js +77 -3
  4. package/moj/all.js +2022 -1444
  5. package/moj/all.scss +2 -0
  6. package/moj/all.spec.js +15 -13
  7. package/moj/components/_all.scss +1 -0
  8. package/moj/components/action-bar/_action-bar.scss +4 -6
  9. package/moj/components/add-another/_add-another.scss +9 -7
  10. package/moj/components/add-another/add-another.js +90 -69
  11. package/moj/components/add-another/add-another.spec.js +165 -0
  12. package/moj/components/alert/README.md +0 -0
  13. package/moj/components/alert/_alert.scss +142 -0
  14. package/moj/components/alert/alert.js +247 -0
  15. package/moj/components/alert/alert.spec.helper.js +67 -0
  16. package/moj/components/alert/alert.spec.js +229 -0
  17. package/moj/components/alert/macro.njk +3 -0
  18. package/moj/components/alert/template.njk +83 -0
  19. package/moj/components/badge/_badge.scss +3 -4
  20. package/moj/components/banner/_banner.scss +5 -10
  21. package/moj/components/button-menu/_button-menu.scss +10 -9
  22. package/moj/components/button-menu/button-menu.js +139 -136
  23. package/moj/components/button-menu/button-menu.spec.js +295 -296
  24. package/moj/components/cookie-banner/_cookie-banner.scss +6 -5
  25. package/moj/components/currency-input/_currency-input.scss +4 -4
  26. package/moj/components/date-picker/README.md +14 -17
  27. package/moj/components/date-picker/_date-picker.scss +122 -106
  28. package/moj/components/date-picker/date-picker.js +473 -471
  29. package/moj/components/date-picker/date-picker.spec.js +962 -914
  30. package/moj/components/filter/README.md +1 -1
  31. package/moj/components/filter/_filter.scss +53 -75
  32. package/moj/components/filter-toggle-button/filter-toggle-button.js +71 -67
  33. package/moj/components/filter-toggle-button/filter-toggle-button.spec.js +203 -205
  34. package/moj/components/form-validator/form-validator.js +117 -109
  35. package/moj/components/header/_header.scss +17 -19
  36. package/moj/components/identity-bar/_identity-bar.scss +5 -5
  37. package/moj/components/interruption-card/_interruption-card.scss +9 -2
  38. package/moj/components/messages/_messages.scss +12 -19
  39. package/moj/components/multi-file-upload/README.md +1 -1
  40. package/moj/components/multi-file-upload/_multi-file-upload.scss +34 -30
  41. package/moj/components/multi-file-upload/multi-file-upload.js +188 -152
  42. package/moj/components/multi-file-upload/multi-file-upload.spec.js +510 -0
  43. package/moj/components/multi-select/_multi-select.scss +4 -3
  44. package/moj/components/multi-select/multi-select.js +55 -50
  45. package/moj/components/multi-select/multi-select.spec.js +128 -0
  46. package/moj/components/notification-badge/_notification-badge.scss +12 -12
  47. package/moj/components/organisation-switcher/_organisation-switcher.scss +1 -1
  48. package/moj/components/page-header-actions/_page-header-actions.scss +3 -2
  49. package/moj/components/pagination/_pagination.scss +26 -31
  50. package/moj/components/password-reveal/_password-reveal.scss +1 -2
  51. package/moj/components/password-reveal/password-reveal.js +22 -21
  52. package/moj/components/password-reveal/password-reveal.spec.js +39 -37
  53. package/moj/components/primary-navigation/_primary-navigation.scss +26 -29
  54. package/moj/components/progress-bar/_progress-bar.scss +21 -26
  55. package/moj/components/rich-text-editor/_rich-text-editor.scss +17 -16
  56. package/moj/components/rich-text-editor/rich-text-editor.js +117 -103
  57. package/moj/components/search/_search.scss +6 -4
  58. package/moj/components/search-toggle/search-toggle.js +29 -30
  59. package/moj/components/search-toggle/search-toggle.scss +21 -15
  60. package/moj/components/search-toggle/search-toggle.spec.js +129 -0
  61. package/moj/components/side-navigation/_side-navigation.scss +12 -21
  62. package/moj/components/sortable-table/_sortable-table.scss +25 -23
  63. package/moj/components/sortable-table/sortable-table.js +139 -117
  64. package/moj/components/sortable-table/sortable-table.spec.js +362 -0
  65. package/moj/components/sub-navigation/_sub-navigation.scss +24 -28
  66. package/moj/components/tag/_tag.scss +8 -9
  67. package/moj/components/task-list/_task-list.scss +8 -7
  68. package/moj/components/ticket-panel/_ticket-panel.scss +14 -6
  69. package/moj/components/timeline/_timeline.scss +18 -20
  70. package/moj/filters/all.js +28 -30
  71. package/moj/filters/prototype-kit-13-filters.js +2 -1
  72. package/moj/helpers/_all.scss +1 -0
  73. package/moj/helpers/_hidden.scss +1 -1
  74. package/moj/helpers/_links.scss +20 -0
  75. package/moj/helpers.js +160 -31
  76. package/moj/helpers.spec.js +235 -0
  77. package/moj/init.js +2 -2
  78. package/moj/moj-frontend.min.css +2 -2
  79. package/moj/moj-frontend.min.js +77 -3
  80. package/moj/namespace.js +2 -1
  81. package/moj/objects/_filter-layout.scss +11 -10
  82. package/moj/objects/_scrollable-pane.scss +11 -14
  83. package/moj/settings/_colours.scss +5 -0
  84. package/moj/settings/_measurements.scss +0 -2
  85. package/moj/utilities/_hidden.scss +3 -3
  86. package/moj/utilities/_width-container.scss +1 -1
  87. package/package.json +1 -1
package/moj/all.scss CHANGED
@@ -1,3 +1,5 @@
1
+ $govuk-suppressed-warnings: ("govuk-typography-scale-14");
2
+
1
3
  @import "node_modules/govuk-frontend/dist/govuk/base";
2
4
 
3
5
  @import "settings/all";
package/moj/all.spec.js CHANGED
@@ -1,22 +1,24 @@
1
- const { getByText, getByTestId } = require("@testing-library/dom");
1
+ /* eslint-disable no-new */
2
2
 
3
- require("./helpers");
4
- require("./all.js");
3
+ const { getByTestId } = require('@testing-library/dom')
5
4
 
6
- describe("initAll", () => {
7
- test("initialises container", () => {
8
- MOJFrontend.PasswordReveal = jest.fn();
5
+ require('./helpers')
6
+ require('./all.js')
9
7
 
10
- const container = document.createElement("div");
8
+ describe('initAll', () => {
9
+ test('initialises container', () => {
10
+ MOJFrontend.PasswordReveal = jest.fn()
11
+
12
+ const container = document.createElement('div')
11
13
 
12
14
  container.innerHTML = `
13
15
  <input data-module="moj-password-reveal" data-testid="password-reveal" type="password" />
14
- `;
16
+ `
15
17
 
16
- new MOJFrontend.initAll({ scope: container });
18
+ MOJFrontend.initAll({ scope: container })
17
19
 
18
20
  expect(MOJFrontend.PasswordReveal).toHaveBeenCalledWith(
19
- getByTestId(container, "password-reveal"),
20
- );
21
- });
22
- });
21
+ getByTestId(container, 'password-reveal')
22
+ )
23
+ })
24
+ })
@@ -1,5 +1,6 @@
1
1
  @import "action-bar/action-bar";
2
2
  @import "add-another/add-another";
3
+ @import "alert/alert";
3
4
  @import "badge/badge";
4
5
  @import "banner/banner";
5
6
  @import "button-menu/button-menu";
@@ -14,14 +14,14 @@
14
14
  margin-right: govuk-spacing(2);
15
15
  padding-right: govuk-spacing(2) + 2px; // Takes into account divider width
16
16
 
17
- &:after {
17
+ &::after {
18
18
  content: "";
19
- background-color: govuk-colour("light-grey");
20
- height: 40px;
21
19
  position: absolute;
22
- right: 0;
23
20
  top: 0;
21
+ right: 0;
24
22
  width: 2px;
23
+ height: 40px;
24
+ background-color: govuk-colour("light-grey");
25
25
  }
26
26
  }
27
27
 
@@ -29,5 +29,3 @@
29
29
  vertical-align: baseline;
30
30
  }
31
31
  }
32
-
33
-
@@ -4,10 +4,10 @@
4
4
 
5
5
  .moj-add-another {
6
6
  &__item {
7
+ position: relative;
7
8
  margin: 0;
8
9
  margin-top: govuk-spacing(6);
9
10
  padding: 0;
10
- position: relative;
11
11
 
12
12
  &:first-of-type {
13
13
  margin-top: 0;
@@ -15,9 +15,9 @@
15
15
  }
16
16
 
17
17
  &__title {
18
- float: left;
19
- padding: 4px 100px 4px 0;
20
18
  width: 100%;
19
+ padding: 4px 100px 4px 0;
20
+ float: left;
21
21
 
22
22
  & + .govuk-form-group {
23
23
  clear: left;
@@ -26,8 +26,8 @@
26
26
 
27
27
  &__remove-button {
28
28
  position: absolute;
29
- right: 0;
30
29
  top: 0;
30
+ right: 0;
31
31
  width: auto;
32
32
  }
33
33
 
@@ -37,8 +37,10 @@
37
37
  }
38
38
 
39
39
  .moj-add-another__heading:focus {
40
- background-color: $govuk-focus-colour;
41
- color: $govuk-focus-text-colour;
42
- box-shadow: 0 -2px $govuk-focus-colour, 0 4px $govuk-focus-text-colour;
43
40
  outline: none;
41
+ color: $govuk-focus-text-colour;
42
+ background-color: $govuk-focus-colour;
43
+ box-shadow:
44
+ 0 -2px $govuk-focus-colour,
45
+ 0 4px $govuk-focus-text-colour;
44
46
  }
@@ -1,83 +1,104 @@
1
- MOJFrontend.AddAnother = function(container) {
2
- this.container = $(container);
1
+ MOJFrontend.AddAnother = function (container) {
2
+ this.container = $(container)
3
3
 
4
- if (this.container.data('moj-add-another-initialised')) {
5
- return
6
- }
4
+ if (this.container.data('moj-add-another-initialised')) {
5
+ return
6
+ }
7
7
 
8
- this.container.data('moj-add-another-initialised', true);
8
+ this.container.data('moj-add-another-initialised', true)
9
9
 
10
- this.container.on('click', '.moj-add-another__remove-button', $.proxy(this, 'onRemoveButtonClick'));
11
- this.container.on('click', '.moj-add-another__add-button', $.proxy(this, 'onAddButtonClick'));
12
- this.container.find('.moj-add-another__add-button, moj-add-another__remove-button').prop('type', 'button');
13
- };
10
+ this.container.on(
11
+ 'click',
12
+ '.moj-add-another__remove-button',
13
+ $.proxy(this, 'onRemoveButtonClick')
14
+ )
15
+ this.container.on(
16
+ 'click',
17
+ '.moj-add-another__add-button',
18
+ $.proxy(this, 'onAddButtonClick')
19
+ )
20
+ this.container
21
+ .find('.moj-add-another__add-button, moj-add-another__remove-button')
22
+ .prop('type', 'button')
23
+ }
14
24
 
15
- MOJFrontend.AddAnother.prototype.onAddButtonClick = function(e) {
16
- var item = this.getNewItem();
17
- this.updateAttributes(this.getItems().length, item);
18
- this.resetItem(item);
19
- var firstItem = this.getItems().first();
20
- if(!this.hasRemoveButton(firstItem)) {
21
- this.createRemoveButton(firstItem);
22
- }
23
- this.getItems().last().after(item);
24
- item.find('input, textarea, select').first().focus();
25
- };
25
+ MOJFrontend.AddAnother.prototype.onAddButtonClick = function (e) {
26
+ const item = this.getNewItem()
27
+ this.updateAttributes(this.getItems().length, item)
28
+ this.resetItem(item)
29
+ const firstItem = this.getItems().first()
30
+ if (!this.hasRemoveButton(firstItem)) {
31
+ this.createRemoveButton(firstItem)
32
+ }
33
+ this.getItems().last().after(item)
34
+ item.find('input, textarea, select').first().focus()
35
+ }
26
36
 
27
- MOJFrontend.AddAnother.prototype.hasRemoveButton = function(item) {
28
- return item.find('.moj-add-another__remove-button').length;
29
- };
37
+ MOJFrontend.AddAnother.prototype.hasRemoveButton = function (item) {
38
+ return item.find('.moj-add-another__remove-button').length
39
+ }
30
40
 
31
- MOJFrontend.AddAnother.prototype.getItems = function() {
32
- return this.container.find('.moj-add-another__item');
33
- };
41
+ MOJFrontend.AddAnother.prototype.getItems = function () {
42
+ return this.container.find('.moj-add-another__item')
43
+ }
34
44
 
35
- MOJFrontend.AddAnother.prototype.getNewItem = function() {
36
- var item = this.getItems().first().clone();
37
- if(!this.hasRemoveButton(item)) {
38
- this.createRemoveButton(item);
39
- }
40
- return item;
41
- };
45
+ MOJFrontend.AddAnother.prototype.getNewItem = function () {
46
+ const item = this.getItems().first().clone()
47
+ if (!this.hasRemoveButton(item)) {
48
+ this.createRemoveButton(item)
49
+ }
50
+ return item
51
+ }
42
52
 
43
- MOJFrontend.AddAnother.prototype.updateAttributes = function(index, item) {
44
- item.find('[data-name]').each(function(i, el) {
45
- var originalId = el.id
53
+ MOJFrontend.AddAnother.prototype.updateAttributes = function (index, item) {
54
+ item.find('[data-name]').each(function (i, el) {
55
+ const originalId = el.id
46
56
 
47
- el.name = $(el).attr('data-name').replace(/%index%/, index);
48
- el.id = $(el).attr('data-id').replace(/%index%/, index);
57
+ el.name = $(el)
58
+ .attr('data-name')
59
+ .replace(/%index%/, index)
60
+ el.id = $(el)
61
+ .attr('data-id')
62
+ .replace(/%index%/, index)
49
63
 
50
- var label = $(el).siblings('label')[0] || $(el).parents('label')[0] || item.find('[for="' + originalId + '"]')[0];
51
- label.htmlFor = el.id;
52
- });
53
- };
64
+ const label =
65
+ $(el).siblings('label')[0] ||
66
+ $(el).parents('label')[0] ||
67
+ item.find(`[for="${originalId}"]`)[0]
68
+ label.htmlFor = el.id
69
+ })
70
+ }
54
71
 
55
- MOJFrontend.AddAnother.prototype.createRemoveButton = function(item) {
56
- item.append('<button type="button" class="govuk-button govuk-button--secondary moj-add-another__remove-button">Remove</button>');
57
- };
72
+ MOJFrontend.AddAnother.prototype.createRemoveButton = function (item) {
73
+ item.append(
74
+ '<button type="button" class="govuk-button govuk-button--secondary moj-add-another__remove-button">Remove</button>'
75
+ )
76
+ }
58
77
 
59
- MOJFrontend.AddAnother.prototype.resetItem = function(item) {
60
- item.find('[data-name], [data-id]').each(function(index, el) {
61
- if(el.type == 'checkbox' || el.type == 'radio') {
62
- el.checked = false;
63
- } else {
64
- el.value = '';
65
- }
66
- });
67
- };
78
+ MOJFrontend.AddAnother.prototype.resetItem = function (item) {
79
+ item.find('[data-name], [data-id]').each(function (index, el) {
80
+ if (el.type === 'checkbox' || el.type === 'radio') {
81
+ el.checked = false
82
+ } else {
83
+ el.value = ''
84
+ }
85
+ })
86
+ }
68
87
 
69
- MOJFrontend.AddAnother.prototype.onRemoveButtonClick = function(e) {
70
- $(e.currentTarget).parents('.moj-add-another__item').remove();
71
- var items = this.getItems();
72
- if(items.length === 1) {
73
- items.find('.moj-add-another__remove-button').remove();
74
- }
75
- items.each($.proxy(function(index, el) {
76
- this.updateAttributes(index, $(el));
77
- }, this));
78
- this.focusHeading();
79
- };
88
+ MOJFrontend.AddAnother.prototype.onRemoveButtonClick = function (e) {
89
+ $(e.currentTarget).parents('.moj-add-another__item').remove()
90
+ const items = this.getItems()
91
+ if (items.length === 1) {
92
+ items.find('.moj-add-another__remove-button').remove()
93
+ }
94
+ items.each(
95
+ $.proxy(function (index, el) {
96
+ this.updateAttributes(index, $(el))
97
+ }, this)
98
+ )
99
+ this.focusHeading()
100
+ }
80
101
 
81
- MOJFrontend.AddAnother.prototype.focusHeading = function() {
82
- this.container.find('.moj-add-another__heading').focus();
83
- };
102
+ MOJFrontend.AddAnother.prototype.focusHeading = function () {
103
+ this.container.find('.moj-add-another__heading').get(0).focus()
104
+ }
@@ -0,0 +1,165 @@
1
+ /* eslint-disable no-new */
2
+
3
+ const {
4
+ getByLabelText,
5
+ getByRole,
6
+ queryByRole
7
+ } = require('@testing-library/dom')
8
+ const { userEvent } = require('@testing-library/user-event')
9
+
10
+ require('./add-another.js')
11
+
12
+ const user = userEvent.setup()
13
+
14
+ const createComponent = () => {
15
+ const html = `
16
+ <div data-module="moj-add-another">
17
+ <h2 class="govuk-heading-l moj-add-another__heading" tabindex="-1">Add a person</h2>
18
+ <form>
19
+ <fieldset class="govuk-fieldset moj-add-another__item">
20
+ <legend>Person</legend>
21
+ <div class="govuk-form-group">
22
+ <label for="person[0][first_name]">First name</label>
23
+ <input class="govuk-input" id="person[0][first_name]" name="person[0][first_name]" type="text" data-name="person[%index%][first_name]" data-id="person[%index%][first_name]">
24
+ </div>
25
+ <div class="govuk-form-group">
26
+ <label for="person[0][last_name]">Last name</label>
27
+ <input class="govuk-input" id="person[0][last_name]" name="person[0][last_name]" type="text" data-name="person[%index%][last_name]" data-id="person[%index%][last_name]">
28
+ </div>
29
+ </fieldset>
30
+ <button type="button" class="govuk-button moj-add-another__add-button">Add another person</button>
31
+ </form>
32
+ </div>`
33
+ document.body.innerHTML = html
34
+ const component = document.querySelector('[data-module="moj-add-another"]')
35
+ return component
36
+ }
37
+
38
+ describe('Add Another component', () => {
39
+ let component
40
+ let addButton
41
+
42
+ beforeEach(() => {
43
+ component = createComponent()
44
+ new MOJFrontend.AddAnother(component)
45
+ addButton = getByRole(component, 'button', { name: 'Add another person' })
46
+ })
47
+
48
+ afterEach(() => {
49
+ document.body.innerHTML = ''
50
+ })
51
+
52
+ test('adds a new item when "Add another person" is clicked', async () => {
53
+ const initialItems = component.querySelectorAll('.moj-add-another__item')
54
+ expect(initialItems).toHaveLength(1)
55
+
56
+ await user.click(addButton)
57
+
58
+ const updatedItems = component.querySelectorAll('.moj-add-another__item')
59
+ expect(updatedItems).toHaveLength(2)
60
+
61
+ const secondItemFirstName = updatedItems[1].querySelector(
62
+ '[name="person[1][first_name]"]'
63
+ )
64
+ expect(secondItemFirstName).toBeInTheDocument()
65
+ expect(secondItemFirstName.value).toBe('')
66
+ })
67
+
68
+ test('adds a remove button to new items', async () => {
69
+ await user.click(addButton)
70
+
71
+ const firstItem = component.querySelectorAll('.moj-add-another__item')[0]
72
+ const secondItem = component.querySelectorAll('.moj-add-another__item')[1]
73
+ const firstItemRemoveButton = getByRole(firstItem, 'button', {
74
+ name: 'Remove'
75
+ })
76
+ const secondItemRemoveButton = getByRole(secondItem, 'button', {
77
+ name: 'Remove'
78
+ })
79
+
80
+ expect(firstItemRemoveButton).toBeInTheDocument()
81
+ expect(secondItemRemoveButton).toBeInTheDocument()
82
+ })
83
+
84
+ test('removes an item when the "Remove" button is clicked', async () => {
85
+ await user.click(addButton)
86
+
87
+ const secondItem = component.querySelectorAll('.moj-add-another__item')[1]
88
+ const removeButton = getByRole(secondItem, 'button', { name: 'Remove' })
89
+
90
+ await user.click(removeButton)
91
+
92
+ const remainingItems = component.querySelectorAll('.moj-add-another__item')
93
+
94
+ expect(remainingItems).toHaveLength(1)
95
+ expect(
96
+ queryByRole(component, 'button', { name: 'Remove' })
97
+ ).not.toBeInTheDocument()
98
+ })
99
+
100
+ test('new item inputs have no value', async () => {
101
+ await user.click(addButton)
102
+
103
+ const secondItem = component.querySelectorAll('.moj-add-another__item')[1]
104
+ const firstNameInput = getByLabelText(secondItem, 'First name')
105
+ const lastNameInput = getByLabelText(secondItem, 'Last name')
106
+
107
+ expect(firstNameInput.value).toBe('')
108
+ expect(lastNameInput.value).toBe('')
109
+ })
110
+
111
+ test('resets form values in a new item', async () => {
112
+ await user.click(addButton)
113
+
114
+ const firstItem = component.querySelectorAll('.moj-add-another__item')[0]
115
+ const firstItemFirstNameInput = getByLabelText(firstItem, 'First name')
116
+ const firstItemLastNameInput = getByLabelText(firstItem, 'Last name')
117
+
118
+ await user.type(firstItemFirstNameInput, 'Steve')
119
+ await user.type(firstItemLastNameInput, 'Jobs')
120
+
121
+ expect(firstItemFirstNameInput.value).toBe('Steve')
122
+ expect(firstItemLastNameInput.value).toBe('Jobs')
123
+
124
+ const secondItem = component.querySelectorAll('.moj-add-another__item')[1]
125
+ const secondItemFirstNameInput = getByLabelText(secondItem, 'First name')
126
+ const secondItemLastNameInput = getByLabelText(secondItem, 'Last name')
127
+
128
+ expect(secondItemFirstNameInput.value).toBe('')
129
+ expect(secondItemLastNameInput.value).toBe('')
130
+ })
131
+
132
+ test('focuses the heading after removing an item', async () => {
133
+ await user.click(addButton)
134
+
135
+ const heading = queryByRole(component, 'heading', { level: 2 })
136
+ const secondItem = component.querySelectorAll('.moj-add-another__item')[1]
137
+ const removeButton = getByRole(secondItem, 'button', { name: 'Remove' })
138
+
139
+ await user.click(removeButton)
140
+
141
+ expect(heading).toHaveFocus()
142
+ })
143
+
144
+ test('updates attributes correctly after removing an item', async () => {
145
+ await user.click(addButton)
146
+ await user.click(addButton)
147
+
148
+ const secondItem = component.querySelectorAll('.moj-add-another__item')[1]
149
+ const removeButton = getByRole(secondItem, 'button', { name: 'Remove' })
150
+
151
+ await user.click(removeButton)
152
+
153
+ const remainingItems = component.querySelectorAll('.moj-add-another__item')
154
+ remainingItems.forEach((item, index) => {
155
+ const firstNameInput = item.querySelector(
156
+ `[name="person[${index}][first_name]"]`
157
+ )
158
+ const lastNameInput = item.querySelector(
159
+ `[name="person[${index}][last_name]"]`
160
+ )
161
+ expect(firstNameInput).toBeInTheDocument()
162
+ expect(lastNameInput).toBeInTheDocument()
163
+ })
164
+ })
165
+ })
File without changes
@@ -0,0 +1,142 @@
1
+ .moj-alert {
2
+ @include govuk-font($size: false);
3
+ display: -ms-grid;
4
+ display: grid;
5
+ margin-bottom: govuk-spacing(6);
6
+ padding: govuk-spacing(2);
7
+ border: 5px solid transparent;
8
+ background: govuk-colour("white");
9
+ -ms-grid-columns: min-content fit-content(960px);
10
+ grid-template-columns: min-content fit-content(960px);
11
+
12
+ gap: govuk-spacing(2);
13
+
14
+ &:focus {
15
+ outline: $govuk-focus-width solid $govuk-focus-colour;
16
+ }
17
+ }
18
+
19
+ .moj-alert[data-dismissible] {
20
+ @include govuk-media-query($from: tablet) {
21
+ grid-template-columns: min-content fit-content(920px) auto;
22
+ }
23
+ }
24
+
25
+ .moj-alert__icon {
26
+ display: block;
27
+ width: govuk-px-to-rem(30px);
28
+ height: govuk-px-to-rem(30px);
29
+ fill: currentcolor;
30
+ }
31
+
32
+ .moj-alert__content {
33
+ @include govuk-font-size($size: 19);
34
+ display: block;
35
+ // Padding to align text with icon
36
+ padding-top: govuk-px-to-rem(5px);
37
+ overflow: hidden;
38
+ color: govuk-colour("black");
39
+
40
+ @include govuk-media-query($from: tablet) {
41
+ padding-top: govuk-px-to-rem(2px);
42
+ }
43
+ }
44
+
45
+ .moj-alert__action {
46
+ grid-column-start: 2;
47
+ grid-column-end: -1;
48
+
49
+ @include govuk-media-query($from: tablet) {
50
+ grid-column-start: 3;
51
+ justify-self: right;
52
+ }
53
+ }
54
+
55
+ .moj-alert__dismiss {
56
+ // Give the button link styling
57
+ margin-bottom: 0;
58
+ padding: 0;
59
+ border: none;
60
+ color: unset;
61
+ background-color: transparent;
62
+ -webkit-appearance: none;
63
+ cursor: pointer;
64
+ appearance: none;
65
+ @include govuk-font-size($size: 19);
66
+ @include govuk-link-common;
67
+ @include govuk-link-style-default;
68
+ @include govuk-link-print-friendly;
69
+ }
70
+
71
+ .moj-alert__content h2,
72
+ .moj-alert__content h3,
73
+ .moj-alert__content h4 {
74
+ margin-bottom: 2px;
75
+ line-height: 30px;
76
+ }
77
+
78
+ .moj-alert--with-heading .moj-alert__content {
79
+ // No padding needed when there is a heading
80
+ padding-top: 0;
81
+
82
+ @include govuk-media-query($from: tablet) {
83
+ padding-top: 0;
84
+ }
85
+ }
86
+
87
+ .moj-alert__content *:last-child {
88
+ margin-bottom: 0;
89
+ }
90
+
91
+ /* Style variants
92
+ ========================================================================== */
93
+ .moj-alert--information {
94
+ border-color: $govuk-brand-colour;
95
+ color: $govuk-brand-colour;
96
+
97
+ .moj-alert__dismiss,
98
+ .moj-alert__content a {
99
+ @include govuk-link-common;
100
+ @include govuk-link-style-default;
101
+ }
102
+ }
103
+
104
+ .moj-alert--success {
105
+ border-color: govuk-colour("green");
106
+ color: govuk-colour("green");
107
+
108
+ .moj-alert__dismiss,
109
+ .moj-alert__content a,
110
+ .moj-alert__content .govuk-link {
111
+ @include govuk-link-common;
112
+ @include govuk-link-style-success;
113
+ }
114
+ }
115
+
116
+ .moj-alert--warning {
117
+ border-color: $moj-warning-colour;
118
+ color: $moj-warning-colour;
119
+
120
+ .moj-alert__dismiss {
121
+ color: $moj-warning-link-colour;
122
+ }
123
+
124
+ .moj-alert__dismiss,
125
+ .moj-alert__content a,
126
+ .moj-alert__content .govuk-link {
127
+ @include govuk-link-common;
128
+ @include moj-link-style-warning;
129
+ }
130
+ }
131
+
132
+ .moj-alert--error {
133
+ border-color: govuk-colour("red");
134
+ color: govuk-colour("red");
135
+
136
+ .moj-alert__dismiss,
137
+ .moj-alert__content a,
138
+ .moj-alert__content .govuk-link {
139
+ @include govuk-link-common;
140
+ @include govuk-link-style-error;
141
+ }
142
+ }