@comicrelief/component-library 8.35.1 → 8.36.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 (32) hide show
  1. package/dist/components/Atoms/Input/Input.js +18 -7
  2. package/dist/components/Atoms/Input/Input.md +19 -0
  3. package/dist/components/Atoms/Input/input.test.js +0 -2
  4. package/dist/components/Atoms/TextArea/TextArea.js +1 -0
  5. package/dist/components/Atoms/TextArea/TextArea.test.js +1 -0
  6. package/dist/components/Atoms/TextInputWithDropdown/__snapshots__/TextInputWithDropdown.test.js.snap +0 -3
  7. package/dist/components/Molecules/SchoolLookup/__snapshots__/SchoolLookup.test.js.snap +0 -1
  8. package/dist/components/Molecules/SearchInput/SearchInput.test.js +0 -1
  9. package/dist/components/Molecules/Typeahead/__snapshots__/Typeahead.test.js.snap +0 -1
  10. package/dist/components/Organisms/Donate/__snapshots__/Donate.test.js.snap +0 -7
  11. package/dist/components/Organisms/EmailSignUp/__snapshots__/EmailSignUp.test.js.snap +0 -3
  12. package/dist/components/Organisms/Membership/Membership.test.js +0 -4
  13. package/package.json +1 -1
  14. package/playwright/components/atoms/input.spec.js +7 -14
  15. package/playwright/components/atoms/textArea.spec.js +4 -6
  16. package/playwright/components/molecules/schoolLookup.spec.js +1 -2
  17. package/playwright/components/molecules/searchInput.spec.js +1 -2
  18. package/playwright/components/molecules/simpleSchoolLookUp.spec.js +1 -2
  19. package/playwright/components/molecules/typeahead.spec.js +1 -2
  20. package/playwright/components/organisms/emailSignUpForm.spec.js +3 -3
  21. package/src/components/Atoms/Input/Input.js +17 -4
  22. package/src/components/Atoms/Input/Input.md +19 -0
  23. package/src/components/Atoms/Input/input.test.js +0 -2
  24. package/src/components/Atoms/TextArea/TextArea.js +1 -0
  25. package/src/components/Atoms/TextArea/TextArea.test.js +1 -0
  26. package/src/components/Atoms/TextInputWithDropdown/__snapshots__/TextInputWithDropdown.test.js.snap +0 -3
  27. package/src/components/Molecules/SchoolLookup/__snapshots__/SchoolLookup.test.js.snap +0 -1
  28. package/src/components/Molecules/SearchInput/SearchInput.test.js +0 -1
  29. package/src/components/Molecules/Typeahead/__snapshots__/Typeahead.test.js.snap +0 -1
  30. package/src/components/Organisms/Donate/__snapshots__/Donate.test.js.snap +0 -7
  31. package/src/components/Organisms/EmailSignUp/__snapshots__/EmailSignUp.test.js.snap +0 -3
  32. package/src/components/Organisms/Membership/Membership.test.js +0 -4
@@ -70,14 +70,22 @@ const Prefix = _styledComponents.default.div.withConfig({
70
70
  } = _ref6;
71
71
  return theme.color('grey_dark');
72
72
  });
