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

fix: simplify studioToggleableTextfield #14402

Closed
wants to merge 12 commits into from
4 changes: 1 addition & 3 deletions frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@
"process_editor.configuration_panel_actions_set_server_action_info": "Angir at handlingen knyttes til neste steg i prosessen.",
"process_editor.configuration_panel_actions_set_server_action_label": "Knytt handlingen til neste steg.",
"process_editor.configuration_panel_actions_title": "Handlinger",
"process_editor.configuration_panel_change_task_id": "Endre ID",
"process_editor.configuration_panel_change_task_id_label": "Oppgave-ID",
"process_editor.configuration_panel_confirmation_task": "Oppgave: Bekreftelse",
"process_editor.configuration_panel_custom_receipt_accordion_header": "Kvittering",
"process_editor.configuration_panel_custom_receipt_cancel_button": "Avbryt",
Expand All @@ -710,7 +710,6 @@
"process_editor.configuration_panel_custom_receipt_delete_receipt": "Er du sikker på at du vil slette kvitteringen din?",
"process_editor.configuration_panel_custom_receipt_heading": "Opprett din egen kvittering",
"process_editor.configuration_panel_custom_receipt_info": "Hvis du heller vil lage din egen kvittering, kan du opprette den her. Kvitteringen du lager selv vil overstyre standardkvitteringen.",
"process_editor.configuration_panel_custom_receipt_layout_set_name": "Navn på kvittering: ",
"process_editor.configuration_panel_custom_receipt_layout_set_name_validation": "Navnet må ha minst 2 tegn",
"process_editor.configuration_panel_custom_receipt_navigate_to_design_button": "Gå til Utforming",
"process_editor.configuration_panel_custom_receipt_navigate_to_design_title": "Gå til Utforming for å utforme kvitteringen din",
Expand Down Expand Up @@ -1567,7 +1566,6 @@
"ux_editor.file_upload_component.valid_file_endings": "Innstillinger for filopplastingskomponent",
"ux_editor.formLayout.warning_duplicates": "Du har den samme ID-en på flere komponenter: ",
"ux_editor.formLayout.warning_duplicates.cannot_publish": "Du kan ikke publisere appen eller konfigurere komponentene før du har rettet opp feilen.",
"ux_editor.id_identifier": "ID: {{item}}",
"ux_editor.image_component.settings": "Innstillinger for bilde",
"ux_editor.info": "Informasjon",
"ux_editor.input_popover_label": "Gi nytt navn til siden",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
.container {
display: flex;
gap: var(--fds-spacing-2);
padding: var(--fds-spacing-3);
box-sizing: border-box;
align-items: flex-start;
padding: var(--fds-spacing-2);
}

.prefixIcon {
color: var(--fds-semantic-text-neutral-default);
margin-top: var(--fds-spacing-7);
margin-top: var(--fds-spacing-10);
font-size: var(--fds-sizing-4);
align-content: center;
}

