refactor(web): unify Base UI component props to namespace types (#35306)

This commit is contained in:
yyh 2026-04-16 15:35:04 +08:00 committed by GitHub
parent 54e51be665
commit a1f990584b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 76 additions and 77 deletions

View File

@ -1,9 +1,9 @@
'use client'
import type { ComponentPropsWithoutRef, ReactNode } from 'react'
import type { ButtonProps } from '@/app/components/base/ui/button'
import { AlertDialog as BaseAlertDialog } from '@base-ui/react/alert-dialog'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { Button } from '@/app/components/base/ui/button'
export const AlertDialog = BaseAlertDialog.Root
@ -12,11 +12,11 @@ export const AlertDialogTitle = BaseAlertDialog.Title
export const AlertDialogDescription = BaseAlertDialog.Description
type AlertDialogContentProps = {
children: React.ReactNode
children: ReactNode
className?: string
overlayClassName?: string
popupProps?: Omit<React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Popup>, 'children' | 'className'>
backdropProps?: Omit<React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Backdrop>, 'className'>
popupProps?: Omit<BaseAlertDialog.Popup.Props, 'children' | 'className'>
backdropProps?: Omit<BaseAlertDialog.Backdrop.Props, 'className'>
}
export function AlertDialogContent({
@ -50,7 +50,7 @@ export function AlertDialogContent({
)
}
type AlertDialogActionsProps = React.ComponentPropsWithoutRef<'div'>
type AlertDialogActionsProps = ComponentPropsWithoutRef<'div'>
export function AlertDialogActions({ className, ...props }: AlertDialogActionsProps) {
return (
@ -62,8 +62,8 @@ export function AlertDialogActions({ className, ...props }: AlertDialogActionsPr
}
type AlertDialogCancelButtonProps = Omit<ButtonProps, 'children'> & {
children: React.ReactNode
closeProps?: Omit<React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Close>, 'children' | 'render'>
children: ReactNode
closeProps?: Omit<BaseAlertDialog.Close.Props, 'children' | 'render'>
}
export function AlertDialogCancelButton({

View File

@ -1,5 +1,4 @@
import type { ImageLoadingStatus } from '@base-ui/react/avatar'
import type * as React from 'react'
import { Avatar as BaseAvatar } from '@base-ui/react/avatar'
import { cn } from '@langgenius/dify-ui/cn'
@ -24,7 +23,7 @@ export type AvatarProps = {
onLoadingStatusChange?: (status: ImageLoadingStatus) => void
}
type AvatarRootProps = React.ComponentPropsWithRef<typeof BaseAvatar.Root> & {
type AvatarRootProps = BaseAvatar.Root.Props & {
size?: AvatarSize
}
@ -45,7 +44,7 @@ export function AvatarRoot({
)
}
type AvatarFallbackProps = React.ComponentPropsWithRef<typeof BaseAvatar.Fallback> & {
type AvatarFallbackProps = BaseAvatar.Fallback.Props & {
size?: AvatarSize
}
@ -66,7 +65,7 @@ export function AvatarFallback({
)
}
type AvatarImageProps = React.ComponentPropsWithRef<typeof BaseAvatar.Image>
type AvatarImageProps = BaseAvatar.Image.Props
export function AvatarImage({
className,

View File

@ -1,9 +1,9 @@
'use client'
import type { ReactNode } from 'react'
import type { Placement } from '@/app/components/base/ui/placement'
import { ContextMenu as BaseContextMenu } from '@base-ui/react/context-menu'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import {
overlayBackdropClassName,
overlayGroupLabelClassName,
@ -22,18 +22,18 @@ export const ContextMenuGroup = BaseContextMenu.Group
export const ContextMenuRadioGroup = BaseContextMenu.RadioGroup
type ContextMenuContentProps = {
children: React.ReactNode
children: ReactNode
placement?: Placement
sideOffset?: number
alignOffset?: number
className?: string
popupClassName?: string
positionerProps?: Omit<
React.ComponentPropsWithoutRef<typeof BaseContextMenu.Positioner>,
BaseContextMenu.Positioner.Props,
'children' | 'className' | 'side' | 'align' | 'sideOffset' | 'alignOffset'
>
popupProps?: Omit<
React.ComponentPropsWithoutRef<typeof BaseContextMenu.Popup>,
BaseContextMenu.Popup.Props,
'children' | 'className'
>
}
@ -113,7 +113,7 @@ export function ContextMenuContent({
})
}
type ContextMenuItemProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Item> & {
type ContextMenuItemProps = BaseContextMenu.Item.Props & {
destructive?: boolean
}
@ -130,7 +130,7 @@ export function ContextMenuItem({
)
}
type ContextMenuLinkItemProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.LinkItem> & {
type ContextMenuLinkItemProps = BaseContextMenu.LinkItem.Props & {
destructive?: boolean
}
@ -152,7 +152,7 @@ export function ContextMenuLinkItem({
export function ContextMenuRadioItem({
className,
...props
}: React.ComponentPropsWithoutRef<typeof BaseContextMenu.RadioItem>) {
}: BaseContextMenu.RadioItem.Props) {
return (
<BaseContextMenu.RadioItem
className={cn(overlayRowClassName, className)}
@ -164,7 +164,7 @@ export function ContextMenuRadioItem({
export function ContextMenuCheckboxItem({
className,
...props
}: React.ComponentPropsWithoutRef<typeof BaseContextMenu.CheckboxItem>) {
}: BaseContextMenu.CheckboxItem.Props) {
return (
<BaseContextMenu.CheckboxItem
className={cn(overlayRowClassName, className)}
@ -176,7 +176,7 @@ export function ContextMenuCheckboxItem({
export function ContextMenuCheckboxItemIndicator({
className,
...props
}: Omit<React.ComponentPropsWithoutRef<typeof BaseContextMenu.CheckboxItemIndicator>, 'children'>) {
}: Omit<BaseContextMenu.CheckboxItemIndicator.Props, 'children'>) {
return (
<BaseContextMenu.CheckboxItemIndicator
className={cn(overlayIndicatorClassName, className)}
@ -190,7 +190,7 @@ export function ContextMenuCheckboxItemIndicator({
export function ContextMenuRadioItemIndicator({
className,
...props
}: Omit<React.ComponentPropsWithoutRef<typeof BaseContextMenu.RadioItemIndicator>, 'children'>) {
}: Omit<BaseContextMenu.RadioItemIndicator.Props, 'children'>) {
return (
<BaseContextMenu.RadioItemIndicator
className={cn(overlayIndicatorClassName, className)}
@ -201,7 +201,7 @@ export function ContextMenuRadioItemIndicator({
)
}
type ContextMenuSubTriggerProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.SubmenuTrigger> & {
type ContextMenuSubTriggerProps = BaseContextMenu.SubmenuTrigger.Props & {
destructive?: boolean
}
@ -223,7 +223,7 @@ export function ContextMenuSubTrigger({
}
type ContextMenuSubContentProps = {
children: React.ReactNode
children: ReactNode
placement?: Placement
sideOffset?: number
alignOffset?: number
@ -258,7 +258,7 @@ export function ContextMenuSubContent({
export function ContextMenuGroupLabel({
className,
...props
}: React.ComponentPropsWithoutRef<typeof BaseContextMenu.GroupLabel>) {
}: BaseContextMenu.GroupLabel.Props) {
return (
<BaseContextMenu.GroupLabel
className={cn(overlayGroupLabelClassName, className)}
@ -270,7 +270,7 @@ export function ContextMenuGroupLabel({
export function ContextMenuSeparator({
className,
...props
}: React.ComponentPropsWithoutRef<typeof BaseContextMenu.Separator>) {
}: BaseContextMenu.Separator.Props) {
return (
<BaseContextMenu.Separator
className={cn(overlaySeparatorClassName, className)}

View File

@ -7,9 +7,9 @@
// This ensures overlays inside a Dialog (e.g. a Tooltip on a dialog button) render
// above the dialog backdrop instead of being clipped by it.
import type { ReactNode } from 'react'
import { Dialog as BaseDialog } from '@base-ui/react/dialog'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
export const Dialog = BaseDialog.Root
/** @public */
@ -18,7 +18,7 @@ export const DialogTitle = BaseDialog.Title
export const DialogDescription = BaseDialog.Description
export const DialogPortal = BaseDialog.Portal
type DialogCloseButtonProps = Omit<React.ComponentPropsWithoutRef<typeof BaseDialog.Close>, 'children'>
type DialogCloseButtonProps = Omit<BaseDialog.Close.Props, 'children'>
export function DialogCloseButton({
className,
@ -40,10 +40,10 @@ export function DialogCloseButton({
}
type DialogContentProps = {
children: React.ReactNode
children: ReactNode
className?: string
overlayClassName?: string
backdropProps?: React.ComponentPropsWithoutRef<typeof BaseDialog.Backdrop>
backdropProps?: BaseDialog.Backdrop.Props
}
export function DialogContent({

View File

@ -1,9 +1,9 @@
'use client'
import type { ReactNode } from 'react'
import type { Placement } from '@/app/components/base/ui/placement'
import { Menu } from '@base-ui/react/menu'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import {
overlayGroupLabelClassName,
overlayIndicatorClassName,
@ -23,7 +23,7 @@ export const DropdownMenuRadioGroup = Menu.RadioGroup
export function DropdownMenuRadioItem({
className,
...props
}: React.ComponentPropsWithoutRef<typeof Menu.RadioItem>) {
}: Menu.RadioItem.Props) {
return (
<Menu.RadioItem
className={cn(overlayRowClassName, className)}
@ -35,7 +35,7 @@ export function DropdownMenuRadioItem({
export function DropdownMenuRadioItemIndicator({
className,
...props
}: Omit<React.ComponentPropsWithoutRef<typeof Menu.RadioItemIndicator>, 'children'>) {
}: Omit<Menu.RadioItemIndicator.Props, 'children'>) {
return (
<Menu.RadioItemIndicator
className={cn(overlayIndicatorClassName, className)}
@ -49,7 +49,7 @@ export function DropdownMenuRadioItemIndicator({
export function DropdownMenuCheckboxItem({
className,
...props
}: React.ComponentPropsWithoutRef<typeof Menu.CheckboxItem>) {
}: Menu.CheckboxItem.Props) {
return (
<Menu.CheckboxItem
className={cn(overlayRowClassName, className)}
@ -61,7 +61,7 @@ export function DropdownMenuCheckboxItem({
export function DropdownMenuCheckboxItemIndicator({
className,
...props
}: Omit<React.ComponentPropsWithoutRef<typeof Menu.CheckboxItemIndicator>, 'children'>) {
}: Omit<Menu.CheckboxItemIndicator.Props, 'children'>) {
return (
<Menu.CheckboxItemIndicator
className={cn(overlayIndicatorClassName, className)}
@ -75,7 +75,7 @@ export function DropdownMenuCheckboxItemIndicator({
export function DropdownMenuGroupLabel({
className,
...props
}: React.ComponentPropsWithoutRef<typeof Menu.GroupLabel>) {
}: Menu.GroupLabel.Props) {
return (
<Menu.GroupLabel
className={cn(overlayGroupLabelClassName, className)}
@ -85,18 +85,18 @@ export function DropdownMenuGroupLabel({
}
type DropdownMenuContentProps = {
children: React.ReactNode
children: ReactNode
placement?: Placement
sideOffset?: number
alignOffset?: number
className?: string
popupClassName?: string
positionerProps?: Omit<
React.ComponentPropsWithoutRef<typeof Menu.Positioner>,
Menu.Positioner.Props,
'children' | 'className' | 'side' | 'align' | 'sideOffset' | 'alignOffset'
>
popupProps?: Omit<
React.ComponentPropsWithoutRef<typeof Menu.Popup>,
Menu.Popup.Props,
'children' | 'className'
>
}
@ -170,7 +170,7 @@ export function DropdownMenuContent({
})
}
type DropdownMenuSubTriggerProps = React.ComponentPropsWithoutRef<typeof Menu.SubmenuTrigger> & {
type DropdownMenuSubTriggerProps = Menu.SubmenuTrigger.Props & {
destructive?: boolean
}
@ -192,7 +192,7 @@ export function DropdownMenuSubTrigger({
}
type DropdownMenuSubContentProps = {
children: React.ReactNode
children: ReactNode
placement?: Placement
sideOffset?: number
alignOffset?: number
@ -224,7 +224,7 @@ export function DropdownMenuSubContent({
})
}
type DropdownMenuItemProps = React.ComponentPropsWithoutRef<typeof Menu.Item> & {
type DropdownMenuItemProps = Menu.Item.Props & {
destructive?: boolean
}
@ -241,7 +241,7 @@ export function DropdownMenuItem({
)
}
type DropdownMenuLinkItemProps = React.ComponentPropsWithoutRef<typeof Menu.LinkItem> & {
type DropdownMenuLinkItemProps = Menu.LinkItem.Props & {
destructive?: boolean
}
@ -263,7 +263,7 @@ export function DropdownMenuLinkItem({
export function DropdownMenuSeparator({
className,
...props
}: React.ComponentPropsWithoutRef<typeof Menu.Separator>) {
}: Menu.Separator.Props) {
return (
<Menu.Separator
className={cn(overlaySeparatorClassName, className)}

View File

@ -1,13 +1,13 @@
'use client'
import type { VariantProps } from 'class-variance-authority'
import type { HTMLAttributes } from 'react'
import { NumberField as BaseNumberField } from '@base-ui/react/number-field'
import { cn } from '@langgenius/dify-ui/cn'
import { cva } from 'class-variance-authority'
import * as React from 'react'
export const NumberField = BaseNumberField.Root
export type NumberFieldRootProps = React.ComponentPropsWithoutRef<typeof BaseNumberField.Root>
export type NumberFieldRootProps = BaseNumberField.Root.Props
export const numberFieldGroupVariants = cva(
[
@ -32,7 +32,7 @@ export const numberFieldGroupVariants = cva(
)
export type NumberFieldSize = NonNullable<VariantProps<typeof numberFieldGroupVariants>['size']>
export type NumberFieldGroupProps = React.ComponentPropsWithoutRef<typeof BaseNumberField.Group> & VariantProps<typeof numberFieldGroupVariants>
export type NumberFieldGroupProps = BaseNumberField.Group.Props & VariantProps<typeof numberFieldGroupVariants>
export function NumberFieldGroup({
className,
@ -67,7 +67,7 @@ export const numberFieldInputVariants = cva(
},
)
export type NumberFieldInputProps = Omit<React.ComponentPropsWithoutRef<typeof BaseNumberField.Input>, 'size'> & VariantProps<typeof numberFieldInputVariants>
export type NumberFieldInputProps = Omit<BaseNumberField.Input.Props, 'size'> & VariantProps<typeof numberFieldInputVariants>
export function NumberFieldInput({
className,
@ -97,7 +97,7 @@ export const numberFieldUnitVariants = cva(
},
)
export type NumberFieldUnitProps = React.HTMLAttributes<HTMLSpanElement> & VariantProps<typeof numberFieldUnitVariants>
export type NumberFieldUnitProps = HTMLAttributes<HTMLSpanElement> & VariantProps<typeof numberFieldUnitVariants>
export function NumberFieldUnit({
className,
@ -116,7 +116,7 @@ const numberFieldControlsVariants = cva(
'flex shrink-0 flex-col items-stretch border-l border-divider-subtle bg-transparent text-text-tertiary',
)
export type NumberFieldControlsProps = React.HTMLAttributes<HTMLDivElement>
export type NumberFieldControlsProps = HTMLAttributes<HTMLDivElement>
export function NumberFieldControls({
className,
@ -185,7 +185,7 @@ type NumberFieldButtonVariantProps = Omit<
'direction'
>
export type NumberFieldButtonProps = React.ComponentPropsWithoutRef<typeof BaseNumberField.Increment> & NumberFieldButtonVariantProps
export type NumberFieldButtonProps = BaseNumberField.Increment.Props & NumberFieldButtonVariantProps
const incrementAriaLabel = 'Increment value'
const decrementAriaLabel = 'Decrement value'

View File

@ -1,9 +1,9 @@
'use client'
import type { ReactNode } from 'react'
import type { Placement } from '@/app/components/base/ui/placement'
import { Popover as BasePopover } from '@base-ui/react/popover'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { parsePlacement } from '@/app/components/base/ui/placement'
export const Popover = BasePopover.Root
@ -15,18 +15,18 @@ export const PopoverTitle = BasePopover.Title
export const PopoverDescription = BasePopover.Description
type PopoverContentProps = {
children: React.ReactNode
children: ReactNode
placement?: Placement
sideOffset?: number
alignOffset?: number
className?: string
popupClassName?: string
positionerProps?: Omit<
React.ComponentPropsWithoutRef<typeof BasePopover.Positioner>,
BasePopover.Positioner.Props,
'children' | 'className' | 'side' | 'align' | 'sideOffset' | 'alignOffset'
>
popupProps?: Omit<
React.ComponentPropsWithoutRef<typeof BasePopover.Popup>,
BasePopover.Popup.Props,
'children' | 'className'
>
}

View File

@ -1,12 +1,12 @@
'use client'
import type { ReactNode } from 'react'
import { ScrollArea as BaseScrollArea } from '@base-ui/react/scroll-area'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import './scroll-area.css'
export const ScrollAreaRoot = BaseScrollArea.Root
type ScrollAreaRootProps = React.ComponentPropsWithRef<typeof BaseScrollArea.Root>
type ScrollAreaRootProps = BaseScrollArea.Root.Props
export const ScrollAreaContent = BaseScrollArea.Content
@ -17,7 +17,7 @@ type ScrollAreaSlotClassNames = {
}
type ScrollAreaProps = Omit<ScrollAreaRootProps, 'children'> & {
children: React.ReactNode
children: ReactNode
orientation?: 'vertical' | 'horizontal'
slotClassNames?: ScrollAreaSlotClassNames
label?: string
@ -45,7 +45,7 @@ const scrollAreaViewportClassName = cn(
const scrollAreaCornerClassName = 'bg-transparent'
type ScrollAreaViewportProps = React.ComponentPropsWithRef<typeof BaseScrollArea.Viewport>
type ScrollAreaViewportProps = BaseScrollArea.Viewport.Props
export function ScrollAreaViewport({
className,
@ -59,7 +59,7 @@ export function ScrollAreaViewport({
)
}
type ScrollAreaScrollbarProps = React.ComponentPropsWithRef<typeof BaseScrollArea.Scrollbar>
type ScrollAreaScrollbarProps = BaseScrollArea.Scrollbar.Props
export function ScrollAreaScrollbar({
className,
@ -74,7 +74,7 @@ export function ScrollAreaScrollbar({
)
}
type ScrollAreaThumbProps = React.ComponentPropsWithRef<typeof BaseScrollArea.Thumb>
type ScrollAreaThumbProps = BaseScrollArea.Thumb.Props
export function ScrollAreaThumb({
className,
@ -88,7 +88,7 @@ export function ScrollAreaThumb({
)
}
type ScrollAreaCornerProps = React.ComponentPropsWithRef<typeof BaseScrollArea.Corner>
type ScrollAreaCornerProps = BaseScrollArea.Corner.Props
export function ScrollAreaCorner({
className,

View File

@ -1,9 +1,9 @@
'use client'
import type { ReactNode } from 'react'
import type { Placement } from '@/app/components/base/ui/placement'
import { Select as BaseSelect } from '@base-ui/react/select'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import {
overlayGroupLabelClassName,
overlaySeparatorClassName,
@ -21,7 +21,7 @@ const selectSizeClassName: Record<string, string> = {
large: 'h-9 gap-0.5 rounded-[10px] px-4 py-2 system-md-regular',
}
type SelectTriggerProps = React.ComponentPropsWithoutRef<typeof BaseSelect.Trigger> & {
type SelectTriggerProps = BaseSelect.Trigger.Props & {
size?: 'small' | 'regular' | 'large'
}
@ -58,7 +58,7 @@ export function SelectTrigger({
export function SelectGroupLabel({
className,
...props
}: React.ComponentPropsWithoutRef<typeof BaseSelect.GroupLabel>) {
}: BaseSelect.GroupLabel.Props) {
return (
<BaseSelect.GroupLabel
className={cn(overlayGroupLabelClassName, className)}
@ -71,7 +71,7 @@ export function SelectGroupLabel({
export function SelectSeparator({
className,
...props
}: React.ComponentPropsWithoutRef<typeof BaseSelect.Separator>) {
}: BaseSelect.Separator.Props) {
return (
<BaseSelect.Separator
className={cn(overlaySeparatorClassName, className)}
@ -81,7 +81,7 @@ export function SelectSeparator({
}
type SelectContentProps = {
children: React.ReactNode
children: ReactNode
placement?: Placement
sideOffset?: number
alignOffset?: number
@ -89,15 +89,15 @@ type SelectContentProps = {
popupClassName?: string
listClassName?: string
positionerProps?: Omit<
React.ComponentPropsWithoutRef<typeof BaseSelect.Positioner>,
BaseSelect.Positioner.Props,
'children' | 'className' | 'side' | 'align' | 'sideOffset' | 'alignOffset'
>
popupProps?: Omit<
React.ComponentPropsWithoutRef<typeof BaseSelect.Popup>,
BaseSelect.Popup.Props,
'children' | 'className'
>
listProps?: Omit<
React.ComponentPropsWithoutRef<typeof BaseSelect.List>,
BaseSelect.List.Props,
'children' | 'className'
>
}
@ -150,7 +150,7 @@ export function SelectContent({
export function SelectItem({
className,
...props
}: React.ComponentPropsWithoutRef<typeof BaseSelect.Item>) {
}: BaseSelect.Item.Props) {
return (
<BaseSelect.Item
className={cn(
@ -166,7 +166,7 @@ export function SelectItem({
export function SelectItemText({
className,
...props
}: React.ComponentPropsWithoutRef<typeof BaseSelect.ItemText>) {
}: BaseSelect.ItemText.Props) {
return (
<BaseSelect.ItemText
className={cn('mr-1 min-w-0 grow truncate px-1', className)}
@ -178,7 +178,7 @@ export function SelectItemText({
export function SelectItemIndicator({
className,
...props
}: Omit<React.ComponentPropsWithoutRef<typeof BaseSelect.ItemIndicator>, 'children'>) {
}: Omit<BaseSelect.ItemIndicator.Props, 'children'>) {
return (
<BaseSelect.ItemIndicator
className={cn('ml-auto flex shrink-0 items-center text-text-accent', className)}

View File

@ -1,22 +1,22 @@
'use client'
import type { ReactNode } from 'react'
import type { Placement } from '@/app/components/base/ui/placement'
import { Tooltip as BaseTooltip } from '@base-ui/react/tooltip'
import { cn } from '@langgenius/dify-ui/cn'
import * as React from 'react'
import { parsePlacement } from '@/app/components/base/ui/placement'
type TooltipContentVariant = 'default' | 'plain'
type TooltipContentProps = {
children: React.ReactNode
children: ReactNode
placement?: Placement
sideOffset?: number
alignOffset?: number
positionerClassName?: string
className?: string
variant?: TooltipContentVariant
} & Omit<React.ComponentPropsWithoutRef<typeof BaseTooltip.Popup>, 'children' | 'className'>
} & Omit<BaseTooltip.Popup.Props, 'children' | 'className'>
export function TooltipContent({
children,

View File

@ -163,7 +163,7 @@ describe('WorkplaceSelector', () => {
await waitFor(() => {
expect(mockNotify).toHaveBeenCalledWith({
type: 'error',
message: 'common.provider.saveFailed',
message: 'common.actionMsg.modifiedUnsuccessfully',
})
})
})

View File

@ -29,7 +29,7 @@ const WorkplaceSelector = () => {
location.assign(`${location.origin}${basePath}`)
}
catch {
toast.error(t('provider.saveFailed', { ns: 'common' }))
toast.error(t('actionMsg.modifiedUnsuccessfully', { ns: 'common' }))
}
}