List components #31
@ -1,63 +1,70 @@
|
||||
import type { HTMLAttributes } from 'react';
|
||||
import type { HTMLAttributes } from "react";
|
||||
import clsx from "clsx";
|
||||
import { RemoveIcon } from "../Icon/Icon";
|
||||
|
||||
export interface ListCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
onRemove?: () => void;
|
||||
export interface ListCardProps
|
||||
extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
onRemove?: () => void;
|
||||
}
|
||||
|
||||
const baseClasses = [
|
||||
'px-(--padding-md) py-(--padding-md)',
|
||||
'bg-sky-35 border border-sky-100 rounded-(--border-radius-md)',
|
||||
'flex items-center justify-between',
|
||||
'group text-base-ink-strong hover:bg-sky-70 hover:text-base-ink-max focus-visible:text-base-ink-max',
|
||||
'focus-visible:border-primary focus-visible:border-[length:var(--border-width-sm)] focus-visible:outline focus-visible:outline-sky-100 focus-visible:outline-[length:var(--border-width-lg)]',
|
||||
].join(' ');
|
||||
const baseClasses = clsx(
|
||||
"px-(--padding-md) py-(--padding-md)",
|
||||
"bg-sky-35 border border-sky-100 rounded-(--border-radius-md)",
|
||||
"flex items-center justify-between",
|
||||
"group cursor-pointer",
|
||||
);
|
||||
|
||||
const removeIconClasses = 'w-(--font-size-body-md) h-(--font-size-body-md)';
|
||||
const stateClasses = clsx(
|
||||
"text-base-ink-strong",
|
||||
"hover:bg-sky-70 hover:text-base-ink-max",
|
||||
"focus-visible:text-base-ink-max",
|
||||
"focus-visible:border-primary focus-visible:border-[length:var(--border-width-sm)]",
|
||||
"focus-visible:outline focus-visible:outline-sky-100 focus-visible:outline-[length:var(--border-width-lg)]",
|
||||
);
|
||||
|
||||
function RemoveIcon() {
|
||||
return (
|
||||
<svg
|
||||
className={removeIconClasses}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
const removeButtonClasses = clsx(
|
||||
"shrink-0 ml-(--spacing-sm) cursor-pointer",
|
||||
"text-base-ink-placeholder",
|
||||
"group-hover:text-base-ink-max group-focus-visible:text-base-ink-max",
|
||||
"focus-visible:outline-none",
|
||||
);
|
||||
|
||||
export default function ListCard({
|
||||
title,
|
||||
subtitle,
|
||||
onRemove,
|
||||
className,
|
||||
...props
|
||||
}: ListCardProps) {
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === "Enter" && onRemove) {
|
||||
onRemove();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(baseClasses, stateClasses, className)}
|
||||
tabIndex={0}
|
||||
onKeyDown={handleKeyDown}
|
||||
{...props}
|
||||
>
|
||||
<div>
|
||||
<div className="body-light-sm">{title}</div>
|
||||
{subtitle && <div className="body-light-sm">{subtitle}</div>}
|
||||
</div>
|
||||
{onRemove && (
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
onClick={onRemove}
|
||||
className={removeButtonClasses}
|
||||
>
|
||||
<line x1="18" y1="6" x2="6" y2="18" />
|
||||
<line x1="6" y1="6" x2="18" y2="18" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ListCard({ title, subtitle = '', onRemove, className = '', ...props }: ListCardProps) {
|
||||
const classes = [baseClasses, className].filter(Boolean).join(' ');
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter' && onRemove) {
|
||||
onRemove();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classes} {...props} tabIndex={0} onKeyDown={handleKeyDown}>
|
||||
<div>
|
||||
<div className="body-light-sm">{title}</div>
|
||||
{subtitle && <div className="body-light-sm">{subtitle}</div>}
|
||||
</div>
|
||||
{onRemove && (
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
onClick={onRemove}
|
||||
className="shrink-0 ml-(--spacing-sm) text-base-ink-placeholder group-hover:text-base-ink-max group-focus-visible:text-base-ink-max focus-visible:outline-none cursor-pointer"
|
||||
>
|
||||
<RemoveIcon />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
<RemoveIcon />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user