73
- const Input = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
73
+ const DescriptionWrapper = _styledComponents.default.div.withConfig({
74
+ displayName: "Input__DescriptionWrapper",
75
+ componentId: "sc-bcqy1o-5"
76
+ })(["margin-bottom:0.5rem;*{font-size:", ";}"], _ref7 => {
77
+ let {
78
+ theme
79
+ } = _ref7;
80
+ return theme.fontSize('xs');
81
+ });
82
+ const Input = /*#__PURE__*/_react.default.forwardRef((_ref8, ref) => {
74
83
  let {
75
84
  errorMsg = '',
76
85
  id,
77
86
  label,
78
87
  showLabel = true,
79
88
  type,
80
- hasAria = true,
81
89
  className = '',
82
90
  placeholder = '',
83
91
  labelProps = {},
@@ -85,8 +93,9 @@ const Input = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
85
93
  optional = null,
86
94
  maxPxWidthMediumBreakpoint,
87
95
  maxPxWidthLargeBreakpoint,
96
+ description = null,
88
97
  ...rest
89
- } = _ref7;
98
+ } = _ref8;
90
99
  return /*#__PURE__*/_react.default.createElement(_Label.default, Object.assign({
91
100
  className: className,
92
101
  htmlFor: id,
@@ -94,7 +103,9 @@ const Input = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
94
103
  hideLabel: !showLabel,
95
104
  errorMsg: errorMsg,
96
105
  optional: optional
97
- }, labelProps), /*#__PURE__*/_react.default.createElement(InputWrapper, {
106
+ }, labelProps), description && /*#__PURE__*/_react.default.createElement(DescriptionWrapper, {
107
+ id: `${id}-description`
108
+ }, description), /*#__PURE__*/_react.default.createElement(InputWrapper, {
98
109
  error: Boolean(errorMsg)
99
110
  }, prefix && /*#__PURE__*/_react.default.createElement(Prefix, {
100
111
  length: prefix.length
@@ -107,7 +118,7 @@ const Input = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
107
118
  type: type,
108
119
  placeholder: placeholder,
109
120
  error: Boolean(errorMsg),
110
- "aria-describedby": hasAria ? id : undefined,
121
+ "aria-describedby": description ? `${id}-description` : undefined,
111
122
  ref: ref,
112
123
  prefixLength: prefix.length,
113
124
  required: optional === false
@@ -126,7 +137,6 @@ Input.propTypes = {
126
137
  // don't want to display a label, it should be present for screen readers).
127
138
  // todo: convert this to 'hideLabel' to make it consistent with other components
128
139
  showLabel: _propTypes.default.bool,
129
- hasAria: _propTypes.default.bool,
130
140
  id: _propTypes.default.string.isRequired,
131
141
  /** text, email, number, date, search, tel, url, password */
132
142
  type: _propTypes.default.string.isRequired,
@@ -137,6 +147,7 @@ Input.propTypes = {
137
147
  prefix: _propTypes.default.string,
138
148
  optional: _propTypes.default.bool,
139
149
  maxPxWidthMediumBreakpoint: _propTypes.default.number,
140
- maxPxWidthLargeBreakpoint: _propTypes.default.number
150
+ maxPxWidthLargeBreakpoint: _propTypes.default.number,
151
+ description: _propTypes.default.node
141
152
  };
142
153
  var _default = exports.default = Input;
@@ -130,3 +130,22 @@ const ItalicText = styled(Text).attrs({weight: 'normal'})`
130
130
  id="input-example-8"
131
131
  />
132
132
  ```
133
+
134
+ ```js
135
+ import Text from '../../Atoms/Text/Text';
136
+
137
+ const exampleDescription = (
138
+ <Text>Here's a description with some <b>formatting</b></Text>
139
+ );
140
+
141
+ <>
142
+ <h4>Input with Description:</h4>
143
+ <Input
144
+ placeholder="I have a description"
145
+ type="text"
146
+ label="My Great Input"
147
+ id="input-example-9"
148
+ description={exampleDescription}
149
+ />
150
+ </>
151
+ ```
@@ -117,7 +117,6 @@ it('renders correctly', () => {
117
117
  className="c4"
118
118
  >
119
119
  <input
120
- aria-describedby="Accessibility info go here"
121
120
  className="c5"
122
121
  id="Accessibility info go here"
123
122
  name="fullname"
@@ -249,7 +248,6 @@ it('renders with responsive max widths correctly', () => {
249
248
  className="c4"
250
249
  >
251
250
  <input
252
- aria-describedby="input-example-7"
253
251
  className="c5"
254
252
  id="input-example-7"
255
253
  name="responsive-width"
@@ -43,6 +43,7 @@ const TextArea = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
43
43
  placeholder: placeholder,
44
44
  rows: rows,
45
45
  error: !!errorMsg,
46
+ id: id,
46
47
  "aria-describedby": id,
47
48
  ref: ref
48
49
  })), errorMsg && /*#__PURE__*/_react.default.createElement(_ErrorText.default, {
@@ -97,6 +97,7 @@ it('renders correctly', () => {
97
97
  <textarea
98
98
  aria-describedby="Please leave your comment here"
99
99
  className="c3"
100
+ id="Please leave your comment here"
100
101
  name="description"
101
102
  placeholder="This is text area"
102
103
  rows={5}
@@ -111,7 +111,6 @@ exports[`renders correctly with no value and no options 1`] = `
111
111
  className="c5"
112
112
  >
113
113
  <input
114
- aria-describedby="text-input-with-dropdown"
115
114
  autoComplete="off"
116
115
  className="c6"
117
116
  id="text-input-with-dropdown"
@@ -241,7 +240,6 @@ exports[`renders correctly with value and no options 1`] = `
241
240
  className="c5"
242
241
  >
243
242
  <input
244
- aria-describedby="text-input-with-dropdown"
245
243
  autoComplete="off"
246
244
  className="c6"
247
245
  id="text-input-with-dropdown"
@@ -410,7 +408,6 @@ exports[`renders correctly with value and options 1`] = `
410
408
  className="c5"
411
409
  >
412
410
  <input
413
- aria-describedby="text-input-with-dropdown"
414
411
  autoComplete="off"
415
412
  className="c6"
416
413
  id="text-input-with-dropdown"
@@ -111,7 +111,6 @@ exports[`renders correctly 1`] = `
111
111
  className="c5"
112
112
  >
113
113
  <input
114
- aria-describedby="school-lookup"
115
114
  autoComplete="off"
116
115
  className="c6"
117
116
  defaultValue=""
@@ -182,7 +182,6 @@ it('renders correctly', () => {
182
182
  className="c9"
183
183
  >
184
184
  <input
185
- aria-describedby="search"
186
185
  className="c10"
187
186
  id="search"
188
187
  name="search"
@@ -111,7 +111,6 @@ exports[`renders correctly 1`] = `
111
111
  className="c5"
112
112
  >
113
113
  <input
114
- aria-describedby="typeahead-test"
115
114
  autoComplete="off"
116
115
  className="c6"
117
116
  defaultValue=""
@@ -647,7 +647,6 @@ exports[`"Single Giving, No Money Buys, with overridden manual input value" rend
647
647
  className="c23"
648
648
  >
649
649
  <input
650
- aria-describedby="mship-4--MoneyBuy-userInput"
651
650
  aria-label="Input a different amount"
652
651
  className="c24"
653
652
  id="mship-4--MoneyBuy-userInput"
@@ -1314,7 +1313,6 @@ exports[`Monthly donation renders correctly 1`] = `
1314
1313
  className="c24"
1315
1314
  >
1316
1315
  <input
1317
- aria-describedby="mship-1--MoneyBuy-userInput"
1318
1316
  aria-label="Input a different amount"
1319
1317
  className="c25"
1320
1318
  id="mship-1--MoneyBuy-userInput"
@@ -1949,7 +1947,6 @@ exports[`Single donation renders correctly 1`] = `
1949
1947
  className="c17"
1950
1948
  >
1951
1949
  <input
1952
- aria-describedby="mship-1--moneyBuy-box1"
1953
1950
  aria-label="£10"
1954
1951
  className="c18"
1955
1952
  id="mship-1--moneyBuy-box1"
@@ -1987,7 +1984,6 @@ exports[`Single donation renders correctly 1`] = `
1987
1984
  className="c17"
1988
1985
  >
1989
1986
  <input
1990
- aria-describedby="mship-1--moneyBuy-box2"
1991
1987
  aria-label="£20"
1992
1988
  className="c18"
1993
1989
  id="mship-1--moneyBuy-box2"
@@ -2025,7 +2021,6 @@ exports[`Single donation renders correctly 1`] = `
2025
2021
  className="c17"
2026
2022
  >
2027
2023
  <input
2028
- aria-describedby="mship-1--moneyBuy-box3"
2029
2024
  aria-label="£30"
2030
2025
  className="c18"
2031
2026
  id="mship-1--moneyBuy-box3"
@@ -2074,7 +2069,6 @@ exports[`Single donation renders correctly 1`] = `
2074
2069
  className="c17"
2075
2070
  >
2076
2071
  <input
2077
- aria-describedby="mship-1--MoneyBuy-userInput"
2078
2072
  aria-label="Input a different amount"
2079
2073
  className="c18"
2080
2074
  id="mship-1--MoneyBuy-userInput"
@@ -2571,7 +2565,6 @@ exports[`Single donation with no Money Buys renders correctly 1`] = `
2571
2565
  className="c17"
2572
2566
  >
2573
2567
  <input
2574
- aria-describedby="mship-1--MoneyBuy-userInput"
2575
2568
  aria-label="Input a different amount"
2576
2569
  className="c18"
2577
2570
  id="mship-1--MoneyBuy-userInput"
@@ -321,7 +321,6 @@ exports[`renders correctly 1`] = `
321
321
  className="c12"
322
322
  >
323
323
  <input
324
- aria-describedby="first-name"
325
324
  aria-required={true}
326
325
  className="c13"
327
326
  id="first-name"
@@ -359,7 +358,6 @@ exports[`renders correctly 1`] = `
359
358
  className="c12"
360
359
  >
361
360
  <input
362
- aria-describedby="last-name"
363
361
  aria-required={true}
364
362
  className="c13"
365
363
  id="last-name"
@@ -398,7 +396,6 @@ exports[`renders correctly 1`] = `
398
396
  className="c12"
399
397
  >
400
398
  <input
401
- aria-describedby="email"
402
399
  aria-required={true}
403
400
  className="c13"
404
401
  id="email"
@@ -487,7 +487,6 @@ it('renders correctly', () => {
487
487
  className="c18"
488
488
  >
489
489
  <input
490
- aria-describedby="mship-1--moneyBuy-box1"
491
490
  aria-label="£5"
492
491
  className="c19"
493
492
  id="mship-1--moneyBuy-box1"
@@ -525,7 +524,6 @@ it('renders correctly', () => {
525
524
  className="c18"
526
525
  >
527
526
  <input
528
- aria-describedby="mship-1--moneyBuy-box2"
529
527
  aria-label="£10"
530
528
  className="c19"
531
529
  id="mship-1--moneyBuy-box2"
@@ -563,7 +561,6 @@ it('renders correctly', () => {
563
561
  className="c18"
564
562
  >
565
563
  <input
566
- aria-describedby="mship-1--moneyBuy-box3"
567
564
  aria-label="£20"
568
565
  className="c19"
569
566
  id="mship-1--moneyBuy-box3"
@@ -612,7 +609,6 @@ it('renders correctly', () => {
612
609
  className="c18"
613
610
  >
614
611
  <input
615
- aria-describedby="mship-1--MoneyBuy-userInput"
616
612
  aria-label="Input a different amount"
617
613
  className="c19"
618
614
  id="mship-1--MoneyBuy-userInput"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comicrelief/component-library",
3
3
  "author": "Comic Relief Engineering Team",
4
- "version": "8.35.1",
4
+ "version": "8.36.0",
5
5
  "main": "dist/index.js",
6
6
  "license": "ISC",
7
7
  "jest": {
@@ -2,14 +2,13 @@ const { test, expect } = require('@playwright/test');
2
2
 
3
3
  test.describe('input component', () => {
4
4
  test('input required with label and hint', async ({ page }) => {
5
-
6
5
  await page.goto('/#input');
7
6
 
8
7
  // input required with label and hint
9
8
  const specificElement = page.locator('input#input-example-1');
10
9
  await expect(specificElement).toBeVisible();
11
10
 
12
- const inputElement = page.locator('[aria-describedby="input-example-1"]');
11
+ const inputElement = page.locator('#input-example-1');
13
12
 
14
13
  // Get the placeholder attribute
15
14
  const placeholderText = await inputElement.getAttribute('placeholder');
@@ -23,14 +22,13 @@ test.describe('input component', () => {
23
22
  });
24
23
 
25
24
  test('input with error message', async ({ page }) => {
26
-
27
25
  await page.goto('/#input');
28
26
 
29
27
  // input required with label and hint
30
28
  const specificElement = page.locator('input#input-example-2');
31
29
  await expect(specificElement).toBeVisible();
32
30
 
33
- const inputElement = page.locator('[aria-describedby="input-example-2"]');
31
+ const inputElement = page.locator('#input-example-2');
34
32
 
35
33
  // Get the placeholder attribute
36
34
  const placeholderText = await inputElement.getAttribute('placeholder');
@@ -47,14 +45,13 @@ test.describe('input component', () => {
47
45
  });
48
46
 
49
47
  test('Simple input (optional)', async ({ page }) => {
50
-
51
48
  await page.goto('/#input');
52
49
 
53
50
  // input required with label and hint
54
51
  const specificElement = page.locator('input#input-example-3');
55
52
  await expect(specificElement).toBeVisible();
56
53
 
57
- const inputElement = page.locator('[aria-describedby="input-example-3"]');
54
+ const inputElement = page.locator('#input-example-3');
58
55
 
59
56
  // Get the 'name' attribute
60
57
  const nameAttribute = await inputElement.getAttribute('name');
@@ -68,14 +65,13 @@ test.describe('input component', () => {
68
65
  });
69
66
 
70
67
  test('Simple input (required)', async ({ page }) => {
71
-
72
68
  await page.goto('/#input');
73
69
 
74
70
  // input required with label and hint
75
71
  const specificElement = page.locator('input#input-example-4');
76
72
  await expect(specificElement).toBeVisible();
77
73
 
78
- const inputElement = page.locator('[aria-describedby="input-example-4"]');
74
+ const inputElement = page.locator('#input-example-4');
79
75
 
80
76
  // Get the 'name' attribute
81
77
  const nameAttribute = await inputElement.getAttribute('name');
@@ -89,14 +85,13 @@ test.describe('input component', () => {
89
85
  });
90
86
 
91
87
  test('Input Label with markup', async ({ page }) => {
92
-
93
88
  await page.goto('/#input');
94
89
 
95
90
  // input required with label and hint
96
91
  const specificElement = page.locator('input#input-example-5');
97
92
  await expect(specificElement).toBeVisible();
98
93
 
99
- const inputElement = page.locator('[aria-describedby="input-example-5"]');
94
+ const inputElement = page.locator('#input-example-5');
100
95
 
101
96
  // Get the 'name' attribute
102
97
  const nameAttribute = await inputElement.getAttribute('name');
@@ -110,14 +105,13 @@ test.describe('input component', () => {
110
105
  });
111
106
 
112
107
  test('Input label as React element', async ({ page }) => {
113
-
114
108
  await page.goto('/#input');
115
109
 
116
110
  // input required with label and hint
117
111
  const specificElement = page.locator('input#input-example-6');
118
112
  await expect(specificElement).toBeVisible();
119
113
 
120
- const inputElement = page.locator('[aria-describedby="input-example-6"]');
114
+ const inputElement = page.locator('#input-example-6');
121
115
 
122
116
  // Get the 'name' attribute
123
117
  const nameAttribute = await inputElement.getAttribute('name');
@@ -131,14 +125,13 @@ test.describe('input component', () => {
131
125
  });
132
126
 
133
127
  test('Input with prefix', async ({ page }) => {
134
-
135
128
  await page.goto('/#input');
136
129
 
137
130
  // input required with label and hint
138
131
  const specificElement = page.locator('#price');
139
132
  await expect(specificElement).toBeVisible();
140
133
 
141
- const inputElement = page.locator('[aria-describedby="price"]');
134
+ const inputElement = page.locator('#price');
142
135
 
143
136
  // Get the 'name' attribute
144
137
  const nameAttribute = await inputElement.getAttribute('name');
@@ -2,14 +2,13 @@ const { test, expect } = require('@playwright/test');
2
2
 
3
3
  test.describe('text area component', () => {
4
4
  test('text area - Long copy/Message field', async ({ page }) => {
5
-
6
5
  await page.goto('/#textarea');
7
6
 
8
7
  // input required with label and hint
9
8
  const specificElement = page.locator('[data-testid="TextArea-example-1"]');
10
9
  await expect(specificElement).toBeVisible();
11
10
 
12
- const inputElement = page.locator('[aria-describedby="textarea-test"]');
11
+ const inputElement = page.locator('#textarea-test');
13
12
 
14
13
  // Get the placeholder attribute
15
14
  const placeholderText = await inputElement.getAttribute('placeholder');
@@ -17,22 +16,21 @@ test.describe('text area component', () => {
17
16
  // Verify the placeholder text
18
17
  expect(placeholderText).toBe('This is a placeholder');
19
18
 
20
- await page.locator('[aria-describedby="textarea-test"]').type('This is test text for textarea field');
19
+ await page.locator('#textarea-test').type('This is test text for textarea field');
21
20
 
22
21
  await page.close();
23
22
  });
24
23
 
25
24
  test('text area - Long copy/Message field with error message', async ({ page }) => {
26
-
27
25
  await page.goto('/#textarea');
28
26
 
29
27
  const specificElement = page.locator('[data-testid="TextArea-example-1"]');
30
28
  await expect(specificElement).toBeVisible();
31
29
 
32
- await page.locator('[aria-describedby="textarea-test-2"]').type('This is test text for textarea field');
30
+ await page.locator('#textarea-test-2').type('This is test text for textarea field');
33
31
 
34
32
  // error message should be visible
35
- await expect(page.locator('[aria-describedby="textarea-test-2"] ~ span[data-test="error-message"]')).toBeVisible();
33
+ await expect(page.locator('#textarea-test-2 ~ span[data-test="error-message"]')).toBeVisible();
36
34
 
37
35
  await page.close();
38
36
  });
@@ -2,14 +2,13 @@ const { test, expect } = require('@playwright/test');
2
2
 
3
3
  test.describe('school lookup component', () => {
4
4
  test('school lookup', async ({ page, context }) => {
5
-
6
5
  await page.goto('/#schoollookup');
7
6
 
8
7
  // school lookup elements should be visible
9
8
  await expect(page.locator('[data-testid="SchoolLookup-example-1"]')).toBeVisible();
10
9
  await expect(page.locator('[data-preview="SchoolLookup"]')).toBeVisible();
11
10
 
12
- const inputElement = page.locator('[aria-describedby="school-lookup"]');
11
+ const inputElement = page.locator('#school-lookup');
13
12
 
14
13
  // Get the 'placeholder' attribute
15
14
  const placeholderAttribute = await inputElement.getAttribute('placeholder');
@@ -2,14 +2,13 @@ const { test, expect } = require('@playwright/test');
2
2
 
3
3
  test.describe('search input component', () => {
4
4
  test('search input', async ({ page, context }) => {
5
-
6
5
  await page.goto('/#searchinput');
7
6
 
8
7
  // accordian elements should be visible
9
8
  await expect(page.locator('[data-testid="SearchInput-example-1"]')).toBeVisible();
10
9
  await expect(page.locator('[data-preview="SearchInput"]')).toBeVisible();
11
10
 
12
- const inputElement = page.locator('[aria-describedby="school-lookup"]');
11
+ const inputElement = page.locator('#school-lookup');
13
12
 
14
13
  // Get the 'placeholder' attribute
15
14
  const placeholderAttribute = await inputElement.getAttribute('placeholder');
@@ -2,14 +2,13 @@ const { test, expect } = require('@playwright/test');
2
2
 
3
3
  test.describe('simple school lookup component', () => {
4
4
  test('simple school lookup', async ({ page, context }) => {
5
-
6
5
  await page.goto('/#simpleschoollookup');
7
6
 
8
7
  // simple school lookup elements should be visible
9
8
  await expect(page.locator('[data-testid="SimpleSchoolLookup-example-0"]')).toBeVisible();
10
9
  await expect(page.locator('[data-preview="SimpleSchoolLookup"]')).toBeVisible();
11
10
 
12
- const inputElement = page.locator('[aria-describedby="school_lookup"]');
11
+ const inputElement = page.locator('#school_lookup');
13
12
 
14
13
  // Get the 'placeholder' attribute
15
14
  const placeholderAttribute = await inputElement.getAttribute('placeholder');
@@ -2,14 +2,13 @@ const { test, expect } = require('@playwright/test');
2
2
 
3
3
  test.describe('typeahead component', () => {
4
4
  test('typeahead', async ({ page }) => {
5
-
6
5
  await page.goto('/#typeahead');
7
6
 
8
7
  await expect(page.locator('[data-testid="Typeahead-example-1"]')).toBeVisible();
9
8
 
10
9
  await expect(page.locator('[data-preview="Typeahead"]')).toBeVisible();
11
10
 
12
- const inputElement = page.locator('[aria-describedby="typeahead-test"]');
11
+ const inputElement = page.locator('#typeahead-test');
13
12
 
14
13
  // Get the 'placeholder' attribute
15
14
  const placeholderAttribute = await inputElement.getAttribute('placeholder');
@@ -10,7 +10,7 @@ test.describe('Email Signup Form component', () => {
10
10
  await expect(page.locator('[data-testid="EmailSignUpForm-example-1"] #email')).toBeVisible();
11
11
 
12
12
  // firstname field
13
- const firstnamePlaceholder = page.locator('[aria-describedby="first-name"]');
13
+ const firstnamePlaceholder = page.locator('#first-name');
14
14
 
15
15
  // Get the 'placeholder' attribute
16
16
  const placeholderAttribute = await firstnamePlaceholder.getAttribute('placeholder');
@@ -37,7 +37,7 @@ test.describe('Email Signup Form component', () => {
37
37
  await page.locator('[data-testid="EmailSignUpForm-example-1"] #first-name').fill('');
38
38
 
39
39
  // lastname
40
- const lastnamePlaceholder = page.locator('[aria-describedby="last-name"]');
40
+ const lastnamePlaceholder = page.locator('#last-name');
41
41
 
42
42
  // Get the 'placeholder' attribute
43
43
  const lastnamePlaceholderAttribute = await lastnamePlaceholder.getAttribute('placeholder');
@@ -64,7 +64,7 @@ test.describe('Email Signup Form component', () => {
64
64
  await page.locator('[data-testid="EmailSignUpForm-example-1"] #last-name').fill('');
65
65
 
66
66
  // email
67
- const emailPlaceholder = page.locator('[aria-describedby="email"]');
67
+ const emailPlaceholder = page.locator('#email');
68
68
 
69
69
  // Get the 'placeholder' attribute
70
70
  const emailPlaceholderAttribute = await emailPlaceholder.getAttribute('placeholder');
@@ -82,6 +82,14 @@ const Prefix = styled.div`
82
82
  margin-left: 2px; // Just doesn't look quite right without this.
83
83
  `;
84
84
 
85
+ const DescriptionWrapper = styled.div`
86
+ margin-bottom: 0.5rem;
87
+
88
+ * {
89
+ font-size: ${({ theme }) => theme.fontSize('xs')};
90
+ }
91
+ `;
92
+
85
93
  const Input = React.forwardRef(
86
94
  (
87
95
  {
@@ -90,7 +98,6 @@ const Input = React.forwardRef(
90
98
  label,
91
99
  showLabel = true,
92
100
  type,
93
- hasAria = true,
94
101
  className = '',
95
102
  placeholder = '',
96
103
  labelProps = {},
@@ -98,6 +105,7 @@ const Input = React.forwardRef(
98
105
  optional = null,
99
106
  maxPxWidthMediumBreakpoint,
100
107
  maxPxWidthLargeBreakpoint,
108
+ description = null,
101
109
  ...rest
102
110
  },
103
111
  ref
@@ -111,6 +119,11 @@ const Input = React.forwardRef(
111
119
  optional={optional}
112
120
  {...labelProps}
113
121
  >
122
+ {description && (
123
+ <DescriptionWrapper id={`${id}-description`}>
124
+ {description}
125
+ </DescriptionWrapper>
126
+ )}
114
127
  <InputWrapper error={Boolean(errorMsg)}>
115
128
  {prefix && <Prefix length={prefix.length}>{prefix}</Prefix>}
116
129
  <InputFieldContainer
@@ -123,7 +136,7 @@ const Input = React.forwardRef(
123
136
  type={type}
124
137
  placeholder={placeholder}
125
138
  error={Boolean(errorMsg)}
126
- aria-describedby={hasAria ? id : undefined}
139
+ aria-describedby={description ? `${id}-description` : undefined}
127
140
  ref={ref}
128
141
  prefixLength={prefix.length}
129
142
  required={optional === false}
@@ -158,7 +171,6 @@ Input.propTypes = {
158
171
  // don't want to display a label, it should be present for screen readers).
159
172
  // todo: convert this to 'hideLabel' to make it consistent with other components
160
173
  showLabel: PropTypes.bool,
161
- hasAria: PropTypes.bool,
162
174
  id: PropTypes.string.isRequired,
163
175
  /** text, email, number, date, search, tel, url, password */
164
176
  type: PropTypes.string.isRequired,
@@ -169,7 +181,8 @@ Input.propTypes = {
169
181
  prefix: PropTypes.string,
170
182
  optional: PropTypes.bool,
171
183
  maxPxWidthMediumBreakpoint: PropTypes.number,
172
- maxPxWidthLargeBreakpoint: PropTypes.number
184
+ maxPxWidthLargeBreakpoint: PropTypes.number,
185
+ description: PropTypes.node
173
186
  };
174
187
 
175
188
  export default Input;
@@ -130,3 +130,22 @@ const ItalicText = styled(Text).attrs({weight: 'normal'})`
130
130
  id="input-example-8"
131
131
  />
132
132
  ```
133
+
134
+ ```js
135
+ import Text from '../../Atoms/Text/Text';
136
+
137
+ const exampleDescription = (
138
+ <Text>Here's a description with some <b>formatting</b></Text>
139
+ );
140
+
141
+ <>
142
+ <h4>Input with Description:</h4>
143
+ <Input
144
+ placeholder="I have a description"
145
+ type="text"
146
+ label="My Great Input"
147
+ id="input-example-9"
148
+ description={exampleDescription}
149
+ />
150
+ </>
151
+ ```
@@ -118,7 +118,6 @@ it('renders correctly', () => {
118
118
  className="c4"
119
119
  >
120
120
  <input
121
- aria-describedby="Accessibility info go here"
122
121
  className="c5"
123
122
  id="Accessibility info go here"
124
123
  name="fullname"
@@ -254,7 +253,6 @@ it('renders with responsive max widths correctly', () => {
254
253
  className="c4"
255
254
  >
256
255
  <input
257
- aria-describedby="input-example-7"
258
256
  className="c5"
259
257
  id="input-example-7"
260
258
  name="responsive-width"
@@ -46,6 +46,7 @@ const TextArea = React.forwardRef(({
46
46
  placeholder={placeholder}
47
47
  rows={rows}
48
48
  error={!!errorMsg}
49
+ id={id}
49
50
  aria-describedby={id}
50
51
  ref={ref}
51
52
  />
@@ -98,6 +98,7 @@ it('renders correctly', () => {
98
98
  <textarea
99
99
  aria-describedby="Please leave your comment here"
100
100
  className="c3"
101
+ id="Please leave your comment here"
101
102
  name="description"
102
103
  placeholder="This is text area"
103
104
  rows={5}
@@ -111,7 +111,6 @@ exports[`renders correctly with no value and no options 1`] = `
111
111
  className="c5"
112
112
  >
113
113
  <input
114
- aria-describedby="text-input-with-dropdown"
115
114
  autoComplete="off"
116
115
  className="c6"
117
116
  id="text-input-with-dropdown"
@@ -241,7 +240,6 @@ exports[`renders correctly with value and no options 1`] = `
241
240
  className="c5"
242
241
  >
243
242
  <input
244
- aria-describedby="text-input-with-dropdown"
245
243
  autoComplete="off"
246
244
  className="c6"
247
245
  id="text-input-with-dropdown"
@@ -410,7 +408,6 @@ exports[`renders correctly with value and options 1`] = `
410
408
  className="c5"
411
409
  >
412
410
  <input
413
- aria-describedby="text-input-with-dropdown"
414
411
  autoComplete="off"
415
412
  className="c6"
416
413
  id="text-input-with-dropdown"
@@ -111,7 +111,6 @@ exports[`renders correctly 1`] = `
111
111
  className="c5"
112
112
  >
113
113
  <input
114
- aria-describedby="school-lookup"
115
114
  autoComplete="off"
116
115
  className="c6"
117
116
  defaultValue=""
@@ -183,7 +183,6 @@ it('renders correctly', () => {
183
183
  className="c9"
184
184
  >
185
185
  <input
186
- aria-describedby="search"
187
186
  className="c10"
188
187
  id="search"
189
188
  name="search"
@@ -111,7 +111,6 @@ exports[`renders correctly 1`] = `
111
111
  className="c5"
112
112
  >
113
113
  <input
114
- aria-describedby="typeahead-test"
115
114
  autoComplete="off"
116
115
  className="c6"
117
116
  defaultValue=""
@@ -647,7 +647,6 @@ exports[`"Single Giving, No Money Buys, with overridden manual input value" rend
647
647
  className="c23"
648
648
  >
649
649
  <input
650
- aria-describedby="mship-4--MoneyBuy-userInput"
651
650
  aria-label="Input a different amount"
652
651
  className="c24"
653
652
  id="mship-4--MoneyBuy-userInput"
@@ -1314,7 +1313,6 @@ exports[`Monthly donation renders correctly 1`] = `
1314
1313
  className="c24"
1315
1314
  >
1316
1315
  <input
1317
- aria-describedby="mship-1--MoneyBuy-userInput"
1318
1316
  aria-label="Input a different amount"
1319
1317
  className="c25"
1320
1318
  id="mship-1--MoneyBuy-userInput"
@@ -1949,7 +1947,6 @@ exports[`Single donation renders correctly 1`] = `
1949
1947
  className="c17"
1950
1948
  >
1951
1949
  <input
1952
- aria-describedby="mship-1--moneyBuy-box1"
1953
1950
  aria-label="£10"
1954
1951
  className="c18"
1955
1952
  id="mship-1--moneyBuy-box1"
@@ -1987,7 +1984,6 @@ exports[`Single donation renders correctly 1`] = `
1987
1984
  className="c17"
1988
1985
  >
1989
1986
  <input
1990
- aria-describedby="mship-1--moneyBuy-box2"
1991
1987
  aria-label="£20"
1992
1988
  className="c18"
1993
1989
  id="mship-1--moneyBuy-box2"
@@ -2025,7 +2021,6 @@ exports[`Single donation renders correctly 1`] = `
2025
2021
  className="c17"
2026
2022
  >
2027
2023
  <input
2028
- aria-describedby="mship-1--moneyBuy-box3"
2029
2024
  aria-label="£30"
2030
2025
  className="c18"
2031
2026
  id="mship-1--moneyBuy-box3"
@@ -2074,7 +2069,6 @@ exports[`Single donation renders correctly 1`] = `
2074
2069
  className="c17"
2075
2070
  >
2076
2071
  <input
2077
- aria-describedby="mship-1--MoneyBuy-userInput"
2078
2072
  aria-label="Input a different amount"
2079
2073
  className="c18"
2080
2074
  id="mship-1--MoneyBuy-userInput"
@@ -2571,7 +2565,6 @@ exports[`Single donation with no Money Buys renders correctly 1`] = `
2571
2565
  className="c17"
2572
2566
  >
2573
2567
  <input
2574
- aria-describedby="mship-1--MoneyBuy-userInput"
2575
2568
  aria-label="Input a different amount"
2576
2569
  className="c18"
2577
2570
  id="mship-1--MoneyBuy-userInput"
@@ -321,7 +321,6 @@ exports[`renders correctly 1`] = `
321
321
  className="c12"
322
322
  >
323
323
  <input
324
- aria-describedby="first-name"
325
324
  aria-required={true}
326
325
  className="c13"
327
326
  id="first-name"
@@ -359,7 +358,6 @@ exports[`renders correctly 1`] = `
359
358
  className="c12"
360
359
  >
361
360
  <input
362
- aria-describedby="last-name"
363
361
  aria-required={true}
364
362
  className="c13"
365
363
  id="last-name"
@@ -398,7 +396,6 @@ exports[`renders correctly 1`] = `
398
396
  className="c12"
399
397
  >
400
398
  <input
401
- aria-describedby="email"
402
399
  aria-required={true}
403
400
  className="c13"
404
401
  id="email"
@@ -489,7 +489,6 @@ it('renders correctly', () => {
489
489
  className="c18"
490
490
  >
491
491
  <input
492
- aria-describedby="mship-1--moneyBuy-box1"
493
492
  aria-label="£5"
494
493
  className="c19"
495
494
  id="mship-1--moneyBuy-box1"
@@ -527,7 +526,6 @@ it('renders correctly', () => {
527
526
  className="c18"
528
527
  >
529
528
  <input
530
- aria-describedby="mship-1--moneyBuy-box2"
531
529
  aria-label="£10"
532
530
  className="c19"
533
531
  id="mship-1--moneyBuy-box2"
@@ -565,7 +563,6 @@ it('renders correctly', () => {
565
563
  className="c18"
566
564
  >
567
565
  <input
568
- aria-describedby="mship-1--moneyBuy-box3"
569
566
  aria-label="£20"
570
567
  className="c19"
571
568
  id="mship-1--moneyBuy-box3"
@@ -614,7 +611,6 @@ it('renders correctly', () => {
614
611
  className="c18"
615
612
  >
616
613
  <input
617
- aria-describedby="mship-1--MoneyBuy-userInput"
618
614
  aria-label="Input a different amount"
619
615
  className="c19"
620
616
  id="mship-1--MoneyBuy-userInput"