mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-15 01:18:26 +08:00
refactor(ui): update knowledge graph, chunk, metadata, agent log styles (#13518)
### What problem does this PR solve? Update UI styles: - **Dataset** > **Knowledge graph** tooltip - **Dataset** > **Files** > **Manage metadata** modal - **Dataset** > **Files** > **Modify Chunking Method** > **Auto metadata** > **Manage generation settings** modal - **Agent** > **Canvas (Ingestion pipeline)** > **Dataflow result** ### Type of change - [x] Refactoring
This commit is contained in:
@@ -86,7 +86,7 @@ const buttonVariants = cva(
|
||||
|
||||
// Static
|
||||
// Button has no interaction transitions
|
||||
static: '',
|
||||
static: 'text-text-secondary',
|
||||
},
|
||||
size: {
|
||||
auto: '',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
||||
import { Check } from 'lucide-react';
|
||||
import { LucideCheck } from 'lucide-react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -13,7 +13,7 @@ const Checkbox = React.forwardRef<
|
||||
<CheckboxPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'peer size-4 shrink-0 rounded-2xs border border-text-disabled outline-0 transition-colors bg-transparent',
|
||||
'peer size-3.5 shrink-0 rounded-2xs border border-text-disabled outline-0 transition-colors bg-transparent',
|
||||
'hover:border-border-default hover:bg-border-button',
|
||||
'focus-visible:border-border-default focus-visible:bg-border-default',
|
||||
'disabled:cursor-not-allowed disabled:opacity-50',
|
||||
@@ -22,10 +22,8 @@ const Checkbox = React.forwardRef<
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<CheckboxPrimitive.Indicator
|
||||
className={cn('flex items-center justify-center text-current')}
|
||||
>
|
||||
<Check className="size-3" />
|
||||
<CheckboxPrimitive.Indicator className="flex items-center justify-center text-current">
|
||||
<LucideCheck className="size-2.5 stroke-[3]" />
|
||||
</CheckboxPrimitive.Indicator>
|
||||
</CheckboxPrimitive.Root>
|
||||
));
|
||||
|
||||
@@ -102,13 +102,14 @@ const FormLabel = React.forwardRef<
|
||||
return (
|
||||
<Label
|
||||
ref={ref}
|
||||
className={cn(className, 'flex pb-0.5')}
|
||||
className={cn(
|
||||
className,
|
||||
required && 'before:content-["*"] before:text-state-error',
|
||||
)}
|
||||
htmlFor={formItemId}
|
||||
{...props}
|
||||
>
|
||||
{required && <span className="text-state-error">*</span>}
|
||||
{props.children}
|
||||
|
||||
<span>{props.children}</span>
|
||||
{tooltip && <FormTooltip tooltip={tooltip}></FormTooltip>}
|
||||
</Label>
|
||||
);
|
||||
|
||||
@@ -14,16 +14,19 @@ type RadioProps = {
|
||||
disabled?: boolean;
|
||||
onChange?: (checked: boolean) => void;
|
||||
children?: React.ReactNode;
|
||||
testId?: string;
|
||||
};
|
||||
} & Omit<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
'value' | 'checked' | 'onChange'
|
||||
>;
|
||||
|
||||
function Radio({
|
||||
className,
|
||||
value,
|
||||
checked,
|
||||
disabled,
|
||||
onChange,
|
||||
children,
|
||||
testId,
|
||||
...props
|
||||
}: RadioProps) {
|
||||
const groupContext = useContext(RadioGroupContext);
|
||||
const isControlled = checked !== undefined;
|
||||
@@ -57,24 +60,23 @@ function Radio({
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name={groupContext?.name}
|
||||
value={value}
|
||||
checked={isChecked}
|
||||
onClick={handleClick}
|
||||
disabled={mergedDisabled}
|
||||
data-testid={testId}
|
||||
className="peer absolute size-[1px] opacity-0"
|
||||
className={cn('peer absolute size-[1px] opacity-0', className)}
|
||||
{...props}
|
||||
name={groupContext?.name}
|
||||
/>
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
'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',
|
||||
'flex h-4 w-4 items-center justify-center rounded-full text-border-button border border-current transition-colors',
|
||||
'group-hover/radio:text-border-default hover:text-border-default',
|
||||
'peer-focus:text-text-primary',
|
||||
isChecked && 'border-primary bg-primary/10',
|
||||
mergedDisabled && 'border-muted',
|
||||
)}
|
||||
data-testid={testId}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { supportsCssAnchor } from '@/utils/css-support';
|
||||
import * as React from 'react';
|
||||
import { useId } from 'react';
|
||||
import { Button, ButtonVariants } from './button';
|
||||
export declare type SegmentedValue = string | number;
|
||||
export declare type SegmentedRawOption = SegmentedValue;
|
||||
@@ -60,71 +62,152 @@ export interface SegmentedProps extends Omit<
|
||||
buttonSize?: ButtonVariants['size'];
|
||||
}
|
||||
|
||||
export const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
|
||||
(
|
||||
{
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
className,
|
||||
activeClassName,
|
||||
itemClassName,
|
||||
rounded = 'default',
|
||||
sizeType = 'default',
|
||||
buttonSize = 'default',
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const [selectedValue, setSelectedValue] = React.useState<
|
||||
SegmentedValue | undefined
|
||||
>(value);
|
||||
React.useEffect(() => {
|
||||
setSelectedValue(value);
|
||||
}, [value]);
|
||||
const handleOnChange = (e: SegmentedValue) => {
|
||||
if (onChange) {
|
||||
onChange(e);
|
||||
}
|
||||
setSelectedValue(e);
|
||||
};
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex items-center p-1 gap-2 bg-bg-card',
|
||||
segmentedVariants.round[rounded],
|
||||
segmentedVariants.size[sizeType],
|
||||
const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
|
||||
supportsCssAnchor
|
||||
? (
|
||||
{
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{options.map((option) => {
|
||||
const isObject = typeof option === 'object';
|
||||
const actualValue = isObject ? option.value : option;
|
||||
activeClassName,
|
||||
itemClassName,
|
||||
rounded = 'default',
|
||||
sizeType = 'default',
|
||||
buttonSize = 'default',
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const anchorNamePrefix = useId().replace(/:/g, '');
|
||||
const [selectedValue, setSelectedValue] = React.useState<
|
||||
SegmentedValue | undefined
|
||||
>(value);
|
||||
React.useEffect(() => {
|
||||
setSelectedValue(value);
|
||||
}, [value]);
|
||||
const handleOnChange = (e: SegmentedValue) => {
|
||||
if (onChange) {
|
||||
onChange(e);
|
||||
}
|
||||
setSelectedValue(e);
|
||||
};
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex items-center p-1 gap-2 bg-bg-card',
|
||||
segmentedVariants.round[rounded],
|
||||
segmentedVariants.size[sizeType],
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{options.map((option) => {
|
||||
const isObject = typeof option === 'object';
|
||||
const actualValue = isObject ? option.value : option;
|
||||
|
||||
return (
|
||||
<Button
|
||||
key={actualValue}
|
||||
type="button"
|
||||
size={buttonSize}
|
||||
variant="static"
|
||||
console.log(actualValue);
|
||||
|
||||
return (
|
||||
<Button
|
||||
key={actualValue}
|
||||
type="button"
|
||||
size={buttonSize}
|
||||
variant="static"
|
||||
className={cn(
|
||||
selectedValue === actualValue && 'text-text-primary',
|
||||
itemClassName,
|
||||
selectedValue === actualValue && activeClassName,
|
||||
'relative z-10',
|
||||
)}
|
||||
onClick={() => handleOnChange(actualValue)}
|
||||
style={{
|
||||
anchorName: `--${anchorNamePrefix}-${String(actualValue).replace('/', '')}`,
|
||||
}}
|
||||
>
|
||||
{isObject ? option.label : option}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
{
|
||||
'text-text-primary bg-bg-base': selectedValue === actualValue,
|
||||
},
|
||||
itemClassName,
|
||||
activeClassName && selectedValue === actualValue
|
||||
? activeClassName
|
||||
: '',
|
||||
'absolute bg-bg-base rounded-sm transition-all',
|
||||
)}
|
||||
onClick={() => handleOnChange(actualValue)}
|
||||
>
|
||||
{isObject ? option.label : option}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
style={{
|
||||
positionAnchor: `--${anchorNamePrefix}-${String(selectedValue).replace('/', '')}`,
|
||||
width: 'anchor-size(width)',
|
||||
height: 'anchor-size(height)',
|
||||
top: 'anchor(top)',
|
||||
left: 'anchor(left)',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
: (
|
||||
{
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
className,
|
||||
activeClassName,
|
||||
itemClassName,
|
||||
rounded = 'default',
|
||||
sizeType = 'default',
|
||||
buttonSize = 'default',
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const [selectedValue, setSelectedValue] = React.useState<
|
||||
SegmentedValue | undefined
|
||||
>(value);
|
||||
React.useEffect(() => {
|
||||
setSelectedValue(value);
|
||||
}, [value]);
|
||||
const handleOnChange = (e: SegmentedValue) => {
|
||||
if (onChange) {
|
||||
onChange(e);
|
||||
}
|
||||
setSelectedValue(e);
|
||||
};
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex items-center p-1 gap-2 bg-bg-card',
|
||||
segmentedVariants.round[rounded],
|
||||
segmentedVariants.size[sizeType],
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{options.map((option) => {
|
||||
const isObject = typeof option === 'object';
|
||||
const actualValue = isObject ? option.value : option;
|
||||
|
||||
return (
|
||||
<Button
|
||||
key={actualValue}
|
||||
type="button"
|
||||
size={buttonSize}
|
||||
variant="static"
|
||||
className={cn(
|
||||
{
|
||||
'text-text-primary bg-bg-base':
|
||||
selectedValue === actualValue,
|
||||
},
|
||||
itemClassName,
|
||||
selectedValue === actualValue && activeClassName,
|
||||
)}
|
||||
onClick={() => handleOnChange(actualValue)}
|
||||
>
|
||||
{isObject ? option.label : option}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Segmented.displayName = 'Segmented';
|
||||
export { Segmented };
|
||||
|
||||
@@ -16,15 +16,17 @@ const TooltipContent = React.forwardRef<
|
||||
React.ElementRef<typeof TooltipPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
||||
>(({ className, sideOffset = 4, ...props }, ref) => (
|
||||
<TooltipPrimitive.Content
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'z-50 overflow-auto scrollbar-auto rounded-md whitespace-pre-wrap border bg-bg-base px-3 py-1.5 text-sm text-text-primary shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 max-w-[30vw]',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
<TooltipPrimitive.Portal>
|
||||
<TooltipPrimitive.Content
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'z-50 overflow-auto scrollbar-auto rounded-md whitespace-pre-wrap border bg-bg-base px-3 py-1.5 text-sm text-text-primary shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 max-w-[30vw]',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</TooltipPrimitive.Portal>
|
||||
));
|
||||
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
||||
|
||||
@@ -35,11 +37,12 @@ export const FormTooltip = ({ tooltip }: { tooltip: React.ReactNode }) => {
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
tabIndex={-1}
|
||||
className="align-text-top"
|
||||
onClick={(e) => {
|
||||
e.preventDefault(); // Prevent clicking the tooltip from triggering form save
|
||||
}}
|
||||
>
|
||||
<CircleQuestionMark className="size-3 ml-[2px] -translate-y-1" />
|
||||
<CircleQuestionMark className="size-[.85em] ml-[.25em]" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{tooltip}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
Reference in New Issue
Block a user