mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-25 02:41:07 +01:00
Remove most of Radix UI
This commit is contained in:
@@ -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>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user