Skip to content

Commit 1f9a124

Browse files
committed
refactor(TextArea): refresh
1 parent 6b6f04c commit 1f9a124

2 files changed

Lines changed: 105 additions & 63 deletions

File tree

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,80 @@
1-
import { style, globalStyle } from 'treat';
1+
import { style, styleMap } from 'treat';
22

33
export const root = style({
44
position: 'relative',
5-
flexDirection: 'column-reverse', // because we select the `label` using the CSS `+` adjacent sibling selector
65
display: 'flex',
7-
textAlign: 'left',
6+
flexDirection: 'column',
87
});
98

10-
export const textArea = style(({ palette, sizing, shadows, shape, typography }) => ({
11-
// reset
12-
display: 'inherit',
13-
margin: 0,
14-
outline: 0,
15-
boxSizing: 'border-box',
16-
backgroundClip: 'padding-box',
17-
whiteSpace: 'nowrap',
18-
'--webkit-appearance': 'none',
19-
// ./reset
20-
boxShadow: shadows.line,
21-
border: `1px solid ${palette.border}`,
22-
borderRadius: shape.borderRadius.tiny,
23-
minWidth: 256,
24-
minHeight: sizing('tiny') * 6,
25-
padding: sizing('tiny') - 2.5,
26-
backgroundColor: palette.white,
27-
...typography.variant('small'),
28-
textAlign: 'inherit',
29-
color: palette.textDark,
30-
':invalid': {
31-
borderColor: palette.warning,
32-
},
33-
'::placeholder': {
34-
color: palette.light('textDark'),
35-
},
36-
}));
9+
export const label = style(() => ({}));
3710

38-
export const label = style(({ palette }) => ({
39-
selectors: {
40-
[`${textArea}:invalid + &`]: {
41-
color: palette.warning,
11+
export const textArea = styleMap(({ palette, sizing, shape, typography }) => ({
12+
container: {
13+
display: 'flex',
14+
flexWrap: 'nowrap',
15+
alignItems: 'center',
16+
backgroundColor: palette.surface,
17+
borderRadius: shape.borderRadius.small,
18+
border: `1px solid ${palette.border}`,
19+
},
20+
root: {
21+
flex: 1,
22+
border: 0,
23+
outline: 0,
24+
margin: 0,
25+
backgroundColor: 'transparent',
26+
backgroundClip: 'padding-box',
27+
color: palette.text,
28+
padding: sizing('small'),
29+
...typography.variant('regular'),
30+
textAlign: 'inherit',
31+
textOverflow: 'ellipsis',
32+
whiteSpace: 'nowrap',
33+
'--webkit-appearance': 'none',
34+
'::placeholder': {
35+
color: palette.light('text'),
4236
},
37+
minWidth: 256,
38+
minHeight: sizing('large'),
4339
},
4440
}));
4541

4642
export const dense = style(({ sizing }) => ({
4743
selectors: {
48-
[`${textArea}&`]: {
49-
padding: sizing('tiny') / 2 + 0.5,
44+
[`${label}&`]: {
45+
lineHeight: 1.125,
46+
},
47+
[`${textArea.root}&`]: {
48+
padding: sizing('tiny'),
5049
},
5150
},
5251
}));
5352

5453
export const disabled = style(({ palette }) => ({
5554
selectors: {
56-
[`${textArea}&`]: {
57-
boxShadow: 'none',
55+
[`${textArea.container}&`]: {
5856
cursor: 'not-allowed',
59-
color: palette.lighten('textDark', 0.68),
57+
backgroundColor: palette.disabled,
6058
},
6159
},
6260
}));
6361

64-
globalStyle(`${textArea}:hover:not(${disabled}), ${textArea}:focus`, ({ palette }) => ({
65-
borderColor: palette.dark('border'),
62+
export const invalid = style(({ palette }) => ({
63+
selectors: {
64+
[`${textArea.container}&`]: {
65+
borderColor: palette.warning,
66+
},
67+
[`${textArea.root}&`]: {
68+
borderColor: palette.warning,
69+
},
70+
},
6671
}));
6772

68-
globalStyle(
69-
`${textArea}:hover:not(${disabled}):invalid, ${textArea}:focus:invalid`,
70-
({ palette }) => ({
71-
borderColor: palette.dark('warning'),
72-
}),
73-
);
73+
export const focused = style(({ palette, shadows }) => ({
74+
selectors: {
75+
[`${textArea.container}&`]: {
76+
boxShadow: shadows.line,
77+
outline: `${palette.focus} auto 5px`,
78+
},
79+
},
80+
}));

packages/ui/src/TextArea/TextArea.tsx

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@
44
*
55
*/
66

7-
import React from 'react';
7+
import React, { useState } from 'react';
88
import clsx from 'clsx';
9-
9+
import { Label } from '../Typography';
1010
import { useStyles } from 'react-treat';
11-
12-
import { Label } from '../Label';
13-
14-
import * as styles from './TextArea.treat';
11+
import * as classesRef from './TextArea.treat';
1512

1613
export interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
1714
dense?: boolean;
@@ -23,19 +20,57 @@ export const TextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(fun
2320
props,
2421
ref,
2522
) {
26-
const { className, dense, disabled, label, ...rest } = props;
27-
28-
const classes = useStyles(styles);
23+
const { className, dense, disabled, label, onFocus, onBlur, onInvalid, onInput, ...rest } = props;
24+
const classes = useStyles(classesRef);
25+
const [focused, setFocused] = useState(false);
26+
const [invalid, setInvalid] = useState(false);
2927

3028
return (
3129
<div className={clsx(classes.root, className)}>
32-
<textarea
33-
{...rest}
34-
ref={ref}
35-
disabled={disabled}
36-
className={clsx(classes.textArea, dense && classes.dense, disabled && classes.disabled)}
37-
/>
38-
{label && <Label className={clsx(classes.label, dense && classes.dense)}>{label}</Label>}
30+
{label && (
31+
<Label
32+
color={invalid ? 'warning' : undefined}
33+
className={clsx(classes.label, dense && classes.dense)}
34+
>
35+
{label}
36+
</Label>
37+
)}
38+
<div
39+
className={clsx(
40+
classes.textArea.container,
41+
focused && classes.focused,
42+
invalid && classes.invalid,
43+
disabled && classes.disabled,
44+
dense && classes.dense,
45+
)}
46+
>
47+
<textarea
48+
{...rest}
49+
ref={ref}
50+
disabled={disabled}
51+
onFocus={(event) => {
52+
setFocused(true);
53+
if (onFocus) onFocus(event);
54+
}}
55+
onBlur={(event) => {
56+
setFocused(false);
57+
if (onBlur) onBlur(event);
58+
}}
59+
onInvalid={(event) => {
60+
setInvalid(true);
61+
if (onInvalid) onInvalid(event);
62+
}}
63+
onInput={(event) => {
64+
if (event.currentTarget.checkValidity()) setInvalid(false);
65+
if (onInput) onInput(event);
66+
}}
67+
className={clsx(
68+
classes.textArea.root,
69+
dense && classes.dense,
70+
disabled && classes.disabled,
71+
)}
72+
/>
73+
</div>
3974
</div>
4075
);
4176
});

0 commit comments

Comments
 (0)