Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 63 additions & 25 deletions starter_app/src/app/components/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,81 @@ import React, { ComponentProps } from 'react';
import cn from '../utils/styleUtil';

export interface MenuProps extends ComponentProps<'div'> {
scrollbar?: boolean;
width?: 'fit-content' | 'fit-parent';
scrollbar?: boolean;
width?: 'fit-content' | 'fit-parent';
}

interface MenuItemProps extends ComponentProps<'li'> {
selected?: boolean;
condensed?: boolean;
export interface MenuItemProps extends ComponentProps<'li'> {
selected?: boolean;
condensed?: boolean;
value?: string;
highlighted?: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between selected and highlighted here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Selected - currently chosen (1st item)
Highlighted - currently focused via keyboard navigation (2nd item)

image

}

interface MenuDividerProps extends ComponentProps<'hr'> {
marginTop?: boolean;
marginBottom?: boolean;
export interface MenuDividerProps extends ComponentProps<'hr'> {
marginTop?: boolean;
marginBottom?: boolean;
}

export interface MenuGroupProps {
label: string;
children: React.ReactNode;
}

export interface MenuClearProps {
onClear?: () => void;
children?: React.ReactNode;
}

export default function Menu ({scrollbar, width = 'fit-content', ...props}: MenuProps) {
return (
<div className={cn(`absolute z-1 bg-container text-onSurface shadow-lg w-max rounded-md ${scrollbar && 'overflow-y-auto'} ${width === 'fit-content' ? 'w-max' : 'w-full'}`, props.className)}>
<ul className='rounded-md overflow-hidden'>
{props.children}
</ul>
</div>
)
return (
<div className={cn(`absolute z-1 bg-container text-onSurface shadow-lg w-max rounded-md ${scrollbar && 'overflow-y-auto'} ${width === 'fit-content' ? 'w-max' : 'w-full'}`, props.className)}>
<ul className='rounded-md overflow-hidden'>
{props.children}
</ul>
</div>
)
}

function MenuItem ({condensed = false, selected, ...props}: MenuItemProps) {
return (
<li className={cn(`px-4 hover:bg-containerHigh ${condensed ? 'py-1' : 'py-3'} ${selected && 'bg-containerHighest'}`, props.className)}>
{props.children}
</li>
)
function MenuItem({ condensed = false, selected, highlighted, ...props }: MenuItemProps) {
return (
<li {...props}
className={cn(`px-4 hover:bg-containerHigh ${condensed ? 'py-1' : 'py-3'} ${(selected || highlighted) && 'bg-containerHighest'}`, props.className)}>
{props.children}
</li>
)
}

function MenuDivider ({marginTop = true, marginBottom = true}: MenuDividerProps) {
return (
<hr className={cn(`border-outline mx-0 ${marginTop && 'mt-[8px]'} ${marginBottom && 'mb-[8px]'}`)} />
)
return (
<hr className={cn(`border-outline mx-0 ${marginTop && 'mt-[8px]'} ${marginBottom && 'mb-[8px]'}`)} />
)
}

function MenuGroup({ label, children }: MenuGroupProps) {
return (
<li className="w-full">
<div className="px-4 py-2 text-sm font-semibold bg-containerHigh text-onSurface">
{label}
</div>

<ul>{children}</ul>
</li>
);
}

function MenuClear({ onClear, children }: MenuClearProps) {
return (
<div
className="px-4 py-2 text-sm cursor-pointer hover:bg-containerHigh text-primary"
onClick={onClear}
>
{children ?? 'Clear All'}
</div>
);
}

Menu.Item = MenuItem;
Menu.Divider = MenuDivider;
Menu.Divider = MenuDivider;
Menu.Group = MenuGroup;
Menu.Clear = MenuClear;
Loading