Skip to content

Commit

Permalink
refactor: Replace Textfield and Textarea with StudioTextfield a…
Browse files Browse the repository at this point in the history
…nd `StudioTextarea` (#14711)

Co-authored-by: JamalAlabdullah <[email protected]>
  • Loading branch information
mlqn and JamalAlabdullah authored Feb 27, 2025
1 parent 21f546a commit 085d2c5
Show file tree
Hide file tree
Showing 26 changed files with 78 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ describe('CreateRelease', () => {
textMock('app_create_release.release_version_number'),
);
await user.type(inputVersionNumber, existingTagName);
await inputVersionNumber.blur();
await waitFor(() => inputVersionNumber.blur());

await waitFor(() => {
expect(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import React, { useState } from 'react';
import classes from './CreateRelease.module.css';
import type { ChangeEvent } from 'react';
import { Textfield, Textarea } from '@digdir/designsystemet-react';
import { versionNameValid } from './utils';
import { useBranchStatusQuery, useAppReleasesQuery } from '../../../hooks/queries';
import { useCreateReleaseMutation } from '../../../hooks/mutations';
import { useTranslation } from 'react-i18next';
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import { FormField } from 'app-shared/components/FormField';
import { StudioButton } from '@studio/components';
import { StudioButton, StudioTextarea, StudioTextfield } from '@studio/components';

export function CreateRelease() {
const { org, app } = useStudioEnvironmentParams();
Expand Down Expand Up @@ -54,25 +53,23 @@ export function CreateRelease() {
customValidationMessages={(errorCode) => errorCode}
renderField={({ fieldProps }) => (
<div className={classes.releaseVersionInput}>
<Textfield
<StudioTextfield
{...fieldProps}
label={t('app_create_release.release_version_number')}
onChange={handleTagNameChange}
size='small'
/>
</div>
)}
/>
<FormField
value={body}
renderField={({ fieldProps }) => (
<Textarea
<StudioTextarea
{...fieldProps}
label={t('app_create_release.release_description')}
value={body}
onChange={handleBodyChange}
rows={4}
size='small'
/>
)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useState } from 'react';
import classes from './InputFields.module.css';
import { useTranslation } from 'react-i18next';
import type { AppConfig } from 'app-shared/types/AppConfig';
import { Textfield } from '@digdir/designsystemet-react';
import { StudioTextfield } from '@studio/components';

type AppConfigForm = Pick<AppConfig, 'serviceName' | 'serviceId'>;

Expand Down Expand Up @@ -39,25 +39,22 @@ export const InputFields = ({ appConfig, onSave }: InputFieldsProps): ReactNode

return (
<form className={classes.wrapper} onBlur={handleAppConfigFormBlur}>
<Textfield
<StudioTextfield
label={t('settings_modal.about_tab_repo_label')}
description={t('settings_modal.about_tab_repo_description')}
size='small'
defaultValue={appConfig.repositoryName}
readOnly
/>
<Textfield
<StudioTextfield
label={t('settings_modal.about_tab_name_label')}
description={t('settings_modal.about_tab_name_description')}
size='small'
name='serviceName'
error={appConfigFormErrors.serviceName}
defaultValue={appConfig.serviceName}
/>
<Textfield
<StudioTextfield
label={t('settings_modal.about_tab_alt_id_label')}
description={t('settings_modal.about_tab_alt_id_description')}
size='small'
name='serviceId'
defaultValue={appConfig.serviceId}
/>
Expand Down
10 changes: 5 additions & 5 deletions frontend/dashboard/components/RepoNameInput/RepoNameInput.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import React from 'react';
import classes from './RepoNameInput.module.css';
import type { TextfieldProps } from '@digdir/designsystemet-react';
import { Paragraph, Textfield } from '@digdir/designsystemet-react';
import { Paragraph } from '@digdir/designsystemet-react';
import { useTranslation } from 'react-i18next';
import type { StudioTextfieldProps } from '@studio/components';
import { StudioTextfield } from '@studio/components';

type RepoNameInputProps = {
repoName?: string;
errorMessage?: string;
} & TextfieldProps;
} & StudioTextfieldProps;

export const RepoNameInput = ({ repoName, errorMessage, name, onChange }: RepoNameInputProps) => {
const { t } = useTranslation();

return (
<div>
<Textfield
<StudioTextfield
name={name}
id='service-saved-name'
label={t('general.service_name')}
defaultValue={repoName}
error={errorMessage}
onChange={onChange}
size='small'
/>
<Paragraph size='small' className={classes.textWrapper}>
{t('dashboard.service_saved_name_description')}{' '}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const StudioDecimalInput = forwardRef(
description={description}
value={inputValue}
onChange={handleInputChange}
errorAfterBlur={errorMessage}
error={errorMessage}
inputMode='decimal'
ref={ref}
{...rest}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const ManualEditor = ({
return (
<StudioTextarea
className={classes.manualEditor}
errorAfterBlur={errorMessage}
error={errorMessage}
hideLabel
label={texts.expression}
onChange={handleChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import type { SimpleSubexpressionValueType } from '../../../../../enums/SimpleSu
import type { ChangeEvent } from 'react';
import React from 'react';
import { useStudioExpressionContext } from '../../../../../StudioExpressionContext';
import { Textfield } from '@digdir/designsystemet-react';
import { StudioTextfield } from '@studio/components';

export const StringInput = ({ value, onChange }: Props<SimpleSubexpressionValueType.String>) => {
const { texts } = useStudioExpressionContext();

const handleChange = (event: ChangeEvent<HTMLInputElement>) =>
onChange({ ...value, value: event.target.value });

return <Textfield size='small' value={value.value} onChange={handleChange} label={texts.value} />;
return <StudioTextfield value={value.value} onChange={handleChange} label={texts.value} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const StudioToggleableTextfield = forwardRef<HTMLDivElement, StudioToggle
onIsViewMode,
title,
value,
defaultValue,
...rest
}: StudioToggleableTextfieldProps,
ref,
Expand Down Expand Up @@ -77,7 +78,7 @@ export const StudioToggleableTextfield = forwardRef<HTMLDivElement, StudioToggle
property={label}
onClick={toggleViewMode}
title={title}
value={value}
value={value ?? defaultValue}
className={classes.propertyButton}
/>
);
Expand All @@ -93,6 +94,7 @@ export const StudioToggleableTextfield = forwardRef<HTMLDivElement, StudioToggle
ref={ref}
title={title}
value={value}
defaultValue={defaultValue}
{...rest}
/>
);
Expand Down
12 changes: 7 additions & 5 deletions frontend/libs/studio-components/src/hooks/useTextInputProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export function useTextInputProps<E extends ElementType>(
props: SharedTextInputProps<E>,
): Omit<SharedTextInputProps<E>, keyof AdditionalProps> {
const {
value = '',
value,
defaultValue,
onChange,
onBlur,
error,
Expand All @@ -20,16 +21,17 @@ export function useTextInputProps<E extends ElementType>(
...rest
} = props;

const [valueState, setValueState] = useState(value);
const initialValue = value ?? defaultValue ?? '';
const [valueState, setValueState] = useState(initialValue);
const [showError, setShowError] = useState(false);

const disableError = () => setShowError(false);
const enableError = () => setShowError(true);

useEffect(() => {
if (!value) disableError();
setValueState(value);
}, [value]);
if (!initialValue) disableError();
setValueState(initialValue);
}, [initialValue]);

const handleChange = (event: ChangeEvent<E>) => {
setValueState(event.target.value);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { ChangeEvent, KeyboardEvent } from 'react';
import React, { useEffect, useState } from 'react';
import { Textfield } from '@digdir/designsystemet-react';
import classes from './EnumField.module.css';
import { useTranslation } from 'react-i18next';
import { TrashIcon } from '@studio/icons';
import { StudioButton } from '@studio/components';
import { StudioButton, StudioTextfield } from '@studio/components';

export type EnumFieldProps = {
value: string;
Expand Down Expand Up @@ -45,15 +44,14 @@ export const EnumField = ({

return (
<div className={classes.root}>
<Textfield
<StudioTextfield
label={label}
hideLabel
disabled={readOnly}
value={inputValue}
onChange={handleChange}
onKeyDown={onKeyDown}
error={!isValid}
size='sm'
/>
<StudioButton
title={t('schema_editor.delete_field')}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { BaseSyntheticEvent, ChangeEvent } from 'react';
import React from 'react';
import { Textfield } from '@digdir/designsystemet-react';
import { makeDomFriendlyID } from '../../../../utils/ui-schema-utils';
import { StudioTextfield } from '@studio/components';

export interface IRestrictionFieldProps {
className?: string;
Expand All @@ -24,22 +24,21 @@ export const RestrictionField = ({
value,
}: IRestrictionFieldProps) => {
const fieldId = makeDomFriendlyID(path, { suffix: `${keyName}-value` });
const handleChange = ({ target }: ChangeEvent) => {
const handleChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
const element = target as HTMLInputElement;
if (element.value !== value) {
onChangeValue(path, keyName, element.value);
}
};
return (
<div className={className}>
<Textfield
<StudioTextfield
aria-label={label}
id={fieldId}
label={label}
onChange={handleChange}
readOnly={readOnly}
value={value ?? ''}
size='sm'
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useReducer, useState } from 'react';
import type { RestrictionItemProps } from '../ItemRestrictions';
import { RestrictionField } from '../RestrictionField';
import classes from './StringRestrictions.module.css';
import { Fieldset, Label, Switch, Textfield } from '@digdir/designsystemet-react';
import { Fieldset, Label, Switch } from '@digdir/designsystemet-react';
import type { KeyValuePairs } from 'app-shared/types/KeyValuePairs';
import { StringFormat, StrRestrictionKey } from '@altinn/schema-model';
import { makeDomFriendlyID } from '../../../../utils/ui-schema-utils';
Expand Down Expand Up @@ -94,13 +94,12 @@ export function StringRestrictions({
<>
<div>
<div className={classes.formatFieldsRowContent}>
<Textfield
<StudioTextfield
label={t(formatMinLangKey)}
onChange={(e) =>
dispatchAction(StringRestrictionsReducerActionType.setEarliest, e.target.value)
}
value={formatState.earliest}
size='sm'
/>
<Switch
size='small'
Expand All @@ -115,13 +114,12 @@ export function StringRestrictions({
</div>
<div>
<div className={classes.formatFieldsRowContent}>
<Textfield
<StudioTextfield
label={t(formatMaxLangKey)}
onChange={(e) =>
dispatchAction(StringRestrictionsReducerActionType.setLatest, e.target.value)
}
value={formatState.latest}
size='sm'
/>
<Switch
size='small'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useEffect, useState } from 'react';
import { NameError } from '../../types';
import type { TextfieldProps } from '@digdir/designsystemet-react';
import type { StudioTextfieldProps } from '@studio/components';
import { StudioTextfield } from '@studio/components';
import { extractNameFromPointer, replaceLastPointerSegment } from '@altinn/schema-model';
import { isValidName } from '../../utils/ui-schema-utils';
import { useTranslation } from 'react-i18next';
import { FormField } from 'app-shared/components/FormField';
import { useSchemaEditorAppContext } from '@altinn/schema-editor/hooks/useSchemaEditorAppContext';

export type NameFieldProps = TextfieldProps & {
export type NameFieldProps = StudioTextfieldProps & {
id?: string;
schemaPointer: string;
handleSave: (newNodeName: string, errorCode: string) => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { forwardRef, useState } from 'react';
import classes from './DeleteModal.module.css';
import { useTranslation } from 'react-i18next';
import { StudioButton, StudioModal, StudioSpinner } from '@studio/components';
import { StudioButton, StudioModal, StudioSpinner, StudioTextfield } from '@studio/components';
import { useForwardedRef } from '@studio/hooks';
import { TrashIcon } from '@studio/icons';
import { useResetRepositoryMutation } from 'app-shared/hooks/mutations/useResetRepositoryMutation';
import { toast } from 'react-toastify';
import { Paragraph, Textfield } from '@digdir/designsystemet-react';
import { Paragraph } from '@digdir/designsystemet-react';
import { useQueryClient } from '@tanstack/react-query';

export type DeleteModalProps = {
Expand Down Expand Up @@ -57,12 +57,11 @@ export const DeleteModal = forwardRef<HTMLDialogElement, DeleteModalProps>(
<Paragraph size='small' spacing>
{t('local_changes.modal_delete_modal_text')}
</Paragraph>
<Textfield
<StudioTextfield
label={t('local_changes.modal_delete_modal_textfield_label')}
description={t('local_changes.modal_delete_modal_textfield_description', {
appName: app,
})}
size='small'
value={nameToDelete}
onChange={(e) => setNameToDelete(e.target.value)}
/>
Expand Down
5 changes: 2 additions & 3 deletions frontend/packages/text-editor/src/TextEntry.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { useState } from 'react';
import type { TextTableRowEntry } from './types';
import type { UpsertTextResourceMutation } from 'app-shared/hooks/mutations/useUpsertTextResourceMutation';
import { Textarea } from '@digdir/designsystemet-react';
import { Variables } from './Variables';
import { useAutoSizeTextArea } from 'app-shared/hooks/useAutoSizeTextArea';
import { APP_NAME } from 'app-shared/constants';
import { FormField } from 'app-shared/components/FormField/FormField';
import { useTranslation } from 'react-i18next';
import { StudioTextarea } from '@studio/components';

export interface TextEntryProps extends TextTableRowEntry {
textId: string;
Expand Down Expand Up @@ -47,7 +47,7 @@ export const TextEntry = ({
if (errorCode === 'TextSouldNotBeEmpty') return t('validation_errors.required');
}}
renderField={({ fieldProps }) => (
<Textarea
<StudioTextarea
{...fieldProps}
aria-label={t('text_editor.table_row_input_label', {
lang: t(`language.${lang}`),
Expand All @@ -57,7 +57,6 @@ export const TextEntry = ({
onBlur={handleTextEntryBlur}
onChange={handleTextEntryChange}
ref={textareaRef}
size='small'
/>
)}
></FormField>
Expand Down
Loading

0 comments on commit 085d2c5

Please sign in to comment.