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

Add Typescript types for ProgressIndicator, ProgressIndicatorSkeleton and ProgressStep #15406

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,22 @@ function Step() {
);
}

function ProgressIndicatorSkeleton({ className, vertical, ...rest }) {
interface ProgressIndicatorSkeletonProps {
/**
* Specify an optional className to add.
*/
className?: string;
/**
* Determines whether or not the ProgressIndicator should be rendered vertically.
*/
vertical?: boolean;
}

function ProgressIndicatorSkeleton({
className,
vertical,
...rest
}: ProgressIndicatorSkeletonProps) {
const prefix = usePrefix();
return (
<ul
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,40 @@ const defaultTranslations = {
function translateWithId(messageId) {
return defaultTranslations[messageId];
}

interface ProgressIndicatorProps
extends Omit<React.HTMLAttributes<HTMLUListElement>, 'onChange'> {
/**
* Provide `<ProgressStep>` components to be rendered in the
* `<ProgressIndicator>`
*/
children?: React.ReactNode;

/**
* Provide an optional className to be applied to the containing node
*/
className?: string;

/**
* Optionally specify the current step array index
*/
currentIndex?: number;

/**
* Optional callback called if a ProgressStep is clicked on. Returns the index of the step.
*/
onChange?: (data: number) => void;

/**
* Specify whether the progress steps should be split equally in size in the div
*/
spaceEqually?: boolean;
/**
* Determines whether or not the ProgressIndicator should be rendered vertically.
*/
vertical?: boolean;
}

function ProgressIndicator({
children,
className: customClassName,
Expand All @@ -36,7 +70,7 @@ function ProgressIndicator({
spaceEqually,
vertical,
...rest
}) {
}: ProgressIndicatorProps) {
const prefix = usePrefix();
const [currentIndex, setCurrentIndex] = useState(controlledIndex);
const [prevControlledIndex, setPrevControlledIndex] =
Expand All @@ -45,7 +79,7 @@ function ProgressIndicator({
[`${prefix}--progress`]: true,
[`${prefix}--progress--vertical`]: vertical,
[`${prefix}--progress--space-equal`]: spaceEqually && !vertical,
[customClassName]: customClassName,
[customClassName ?? '']: customClassName,
});

if (controlledIndex !== prevControlledIndex) {
Expand All @@ -56,7 +90,7 @@ function ProgressIndicator({
return (
<ul className={className} {...rest}>
{React.Children.map(children, (child, index) => {
if (!React.isValidElement(child)) {
if (!React.isValidElement<ProgressStepProps>(child)) {
return null;
}

Expand Down Expand Up @@ -122,6 +156,78 @@ ProgressIndicator.propTypes = {
vertical: PropTypes.bool,
};

interface ProgressStepProps {
/**
* Provide an optional className to be applied to the containing `<li>` node
*/
className?: string;

/**
* Specify whether the step has been completed
*/
complete?: boolean;

/**
* Specify whether the step is the current step
*/
current?: boolean;

/**
* Provide a description for the `<ProgressStep>`
*/
description?: string;

/**
* Specify whether the step is disabled
*/
disabled?: boolean;

/**
* Index of the current step within the ProgressIndicator
*/
index?: number;

/**
* Specify whether the step is invalid
*/
invalid?: boolean;

/**
* Provide the label for the `<ProgressStep>`
*/
label: string;

/**
* A callback called if the step is clicked or the enter key is pressed
*/
onClick?: (
event:
| React.KeyboardEvent<HTMLButtonElement>
| React.MouseEvent<HTMLButtonElement>
) => void;

/**
* Provide the props that describe a progress step tooltip
*/
overflowTooltipProps?: object;

/**
* Provide an optional secondary label
*/
secondaryLabel?: string;

/**
* The ID of the tooltip content.
*/
tooltipId?: string;

/**
* Optional method that takes in a message id and returns an
* internationalized string.
*/
translateWithId?: (id: string) => string;
}

function ProgressStep({
label,
description,
Expand All @@ -134,25 +240,38 @@ function ProgressStep({
onClick,
translateWithId: t = translateWithId,
...rest
}) {
}: ProgressStepProps) {
const prefix = usePrefix();
const classes = cx({
[`${prefix}--progress-step`]: true,
[`${prefix}--progress-step--current`]: current,
[`${prefix}--progress-step--complete`]: complete,
[`${prefix}--progress-step--incomplete`]: !complete && !current,
[`${prefix}--progress-step--disabled`]: disabled,
[className]: className,
[className ?? '']: className,
});

const handleKeyDown = (e) => {
if (matches(e, [keys.Enter, keys.Space])) {
onClick();
const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {
if (matches(e, [keys.Enter, keys.Space]) && onClick) {
onClick(e);
}
};

// eslint-disable-next-line react/prop-types
const SVGIcon = ({ complete, current, description, invalid, prefix }) => {
interface SVGIconProps {
complete?: boolean;
current?: boolean;
description?: string;
invalid?: boolean;
prefix: string;
}

const SVGIcon = ({
complete,
current,
description,
invalid,
prefix,
}: SVGIconProps) => {
if (invalid) {
return (
<Warning className={`${prefix}--progress__warning`}>
Expand Down