Remove most of Radix UI

This commit is contained in:
Gregory Schier
2023-03-20 13:16:58 -07:00
parent b84a5530be
commit e19ea612f5
31 changed files with 549 additions and 2017 deletions

View File

@@ -1,12 +1,10 @@
import * as T from '@radix-ui/react-tabs';
import classnames from 'classnames';
import { memo } from 'react';
import type { ReactNode } from 'react';
import { memo, useEffect, useRef } from 'react';
import { Button } from '../Button';
import type { DropdownMenuRadioItem, DropdownMenuRadioProps } from '../Dropdown';
import { DropdownMenuRadio, DropdownMenuTrigger } from '../Dropdown';
import { Icon } from '../Icon';
import { ScrollArea } from '../ScrollArea';
import type { RadioDropdownProps } from '../RadioDropdown';
import { RadioDropdown } from '../RadioDropdown';
import { HStack } from '../Stacks';
import './Tabs.css';
@@ -14,11 +12,7 @@ import './Tabs.css';
export type TabItem = {
value: string;
label: string;
options?: {
onValueChange: DropdownMenuRadioProps['onValueChange'];
value: string;
items: DropdownMenuRadioItem[];
};
options?: Omit<RadioDropdownProps, 'children'>;
};
interface Props {
@@ -40,85 +34,95 @@ export const Tabs = memo(function Tabs({
className,
tabListClassName,
}: Props) {
const ref = useRef<HTMLDivElement | null>(null);
const handleTabChange = (value: string) => {
const tabs = ref.current?.querySelectorAll(`[data-tab]`);
for (const tab of tabs ?? []) {
const v = tab.getAttribute('data-tab');
if (v === value) {
tab.setAttribute('tabindex', '0');
tab.setAttribute('data-state', 'active');
} else {
tab.setAttribute('data-state', 'inactive');
}
}
onChangeValue(value);
};
useEffect(() => {
if (value === undefined) return;
handleTabChange(value);
}, [value]);
return (
<T.Root
value={value}
onValueChange={onChangeValue}
<div
ref={ref}
className={classnames(className, 'h-full grid grid-rows-[auto_minmax(0,1fr)] grid-cols-1')}
>
<T.List
<div
aria-label={label}
className={classnames(tabListClassName, 'h-auto flex items-center pb-1')}
>
<ScrollArea>
<HStack space={1}>
{tabs.map((t) => {
const isActive = t.value === value;
if (t.options && isActive) {
return (
<DropdownMenuRadio
key={t.value}
items={t.options.items}
value={t.options.value}
onValueChange={t.options.onValueChange}
<HStack space={1}>
{tabs.map((t) => {
const isActive = t.value === value;
if (t.options && isActive) {
return (
<RadioDropdown
key={t.value}
items={t.options.items}
value={t.options.value}
onChange={t.options.onChange}
>
<Button
color="custom"
size="sm"
onClick={(e) => e.stopPropagation()}
className={classnames(
isActive ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900',
)}
>
<DropdownMenuTrigger>
<Button
color="custom"
size="sm"
onClick={(e) => e.stopPropagation()}
className={classnames(
isActive
? 'bg-gray-100 text-gray-900'
: 'text-gray-600 hover:text-gray-900',
)}
>
{t.options.items.find((i) => i.value === t.options?.value)?.label ?? ''}
<Icon icon="triangleDown" className="-mr-1.5" />
</Button>
</DropdownMenuTrigger>
</DropdownMenuRadio>
);
} else if (t.options && !isActive) {
return (
<T.Trigger asChild key={t.value} value={t.value}>
<Button
color="custom"
size="sm"
className={classnames(
isActive
? 'bg-gray-100 text-gray-900'
: 'text-gray-600 hover:text-gray-900',
)}
>
{t.options.items.find((i) => i.value === t.options?.value)?.label ?? ''}
<Icon icon="triangleDown" className="-mr-1.5 opacity-40" />
</Button>
</T.Trigger>
);
} else {
return (
<T.Trigger asChild key={t.value} value={t.value}>
<Button
color="custom"
size="sm"
className={classnames(
isActive
? 'bg-gray-100 text-gray-900'
: 'text-gray-600 hover:text-gray-900',
)}
>
{t.label}
</Button>
</T.Trigger>
);
}
})}
</HStack>
</ScrollArea>
</T.List>
{t.options.items.find((i) => i.value === t.options?.value)?.label ?? ''}
<Icon icon="triangleDown" className="-mr-1.5" />
</Button>
</RadioDropdown>
);
} else if (t.options && !isActive) {
return (
<Button
key={t.value}
color="custom"
size="sm"
onClick={() => handleTabChange(t.value)}
className={classnames(
isActive ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900',
)}
>
{t.options.items.find((i) => i.value === t.options?.value)?.label ?? ''}
<Icon icon="triangleDown" className="-mr-1.5 opacity-40" />
</Button>
);
} else {
return (
<Button
key={t.value}
color="custom"
size="sm"
onClick={() => handleTabChange(t.value)}
className={classnames(
isActive ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900',
)}
>
{t.label}
</Button>
);
}
})}
</HStack>
</div>
{children}
</T.Root>
</div>
);
});
@@ -134,13 +138,12 @@ export const TabContent = memo(function TabContent({
className,
}: TabContentProps) {
return (
<T.Content
<div
tabIndex={-1}
forceMount
value={value}
data-tab={value}
className={classnames(className, 'tab-content', 'w-full h-full overflow-auto')}
>
{children}
</T.Content>
</div>
);
});