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