Skip to content

Commit 85a4647

Browse files
committed
simplify studioToggleableTextfield some
1 parent 683992b commit 85a4647

File tree

41 files changed

+395
-656
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+395
-656
lines changed

frontend/language/src/nb.json

+1-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
"app_content_library.code_lists.code_list_accordion_title": "Kodeliste: {{codeListTitle}}",
1616
"app_content_library.code_lists.code_list_edit_id_label": "Navn på kodeliste",
1717
"app_content_library.code_lists.code_list_edit_id_title": "Rediger navn på kodelisten {{codeListName}}",
18-
"app_content_library.code_lists.code_list_view_id_title": "Navn på kodeliste: {{codeListName}}",
1918
"app_content_library.code_lists.code_lists_count_info_none": "Det finnes ingen kodelister i biblioteket.",
2019
"app_content_library.code_lists.code_lists_count_info_plural": "Det finnes <bold>{{codeListsCount}}</bold> kodelister i biblioteket.",
2120
"app_content_library.code_lists.code_lists_count_info_single": "Det finnes <bold>1</bold> kodeliste i biblioteket.",
@@ -689,7 +688,7 @@
689688
"process_editor.configuration_panel_actions_set_server_action_info": "Angir at handlingen knyttes til neste steg i prosessen.",
690689
"process_editor.configuration_panel_actions_set_server_action_label": "Knytt handlingen til neste steg.",
691690
"process_editor.configuration_panel_actions_title": "Handlinger",
692-
"process_editor.configuration_panel_change_task_id": "Endre ID",
691+
"process_editor.configuration_panel_change_task_id_label": "Oppgave-ID",
693692
"process_editor.configuration_panel_confirmation_task": "Oppgave: Bekreftelse",
694693
"process_editor.configuration_panel_custom_receipt_accordion_header": "Kvittering",
695694
"process_editor.configuration_panel_custom_receipt_cancel_button": "Avbryt",
@@ -703,7 +702,6 @@
703702
"process_editor.configuration_panel_custom_receipt_delete_receipt": "Er du sikker på at du vil slette kvitteringen din?",
704703
"process_editor.configuration_panel_custom_receipt_heading": "Opprett din egen kvittering",
705704
"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.",
706-
"process_editor.configuration_panel_custom_receipt_layout_set_name": "Navn på kvittering: ",
707705
"process_editor.configuration_panel_custom_receipt_layout_set_name_validation": "Navnet må ha minst 2 tegn",
708706
"process_editor.configuration_panel_custom_receipt_navigate_to_design_button": "Gå til Utforming",
709707
"process_editor.configuration_panel_custom_receipt_navigate_to_design_title": "Gå til Utforming for å utforme kvitteringen din",
@@ -1553,7 +1551,6 @@
15531551
"ux_editor.file_upload_component.valid_file_endings": "Innstillinger for filopplastingskomponent",
15541552
"ux_editor.formLayout.warning_duplicates": "Du har den samme ID-en på flere komponenter: ",
15551553
"ux_editor.formLayout.warning_duplicates.cannot_publish": "Du kan ikke publisere appen eller konfigurere komponentene før du har rettet opp feilen.",
1556-
"ux_editor.id_identifier": "ID: {{item}}",
15571554
"ux_editor.image_component.settings": "Innstillinger for bilde",
15581555
"ux_editor.info": "Informasjon",
15591556
"ux_editor.input_popover_label": "Gi nytt navn til siden",

frontend/libs/studio-components/src/components/StudioIconTextfield/StudioIconTextfield.module.css

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
.container {
22
display: flex;
33
gap: var(--fds-spacing-2);
4-
padding: var(--fds-spacing-3);
5-
box-sizing: border-box;
4+
align-items: flex-start;
5+
padding: var(--fds-spacing-2) var(--fds-spacing-2);
66
}
77

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

