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(ErrorSummary): split .Item into two components, add asChild support #3040

Merged
merged 5 commits into from
Jan 22, 2025
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
7 changes: 7 additions & 0 deletions .changeset/chatty-items-sell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@digdir/designsystemet-react": minor
---

**ErrorSummary**: Split `.Item` into two components
- `ErrorSummary.Item` renders a `li`
- `ErrorSummary.Link` renders the link
5 changes: 5 additions & 0 deletions .changeset/little-berries-divide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@digdir/designsystemet-react": patch
---

**ErrorSummary**: Add support for `asChild`
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@ export const Preview: Story = (args) => (
For å gå videre må du rette opp følgende feil:
</ErrorSummary.Heading>
<ErrorSummary.List>
<ErrorSummary.Item href='#'>
Fødselsdato kan ikke være etter år 2005
<ErrorSummary.Item>
<ErrorSummary.Link href='#'>
Fødselsdato kan ikke være etter år 2005
</ErrorSummary.Link>
</ErrorSummary.Item>
<ErrorSummary.Item href='#'>
Telefonnummer kan kun inneholde siffer
<ErrorSummary.Item>
<ErrorSummary.Link href='#'>
Telefonnummer kan kun inneholde siffer
</ErrorSummary.Link>
</ErrorSummary.Item>
<ErrorSummary.Item>
<ErrorSummary.Link href='#'>E-post må være gyldig</ErrorSummary.Link>
</ErrorSummary.Item>
<ErrorSummary.Item href='#'>E-post må være gyldig</ErrorSummary.Item>
</ErrorSummary.List>
</ErrorSummary>
);
Expand All @@ -51,11 +57,15 @@ export const WithForm: Story = () => (
For å gå videre må du rette opp følgende feil:
</ErrorSummary.Heading>
<ErrorSummary.List>
<ErrorSummary.Item href='#fornavn'>
Fornavn må være minst 2 tegn
<ErrorSummary.Item>
<ErrorSummary.Link href='#fornavn'>
Fornavn må være minst 2 tegn
</ErrorSummary.Link>
</ErrorSummary.Item>
<ErrorSummary.Item href='#telefon'>
Telefonnummer kan kun inneholde siffer
<ErrorSummary.Item>
<ErrorSummary.Link href='#telefon'>
Telefonnummer kan kun inneholde siffer
</ErrorSummary.Link>
</ErrorSummary.Item>
</ErrorSummary.List>
</ErrorSummary>
Expand Down Expand Up @@ -86,11 +96,15 @@ export const ShowHide: Story = () => {
For å gå videre må du rette opp følgende feil:
</ErrorSummary.Heading>
<ErrorSummary.List>
<ErrorSummary.Item href='#fornavn'>
Fornavn må være minst 2 tegn
<ErrorSummary.Item>
<ErrorSummary.Link href='#fornavn'>
Fornavn må være minst 2 tegn
</ErrorSummary.Link>
</ErrorSummary.Item>
<ErrorSummary.Item href='#telefon'>
Telefonnummer kan kun inneholde siffer
<ErrorSummary.Item>
<ErrorSummary.Link href='#telefon'>
Telefonnummer kan kun inneholde siffer
</ErrorSummary.Link>
</ErrorSummary.Item>
</ErrorSummary.List>
</ErrorSummary>
Expand Down
15 changes: 9 additions & 6 deletions packages/react/src/components/ErrorSummary/ErrorSummary.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Slot } from '@radix-ui/react-slot';
import cl from 'clsx/lite';
import { createContext, forwardRef, useId, useState } from 'react';
import type { HTMLAttributes } from 'react';
Expand All @@ -13,28 +14,30 @@ export const ErrorSummaryContext = createContext<ErrorSummaryContextType>({
setHeadingId: () => {},
});

export type ErrorSummaryProps = Omit<
HTMLAttributes<HTMLDivElement> & DefaultProps,
'data-color'
>;
export type ErrorSummaryProps = {
asChild?: React.ReactNode;
} & Omit<HTMLAttributes<HTMLDivElement> & DefaultProps, 'data-color'>;

export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
function ErrorSummary(
{
className,
asChild,
role = 'alert',
'aria-live': ariaLive = 'polite',
'aria-relevant': ariaRelevant = 'all',
className,
...rest
},
ref,
) {
const randomId = useId();
const [headingId, setHeadingId] = useState<string>(randomId);

const Component = asChild ? Slot : 'div';

return (
<ErrorSummaryContext.Provider value={{ headingId, setHeadingId }}>
<div
<Component
aria-labelledby={headingId}
aria-live={ariaLive}
aria-relevant={ariaRelevant}
Expand Down
39 changes: 4 additions & 35 deletions packages/react/src/components/ErrorSummary/ErrorSummaryItem.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,11 @@
import { forwardRef } from 'react';
import type { LinkProps } from '../Link';
import { Link } from '../Link';
import type { ListItemProps } from '../List';
import { List } from '../List';
import { ListItem, type ListItemProps } from '../List';

type RequiredHref = {
href: LinkProps['href'];
/**
* Change the default rendered element for the one passed as a child, merging their props and behavior.
* @default false
*/
asChild?: false;
};

type OptionalHref = {
href?: LinkProps['href'];
/**
* Change the default rendered element for the one passed as a child, merging their props and behavior.
* @default false
*/
asChild: true;
};

export type ErrorSummaryItemProps = (RequiredHref | OptionalHref) &
Omit<ListItemProps, 'asChild' | 'ref'>;
export type ErrorSummaryItemProps = ListItemProps;

export const ErrorSummaryItem = forwardRef<
HTMLLIElement,
ErrorSummaryItemProps
>(function ErrorSummaryItem(
{ href, asChild, children, ...rest }: ErrorSummaryItemProps,
ref,
) {
return (
<List.Item {...rest} ref={ref}>
<Link href={href} asChild={asChild}>
{children}
</Link>
</List.Item>
);
>(function ErrorSummaryItem({ ...rest }: ErrorSummaryItemProps, ref) {
return <ListItem ref={ref} {...rest} />;
});
12 changes: 12 additions & 0 deletions packages/react/src/components/ErrorSummary/ErrorSummaryLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { forwardRef } from 'react';
import type { LinkProps } from '../Link';
import { Link } from '../Link';

export type ErrorSummaryLinkProps = LinkProps;

export const ErrorSummaryLink = forwardRef<
HTMLAnchorElement,
ErrorSummaryLinkProps
>(function ErrorSummaryLink({ ...rest }: ErrorSummaryLinkProps, ref) {
return <Link ref={ref} data-color='neutral' {...rest} />;
});
9 changes: 8 additions & 1 deletion packages/react/src/components/ErrorSummary/index.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,41 @@
import { ErrorSummary as ErrorSummaryParent } from './ErrorSummary';
import { ErrorSummaryHeading } from './ErrorSummaryHeading';
import { ErrorSummaryItem } from './ErrorSummaryItem';
import { ErrorSummaryLink } from './ErrorSummaryLink';
import { ErrorSummaryList } from './ErrorSummaryList';

/**
* @example
* <ErrorSummary>
* <ErrorSummary.Heading>Heading</ErrorSummary.Heading>
* <ErrorSummary.List>
* <ErrorSummary.Item>Item 1</ErrorSummary.Item>
* <ErrorSummary.Item>
* <ErrorSummary.Link>Item 1</ErrorSummary.Link>
* </ErrorSummary.Item>
* </ErrorSummary.List>
* </ErrorSummary>
*/
const ErrorSummary = Object.assign(ErrorSummaryParent, {
Heading: ErrorSummaryHeading,
Item: ErrorSummaryItem,
List: ErrorSummaryList,
Link: ErrorSummaryLink,
});

ErrorSummary.Item.displayName = 'ErrorSummary.Item';
ErrorSummary.Heading.displayName = 'ErrorSummary.Heading';
ErrorSummary.List.displayName = 'ErrorSummary.List';
ErrorSummary.Link.displayName = 'ErrorSummary.Link';

export type { ErrorSummaryProps } from './ErrorSummary';
export type { ErrorSummaryItemProps } from './ErrorSummaryItem';
export type { ErrorSummaryHeadingProps } from './ErrorSummaryHeading';
export type { ErrorSummaryListProps } from './ErrorSummaryList';
export type { ErrorSummaryLinkProps } from './ErrorSummaryLink';
export {
ErrorSummary,
ErrorSummaryItem,
ErrorSummaryHeading,
ErrorSummaryList,
ErrorSummaryLink,
};
12 changes: 8 additions & 4 deletions packages/react/stories/testing.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,11 +277,15 @@ export const Sizes: StoryFn = () => {
For å gå videre må du rette opp følgende feil:
</ErrorSummary.Heading>
<ErrorSummary.List>
<ErrorSummary.Item href='#'>
Fødselsdato kan ikke være etter år 2005
<ErrorSummary.Item>
<ErrorSummary.Link href='#'>
Fødselsdato kan ikke være etter år 2005
</ErrorSummary.Link>
</ErrorSummary.Item>
<ErrorSummary.Item href='#'>
E-post må være gyldig
<ErrorSummary.Item>
<ErrorSummary.Link href='#'>
E-post må være gyldig
</ErrorSummary.Link>
</ErrorSummary.Item>
</ErrorSummary.List>
</ErrorSummary>
Expand Down
Loading