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

Extract <Fieldset /> component #2758

Merged
merged 27 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b51ca81
extracts helptext button from label html tag
cammiida Nov 26, 2024
55d4cb1
extracts fieldset/legend label type to app-components
cammiida Nov 26, 2024
60c7a6d
updates useLabel args to only need node and overrideDisplay as props
cammiida Nov 27, 2024
0d6f1ce
updates description tests for inputcomponent and connects description…
cammiida Nov 27, 2024
7c95726
refactors all old fieldset to new, deletes old and adds tests to new
cammiida Nov 27, 2024
9b392e3
fixes cypress test
cammiida Nov 27, 2024
b1c283a
fixes textareacomponent jest test
cammiida Nov 27, 2024
d96a3da
Merge branch 'main' into chore/extract-fieldset
cammiida Nov 29, 2024
f01e5bf
removes padding below label
cammiida Nov 29, 2024
31a0497
Merge branch 'main' into chore/extract-fieldset
cammiida Nov 29, 2024
6203a86
uses dumb panel component for group component panel
cammiida Nov 29, 2024
be0e5aa
readds dumb label description bottom padding
cammiida Nov 29, 2024
559db8b
more styling fixes
cammiida Nov 29, 2024
378b0eb
more group styling fixes
cammiida Nov 29, 2024
9076725
Merge branch 'main' into chore/extract-fieldset
cammiida Nov 29, 2024
d793f14
updates table import casing
cammiida Nov 29, 2024
327ba21
more css tweaks
cammiida Nov 29, 2024
58f31d5
more styling tweaks
cammiida Dec 2, 2024
334966f
Merge branch 'main' into chore/extract-fieldset
cammiida Dec 2, 2024
f52c8b2
reverts groupcomponent changes but adds some new
cammiida Dec 2, 2024
bf908ad
more fixes
cammiida Dec 2, 2024
01cd164
fixes full width panel
cammiida Dec 2, 2024
0db4e7f
fixes legend styling for group component being applied for all legend…
cammiida Dec 2, 2024
9aea47f
Merge branch 'main' into chore/extract-fieldset
cammiida Dec 3, 2024
b490d04
adds padding to group legend and description and fixes summary test
cammiida Dec 3, 2024
7bd60ff
fixes summary group styling
cammiida Dec 3, 2024
3a8c9b1
adds size prop to fieldset with default md and sets fieldset size sm …
cammiida Dec 3, 2024
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
Original file line number Diff line number Diff line change
@@ -1,43 +1,48 @@
import React from 'react';

import { screen } from '@testing-library/react';
import { render, screen } from '@testing-library/react';

import { Fieldset } from 'src/components/form/Fieldset';
import { renderWithoutInstanceAndLayout } from 'src/test/renderWithProviders';
import type { FieldsetProps } from 'src/components/form/Fieldset';
import { Fieldset } from 'src/app-components/Label/Fieldset';

