Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(TextInput, TextArea): add readOnly property #1747

Merged
merged 5 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/controls/TextArea/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ LANDING_BLOCK-->
| pin | The control's border view | `string` | `"round-round"` |
| placeholder | Text that appears in the control when no value is set | `string` | |
| qa | Test id attribute (`data-qa`) | `string` | |
| readOnly | Indicates that the user cannot change control's value | `boolean` | `false` |
| rows | The number of visible text lines for the control. If unspecified, the hight will be calculated automatically based on the content | `number` | |
| size | The control's size | `"s"` `"m"` `"l"` `"xl"` | `"m"` |
| tabIndex | The control's `tabindex` attribute | `string` | |
Expand Down
11 changes: 7 additions & 4 deletions src/components/controls/TextArea/TextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@ export const TextArea = React.forwardRef<HTMLSpanElement, TextAreaProps>(
name,
value,
defaultValue,
disabled = false,
disabled: disabledProp,
readOnly: readOnlyProp,
hasClear = false,
error,
errorMessage: errorMessageProp,
validationState: validationStateProp,
autoComplete,
id: originalId,
id: idProp,
tabIndex,
style,
className,
Expand All @@ -63,6 +64,8 @@ export const TextArea = React.forwardRef<HTMLSpanElement, TextAreaProps>(
onUpdate,
onChange,
} = props;
const disabled = disabledProp ?? controlProps?.disabled;
const readOnly = readOnlyProp ?? controlProps?.readOnly;

const {errorMessage, validationState} = errorPropsMapper({
error,
Expand All @@ -79,8 +82,8 @@ export const TextArea = React.forwardRef<HTMLSpanElement, TextAreaProps>(
const innerId = useUniqId();

const isErrorMsgVisible = validationState === 'invalid' && Boolean(errorMessage);
const isClearControlVisible = Boolean(hasClear && !disabled && inputValue);
const id = originalId || innerId;
const isClearControlVisible = Boolean(hasClear && !disabled && !readOnly && inputValue);
const id = idProp || innerId;

const errorMessageId = useUniqId();
const noteId = useUniqId();
Expand Down
2 changes: 2 additions & 0 deletions src/components/controls/TextArea/TextAreaControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export function TextAreaControl(props: Props) {
maxRows,
autoFocus,
disabled,
readOnly,
onChange,
onFocus,
onBlur,
Expand Down Expand Up @@ -112,6 +113,7 @@ export function TextAreaControl(props: Props) {
onKeyUp={onKeyUp}
onKeyPress={onKeyPress}
disabled={disabled ?? controlProps.disabled}
readOnly={readOnly ?? controlProps.readOnly}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ export function TextAreaShowcase() {
/>
</div>
<TextArea {...textAreaProps} placeholder="disabled" disabled rows={2} />
<TextArea
{...textAreaProps}
placeholder="readonly"
value="readonly value"
readOnly
rows={2}
/>
<TextArea {...textAreaProps} placeholder="rows = 4 & clear" hasClear rows={4} />
<TextArea
{...textAreaProps}
Expand Down Expand Up @@ -113,6 +120,13 @@ value`.trim()}
<TextArea {...textAreaProps} />
<TextArea {...textAreaProps} value={undefined} defaultValue="has clear" hasClear />
<TextArea {...textAreaProps} disabled />
<TextArea
{...textAreaProps}
placeholder="readonly"
value="readonly value"
readOnly
rows={2}
/>
<TextArea {...textAreaProps} error="Error message" />
</div>
<div className={b('custom-theme')}>
Expand All @@ -127,6 +141,13 @@ value`.trim()}
<TextArea {...textAreaProps} />
<TextArea {...textAreaProps} value={undefined} defaultValue="has clear" hasClear />
<TextArea {...textAreaProps} disabled />
<TextArea
{...textAreaProps}
placeholder="readonly"
value="readonly value"
readOnly
rows={2}
/>
<TextArea {...textAreaProps} error="Error message" />
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/controls/TextInput/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ LANDING_BLOCK-->
| onUpdate | Fires when the input’s value is changed by the user. Provides new value as an callback's argument | `function` | |
| pin | The control's border view | `string` | `'round-round'` |
| placeholder | Text that appears in the control when it has no value set | `string` | |
| qa | Test ID attribute (`data-qa`) | `string` | |
| qa | Test ID attribute (`data-qa`) | `string` |
| readOnly | Indicates that the user cannot change control's value | `boolean` | `false` |
| rightContent | User`s node rendered after the input node and clear button | `React.ReactNode` | |
| size | The size of the control | `"s"` `"m"` `"l"` `"xl"` | `"m"` |
| tabIndex | The `tabindex` attribute of the control | `string` | |
Expand Down
21 changes: 12 additions & 9 deletions src/components/controls/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,20 @@ export const TextInput = React.forwardRef<HTMLSpanElement, TextInputProps>(
value,
defaultValue,
label,
disabled = false,
disabled: disabledProp,
readOnly: readOnlyProp,
hasClear = false,
error,
errorMessage: errorMessageProp,
errorPlacement: errorPlacementProp = 'outside',
validationState: validationStateProp,
autoComplete,
id: originalId,
id: idProp,
tabIndex,
style,
className,
qa,
controlProps: originalControlProps,
controlProps: controlPropsProp,
leftContent,
rightContent,
startContent = leftContent,
Expand All @@ -89,6 +90,8 @@ export const TextInput = React.forwardRef<HTMLSpanElement, TextInputProps>(
onUpdate,
onChange,
} = props;
const disabled = disabledProp ?? controlPropsProp?.disabled;
const readOnly = readOnlyProp ?? controlPropsProp?.readOnly;

const {errorMessage, errorPlacement, validationState} = errorPropsMapper({
error,
Expand All @@ -110,14 +113,14 @@ export const TextInput = React.forwardRef<HTMLSpanElement, TextInputProps>(
validationState === 'invalid' && Boolean(errorMessage) && errorPlacement === 'outside';
const isErrorIconVisible =
validationState === 'invalid' && Boolean(errorMessage) && errorPlacement === 'inside';
const isClearControlVisible = Boolean(hasClear && !disabled && inputValue);
const isClearControlVisible = Boolean(hasClear && !disabled && !readOnly && inputValue);
const isStartContentVisible = Boolean(startContent);
const isEndContentVisible = Boolean(endContent);
const isAutoCompleteOff =
isLabelVisible && !originalId && !name && typeof autoComplete === 'undefined';
isLabelVisible && !idProp && !name && typeof autoComplete === 'undefined';

const innerId = useUniqId();
const id = isLabelVisible ? originalId || innerId : originalId;
const id = isLabelVisible ? idProp || innerId : idProp;

const labelSize = useElementSize(isLabelVisible ? labelRef : null, size);
const startContentSize = useElementSize(
Expand All @@ -128,17 +131,17 @@ export const TextInput = React.forwardRef<HTMLSpanElement, TextInputProps>(
const errorMessageId = useUniqId();
const noteId = useUniqId();
const ariaDescribedBy = [
originalControlProps?.['aria-describedby'],
controlPropsProp?.['aria-describedby'],
note ? noteId : undefined,
isErrorMsgVisible ? errorMessageId : undefined,
]
.filter(Boolean)
.join(' ');

const controlProps: TextInputProps['controlProps'] = {
...originalControlProps,
...controlPropsProp,
style: {
...originalControlProps?.style,
...controlPropsProp?.style,
...(isLabelVisible && labelSize.width
? {paddingInlineStart: `${labelSize.width}px`}
: {}),
Expand Down
2 changes: 2 additions & 0 deletions src/components/controls/TextInput/TextInputControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function TextInputControl(props: Props) {
defaultValue,
autoFocus,
disabled,
readOnly,
onChange,
onFocus,
onBlur,
Expand Down Expand Up @@ -54,6 +55,7 @@ export function TextInputControl(props: Props) {
onKeyUp={onKeyUp}
onKeyPress={onKeyPress}
disabled={disabled ?? controlProps.disabled}
readOnly={readOnly ?? controlProps.readOnly}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ export const CustomThemeShowcase = () => {
errorPlacement="inside"
/>
<TextInput {...textInputProps} placeholder="disabled" disabled />
<TextInput
{...textInputProps}
placeholder="disabled"
value="readonlyValue"
readOnly
/>
<TextInput {...textInputProps} placeholder="clear" hasClear />
<TextInput
{...textInputProps}
Expand Down Expand Up @@ -82,6 +88,12 @@ export const CustomThemeShowcase = () => {
errorPlacement="inside"
/>
<TextInput {...textInputProps} placeholder="disabled" disabled />
<TextInput
{...textInputProps}
placeholder="disabled"
value="readonlyValue"
readOnly
/>
<TextInput {...textInputProps} placeholder="clear" hasClear />
<TextInput
{...textInputProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ export function TextInputShowcase() {
/>
</div>
<TextInput {...textInputProps} placeholder="disabled" disabled />
<TextInput
{...textInputProps}
placeholder="readonly"
value="readonlyValue"
readOnly
/>
<TextInput {...textInputProps} placeholder="clear" hasClear />
<TextInput
{...textInputProps}
Expand Down Expand Up @@ -128,6 +134,13 @@ export function TextInputShowcase() {
/>
</div>
<TextInput {...textInputProps} placeholder="disabled" label={LABEL} disabled />
<TextInput
{...textInputProps}
placeholder="readonly"
value="readonlyValue"
label={LABEL}
readOnly
/>
<TextInput {...textInputProps} placeholder="clear" label={LABEL} hasClear />
<TextInput
{...textInputProps}
Expand Down Expand Up @@ -234,6 +247,17 @@ export function TextInputShowcase() {
}
disabled
/>
<TextInput
{...textInputProps}
placeholder="readonly"
type={additionalContentExmpleInputType}
value="readonlyValue"
leftContent={<Icon data={Key} />}
rightContent={
<EyeButton opened={hideValue} onClick={handleEyeButtonClick} />
}
readOnly
/>
<TextInput
{...textInputProps}
placeholder="clear"
Expand Down
2 changes: 2 additions & 0 deletions src/components/controls/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export type BaseInputControlProps<T = Element> = DOMProps &
pin?: InputControlPin;
/** Text that appears in the control when it has no value set */
placeholder?: string;
/** Indicates that the user cannot change control's value */
readOnly?: boolean;
/** The control's size. `'m'` by default */
size?: InputControlSize;
/** The control's `tabindex` attribute */
Expand Down
Loading