List components #31
67
frontend/src/components/ListItem/ListItem.tsx
Normal file
67
frontend/src/components/ListItem/ListItem.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import type { HTMLAttributes, CSSProperties } from 'react';
|
||||
|
||||
export interface ListItemProps extends HTMLAttributes<HTMLDivElement> {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
const iconStyles: CSSProperties = {
|
||||
width: 'var(--font-size-body-md)',
|
||||
height: 'var(--font-size-body-md)',
|
||||
marginLeft: 'var(--spacing-sm)',
|
||||
};
|
||||
|
||||
function CheckmarkIcon() {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
style={iconStyles}
|
||||
>
|
||||
<polyline points="20 6 9 17 4 12" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
const baseClasses = 'w-full px-(--padding-md) py-(--padding-md) cursor-pointer flex items-center justify-between';
|
||||
|
||||
const defaultStateClasses = 'bg-base-canvas text-base-ink-strong hover:bg-sky-100 hover:text-primary focus:bg-sky-100 focus:text-primary focus:outline-none';
|
||||
|
||||
const selectedStateClasses = 'bg-base-canvas text-base-ink-placeholder';
|
||||
|
||||
export default function ListItem({
|
||||
title,
|
||||
subtitle,
|
||||
selected = false,
|
||||
className = '',
|
||||
...props
|
||||
}: ListItemProps) {
|
||||
const stateClasses = selected ? selectedStateClasses : defaultStateClasses;
|
||||
|
||||
const classes = [baseClasses, stateClasses, className].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classes}
|
||||
tabIndex={0}
|
||||
role="option"
|
||||
aria-selected={selected}
|
||||
{...props}
|
||||
>
|
||||
<div>
|
||||
<div className="body-normal-md">{title}</div>
|
||||
{subtitle && <div className="body-light-sm">{subtitle}</div>}
|
||||
</div>
|
||||
{selected && (
|
||||
<div className="shrink-0">
|
||||
<CheckmarkIcon />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user