describe('Fieldset', () => {
const render = async (props?: Partial<FieldsetProps>) =>
await renderWithoutInstanceAndLayout({
renderer: () => (
<Fieldset
legend='legend test'
description='description test'
{...props}
/>
),
});

it('renders with accessible legend', async () => {
await render();
render(<Fieldset legend='legend test' />);
const fieldset = screen.getByRole('group', { name: /legend test/i });
expect(fieldset).toBeInTheDocument();
});

it('renders with accessible description', async () => {
await render();
render(
<Fieldset
legend='legend test'
description={<span>description test</span>}
/>,
);

const description = screen.getByText('description test');
expect(description).toBeInTheDocument();
});

it('provides an optional indicator', async () => {
await render({ required: false, labelSettings: { optionalIndicator: true } });
render(
<Fieldset
legend='legend test'
required={false}
optionalIndicator={<span>(valgfri)</span>}
/>,
);
const fieldset = screen.getByRole('group', { name: /legend test \(valgfri\)/i });
expect(fieldset).toBeInTheDocument();
});

it('provides an required indicator', async () => {
await render({ required: true });
render(
<Fieldset
legend='legend test'
required={true}
requiredIndicator={<span>*</span>}
/>,
);
const fieldset = screen.getByRole('group', { name: /legend test \*/i });
expect(fieldset).toBeInTheDocument();
});
Expand Down
93 changes: 93 additions & 0 deletions src/app-components/Label/Fieldset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from 'react';
import type { JSX, PropsWithChildren, ReactElement } from 'react';

import { Fieldset as DesignsystemetFieldset, Label as DesignsystemetLabel } from '@digdir/designsystemet-react';
import { Grid } from '@material-ui/core';
import cn from 'classnames';
import type { LabelProps as DesignsystemetLabelProps } from '@digdir/designsystemet-react';

import labelClasses from 'src/app-components/Label/Label.module.css';
import type { GridSize } from 'src/app-components/Label/types';

export type FieldsetProps = {
id?: string;
legend: string | ReactElement | undefined;
className?: string;
grid?: GridSize;
optionalIndicator?: ReactElement;
help?: ReactElement;
description?: ReactElement;
required?: boolean;
requiredIndicator?: JSX.Element;
style?: DesignsystemetLabelProps['style'];
};

export function Fieldset({
id,
children,
className,
legend,
grid,
style,
help,
description,
required,
requiredIndicator,
optionalIndicator,
}: PropsWithChildren<FieldsetProps>) {
if (!legend) {
return (
<Grid
id={id}
container
spacing={2}
>
<Grid
item
{...(grid ?? { xs: 12 })}
className={className}
>
{children}
</Grid>
</Grid>
);
}

return (
<Grid
id={id}
container
spacing={2}
>
<Grid
item
{...(grid ?? { xs: 12 })}
>
<DesignsystemetFieldset
className={cn(className)}
legend={
<span className={cn(labelClasses.labelAndHelpWrapper)}>
<DesignsystemetLabel
weight='medium'
size='md'
style={style}
asChild
>
<span>
{legend}
{required && requiredIndicator}
{!required && optionalIndicator}
</span>
</DesignsystemetLabel>
{help}
</span>
}
// FIXME: find a way to use classnames for setting font size. Not working currently
description={description && <div style={{ fontSize: '1rem' }}>{description}</div>}
>
{children}
</DesignsystemetFieldset>
</Grid>
</Grid>
);
}
10 changes: 5 additions & 5 deletions src/app-components/Label/Label.module.css
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
.label {
.labelAndHelpWrapper {
display: flex;
gap: var(--fds-spacing-2);
align-items: center;
}

.description {
padding-bottom: var(--fds-spacing-2);
}

.labelAndDescWrapper {
display: flex;
flex-direction: column;
gap: var(--fds-spacing-1);
align-items: flex-start;
}

.description {
padding-bottom: var(--fds-spacing-2);
}
39 changes: 20 additions & 19 deletions src/app-components/Label/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,37 @@ import React from 'react';
import type { JSX, PropsWithChildren, ReactElement } from 'react';

import { Label as DesignsystemetLabel } from '@digdir/designsystemet-react';
import { Grid, type GridProps } from '@material-ui/core';
import { Grid } from '@material-ui/core';
import cn from 'classnames';
import type { LabelProps as DesignsystemetLabelProps } from '@digdir/designsystemet-react';

import classes from 'src/app-components/Label/Label.module.css';

type GridSize = Pick<GridProps, 'xs' | 'sm' | 'md' | 'lg' | 'xl'>;
import type { GridSize } from 'src/app-components/Label/types';

type LabelProps = {
label: string | undefined;
label: string | ReactElement | undefined;
htmlFor?: DesignsystemetLabelProps['htmlFor'];
required?: boolean;
requiredIndicator?: JSX.Element;
optionalIndicator?: ReactElement;
help?: ReactElement;
description?: ReactElement;
className?: string;
grid?: GridSize;
required?: boolean;
requiredIndicator?: JSX.Element;
} & Pick<DesignsystemetLabelProps, 'htmlFor' | 'style'>;
style?: DesignsystemetLabelProps['style'];
};

export function Label({
label,
htmlFor,
required,
requiredIndicator,
optionalIndicator,
help,
description,
htmlFor,
style,
className,
grid,
style,
children,
}: PropsWithChildren<LabelProps>) {
if (!label) {
Expand All @@ -48,20 +49,20 @@ export function Label({
{...(grid ?? { xs: 12 })}
>
<span className={classes.labelAndDescWrapper}>
<DesignsystemetLabel
weight='medium'
size='md'
htmlFor={htmlFor}
className={cn(classes.label, className)}
style={style}
>
<div>
<span className={classes.labelAndHelpWrapper}>
<DesignsystemetLabel
weight='medium'
size='md'
htmlFor={htmlFor}
className={cn(className)}
style={style}
>
{label}
{required && requiredIndicator}
{!required && optionalIndicator}
</div>
</DesignsystemetLabel>
{help}
</DesignsystemetLabel>
</span>
{description && <div className={classes.description}>{description}</div>}
</span>
</Grid>
Expand Down
3 changes: 3 additions & 0 deletions src/app-components/Label/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { GridProps } from '@material-ui/core';

export type GridSize = Pick<GridProps, 'xs' | 'sm' | 'md' | 'lg' | 'xl'>;
1 change: 1 addition & 0 deletions src/app-components/Panel/Panel.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
display: flex;
flex-direction: column;
gap: var(--fds-spacing-1);
width: 100%;
}

.panelHeader {
Expand Down
3 changes: 3 additions & 0 deletions src/app-components/Panel/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type PanelProps = PropsWithChildren<{
showIcon?: boolean;
forceMobileLayout?: boolean;
title?: JSX.Element;
style?: React.CSSProperties;
}>;

type PanelIconProps = {
Expand Down Expand Up @@ -68,6 +69,7 @@ export const Panel: React.FC<PanelProps> = ({
showIcon = false,
forceMobileLayout = false,
title,
style,
children,
}) => {
const isMobile = useIsMobile();
Expand All @@ -78,6 +80,7 @@ export const Panel: React.FC<PanelProps> = ({
className={cn(classes.panel, {
[classes.panelMobileLayout]: isMobileLayout,
})}
style={style}
>
<div className={cn(classes.panelContentWrapper, classes[`panelContentWrapper_${variant}`])}>
{showIcon && (
Expand Down
5 changes: 2 additions & 3 deletions src/components/ConditionalWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import type { JSX } from 'react';
import type { JSX, PropsWithChildren } from 'react';
import type React from 'react';

interface IConditionalWrapperProps {
condition: boolean;
wrapper: (children: React.ReactNode) => JSX.Element;
children: JSX.Element;
}

export const ConditionalWrapper = ({ condition, wrapper, children }: IConditionalWrapperProps) => {
export const ConditionalWrapper = ({ condition, wrapper, children }: PropsWithChildren<IConditionalWrapperProps>) => {
if (condition) {
return wrapper(children);
} else {
Expand Down
69 changes: 0 additions & 69 deletions src/components/form/Fieldset.tsx

This file was deleted.

Loading
Loading