Corp/frontend/src/components/ui/ModulePrimaryAction.tsx

93 lines
2.3 KiB
TypeScript

"use client";
import Link from "next/link";
import type {
AnchorHTMLAttributes,
ButtonHTMLAttributes,
ReactNode,
} from "react";
type ModulePrimaryActionBaseProps = {
icon: ReactNode;
label: string;
className?: string;
};
type ModulePrimaryActionButtonProps = ModulePrimaryActionBaseProps &
Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> & {
href?: never;
};
type ModulePrimaryActionLinkProps = ModulePrimaryActionBaseProps &
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "children" | "href"> & {
href: string;
};
export type ModulePrimaryActionProps =
| ModulePrimaryActionButtonProps
| ModulePrimaryActionLinkProps;
const baseClassName =
"app-action-primary inline-flex h-10 max-w-full min-w-10 shrink items-center justify-center gap-2 overflow-hidden rounded-lg px-3 text-sm font-medium transition disabled:cursor-not-allowed disabled:opacity-60";
function ActionContents({ icon, label }: Pick<ModulePrimaryActionBaseProps, "icon" | "label">) {
return (
<>
<span className="flex shrink-0 items-center justify-center" aria-hidden="true">
{icon}
</span>
<span className="min-w-0 overflow-hidden whitespace-nowrap">{label}</span>
</>
);
}
export function ModulePrimaryAction(props: ModulePrimaryActionProps) {
const {
icon,
label,
className = "",
"aria-label": ariaLabel,
title,
} = props;
const sharedProps = {
"aria-label": ariaLabel || label,
className: `${baseClassName} ${className}`,
title: title || label,
};
if (props.href) {
const linkVariant = props as ModulePrimaryActionLinkProps;
const {
href,
icon: _icon,
label: _label,
className: _className,
...linkProps
} = linkVariant;
void _icon;
void _label;
void _className;
return (
<Link href={href} {...linkProps} {...sharedProps}>
<ActionContents icon={icon} label={label} />
</Link>
);
}
const buttonVariant = props as ModulePrimaryActionButtonProps;
const {
icon: _icon,
label: _label,
className: _className,
...buttonProps
} = buttonVariant;
void _icon;
void _label;
void _className;
return (
<button type="button" {...buttonProps} {...sharedProps}>
<ActionContents icon={icon} label={label} />
</button>
);
}