93 lines
2.3 KiB
TypeScript
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>
|
|
);
|
|
}
|