ui(admin): fix users list

This commit is contained in:
Matthew Penner 2023-01-25 11:14:39 -07:00
parent 5063db7d95
commit 4b82ca1042
No known key found for this signature in database
5 changed files with 126 additions and 92 deletions

View file

@ -1,27 +1,29 @@
import { ElementType, forwardRef, useMemo } from 'react';
import * as React from 'react';
import { Menu, Transition } from '@headlessui/react';
import styles from './style.module.css';
import classNames from 'classnames';
import DropdownItem from '@/components/elements/dropdown/DropdownItem';
import DropdownButton from '@/components/elements/dropdown/DropdownButton';
import type { ElementType, ReactNode } from 'react';
import { Children as ReactChildren } from 'react';
import { forwardRef, useMemo } from 'react';
import { DropdownButton } from '@/components/elements/dropdown/DropdownButton';
import { DropdownItem } from '@/components/elements/dropdown/DropdownItem';
import styles from './style.module.css';
interface Props {
as?: ElementType;
children: React.ReactNode;
children: ReactNode;
}
const DropdownGap = ({ invisible }: { invisible?: boolean }) => (
<div className={classNames('m-2 border', { 'border-neutral-700': !invisible, 'border-transparent': invisible })} />
);
type TypedChild = (React.ReactChild | React.ReactFragment | React.ReactPortal) & {
type TypedChild = ReactNode & {
type?: JSX.Element;
};
const Dropdown = forwardRef<typeof Menu, Props>(({ as, children }, ref) => {
const [Button, items] = useMemo(() => {
const list = React.Children.toArray(children) as unknown as TypedChild[];
const list = ReactChildren.toArray(children) as unknown as TypedChild[];
return [
list.filter(child => child.type === DropdownButton),
@ -34,18 +36,18 @@ const Dropdown = forwardRef<typeof Menu, Props>(({ as, children }, ref) => {
}
return (
<Menu as={as || 'div'} className={styles.menu} ref={ref}>
<Menu as={as ?? 'div'} className={styles.menu} ref={ref}>
{Button}
<Transition
enter={'transition duration-100 ease-out'}
enterFrom={'transition scale-95 opacity-0'}
enterTo={'transform scale-100 opacity-100'}
leave={'transition duration-75 ease-out'}
leaveFrom={'transform scale-100 opacity-100'}
leaveTo={'transform scale-95 opacity-0'}
enter="transition duration-100 ease-out"
enterFrom="transition scale-95 opacity-0"
enterTo="transform scale-100 opacity-100"
leave="transition duration-75 ease-out"
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
>
<Menu.Items className={classNames(styles.items_container, 'w-56')}>
<div className={'px-1 py-1'}>{items}</div>
<div className="px-1 py-1">{items}</div>
</Menu.Items>
</Transition>
</Menu>

View file

@ -1,24 +1,29 @@
import classNames from 'classnames';
import styles from '@/components/elements/dropdown/style.module.css';
import { ChevronDownIcon } from '@heroicons/react/solid';
import { Menu } from '@headlessui/react';
import * as React from 'react';
import { ChevronDownIcon } from '@heroicons/react/solid';
import classNames from 'classnames';
import type { ReactNode } from 'react';
import styles from './style.module.css';
interface Props {
className?: string;
animate?: boolean;
children: React.ReactNode;
children: ReactNode;
}
export default ({ className, animate = true, children }: Props) => (
<Menu.Button className={classNames(styles.button, className || 'px-4')}>
{typeof children === 'string' ? (
<>
<span className={'mr-2'}>{children}</span>
<ChevronDownIcon aria-hidden={'true'} data-animated={animate.toString()} />
</>
) : (
children
)}
</Menu.Button>
);
function DropdownButton({ className, animate = true, children }: Props) {
return (
<Menu.Button className={classNames(styles.button, className ?? 'px-4')}>
{typeof children === 'string' ? (
<>
<span className="mr-2">{children}</span>
<ChevronDownIcon aria-hidden="true" data-animated={animate.toString()} />
</>
) : (
children
)}
</Menu.Button>
);
}
export { DropdownButton };

View file

@ -1,43 +1,68 @@
import { forwardRef } from 'react';
import * as React from 'react';
import { Menu } from '@headlessui/react';
import styles from './style.module.css';
import classNames from 'classnames';
import type { MouseEvent, ReactNode, Ref } from 'react';
import { forwardRef } from 'react';
import type { NavLinkProps } from 'react-router-dom';
import { NavLink } from 'react-router-dom';
import styles from './style.module.css';
interface Props {
children: React.ReactNode | ((opts: { active: boolean; disabled: boolean }) => JSX.Element);
children: ReactNode | ((opts: { active: boolean; disabled: boolean }) => JSX.Element);
danger?: boolean;
disabled?: boolean;
className?: string;
icon?: JSX.Element;
onClick?: (e: React.MouseEvent) => void;
onClick?: (e: MouseEvent) => void;
}
const DropdownItem = forwardRef<HTMLAnchorElement, Props>(
({ disabled, danger, className, onClick, children, icon: IconComponent }, ref) => {
const DropdownItem = forwardRef<HTMLAnchorElement | HTMLButtonElement, Props & Partial<Omit<NavLinkProps, 'children'>>>(
({ disabled, danger, className, onClick, children, icon: IconComponent, ...props }, ref) => {
return (
<Menu.Item disabled={disabled}>
{({ disabled, active }) => (
<a
ref={ref}
href={'#'}
className={classNames(
styles.menu_item,
{
[styles.danger]: danger,
[styles.disabled]: disabled,
},
className,
<>
{'to' in props && props.to !== undefined ? (
<NavLink
{...props}
to={props.to}
ref={ref as unknown as Ref<HTMLAnchorElement>}
className={classNames(
styles.menu_item,
{
[styles.danger]: danger,
[styles.disabled]: disabled,
},
className,
)}
onClick={onClick}
>
{IconComponent}
{typeof children === 'function' ? children({ disabled, active }) : children}
</NavLink>
) : (
<button
type="button"
ref={ref as unknown as Ref<HTMLButtonElement>}
className={classNames(
styles.menu_item,
{
[styles.danger]: danger,
[styles.disabled]: disabled,
},
className,
)}
onClick={onClick}
>
{IconComponent}
{typeof children === 'function' ? children({ disabled, active }) : children}
</button>
)}
onClick={onClick}
>
{IconComponent}
{typeof children === 'function' ? children({ disabled, active }) : children}
</a>
</>
)}
</Menu.Item>
);
},
);
export default DropdownItem;
export { DropdownItem };