import { ComponentPropsWithoutRef, ReactNode } from 'react';
import { Icon } from '../Icon/Icon';
import './content-diff.css';
// Stand-in for the v2 `mergeClasses` util, which the published package does
// not export. The port uses the real one.
const mergeClasses = (classes: Array<string | null | undefined>) =>
classes.filter(Boolean).join(' ');
export interface ContentDiffProps extends ComponentPropsWithoutRef<'dl'> {
/**
* The new value.
*/
after: ReactNode;
/**
* Name of the new value for screen readers (for example "After"); not
* shown. Provide it translated.
*/
afterLabel: string;
/**
* The current value.
*/
before: ReactNode;
/**
* Name of the current value for screen readers (for example "Before"); not
* shown. Provide it translated.
*/
beforeLabel: string;
/**
* Additional class names.
*/
className?: string;
}
/**
* ContentDiff UI component. A before and after of a piece of content, stacked
* like a text diff: the old value on a red line with a minus, the new value on
* a green line with a plus.
*/
export const ContentDiff = ({
after,
afterLabel,
before,
beforeLabel,
className,
...props
}: ContentDiffProps) => {
const baseClass = 'pds-content-diff';
return (
<dl className={mergeClasses([baseClass, className])} {...props}>
<div className={`${baseClass}__line ${baseClass}__line--before`}>
<dt className='visually-hidden'>{beforeLabel}</dt>
<Icon
aria-hidden='true'
className={`${baseClass}__marker`}
iconName='minus'
size='s'
/>
<dd className={`${baseClass}__text`}>{before}</dd>
</div>
<div className={`${baseClass}__line ${baseClass}__line--after`}>
<dt className='visually-hidden'>{afterLabel}</dt>
<Icon
aria-hidden='true'
className={`${baseClass}__marker`}
iconName='plus'
size='s'
/>
<dd className={`${baseClass}__text`}>{after}</dd>
</div>
</dl>
);
};
Content Diff
A component, ContentDiff: the old value on a red line with a minus, the new value on a green line with a plus, in one bordered block, like a text diff.
Net-new componentOpen in Storybook