diff --git a/web/app/components/base/ui/scroll-area/scroll-area.css b/packages/dify-ui/src/styles/components.css similarity index 64% rename from web/app/components/base/ui/scroll-area/scroll-area.css rename to packages/dify-ui/src/styles/components.css index 7a33076acf..ab02be97fb 100644 --- a/web/app/components/base/ui/scroll-area/scroll-area.css +++ b/packages/dify-ui/src/styles/components.css @@ -15,7 +15,7 @@ width: 4px; height: 12px; transform: translateX(-50%); - background: linear-gradient(to bottom, var(--scroll-area-edge-hint-bg, var(--color-components-panel-bg)), transparent); + background: linear-gradient(to bottom, var(--color-components-panel-bg), transparent); } [data-dify-scrollbar][data-orientation='vertical']::after { @@ -24,7 +24,7 @@ width: 4px; height: 12px; transform: translateX(-50%); - background: linear-gradient(to top, var(--scroll-area-edge-hint-bg, var(--color-components-panel-bg)), transparent); + background: linear-gradient(to top, var(--color-components-panel-bg), transparent); } [data-dify-scrollbar][data-orientation='horizontal']::before { @@ -33,7 +33,7 @@ width: 12px; height: 4px; transform: translateY(-50%); - background: linear-gradient(to right, var(--scroll-area-edge-hint-bg, var(--color-components-panel-bg)), transparent); + background: linear-gradient(to right, var(--color-components-panel-bg), transparent); } [data-dify-scrollbar][data-orientation='horizontal']::after { @@ -42,7 +42,7 @@ width: 12px; height: 4px; transform: translateY(-50%); - background: linear-gradient(to left, var(--scroll-area-edge-hint-bg, var(--color-components-panel-bg)), transparent); + background: linear-gradient(to left, var(--color-components-panel-bg), transparent); } [data-dify-scrollbar][data-orientation='vertical']:not([data-overflow-y-start])::before { @@ -61,12 +61,6 @@ opacity: 1; } -[data-dify-scrollbar][data-hovering] > [data-orientation], -[data-dify-scrollbar][data-scrolling] > [data-orientation], -[data-dify-scrollbar] > [data-orientation]:active { - background-color: var(--scroll-area-thumb-bg-active, var(--color-state-base-handle-hover)); -} - @media (prefers-reduced-motion: reduce) { [data-dify-scrollbar]::before, [data-dify-scrollbar]::after { diff --git a/packages/dify-ui/src/styles/styles.css b/packages/dify-ui/src/styles/styles.css index a712e9c5db..fb410b2d5f 100644 --- a/packages/dify-ui/src/styles/styles.css +++ b/packages/dify-ui/src/styles/styles.css @@ -1,3 +1,4 @@ @import '../themes/light.css' layer(base); @import '../themes/dark.css' layer(base); @import './utilities.css'; +@import './components.css'; diff --git a/web/app/components/app/configuration/dataset-config/params-config/weighted-score.tsx b/web/app/components/app/configuration/dataset-config/params-config/weighted-score.tsx index 8488d0269f..e5080f26e4 100644 --- a/web/app/components/app/configuration/dataset-config/params-config/weighted-score.tsx +++ b/web/app/components/app/configuration/dataset-config/params-config/weighted-score.tsx @@ -1,12 +1,11 @@ -import type { CSSProperties } from 'react' import { noop } from 'es-toolkit/function' import { memo } from 'react' import { useTranslation } from 'react-i18next' import { Slider } from '@/app/components/base/ui/slider' -const weightedScoreSliderStyle: CSSProperties & Record<'--slider-track' | '--slider-range', string> = { - '--slider-track': 'var(--color-util-colors-teal-teal-500)', - '--slider-range': 'var(--color-util-colors-blue-light-blue-light-500)', +const weightedScoreSliderSlotClassNames = { + track: 'bg-util-colors-teal-teal-500', + indicator: 'bg-util-colors-blue-light-blue-light-500', } const formatNumber = (value: number) => { @@ -37,7 +36,7 @@ const WeightedScore = ({ return (
-
+
!readonly && onChange({ value: [v, (10 - v * 10) / 10] })} disabled={readonly} aria-label={t('weightedScore.semantic', { ns: 'dataset' })} + slotClassNames={weightedScoreSliderSlotClassNames} />
diff --git a/web/app/components/base/ui/alert-dialog/index.tsx b/web/app/components/base/ui/alert-dialog/index.tsx index f277c343fc..5f2af43df8 100644 --- a/web/app/components/base/ui/alert-dialog/index.tsx +++ b/web/app/components/base/ui/alert-dialog/index.tsx @@ -14,16 +14,14 @@ export const AlertDialogDescription = BaseAlertDialog.Description type AlertDialogContentProps = { children: ReactNode className?: string - overlayClassName?: string - popupProps?: Omit + backdropClassName?: string backdropProps?: Omit } export function AlertDialogContent({ children, className, - overlayClassName, - popupProps, + backdropClassName, backdropProps, }: AlertDialogContentProps) { return ( @@ -33,11 +31,10 @@ export function AlertDialogContent({ className={cn( 'fixed inset-0 z-1002 bg-background-overlay', 'transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none', - overlayClassName, + backdropClassName, )} /> } export function DialogContent({ children, className, - overlayClassName, + backdropClassName, backdropProps, }: DialogContentProps) { return ( @@ -59,8 +59,7 @@ export function DialogContent({ className={cn( 'fixed inset-0 z-1002 bg-background-overlay', 'transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none', - overlayClassName, - backdropProps?.className, + backdropClassName, )} /> & { } const scrollAreaScrollbarClassName = cn( - 'flex touch-none overflow-clip p-1 opacity-100 transition-opacity select-none motion-reduce:transition-none', + 'group/scrollbar flex touch-none overflow-clip p-1 opacity-100 transition-opacity select-none motion-reduce:transition-none', 'pointer-events-none data-hovering:pointer-events-auto', 'data-scrolling:pointer-events-auto', 'data-[orientation=vertical]:absolute data-[orientation=vertical]:inset-y-0 data-[orientation=vertical]:w-3 data-[orientation=vertical]:justify-center', @@ -36,6 +35,9 @@ const scrollAreaThumbClassName = cn( 'shrink-0 rounded-sm bg-state-base-handle transition-[background-color] motion-reduce:transition-none', 'data-[orientation=vertical]:w-1', 'data-[orientation=horizontal]:h-1', + 'group-data-hovering/scrollbar:bg-state-base-handle-hover', + 'group-data-scrolling/scrollbar:bg-state-base-handle-hover', + 'active:bg-state-base-handle-hover', ) const scrollAreaViewportClassName = cn( diff --git a/web/app/components/base/ui/select/index.tsx b/web/app/components/base/ui/select/index.tsx index 5448379ce6..7de0088af4 100644 --- a/web/app/components/base/ui/select/index.tsx +++ b/web/app/components/base/ui/select/index.tsx @@ -1,9 +1,11 @@ 'use client' +import type { VariantProps } from 'class-variance-authority' 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 { cva } from 'class-variance-authority' import { overlayLabelClassName, overlaySeparatorClassName, @@ -15,34 +17,43 @@ export const SelectValue = BaseSelect.Value /** @public */ export const SelectGroup = BaseSelect.Group -const selectSizeClassName: Record = { - small: 'h-6 gap-px rounded-md px-2 py-1 system-xs-regular', - medium: 'h-8 gap-0.5 rounded-lg px-3 py-2 system-sm-regular', - large: 'h-9 gap-0.5 rounded-[10px] px-4 py-2 system-md-regular', -} +const selectTriggerVariants = cva( + [ + 'group flex w-full items-center border-0 bg-components-input-bg-normal text-left text-components-input-text-filled outline-hidden', + 'hover:bg-state-base-hover-alt focus-visible:bg-state-base-hover-alt', + 'data-placeholder:text-components-input-text-placeholder', + 'data-readonly:cursor-default data-readonly:bg-transparent data-readonly:hover:bg-transparent', + 'data-disabled:cursor-not-allowed data-disabled:bg-components-input-bg-disabled data-disabled:text-components-input-text-filled-disabled data-disabled:hover:bg-components-input-bg-disabled', + 'data-disabled:data-placeholder:text-components-input-text-disabled', + ], + { + variants: { + size: { + small: 'h-6 gap-px rounded-md px-2 py-1 system-xs-regular', + medium: 'h-8 gap-0.5 rounded-lg px-3 py-2 system-sm-regular', + large: 'h-9 gap-0.5 rounded-[10px] px-4 py-2 system-md-regular', + }, + }, + defaultVariants: { + size: 'medium', + }, + }, +) -type SelectTriggerProps = BaseSelect.Trigger.Props & { - size?: 'small' | 'medium' | 'large' -} +type SelectTriggerProps + = Omit + & VariantProps + & { className?: string } export function SelectTrigger({ className, children, - size = 'medium', + size, ...props }: SelectTriggerProps) { return ( diff --git a/web/app/components/base/ui/slider/index.tsx b/web/app/components/base/ui/slider/index.tsx index 931c4e88be..ad1bc0ba8f 100644 --- a/web/app/components/base/ui/slider/index.tsx +++ b/web/app/components/base/ui/slider/index.tsx @@ -2,16 +2,98 @@ import { Slider as BaseSlider } from '@base-ui/react/slider' import { cn } from '@langgenius/dify-ui/cn' -import * as React from 'react' + +/** @public */ +export const SliderRoot = BaseSlider.Root type SliderRootProps = BaseSlider.Root.Props + +const sliderControlClassName = cn( + 'relative flex h-5 w-full touch-none items-center select-none', + 'data-disabled:cursor-not-allowed', +) + +type SliderControlProps = BaseSlider.Control.Props + +/** @public */ +export function SliderControl({ className, ...props }: SliderControlProps) { + return ( + + ) +} + +const sliderTrackClassName = cn( + 'relative h-1 w-full overflow-hidden rounded-full', + 'bg-components-slider-track', +) + +type SliderTrackProps = BaseSlider.Track.Props + +/** @public */ +export function SliderTrack({ className, ...props }: SliderTrackProps) { + return ( + + ) +} + +const sliderIndicatorClassName = cn( + 'h-full rounded-full', + 'bg-components-slider-range', +) + +type SliderIndicatorProps = BaseSlider.Indicator.Props + +/** @public */ +export function SliderIndicator({ className, ...props }: SliderIndicatorProps) { + return ( + + ) +} + +const sliderThumbClassName = cn( + 'block h-5 w-2 shrink-0 rounded-[3px] border-[0.5px]', + 'border-components-slider-knob-border bg-components-slider-knob shadow-sm', + 'transition-[background-color,border-color,box-shadow,opacity] motion-reduce:transition-none', + 'hover:bg-components-slider-knob-hover', + 'focus-visible:ring-2 focus-visible:ring-components-slider-knob-border-hover focus-visible:ring-offset-0 focus-visible:outline-hidden', + 'active:shadow-md', + 'group-data-disabled/slider:border-components-slider-knob-border group-data-disabled/slider:bg-components-slider-knob-disabled group-data-disabled/slider:shadow-none', +) + type SliderThumbProps = BaseSlider.Thumb.Props +/** @public */ +export function SliderThumb({ className, ...props }: SliderThumbProps) { + return ( + + ) +} + +type SliderSlotClassNames = { + control?: string + track?: string + indicator?: string + thumb?: string +} + type SliderBaseProps = Pick< SliderRootProps, 'onValueChange' | 'min' | 'max' | 'step' | 'disabled' | 'name' > & Pick & { className?: string + slotClassNames?: SliderSlotClassNames } type ControlledSliderProps = SliderBaseProps & { @@ -27,30 +109,6 @@ type UncontrolledSliderProps = SliderBaseProps & { type SliderProps = ControlledSliderProps | UncontrolledSliderProps const sliderRootClassName = 'group/slider relative inline-flex w-full data-disabled:opacity-30' -const sliderControlClassName = cn( - 'relative flex h-5 w-full touch-none items-center select-none', - 'data-disabled:cursor-not-allowed', -) -const sliderTrackClassName = cn( - 'relative h-1 w-full overflow-hidden rounded-full', - 'bg-(--slider-track,var(--color-components-slider-track))', -) -const sliderIndicatorClassName = cn( - 'h-full rounded-full', - 'bg-(--slider-range,var(--color-components-slider-range))', -) -const sliderThumbClassName = cn( - 'block h-5 w-2 shrink-0 rounded-[3px] border-[0.5px]', - 'border-(--slider-knob-border,var(--color-components-slider-knob-border))', - 'bg-(--slider-knob,var(--color-components-slider-knob)) shadow-sm', - 'transition-[background-color,border-color,box-shadow,opacity] motion-reduce:transition-none', - 'hover:bg-(--slider-knob-hover,var(--color-components-slider-knob-hover))', - 'focus-visible:ring-2 focus-visible:ring-components-slider-knob-border-hover focus-visible:ring-offset-0 focus-visible:outline-hidden', - 'active:shadow-md', - 'group-data-disabled/slider:bg-(--slider-knob-disabled,var(--color-components-slider-knob-disabled))', - 'group-data-disabled/slider:border-(--slider-knob-border,var(--color-components-slider-knob-border))', - 'group-data-disabled/slider:shadow-none', -) const getSafeValue = (value: number | undefined, min: number) => { if (value === undefined) @@ -69,11 +127,12 @@ export function Slider({ disabled = false, name, className, + slotClassNames, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, }: SliderProps) { return ( - - - - - - + + + + - - + + ) } diff --git a/web/app/components/billing/pricing/index.tsx b/web/app/components/billing/pricing/index.tsx index 0873b2dea4..6b943bde7d 100644 --- a/web/app/components/billing/pricing/index.tsx +++ b/web/app/components/billing/pricing/index.tsx @@ -28,7 +28,7 @@ type PricingProps = { } const pricingScrollAreaClassNames = { - root: 'relative h-full w-full overflow-hidden [--scroll-area-edge-hint-bg:var(--color-saas-background)]', + root: 'relative h-full w-full overflow-hidden', viewport: 'overscroll-contain', content: 'min-h-full min-w-[1200px]', verticalScrollbar: 'data-[orientation=vertical]:my-2 data-[orientation=vertical]:me-1', diff --git a/web/app/components/header/account-setting/menu-dialog.tsx b/web/app/components/header/account-setting/menu-dialog.tsx index ae2be362fb..f1a0307b0d 100644 --- a/web/app/components/header/account-setting/menu-dialog.tsx +++ b/web/app/components/header/account-setting/menu-dialog.tsx @@ -27,7 +27,7 @@ const MenuDialog = ({ }} > = ({