Skip to content

Commit 46a9cec

Browse files
committed
Stop using InputRoot in Input and Textarea
1 parent f7f0393 commit 46a9cec

File tree

5 files changed

+79
-28
lines changed

5 files changed

+79
-28
lines changed

src/components/input/Input.tsx

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,30 @@
1+
import classnames from 'classnames';
12
import type { JSX } from 'preact';
23

34
import type { PresentationalProps } from '../../types';
45
import { downcastRef } from '../../util/typing';
5-
import InputRoot from './InputRoot';
6+
import { inputGroupStyles } from './InputGroup';
7+
8+
export type InputStylesOptions = {
9+
classes?: string | string[];
10+
feedback?: 'error' | 'warning';
11+
};
12+
13+
export function inputStyles({ classes, feedback }: InputStylesOptions) {
14+
return classnames(
15+
'focus-visible-ring ring-inset border rounded w-full p-2',
16+
'bg-grey-0 focus:bg-white disabled:bg-grey-1',
17+
'placeholder:text-color-grey-5 disabled:placeholder:color-grey-6',
18+
{
19+
'ring-2': !!feedback,
20+
'ring-red-error': feedback === 'error',
21+
'ring-yellow-notice': feedback === 'warning',
22+
},
23+
// Adapt styles when this component is inside an InputGroup
24+
inputGroupStyles,
25+
classes,
26+
);
27+
}
628

729
type ComponentProps = {
830
type?: 'text' | 'email' | 'search' | 'number' | 'password' | 'url';
@@ -24,19 +46,30 @@ export type InputProps = PresentationalProps &
2446
export default function Input({
2547
elementRef,
2648
type = 'text',
49+
classes,
2750
feedback,
2851
hasError,
2952

3053
...htmlAttributes
3154
}: InputProps) {
55+
/* istanbul ignore next */
56+
if (feedback === undefined && hasError) {
57+
feedback = 'error';
58+
}
59+
60+
if (!htmlAttributes.id && !htmlAttributes['aria-label']) {
61+
console.warn(
62+
'`Input` component should have either an `id` or an `aria-label` attribute',
63+
);
64+
}
65+
3266
return (
33-
<InputRoot
67+
<input
3468
data-component="Input"
35-
elementRef={downcastRef(elementRef)}
36-
type={type}
37-
feedback={feedback}
38-
hasError={hasError}
3969
{...htmlAttributes}
70+
ref={downcastRef(elementRef)}
71+
type={type}
72+
className={inputStyles({ classes, feedback })}
4073
/>
4174
);
4275
}

src/components/input/InputRoot.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import classnames from 'classnames';
21
import type { JSX } from 'preact';
32

43
import type { PresentationalProps } from '../../types';
54
import { downcastRef } from '../../util/typing';
6-
import { inputGroupStyles } from './InputGroup';
5+
import { inputStyles } from './Input';
76

87
type RootComponentProps = {
98
element?: 'input' | 'select' | 'textarea';
@@ -26,6 +25,7 @@ export type InputRootProps = PresentationalProps &
2625
/**
2726
* Root component for various input types that applies a consistent design
2827
* pattern.
28+
* @deprecated Only `Select` is using this component. Remove once it is deleted
2929
*/
3030
export default function InputRoot({
3131
element: Element = 'input',
@@ -54,19 +54,7 @@ export default function InputRoot({
5454
{...htmlAttributes}
5555
// @ts-ignore-next
5656
ref={downcastRef(elementRef)}
57-
className={classnames(
58-
'focus-visible-ring ring-inset border rounded w-full p-2',
59-
'bg-grey-0 focus:bg-white disabled:bg-grey-1',
60-
'placeholder:text-color-grey-5 disabled:placeholder:color-grey-6',
61-
{
62-
'ring-2': !!feedback,
63-
'ring-red-error': feedback === 'error',
64-
'ring-yellow-notice': feedback === 'warning',
65-
},
66-
// Adapt styles when this component is inside an InputGroup
67-
inputGroupStyles,
68-
classes,
69-
)}
57+
className={inputStyles({ classes, feedback })}
7058
>
7159
{children}
7260
</Element>

src/components/input/Textarea.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { JSX } from 'preact';
22

33
import type { PresentationalProps } from '../../types';
44
import { downcastRef } from '../../util/typing';
5-
import InputRoot from './InputRoot';
5+
import { inputStyles } from './Input';
66

77
type ComponentProps = {
88
feedback?: 'error' | 'warning';
@@ -17,19 +17,23 @@ export type TextareaProps = PresentationalProps &
1717
*/
1818
export default function Textarea({
1919
elementRef,
20-
type = 'text',
2120
feedback,
21+
classes,
2222

2323
...htmlAttributes
2424
}: TextareaProps) {
25+
if (!htmlAttributes.id && !htmlAttributes['aria-label']) {
26+
console.warn(
27+
'`Textarea` component should have either an `id` or an `aria-label` attribute',
28+
);
29+
}
30+
2531
return (
26-
<InputRoot
32+
<textarea
2733
data-component="Textarea"
28-
element="textarea"
29-
elementRef={downcastRef(elementRef)}
30-
type={type}
31-
feedback={feedback}
3234
{...htmlAttributes}
35+
ref={downcastRef(elementRef)}
36+
className={inputStyles({ classes, feedback })}
3337
/>
3438
);
3539
}

src/components/input/test/Input-test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,17 @@ const contentFn = (Component, props = {}) => {
99

1010
describe('Input', () => {
1111
testPresentationalComponent(Input, { createContent: contentFn });
12+
13+
it('should warn in console if accessibility attributes are missing', () => {
14+
sinon.stub(console, 'warn');
15+
16+
mount(<Input placeholder="..." />);
17+
18+
assert.calledWith(
19+
console.warn,
20+
'`Input` component should have either an `id` or an `aria-label` attribute',
21+
);
22+
23+
console.warn.restore();
24+
});
1225
});

src/components/input/test/Textarea-test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,17 @@ const contentFn = (Component, props = {}) => {
99

1010
describe('Textarea', () => {
1111
testPresentationalComponent(Textarea, { createContent: contentFn });
12+
13+
it('should warn in console if accessibility attributes are missing', () => {
14+
sinon.stub(console, 'warn');
15+
16+
mount(<Textarea placeholder="..." />);
17+
18+
assert.calledWith(
19+
console.warn,
20+
'`Textarea` component should have either an `id` or an `aria-label` attribute',
21+
);
22+
23+
console.warn.restore();
24+
});
1225
});

0 commit comments

Comments
 (0)