1514
.textfield {

frontend/libs/studio-components/src/components/StudioIconTextfield/StudioIconTextfield.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default meta;
1919
export const Preview: Story = (args) => <StudioIconTextfield {...args}></StudioIconTextfield>;
2020

2121
Preview.args = {
22-
icon: <PencilIcon />,
22+
Icon: PencilIcon,
2323
value: 2.3,
2424
error: 'Your custom error message!',
2525
};

frontend/libs/studio-components/src/components/StudioIconTextfield/StudioIconTextfield.test.tsx

+18-22
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,38 @@ import { testCustomAttributes } from '../../test-utils/testCustomAttributes';
88

99
describe('StudioIconTextfield', () => {
1010
it('render the icon', async () => {
11-
renderStudioIconTextfield({
12-
icon: <KeyVerticalIcon title='my key icon title' />,
13-
});
14-
expect(screen.getByTitle('my key icon title')).toBeInTheDocument();
11+
renderStudioIconTextfield();
12+
expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument();
1513
});
1614

1715
it('should render label', () => {
18-
renderStudioIconTextfield({
19-
icon: <div />,
20-
label: 'id',
21-
});
22-
expect(screen.getByLabelText('id')).toBeInTheDocument();
16+
renderStudioIconTextfield();
17+
expect(screen.getByLabelText(label)).toBeInTheDocument();
2318
});
2419

2520
it('should execute onChange callback when input value changes', async () => {
2621
const user = userEvent.setup();
27-
const onChangeMock = jest.fn();
28-
29-
renderStudioIconTextfield({
30-
icon: <div />,
31-
label: 'Your ID',
32-
onChange: onChangeMock,
33-
});
34-
35-
const input = screen.getByLabelText('Your ID');
36-
22+
renderStudioIconTextfield();
23+
const input = screen.getByRole('textbox', { name: label });
3724
const inputValue = 'my id is 123';
3825
await user.type(input, inputValue);
39-
expect(onChangeMock).toHaveBeenCalledTimes(inputValue.length);
26+
expect(onChange).toHaveBeenCalledTimes(inputValue.length);
4027
});
4128

4229
it('should forward the rest of the props to the input', () => {
4330
const getTextbox = (): HTMLInputElement => screen.getByRole('textbox') as HTMLInputElement;
4431
testCustomAttributes<HTMLInputElement>(renderStudioIconTextfield, getTextbox);
4532
});
4633
});
47-
const renderStudioIconTextfield = (props: StudioIconTextfieldProps) => {
48-
return render(<StudioIconTextfield {...props} />);
34+
35+
const label = 'label';
36+
const onChange = jest.fn();
37+
const defaultProps: StudioIconTextfieldProps = {
38+
Icon: KeyVerticalIcon,
39+
label,
40+
onChange,
41+
};
42+
43+
const renderStudioIconTextfield = (props: Partial<StudioIconTextfieldProps> = {}) => {
44+
return render(<StudioIconTextfield {...defaultProps} {...props} />);
4945
};

frontend/libs/studio-components/src/components/StudioIconTextfield/StudioIconTextfield.tsx

+4-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
11
import React, { forwardRef } from 'react';
22
import { StudioTextfield, type StudioTextfieldProps } from '../StudioTextfield';
33
import cn from 'classnames';
4-
54
import classes from './StudioIconTextfield.module.css';
65

76
export type StudioIconTextfieldProps = {
8-
icon: React.ReactNode;
7+
Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
98
} & StudioTextfieldProps;
109

1110
export const StudioIconTextfield = forwardRef<HTMLDivElement, StudioIconTextfieldProps>(
1211
(
13-
{ icon, className: givenClassName, ...rest }: StudioIconTextfieldProps,
12+
{ Icon, className: givenClassName, ...rest }: StudioIconTextfieldProps,
1413
ref,
1514
): React.ReactElement => {
1615
const className = cn(givenClassName, classes.container);
1716
return (
1817
<div className={className} ref={ref}>
19-
<div aria-hidden className={classes.prefixIcon}>
20-
{icon}
21-
</div>
22-
<StudioTextfield {...rest} className={classes.textfield} />
18+
<Icon aria-hidden className={classes.prefixIcon} />
19+
<StudioTextfield size='small' {...rest} className={classes.textfield} />
2320
</div>
2421
);
2522
},

frontend/libs/studio-components/src/components/StudioRecommendedNextAction/StudioRecommendedNextAction.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export const ExampleUseCase: ExampleUseCase = (args): React.ReactElement => {
5555
<StudioIconTextfield
5656
error={name !== 'Bernard' ? 'Navnet må være Bernard' : ''}
5757
onChange={(e) => setName(e.target.value)}
58-
icon={<KeyVerticalIcon />}
58+
Icon={KeyVerticalIcon}
5959
size='sm'
6060
label='Nytt navn'
6161
/>

frontend/libs/studio-components/src/components/StudioToggleableTextfield/StudioTextfieldToggleView/StudioTextfieldToggleView.module.css

+4-9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
grid-template-columns: auto 1fr;
1212
text-align: left;
1313
align-items: center;
14+
justify-content: space-between;
1415
color: var(--fds-semantic-text-neutral-default);
1516
width: 100%;
1617
gap: var(--fds-spacing-1);
@@ -33,18 +34,12 @@
3334
flex-direction: column;
3435
}
3536

36-
.editIconWrapper {
37-
flex: 1;
38-
text-align: right;
37+
.editIcon {
3938
display: none;
4039
}
4140

42-
.button:hover .editIconWrapper,
43-
.button:focus .editIconWrapper {
41+
.button:hover .editIcon,
42+
.button:focus .editIcon {
4443
display: flex;
4544
align-items: center;
4645
}
47-
48-
.editIcon {
49-
margin-left: auto;
50-
}

frontend/libs/studio-components/src/components/StudioToggleableTextfield/StudioTextfieldToggleView/StudioTextfieldToggleView.test.tsx

+25-30
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,47 @@ import { render, screen } from '@testing-library/react';
33
import { StudioTextfieldToggleView } from './StudioTextfieldToggleView';
44
import type { StudioTextfieldToggleViewProps } from './StudioTextfieldToggleView';
55
import userEvent from '@testing-library/user-event';
6+
import { KeyVerticalIcon } from '@studio/icons';
67

78
describe('StudioTextfieldToggleView', () => {
89
it('should render button text', () => {
9-
renderStudioTextfieldToggleView({ children: 'My awesome button' });
10-
expect(screen.getByRole('button', { name: 'My awesome button' })).toBeInTheDocument();
10+
renderStudioTextfieldToggleView();
11+
expect(screen.getByRole('button', { name: value })).toBeInTheDocument();
1112
});
1213

1314
it('should execute the "onClick" method when button is clicked', async () => {
1415
const user = userEvent.setup();
15-
const onClickMock = jest.fn();
16-
17-
renderStudioTextfieldToggleView({ children: 'My awesome button text', onClick: onClickMock });
18-
19-
await user.click(screen.getByRole('button', { name: 'My awesome button text' }));
20-
expect(onClickMock).toHaveBeenCalledTimes(1);
21-
});
22-
23-
it('should render the KeyVerticalIcon', () => {
24-
renderStudioTextfieldToggleView({ children: 'My awesome button text' });
25-
26-
// Uses testId to find the KeyVerticalIcon, since it's not available for screen reader.
27-
expect(screen.getByTestId('keyIcon')).toBeInTheDocument();
16+
renderStudioTextfieldToggleView();
17+
await user.click(screen.getByRole('button', { name: value }));
18+
expect(onClick).toHaveBeenCalledTimes(1);
2819
});
2920

30-
it('should render the PencilIcon', () => {
31-
renderStudioTextfieldToggleView({ children: 'My awesome button text' });
32-
33-
// Uses testId to find the EditIcon, since it's not available for screen reader.
34-
expect(screen.getByTestId('editIcon')).toBeInTheDocument();
21+
it('should render the both given Icon and pencilIcon', () => {
22+
renderStudioTextfieldToggleView();
23+
expect(screen.getAllByRole('img', { hidden: true })).toHaveLength(2);
3524
});
3625

3726
it('should forward the rest of the props to the button', () => {
38-
renderStudioTextfieldToggleView({ children: 'My awesome button text', disabled: true });
39-
expect(screen.getByRole('button', { name: 'My awesome button text' })).toBeDisabled();
27+
renderStudioTextfieldToggleView({ disabled: true });
28+
expect(screen.getByRole('button', { name: value })).toBeDisabled();
4029
});
4130

4231
it('should show label if defined', () => {
43-
const studioTextfieldToggleViewLabel = 'studioTextfieldToggleViewLabel';
44-
renderStudioTextfieldToggleView({
45-
children: 'My awesome button text',
46-
label: studioTextfieldToggleViewLabel,
47-
});
48-
expect(screen.getByText(studioTextfieldToggleViewLabel)).toBeInTheDocument();
32+
renderStudioTextfieldToggleView();
33+
expect(screen.getByText(label)).toBeInTheDocument();
4934
});
5035
});
5136

52-
const renderStudioTextfieldToggleView = (props: Partial<StudioTextfieldToggleViewProps>) => {
53-
return render(<StudioTextfieldToggleView {...props} />);
37+
const value = 'value';
38+
const label = 'label';
39+
const onClick = jest.fn();
40+
const defaultProps: StudioTextfieldToggleViewProps = {
41+
value,
42+
label,
43+
onClick,
44+
Icon: KeyVerticalIcon,
45+
};
46+
47+
const renderStudioTextfieldToggleView = (props: Partial<StudioTextfieldToggleViewProps> = {}) => {
48+
return render(<StudioTextfieldToggleView {...defaultProps} {...props} />);
5449
};
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,37 @@
11
import React from 'react';
2-
import { PencilIcon, KeyVerticalIcon } from '@studio/icons';
2+
import { PencilIcon } from '@studio/icons';
33
import { StudioButton, type StudioButtonProps } from '@studio/components';
44
import classes from './StudioTextfieldToggleView.module.css';
55
import cn from 'classnames';
66

7-
export type StudioTextfieldToggleViewProps = StudioButtonProps & {
7+
export type StudioTextfieldToggleViewProps = Omit<StudioButtonProps, 'icon'> & {
8+
Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
89
label?: string;
910
};
1011

1112
export const StudioTextfieldToggleView = ({
1213
onClick,
13-
children,
14-
title,
1514
label,
1615
className: givenClass,
17-
icon = <KeyVerticalIcon data-testid='keyIcon' aria-hidden />,
16+
Icon,
1817
...rest
1918
}: StudioTextfieldToggleViewProps) => {
2019
const className = cn(classes.button, givenClass);
2120

2221
return (
23-
<StudioButton className={className} onClick={onClick} {...rest}>
24-
<span className={classes.viewModeIconsContainer} title={title}>
25-
{icon}
22+
<StudioButton variant='tertiary' className={className} onClick={onClick} {...rest}>
23+
<span className={classes.viewModeIconsContainer}>
24+
<Icon aria-hidden />
2625
<span className={classes.textContainer}>
27-
{label && <span className={classes.label}>{label}</span>}
28-
<span className={classes.ellipsis}>{children}</span>
26+
{label && (
27+
<span className={classes.label} aria-hidden>
28+
{label}
29+
</span>
30+
)}
31+
<span className={classes.ellipsis}>{rest.value}</span>
2932
</span>
3033
</span>
31-
<span className={classes.editIconWrapper}>
32-
<PencilIcon className={classes.editIcon} data-testid='editIcon' aria-hidden />
33-
</span>
34+
<PencilIcon className={classes.editIcon} aria-hidden />
3435
</StudioButton>
3536
);
3637
};
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React from 'react';
22
import type { Meta, StoryFn } from '@storybook/react';
33
import { StudioToggleableTextfield } from './StudioToggleableTextfield';
4-
import { KeyVerticalIcon } from '@studio/icons';
54

65
type Story = StoryFn<typeof StudioToggleableTextfield>;
76

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

1716
Preview.args = {
1817
onIsViewMode: () => {},
19-
viewProps: {
20-
variant: 'tertiary',
21-
size: 'small',
22-
label: 'My awesome label',
23-
children: 'My awesome value',
24-
},
25-
inputProps: {
26-
icon: <KeyVerticalIcon />,
27-
label: 'My awesome label',
28-
size: 'small',
29-
placeholder: 'Placeholder',
30-
error: '',
31-
},
18+
label: 'My awesome label',
19+
title: 'My awesome title',
20+
value: 'My awesome value',
21+
error: '',
3222
};
3323

3424
export default meta;

0 commit comments

Comments
 (0)