-
-
Notifications
You must be signed in to change notification settings - Fork 53
detach support added for all comps #1723
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@radui/ui": patch | ||
| --- | ||
|
|
||
| detach prop support for all comps |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,14 +9,15 @@ const COMPONENT_NAME = 'Avatar'; | |
|
|
||
| export type AvatarRootProps = React.ComponentPropsWithoutRef<typeof AvatarPrimitiveRoot> & { | ||
| customRootClass?: string; | ||
| detach?: boolean; | ||
| className?: string; | ||
| size?: string; | ||
| variant?: string; | ||
| color?: string; | ||
| } | ||
|
|
||
| const AvatarRoot = React.forwardRef<React.ElementRef<typeof AvatarPrimitiveRoot>, AvatarRootProps>(({ children, customRootClass = '', className = '', size = '', variant = '', color = '', ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||
| const AvatarRoot = React.forwardRef<React.ElementRef<typeof AvatarPrimitiveRoot>, AvatarRootProps>(({ children, customRootClass = '', detach = false, className = '', size = '', variant = '', color = '', ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME, detach); | ||
|
Comment on lines
+19
to
+20
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Line [20] yields Proposed fix for descendant class guards# src/components/ui/Avatar/fragments/AvatarImage.tsx
- className={clsx(`${rootClass}-image`)}
+ className={clsx(rootClass && `${rootClass}-image`)}
# src/components/ui/Avatar/fragments/AvatarFallback.tsx
- className={clsx(`${rootClass}-fallback`, className)}
+ className={clsx(rootClass && `${rootClass}-fallback`, className)}🤖 Prompt for AI Agents |
||
|
|
||
| const dataAttributes = useCreateDataAttribute('avatar', { variant, size }); | ||
| const accentAttributes = useCreateDataAccentColorAttribute(color); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,13 +10,14 @@ const COMPONENT_NAME = 'CheckboxGroup'; | |
| export type CheckboxGroupRootElement = ElementRef<typeof CheckboxGroupPrimitive.Root>; | ||
| export type CheckboxGroupRootProps = { | ||
| customRootClass?: string; | ||
| detach?: boolean; | ||
| color?: string; | ||
| variant?: string; | ||
| size?: string; | ||
| } & ComponentPropsWithoutRef<typeof CheckboxGroupPrimitive.Root>; | ||
|
|
||
| const CheckboxGroupRoot = forwardRef<CheckboxGroupRootElement, CheckboxGroupRootProps>(({ children, customRootClass = '', className = '', color = '', variant = '', size = '', ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||
| const CheckboxGroupRoot = forwardRef<CheckboxGroupRootElement, CheckboxGroupRootProps>(({ children, customRootClass = '', detach = false, className = '', color = '', variant = '', size = '', ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME, detach); | ||
|
Comment on lines
+19
to
+20
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Line [20] can set Proposed fix- <CheckboxGroupPrimitive.Root ref={ref} className={clsx(`${rootClass}-root`, rootClass, className)} {...props} {...composedAttributes()}>
+ <CheckboxGroupPrimitive.Root
+ ref={ref}
+ className={clsx(rootClass && `${rootClass}-root`, rootClass, className)}
+ {...props}
+ {...composedAttributes()}
+ >🤖 Prompt for AI Agents |
||
|
|
||
| const dataAttributes = useCreateDataAttribute('checkbox-group', { variant, size }); | ||
| const accentAttributes = useCreateDataAccentColorAttribute(color); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,19 +9,20 @@ export type ContextMenuRootElement = ElementRef<typeof MenuPrimitive.Root>; | |
| export type ContextMenuRootProps = { | ||
| children: React.ReactNode; | ||
| customRootClass?: string; | ||
| detach?: boolean; | ||
| className?: string; | ||
| } & ComponentPropsWithoutRef<typeof MenuPrimitive.Root>; | ||
|
|
||
| const COMPONENT_NAME = 'ContextMenu'; | ||
|
|
||
| const ContextMenuRoot = forwardRef<ContextMenuRootElement, ContextMenuRootProps>(({ children, customRootClass, className, open, defaultOpen = false, onOpenChange, ...props }, ref) => { | ||
| const ContextMenuRoot = forwardRef<ContextMenuRootElement, ContextMenuRootProps>(({ children, customRootClass, detach = false, className, open, defaultOpen = false, onOpenChange, ...props }, ref) => { | ||
| const [isOpen, setIsOpen] = useControllableState( | ||
| open, | ||
| defaultOpen, | ||
| onOpenChange | ||
| ); | ||
| const [coords, setCoords] = React.useState({ x: 0, y: 0 }); | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME, detach); | ||
| return ( | ||
| <ContextMenuContext.Provider value={{ rootClass, setCoords, setIsOpen }} > | ||
| <MenuPrimitive.Root ref={ref} className={clsx(`${rootClass}-root`, className)} mainAxisOffset={-coords.y} crossAxisOffset={coords.x} open={isOpen} onOpenChange={setIsOpen} {...props}> | ||
|
Comment on lines
+18
to
28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Detach is incomplete: generated class tokens are still emitted. Line 28 builds Proposed root-level fix- <MenuPrimitive.Root ref={ref} className={clsx(`${rootClass}-root`, className)} mainAxisOffset={-coords.y} crossAxisOffset={coords.x} open={isOpen} onOpenChange={setIsOpen} {...props}>
+ <MenuPrimitive.Root ref={ref} className={clsx(rootClass && `${rootClass}-root`, className)} mainAxisOffset={-coords.y} crossAxisOffset={coords.x} open={isOpen} onOpenChange={setIsOpen} {...props}>Please mirror this guard in the sibling fragments that append 🤖 Prompt for AI Agents |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,10 +8,11 @@ const COMPONENT_NAME = 'DataList'; | |
| type DataListRootElement = ElementRef<'div'>; | ||
| export interface DataListRootProps extends ComponentPropsWithoutRef<'div'> { | ||
| customRootClass?: string; | ||
| detach?: boolean; | ||
| } | ||
|
|
||
| const DataListRoot = forwardRef<DataListRootElement, DataListRootProps>(({ children, className = '', customRootClass = '', ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||
| const DataListRoot = forwardRef<DataListRootElement, DataListRootProps>(({ children, className = '', customRootClass = '', detach = false, ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME, detach); | ||
|
Comment on lines
+11
to
+15
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for string interpolation patterns with rootClass in DataList
rg -n '\$\{rootClass\}' src/components/ui/DataList/Repository: rad-ui/ui Length of output: 535 🏁 Script executed: #!/bin/bash
# Find customClassSwitcher implementation to understand what it returns
rg -n 'customClassSwitcher' src/components/ui/DataList/ -A 3 -B 3Repository: rad-ui/ui Length of output: 1360 🏁 Script executed: #!/bin/bash
# Find the definition of customClassSwitcher function
fd -t f -e tsx -e ts . | xargs rg -l 'export.*customClassSwitcher|const customClassSwitcher|function customClassSwitcher'Repository: rad-ui/ui Length of output: 108 🏁 Script executed: #!/bin/bash
# Check DataListRoot to see what COMPONENT_NAME and customRootClass values might be
rg -n 'COMPONENT_NAME\|customRootClass' src/components/ui/DataList/fragments/DataListRoot.tsx -B 2 -A 2Repository: rad-ui/ui Length of output: 35 🏁 Script executed: #!/bin/bash
# Read the customClassSwitcher implementation
cat src/core/customClassSwitcher/index.tsRepository: rad-ui/ui Length of output: 779 🏁 Script executed: #!/bin/bash
# Also check what's exported from core to understand the function signature
head -50 src/core/index.tsRepository: rad-ui/ui Length of output: 233 🏁 Script executed: #!/bin/bash
# Search for usage of DataList component with detach prop
rg -n 'detach\s*=' src/components/ui/DataList/ -A 2 -B 2Repository: rad-ui/ui Length of output: 622 🏁 Script executed: #!/bin/bash
# Search for DataList usage in stories or examples
fd -t f -e tsx -e ts . | xargs rg -l 'DataList' | head -20Repository: rad-ui/ui Length of output: 528 🏁 Script executed: #!/bin/bash
# Check if there are tests for DataList detach behavior
fd -t f \( -name '*.test.tsx' -o -name '*.spec.tsx' -o -name '*.stories.tsx' \) | xargs rg -l 'DataList' 2>/dev/nullRepository: rad-ui/ui Length of output: 899 🏁 Script executed: #!/bin/bash
# Check test file for detach usage
rg -n 'detach' src/components/ui/DataList/tests/DataList.test.tsxRepository: rad-ui/ui Length of output: 35 🏁 Script executed: #!/bin/bash
# Check stories file for detach examples
rg -n 'detach' src/components/ui/DataList/stories/DataList.stories.tsxRepository: rad-ui/ui Length of output: 35 🏁 Script executed: #!/bin/bash
# Read the child component implementations to confirm the pattern
cat src/components/ui/DataList/fragments/DataListValue.tsxRepository: rad-ui/ui Length of output: 706 🏁 Script executed: #!/bin/bash
# Check the README or docs for DataList component purpose and detach usage
fd -t f \( -name 'README*' -o -name '*.md' \) . | xargs rg -l 'DataList' | head -5Repository: rad-ui/ui Length of output: 573 🏁 Script executed: #!/bin/bash
# Look at all child components to see the pattern consistency
cat src/components/ui/DataList/fragments/DataListLabel.tsx src/components/ui/DataList/fragments/DataListItem.tsxRepository: rad-ui/ui Length of output: 1355 🏁 Script executed: #!/bin/bash
# Check if detach is exported or documented in the public API
rg -n 'detach' src/components/ui/DataList/DataList.tsxRepository: rad-ui/ui Length of output: 35 Malformed CSS class names when The implementation produces invalid class names. When Since
🤖 Prompt for AI Agents |
||
| return <DataListContext.Provider | ||
| value={{ | ||
| rootClass | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,11 +13,12 @@ type DialogPrimitiveRootProps = React.ComponentPropsWithoutRef<typeof DialogPrim | |
|
|
||
| export type DialogRootProps = DialogPrimitiveRootProps & { | ||
| customRootClass?: string; | ||
| detach?: boolean; | ||
| className?: string; | ||
| }; | ||
|
|
||
| const DialogRoot = forwardRef<DialogRootElement, DialogRootProps>(({ children, customRootClass = '', className = '', ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||
| const DialogRoot = forwardRef<DialogRootElement, DialogRootProps>(({ children, customRootClass = '', detach = false, className = '', ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME, detach); | ||
|
|
||
| const contextProps = { rootClass }; | ||
|
Comment on lines
+20
to
23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Detach leaks generated suffix classes in Dialog children. When Suggested fix (context + child guard)// src/components/ui/Dialog/fragments/DialogRoot.tsx
- const contextProps = { rootClass };
+ const contextProps = { rootClass, detach };// Example pattern for Dialog child fragments
- className={clsx(`${rootClass}-trigger`, className)}
+ className={clsx(detach ? undefined : `${rootClass}-trigger`, className)}Apply the same guard pattern to Trigger/Content/Overlay/Close. 🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,12 +9,13 @@ const COMPONENT_NAME = 'Disclosure'; | |
|
|
||
| export type DisclosureRootProps = React.ComponentPropsWithoutRef<'div'> & { | ||
| customRootClass?: string; | ||
| detach?: boolean; | ||
| defaultOpen?: number | null; | ||
| }; | ||
|
|
||
| const DisclosureRoot = React.forwardRef<React.ElementRef<'div'>, DisclosureRootProps>(({ children, customRootClass, 'aria-label': ariaLabel, ...props }, forwardedRef) => { | ||
| const DisclosureRoot = React.forwardRef<React.ElementRef<'div'>, DisclosureRootProps>(({ children, customRootClass, detach = false, 'aria-label': ariaLabel, ...props }, forwardedRef) => { | ||
| const disclosureRef = useRef<React.ElementRef<'div'> | null>(null); | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME, detach); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Empty When Additionally, the same Also applies to: 42-45 🤖 Prompt for AI Agents |
||
|
|
||
| const [activeItem, setActiveItem] = useState<number | null>(null); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,13 +8,14 @@ export type DropdownMenuRootElement = ElementRef<typeof MenuPrimitive.Root>; | |
| export type DropdownMenuRootProps = { | ||
| children: React.ReactNode; | ||
| customRootClass?: string; | ||
| detach?: boolean; | ||
| className?: string; | ||
| } & ComponentPropsWithoutRef<typeof MenuPrimitive.Root>; | ||
|
|
||
| const COMPONENT_NAME = 'DropdownMenu'; | ||
|
|
||
| const DropdownMenuRoot = forwardRef<DropdownMenuRootElement, DropdownMenuRootProps>(({ children, customRootClass, className, ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||
| const DropdownMenuRoot = forwardRef<DropdownMenuRootElement, DropdownMenuRootProps>(({ children, customRootClass, detach = false, className, ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME, detach); | ||
| return ( | ||
| <DropdownMenuContext.Provider value={{ rootClass }} > | ||
| <MenuPrimitive.Root ref={ref} className={clsx(`${rootClass}-root`, className)} {...props}> | ||
|
Comment on lines
+17
to
21
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Line 21 still produces Proposed fix- <MenuPrimitive.Root ref={ref} className={clsx(`${rootClass}-root`, className)} {...props}>
+ <MenuPrimitive.Root ref={ref} className={clsx(rootClass && `${rootClass}-root`, className)} {...props}>Also apply the same guard in child fragments that build 🤖 Prompt for AI Agents |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Detach mode still outputs
-rootclass inAccordionRoot.Line 149 unconditionally appends
-root. Withdetach=true(Line 44 path), this still emits a generated token (-root) instead of no class output.Also applies to: 149-149
🤖 Prompt for AI Agents