← All proposals

Button

Starting point for a Button proposal.

Extends a PDS componentOpen in Storybook

proposals/Button/utils.tsx64 lines · View on GitHub
import {
	Children,
	ComponentPropsWithoutRef,
	isValidElement,
	ReactNode,
} from 'react';

// Stand-ins for pieces of v2 that the published package does not export.
// In the port these are the real `@libs/...` imports; delete this file.

export type ButtonDisplayType = 'label-only' | 'icon-start' | 'icon-end';

export type ButtonSize = 'xs' | 's' | 'm' | 'l';

export type ButtonType = 'button' | 'submit' | 'reset';

export type ButtonVariant =
	| 'primary'
	| 'secondary'
	| 'subtle'
	| 'brand'
	| 'highlight'
	| 'reverse'
	| 'reverse-secondary'
	| 'critical'
	| 'critical-secondary'
	| 'link';

export type StatusDotType =
	'info' | 'success' | 'warning' | 'critical' | 'discovery' | 'neutral';

export const mergeClasses = (classes: Array<string | null | undefined>) =>
	classes.filter(Boolean).join(' ');

export const extractText = (node: ReactNode): string => {
	if (typeof node === 'string' || typeof node === 'number') {
		return String(node);
	}
	if (isValidElement(node)) {
		const props = node.props as { children?: ReactNode };
		return Children.toArray(props.children).map(extractText).join('');
	}
	return '';
};

interface StatusDotProps extends ComponentPropsWithoutRef<'span'> {
	/**
	 * Status type — determines the dot color
	 */
	status: StatusDotType;
}

// Styled by the package's existing `.pds-status-dot` CSS.
export const StatusDot = ({ className, status, ...props }: StatusDotProps) => (
	<span
		className={mergeClasses([
			'pds-status-dot',
			`pds-status-dot--${status}`,
			className,
		])}
		{...props}
	/>
);