.textfield {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export default meta;
export const Preview: Story = (args) => <StudioIconTextfield {...args}></StudioIconTextfield>;

Preview.args = {
icon: <PencilIcon />,
Icon: PencilIcon,
label: 'Write a text',
value: 2.3,
error: 'Your custom error message!',
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,38 @@ import { testCustomAttributes } from '../../test-utils/testCustomAttributes';

describe('StudioIconTextfield', () => {
it('render the icon', async () => {
renderStudioIconTextfield({
icon: <KeyVerticalIcon title='my key icon title' />,
});
expect(screen.getByTitle('my key icon title')).toBeInTheDocument();
renderStudioIconTextfield();
expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument();
});

it('should render label', () => {
renderStudioIconTextfield({
icon: <div />,
label: 'id',
});
expect(screen.getByLabelText('id')).toBeInTheDocument();
renderStudioIconTextfield();
expect(screen.getByLabelText(label)).toBeInTheDocument();
});

it('should execute onChange callback when input value changes', async () => {
const user = userEvent.setup();
const onChangeMock = jest.fn();

renderStudioIconTextfield({
icon: <div />,
label: 'Your ID',
onChange: onChangeMock,
});

const input = screen.getByLabelText('Your ID');

renderStudioIconTextfield();
const input = screen.getByRole('textbox', { name: label });
const inputValue = 'my id is 123';
await user.type(input, inputValue);
expect(onChangeMock).toHaveBeenCalledTimes(inputValue.length);
expect(onChange).toHaveBeenCalledTimes(inputValue.length);
});

it('should forward the rest of the props to the input', () => {
const getTextbox = (): HTMLInputElement => screen.getByRole('textbox') as HTMLInputElement;
testCustomAttributes<HTMLInputElement>(renderStudioIconTextfield, getTextbox);
});
});
const renderStudioIconTextfield = (props: StudioIconTextfieldProps) => {
return render(<StudioIconTextfield {...props} />);

const label = 'label';
const onChange = jest.fn();
const defaultProps: StudioIconTextfieldProps = {
Icon: KeyVerticalIcon,
label,
onChange,
};

const renderStudioIconTextfield = (props: Partial<StudioIconTextfieldProps> = {}) => {
return render(<StudioIconTextfield {...defaultProps} {...props} />);
};
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
import React, { forwardRef } from 'react';
import { StudioTextfield, type StudioTextfieldProps } from '../StudioTextfield';
import cn from 'classnames';

import classes from './StudioIconTextfield.module.css';

export type StudioIconTextfieldProps = {
icon: React.ReactNode;
Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Når vi sender inn ikonet på denne måten, får vi ikke sendt med propper. Er det noen utfordringer med metoden som var brukt her fra før?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nei. Tror jeg gjorde det i hovedsak for å slippe en ekstra div. Men var usikker på om det fulgte med noen utfordringer. Kan godt bruke den gamle metoden? 😊

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jeg ville holdt meg til den gamle, siden vi også gjør det på den måten i StudioButton.

label: string;
} & StudioTextfieldProps;

export const StudioIconTextfield = forwardRef<HTMLDivElement, StudioIconTextfieldProps>(
(
{ icon, className: givenClassName, ...rest }: StudioIconTextfieldProps,
{ Icon, label, className: givenClassName, ...rest }: StudioIconTextfieldProps,
ref,
): React.ReactElement => {
const className = cn(givenClassName, classes.container);
return (
<div className={className} ref={ref}>
<div aria-hidden className={classes.prefixIcon}>
{icon}
</div>
<StudioTextfield {...rest} className={classes.textfield} />
<Icon aria-hidden className={classes.prefixIcon} />
<StudioTextfield label={label} size='small' {...rest} className={classes.textfield} />
</div>
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const ExampleUseCase: ExampleUseCase = (args): React.ReactElement => {
<StudioIconTextfield
error={name !== 'Bernard' ? 'Navnet må være Bernard' : ''}
onChange={(e) => setName(e.target.value)}
icon={<KeyVerticalIcon />}
Icon={KeyVerticalIcon}
size='sm'
label='Nytt navn'
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
justify-content: flex-start;
align-items: center;
border-radius: 0;
border: none;
width: 100%;
}

Expand All @@ -13,7 +14,7 @@
align-items: center;
color: var(--fds-semantic-text-neutral-default);
width: 100%;
gap: var(--fds-spacing-1);
gap: var(--fds-spacing-2);
}

.textContainer,
Expand All @@ -33,18 +34,12 @@
flex-direction: column;
}

.editIconWrapper {
flex: 1;
text-align: right;
.editIcon {
display: none;
}

.button:hover .editIconWrapper,
.button:focus .editIconWrapper {
.button:hover .editIcon,
.button:focus .editIcon {
display: flex;
align-items: center;
}

.editIcon {
margin-left: auto;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,47 @@ import { render, screen } from '@testing-library/react';
import { StudioTextfieldToggleView } from './StudioTextfieldToggleView';
import type { StudioTextfieldToggleViewProps } from './StudioTextfieldToggleView';
import userEvent from '@testing-library/user-event';
import { KeyVerticalIcon } from '@studio/icons';

describe('StudioTextfieldToggleView', () => {
it('should render button text', () => {
renderStudioTextfieldToggleView({ children: 'My awesome button' });
expect(screen.getByRole('button', { name: 'My awesome button' })).toBeInTheDocument();
renderStudioTextfieldToggleView();
expect(screen.getByRole('button', { name: value })).toBeInTheDocument();
});

it('should execute the "onClick" method when button is clicked', async () => {
const user = userEvent.setup();
const onClickMock = jest.fn();

renderStudioTextfieldToggleView({ children: 'My awesome button text', onClick: onClickMock });

await user.click(screen.getByRole('button', { name: 'My awesome button text' }));
expect(onClickMock).toHaveBeenCalledTimes(1);
});

it('should render the KeyVerticalIcon', () => {
renderStudioTextfieldToggleView({ children: 'My awesome button text' });

// Uses testId to find the KeyVerticalIcon, since it's not available for screen reader.
expect(screen.getByTestId('keyIcon')).toBeInTheDocument();
renderStudioTextfieldToggleView();
await user.click(screen.getByRole('button', { name: value }));
expect(onClick).toHaveBeenCalledTimes(1);
});

it('should render the PencilIcon', () => {
renderStudioTextfieldToggleView({ children: 'My awesome button text' });

// Uses testId to find the EditIcon, since it's not available for screen reader.
expect(screen.getByTestId('editIcon')).toBeInTheDocument();
it('should render the both given Icon and pencilIcon', () => {
renderStudioTextfieldToggleView();
expect(screen.getAllByRole('img', { hidden: true })).toHaveLength(2);
});

it('should forward the rest of the props to the button', () => {
renderStudioTextfieldToggleView({ children: 'My awesome button text', disabled: true });
expect(screen.getByRole('button', { name: 'My awesome button text' })).toBeDisabled();
renderStudioTextfieldToggleView({ disabled: true });
expect(screen.getByRole('button', { name: value })).toBeDisabled();
});

it('should show label if defined', () => {
const studioTextfieldToggleViewLabel = 'studioTextfieldToggleViewLabel';
renderStudioTextfieldToggleView({
children: 'My awesome button text',
label: studioTextfieldToggleViewLabel,
});
expect(screen.getByText(studioTextfieldToggleViewLabel)).toBeInTheDocument();
renderStudioTextfieldToggleView();
expect(screen.getByText(label)).toBeInTheDocument();
});
});

const renderStudioTextfieldToggleView = (props: Partial<StudioTextfieldToggleViewProps>) => {
return render(<StudioTextfieldToggleView {...props} />);
const value = 'value';
const label = 'label';
const onClick = jest.fn();
const defaultProps: StudioTextfieldToggleViewProps = {
value,
label,
onClick,
Icon: KeyVerticalIcon,
};

const renderStudioTextfieldToggleView = (props: Partial<StudioTextfieldToggleViewProps> = {}) => {
return render(<StudioTextfieldToggleView {...defaultProps} {...props} />);
};
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
import React from 'react';
import { PencilIcon, KeyVerticalIcon } from '@studio/icons';
import { PencilIcon } from '@studio/icons';
import { StudioButton, type StudioButtonProps } from '@studio/components';
import classes from './StudioTextfieldToggleView.module.css';
import cn from 'classnames';

export type StudioTextfieldToggleViewProps = StudioButtonProps & {
label?: string;
export type StudioTextfieldToggleViewProps = Omit<StudioButtonProps, 'icon'> & {
Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
label: string;
};

export const StudioTextfieldToggleView = ({
onClick,
children,
title,
label,
className: givenClass,
icon = <KeyVerticalIcon data-testid='keyIcon' aria-hidden />,
Icon,
...rest
}: StudioTextfieldToggleViewProps) => {
const className = cn(classes.button, givenClass);

return (
<StudioButton className={className} onClick={onClick} {...rest}>
<span className={classes.viewModeIconsContainer} title={title}>
{icon}
<StudioButton variant='tertiary' className={className} onClick={onClick} {...rest}>
<span className={classes.viewModeIconsContainer}>
<Icon aria-hidden />
<span className={classes.textContainer}>
{label && <span className={classes.label}>{label}</span>}
<span className={classes.ellipsis}>{children}</span>
{label && (
<span className={classes.label} aria-hidden>
{label}
</span>
)}
<span className={classes.ellipsis}>{rest.value}</span>
</span>
</span>
<span className={classes.editIconWrapper}>
<PencilIcon className={classes.editIcon} data-testid='editIcon' aria-hidden />
</span>
<PencilIcon className={classes.editIcon} aria-hidden />
</StudioButton>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import type { Meta, StoryFn } from '@storybook/react';
import { StudioToggleableTextfield } from './StudioToggleableTextfield';
import { KeyVerticalIcon } from '@studio/icons';

type Story = StoryFn<typeof StudioToggleableTextfield>;

Expand All @@ -16,19 +15,10 @@ export const Preview: Story = (args) => (

Preview.args = {
onIsViewMode: () => {},
viewProps: {
variant: 'tertiary',
size: 'small',
label: 'My awesome label',
children: 'My awesome value',
},
inputProps: {
icon: <KeyVerticalIcon />,
label: 'My awesome label',
size: 'small',
placeholder: 'Placeholder',
error: '',
},
label: 'My awesome label',
title: 'My awesome title',
value: 'My awesome value',
error: '',
};

export default meta;
Loading
Loading