feat: update layout

This commit is contained in:
2024-03-03 18:24:00 +07:00
parent f1f6d65798
commit e007dd4ac4
12 changed files with 169 additions and 121 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ const BaseInput = forwardRef<HTMLInputElement, BaseInputProps>(
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-slate-200 px-3 py-2 text-sm ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/40 bg-transparent dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus-visible:ring-slate-300",
inputClassName
label || error ? inputClassName : className
)}
ref={ref}
{...props}
+22 -20
View File
@@ -58,26 +58,28 @@ const ResizablePanel = forwardRef((props: ResizablePanelProps, ref: any) => {
);
});
const ResizableHandle = ({
withHandle,
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
type ResizableHandleProps = React.ComponentProps<
typeof ResizablePrimitive.PanelResizeHandle
> & {
withHandle?: boolean;
}) => (
<ResizablePrimitive.PanelResizeHandle
className={cn(
"relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
className
)}
{...props}
>
{withHandle && (
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border border-slate-200 bg-slate-200 dark:border-slate-800 dark:bg-slate-800">
<GripVertical className="h-2.5 w-2.5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>
);
};
const ResizableHandle = (props: ResizableHandleProps) => {
const { withHandle, className, ...restProps } = props;
return (
<ResizablePrimitive.PanelResizeHandle
className={cn(
"relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
withHandle && "w-3 bg-black group",
className
)}
{...restProps}
>
{withHandle && (
<div className="z-10 flex h-full max-h-[100px] w-1.5 items-center justify-center rounded-full bg-white/30 group-hover:bg-white/40"></div>
)}
</ResizablePrimitive.PanelResizeHandle>
);
};
export { ResizablePanelGroup, ResizablePanel, ResizableHandle };
+36 -43
View File
@@ -16,17 +16,9 @@ type Props = {
onChange?: (idx: number) => void;
onClose?: (idx: number) => void;
className?: string;
containerClassName?: string;
};
const Tabs = ({
tabs,
current = 0,
onChange,
onClose,
className,
containerClassName,
}: Props) => {
const Tabs = ({ tabs, current = 0, onChange, onClose, className }: Props) => {
const tabContainerRef = useRef<HTMLDivElement>(null);
const onWheel = (e: WheelEvent) => {
@@ -64,43 +56,44 @@ const Tabs = ({
container.scrollTo({ left: scrollX, behavior: "smooth" });
}, [tabs, current]);
const tabView = useMemo(() => {
const tab = tabs[current];
const element = tab?.render ? tab.render() : null;
return element;
}, [tabs, current]);
return (
<div
return tabs.length > 0 ? (
<nav
ref={tabContainerRef}
className={cn(
"w-full flex flex-col items-stretch bg-slate-800",
"flex items-stretch overflow-x-auto h-10 gap-1 hide-scrollbar",
className
)}
>
{tabs.length > 0 ? (
<nav
ref={tabContainerRef}
className="flex items-stretch overflow-x-auto w-full h-10 min-h-10 hide-scrollbar"
>
{tabs.map((tab, idx) => (
<TabItem
key={idx}
index={idx}
title={tab.title}
icon={tab.icon}
isActive={idx === current}
onSelect={() => onChange && onChange(idx)}
onClose={!tab.locked && onClose ? () => onClose(idx) : null}
/>
))}
</nav>
) : null}
{tabs.map((tab, idx) => (
<TabItem
key={idx}
index={idx}
title={tab.title}
icon={tab.icon}
isActive={idx === current}
onSelect={() => onChange && onChange(idx)}
onClose={!tab.locked && onClose ? () => onClose(idx) : null}
/>
))}
</nav>
) : null;
};
<main className={cn("flex-1 overflow-hidden", containerClassName)}>
{tabView}
</main>
</div>
);
type TabViewProps = {
tabs: Tab[];
current: number;
className?: string;
};
export const TabView = ({ tabs, current, className }: TabViewProps) => {
const tabView = useMemo(() => {
const tab = tabs[current];
const element = tab?.render ? tab.render() : null;
return element;
}, [tabs, current]);
return <main className={cn("overflow-hidden", className)}>{tabView}</main>;
};
type TabItemProps = {
@@ -128,8 +121,8 @@ const TabItem = ({
<div
data-idx={index}
className={cn(
"group border-b-2 border-transparent truncate flex-shrink-0 text-white/70 transition-all hover:text-white text-center max-w-[140px] md:max-w-[180px] text-sm flex items-center gap-0 relative z-[1]",
isActive ? "border-slate-500 text-white" : ""
"group truncate flex-shrink-0 h-full bg-white/10 rounded-lg text-white/70 transition-all hover:text-white text-center max-w-[140px] md:max-w-[180px] text-sm flex items-center gap-0 relative z-[1]",
isActive ? "bg-white/20 text-white" : ""
)}
onClick={onSelect}
>