refactor(ui): adjust dataset page styles (#13452)

### What problem does this PR solve?

- Adjust UI styles in **Dataset** pages.
- Adjust several shared components styles
- Modify files and directory structure in `src/layouts`

### Type of change

- [x] Refactoring
This commit is contained in:
Jimmy Ben Klieve
2026-03-06 21:13:14 +08:00
committed by GitHub
parent 7166a7e50e
commit 094eae3cf5
44 changed files with 589 additions and 543 deletions

View File

@@ -39,7 +39,7 @@ const AvatarFallback = React.forwardRef<
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
'flex h-full w-full items-center justify-center rounded-full bg-bg-member',
'flex h-full w-full items-center justify-center bg-bg-member',
className,
)}
{...props}

View File

@@ -8,7 +8,7 @@ import { Link, LinkProps } from 'react-router';
const buttonVariants = cva(
cn(
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors outline-0',
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm transition-colors outline-0',
'disabled:pointer-events-none disabled:opacity-50 rounded border-0.5 border-transparent',
'[&_svg]:pointer-events-none [&_svg:not([class*="size-"])]:size-4 shrink-0 [&_svg]:shrink-0',
),
@@ -83,9 +83,13 @@ const buttonVariants = cva(
`,
link: 'text-primary underline-offset-4 hover:underline',
// Static
// Button has no interaction transitions
static: '',
},
size: {
auto: 'h-full px-1',
auto: '',
xl: 'h-12 rounded-xl px-5',
lg: 'h-10 rounded-lg px-4',
@@ -107,6 +111,8 @@ const buttonVariants = cva(
},
);
export type ButtonVariants = VariantProps<typeof buttonVariants>;
export type ButtonProps<IsAnchor extends boolean = false> = {
asChild?: boolean;
asLink?: boolean;
@@ -114,7 +120,7 @@ export type ButtonProps<IsAnchor extends boolean = false> = {
block?: boolean;
disabled?: boolean;
dot?: boolean;
} & VariantProps<typeof buttonVariants> &
} & ButtonVariants &
(IsAnchor extends true
? LinkProps
: React.ButtonHTMLAttributes<HTMLButtonElement>);
@@ -144,7 +150,7 @@ const Button = React.forwardRef(
<Comp
className={cn(
buttonVariants({ variant, size, className }),
{ 'block w-full': block },
{ 'w-full': block },
{ relative: dot },
)}
// @ts-ignore

View File

@@ -3,10 +3,10 @@ import * as React from 'react';
import { cn } from '@/lib/utils';
const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
HTMLElement,
React.HTMLAttributes<HTMLElement> & { as?: React.ElementType }
>(({ as: As = 'div', className, ...props }, ref) => (
<As
ref={ref}
className={cn(
'rounded-lg border-border-button border-0.5 shadow-sm bg-bg-input transition-shadow',
@@ -19,9 +19,9 @@ Card.displayName = 'Card';
const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
React.HTMLAttributes<HTMLDivElement> & { as?: React.ElementType }
>(({ as: As = 'div', className, ...props }, ref) => (
<As
ref={ref}
className={cn('flex flex-col space-y-1.5 p-6', className)}
{...props}
@@ -32,7 +32,7 @@ CardHeader.displayName = 'CardHeader';
const CardTitle = React.forwardRef<
HTMLElement,
React.HTMLAttributes<HTMLElement> & { as?: React.ElementType }
>(({ className, as: As = 'div', ...props }, ref) => (
>(({ as: As = 'div', className, ...props }, ref) => (
<As
ref={ref}
className={cn('text-2xl leading-normal font-medium', className)}
@@ -43,9 +43,9 @@ CardTitle.displayName = 'CardTitle';
const CardDescription = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
React.HTMLAttributes<HTMLDivElement> & { as?: React.ElementType }
>(({ as: As = 'div', className, ...props }, ref) => (
<As
ref={ref}
className={cn('text-sm text-text-secondary', className)}
{...props}
@@ -55,9 +55,9 @@ CardDescription.displayName = 'CardDescription';
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
React.HTMLAttributes<HTMLDivElement> & { as?: React.ElementType }
>(({ as: As = 'div', className, ...props }, ref) => (
<As
ref={ref}
className={cn('p-6 pt-0 transition-shadow', className)}
{...props}
@@ -67,9 +67,9 @@ CardContent.displayName = 'CardContent';
const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
React.HTMLAttributes<HTMLDivElement> & { as?: React.ElementType }
>(({ as: As = 'div', className, ...props }, ref) => (
<As
ref={ref}
className={cn('flex items-center p-6 pt-0', className)}
{...props}

View File

@@ -38,7 +38,10 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
'outline-0 fixed left-[50%] top-[50%] rounded-lg z-50 grid w-full max-w-xl translate-x-[-50%] translate-y-[-50%] gap-4',
'outline-none outline-0 fixed left-[50%] top-[50%] rounded-lg z-50 grid w-full max-w-xl translate-x-[-50%] translate-y-[-50%]',
// TODO: to keep scrollbar perfectly aligned to header bottom and/or footer top,
// 'gap-4' should be removed, then bring your own body container with padding-y instead.
'gap-4',
'border-0.5 border-border-button bg-bg-base p-6 shadow-lg duration-200 sm:rounded-lg',
'data-[state=open]:animate-in data-[state=closed]:animate-out',
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
@@ -88,7 +91,7 @@ const DialogFooter = ({
<div
className={cn(
// '-mx-6 -mb-6 px-12 pt-4 pb-8',
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-4',
'-mx-6 -mb-6 p-6 flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-4',
className,
)}
{...props}

View File

@@ -18,7 +18,13 @@ const HoverCardContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={cn(
'z-50 w-fit max-w-96 overflow-auto break-words whitespace-pre-wrap rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]',
'z-50 w-fit max-w-96 overflow-auto break-words whitespace-pre-wrap',
'rounded-md border bg-bg-base p-4 text-text-primary shadow-md outline-none',
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0',
'data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',
'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
'origin-[--radix-hover-card-content-transform-origin]',
className,
)}
{...props}

View File

@@ -2,6 +2,7 @@ import { cn } from '@/lib/utils';
import React, { useContext, useState } from 'react';
const RadioGroupContext = React.createContext<{
name?: string;
value: string | number;
onChange: (value: string | number) => void;
disabled?: boolean;
@@ -50,30 +51,46 @@ function Radio({
return (
<label
className={cn(
'flex items-center cursor-pointer gap-2 text-sm',
'group/radio relative flex items-center cursor-pointer gap-2 text-sm',
mergedDisabled && 'cursor-not-allowed opacity-50',
)}
>
<span
<input
type="radio"
name={groupContext?.name}
value={value}
checked={isChecked}
onClick={handleClick}
disabled={mergedDisabled}
data-testid={testId}
className="peer absolute size-[1px] opacity-0"
/>
<div
className={cn(
'flex h-4 w-4 items-center justify-center rounded-full border border-border transition-colors',
'peer outline-none focus-visible:border-border-button',
'flex h-4 w-4 items-center justify-center rounded-full border border-border-button transition-colors',
'group-hover/radio:border-border-default hover:border-border-default',
'peer-focus:border-primary',
isChecked && 'border-primary bg-primary/10',
mergedDisabled && 'border-muted',
)}
onClick={handleClick}
data-testid={testId}
>
{isChecked && (
<div className="h-3 w-3 fill-primary text-primary bg-text-primary rounded-full" />
)}
</span>
<div
className={cn(
'h-2 w-2 fill-primary text-primary bg-text-primary rounded-full opacity-0 scale-0 transition-all',
isChecked && 'opacity-100 scale-100',
)}
/>
</div>
{children && <span className="text-foreground">{children}</span>}
</label>
);
}
type RadioGroupProps = {
name?: string;
value?: string | number;
defaultValue?: string | number;
onChange?: (value: string | number) => void;
@@ -86,6 +103,7 @@ type RadioGroupProps = {
const Group = React.forwardRef<HTMLDivElement, RadioGroupProps>(
(
{
name,
value,
defaultValue,
onChange,
@@ -116,6 +134,7 @@ const Group = React.forwardRef<HTMLDivElement, RadioGroupProps>(
return (
<RadioGroupContext.Provider
value={{
name,
value: mergedValue,
onChange: handleChange,
disabled,

View File

@@ -1,5 +1,6 @@
import { cn } from '@/lib/utils';
import * as React from 'react';
import { Button, ButtonVariants } from './button';
export declare type SegmentedValue = string | number;
export declare type SegmentedRawOption = SegmentedValue;
export interface SegmentedLabeledOption {
@@ -56,7 +57,7 @@ export interface SegmentedProps extends Omit<
itemClassName?: string;
rounded?: keyof typeof segmentedVariants.round;
sizeType?: keyof typeof segmentedVariants.size;
buttonSize?: keyof typeof segmentedVariants.buttonSize;
buttonSize?: ButtonVariants['size'];
}
export const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
@@ -101,12 +102,12 @@ export const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
const actualValue = isObject ? option.value : option;
return (
<div
<Button
key={actualValue}
type="button"
size={buttonSize}
variant="static"
className={cn(
'inline-flex items-center text-base font-normal cursor-pointer',
segmentedVariants.round[rounded],
segmentedVariants.buttonSize[buttonSize],
{
'text-text-primary bg-bg-base': selectedValue === actualValue,
},
@@ -118,7 +119,7 @@ export const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
onClick={() => handleOnChange(actualValue)}
>
{isObject ? option.label : option}
</div>
</Button>
);
})}
</div>