mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-06-01 06:00:19 +00:00
style(ui): update shared form and surface primitives
Align badge, checkbox, input, select, textarea, and tooltip with the new design system. Made-with: Cursor
This commit is contained in:
parent
7d7fccfc6f
commit
b3c00caeb4
6 changed files with 50 additions and 15 deletions
|
|
@ -26,7 +26,19 @@ import {
|
|||
} from './semanticProps';
|
||||
|
||||
const badgeBase = cva(
|
||||
'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ds-ring-brand-default-focus focus:ring-offset-2 focus:ring-offset-ds-bg-neutral-subtle-default'
|
||||
'inline-flex items-center rounded-md border font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ds-ring-brand-default-focus focus:ring-offset-2 focus:ring-offset-ds-bg-neutral-subtle-default',
|
||||
{
|
||||
variants: {
|
||||
size: {
|
||||
xs: 'gap-0.5 px-1 py-0 !text-label-xs',
|
||||
default: 'px-2 py-1 !text-label-sm',
|
||||
sm: 'gap-1 px-2 py-1 !text-label-sm',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'default',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
type BadgeLegacyVariant = 'default' | 'secondary' | 'destructive' | 'outline';
|
||||
|
|
@ -160,21 +172,32 @@ function badgeToneClasses(
|
|||
return BADGE_GHOST[tone];
|
||||
}
|
||||
|
||||
export type BadgeSize = 'xs' | 'default' | 'sm';
|
||||
|
||||
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
variant?: UiVariant | BadgeLegacyVariant;
|
||||
emphasis?: UiEmphasis;
|
||||
tone?: UiToneInput;
|
||||
size?: BadgeSize;
|
||||
}
|
||||
|
||||
function Badge({ className, variant, emphasis, tone, ...props }: BadgeProps) {
|
||||
function Badge({
|
||||
className,
|
||||
variant,
|
||||
emphasis,
|
||||
tone,
|
||||
size = 'default',
|
||||
...props
|
||||
}: BadgeProps) {
|
||||
const resolved = resolveBadgeVisual(variant, tone, emphasis);
|
||||
return (
|
||||
<div
|
||||
data-variant={resolved.publicVariant}
|
||||
data-tone={resolved.tone}
|
||||
data-emphasis={resolved.emphasis}
|
||||
data-size={size === 'default' ? undefined : size}
|
||||
className={cn(
|
||||
badgeBase(),
|
||||
badgeBase({ size }),
|
||||
badgeToneClasses(resolved.styleVariant, resolved.tone),
|
||||
className
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -19,23 +19,32 @@ import * as React from 'react';
|
|||
import { cn } from '@/lib/utils';
|
||||
import { checkboxTokenAliases, mergeAliasStyles } from './tokenAliases';
|
||||
|
||||
export type CheckboxProps = React.ComponentPropsWithoutRef<
|
||||
typeof CheckboxPrimitives.Root
|
||||
> & {
|
||||
iconClassName?: string;
|
||||
};
|
||||
|
||||
const Checkbox = React.forwardRef<
|
||||
React.ElementRef<typeof CheckboxPrimitives.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof CheckboxPrimitives.Root>
|
||||
>(({ className, style, ...props }, ref) => (
|
||||
CheckboxProps
|
||||
>(({ className, style, iconClassName, ...props }, ref) => (
|
||||
<CheckboxPrimitives.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'focus-visible:ring-ds-ring-brand-default-focus peer h-4 w-4 rounded border-ds-border-neutral-default-default bg-ds-bg-neutral-default-default hover:border-ds-border-neutral-strong-default data-[state=checked]:border-ds-border-status-completed-default-default data-[state=checked]:bg-ds-bg-status-completed-default-default data-[state=checked]:text-ds-text-brand-inverse-default shrink-0 border border-solid transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'group/checkbox focus-visible:ring-ds-ring-brand-default-focus peer h-4 w-4 rounded border-ds-border-neutral-default-default bg-ds-bg-neutral-default-default hover:border-ds-border-neutral-strong-default data-[state=checked]:border-ds-border-status-completed-default-default data-[state=checked]:bg-ds-bg-success-default-default shrink-0 border border-solid transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
style={mergeAliasStyles(checkboxTokenAliases, style)}
|
||||
{...props}
|
||||
>
|
||||
<CheckboxPrimitives.Indicator
|
||||
className={cn('flex items-center justify-center text-current')}
|
||||
>
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
<CheckboxPrimitives.Indicator className="flex items-center justify-center">
|
||||
<Check
|
||||
className={cn(
|
||||
'h-3.5 w-3.5 group-data-[state=checked]/checkbox:text-ds-text-brand-inverse-default shrink-0',
|
||||
iconClassName
|
||||
)}
|
||||
/>
|
||||
</CheckboxPrimitives.Indicator>
|
||||
</CheckboxPrimitives.Root>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ const Input = React.forwardRef<HTMLInputElement, BaseInputProps>(
|
|||
|
||||
<div
|
||||
className={cn(
|
||||
'rounded-lg shadow-sm relative flex items-center border border-solid transition-colors',
|
||||
'rounded-xl shadow-sm relative flex items-center border border-solid transition-colors',
|
||||
stateCls.field,
|
||||
formFieldSizeClasses[size],
|
||||
// After field base so hover / focus background wins; subtle surface on interaction
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ type SelectTriggerExtraProps = {
|
|||
note?: string;
|
||||
tooltip?: string;
|
||||
required?: boolean;
|
||||
/** Outer wrapper width; default `w-fit` keeps intrinsic width for inline selects. */
|
||||
wrapperClassName?: string;
|
||||
};
|
||||
|
||||
const SelectTrigger = React.forwardRef<
|
||||
|
|
@ -80,6 +82,7 @@ const SelectTrigger = React.forwardRef<
|
|||
disabled,
|
||||
tooltip,
|
||||
required = false,
|
||||
wrapperClassName,
|
||||
style,
|
||||
...props
|
||||
},
|
||||
|
|
@ -87,7 +90,7 @@ const SelectTrigger = React.forwardRef<
|
|||
) => {
|
||||
const stateCls = formFieldSelectTriggerState(state, Boolean(disabled));
|
||||
return (
|
||||
<div className={cn('w-fit', stateCls.wrapper)}>
|
||||
<div className={cn(wrapperClassName ?? 'w-fit', stateCls.wrapper)}>
|
||||
{title ? (
|
||||
<div className="mb-1.5 gap-1 text-body-sm font-bold text-ds-text-neutral-default-default flex items-center">
|
||||
<span>{title}</span>
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, BaseTextareaProps>(
|
|||
return (
|
||||
<>
|
||||
<textarea
|
||||
{...textareaProps}
|
||||
data-scrollbar="ui-textarea"
|
||||
className={cn(
|
||||
'border-ds-border-neutral-default-default placeholder:text-ds-text-neutral-muted-default/20 focus-visible:ring-ds-ring-brand-default-focus rounded-lg py-2 pl-3 pr-3 text-body-sm shadow-sm flex min-h-[60px] w-full border bg-transparent [scrollbar-gutter:stable] focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
||||
|
|
@ -101,7 +102,6 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, BaseTextareaProps>(
|
|||
}
|
||||
onKeyDown?.(e);
|
||||
}}
|
||||
{...textareaProps}
|
||||
/>
|
||||
<style>{`
|
||||
/* Firefox */
|
||||
|
|
@ -168,6 +168,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, BaseTextareaProps>(
|
|||
) : null}
|
||||
|
||||
<textarea
|
||||
{...textareaProps}
|
||||
data-scrollbar="ui-textarea"
|
||||
ref={ref}
|
||||
disabled={disabled}
|
||||
|
|
@ -190,7 +191,6 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, BaseTextareaProps>(
|
|||
}
|
||||
onKeyDown?.(e);
|
||||
}}
|
||||
{...textareaProps}
|
||||
/>
|
||||
|
||||
{backIcon ? (
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const TooltipContent = React.forwardRef<
|
|||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'rounded-md border-ds-border-neutral-default-default bg-ds-bg-neutral-strong-default px-2 py-1.5 text-xs text-ds-text-neutral-default-default shadow-md backdrop-blur-sm 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 z-50 origin-[--radix-tooltip-content-transform-origin] overflow-hidden border',
|
||||
'rounded-md border-ds-border-neutral-default-default bg-ds-bg-neutral-strong-default px-2 py-1.5 text-xs text-ds-text-neutral-default-default shadow-md backdrop-blur-sm 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 z-[100] origin-[--radix-tooltip-content-transform-origin] overflow-hidden border',
|
||||
className
|
||||
)}
|
||||
style={mergeAliasStyles(tooltipTokenAliases, style)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue