-
-
Notifications
You must be signed in to change notification settings - Fork 39
Featue controlled/uncontrolled modes for accordian #1031
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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -18,9 +18,12 @@ export type AccordionRootProps = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
asChild?: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
loop?: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
openMultiple?: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value?: string | string[]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defaultValue?: string | string[]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onValueChange?: (value: string | string[]) => void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const AccordionRoot = ({ children, orientation = 'vertical', asChild, transitionDuration = 0, transitionTimingFunction = 'linear', customRootClass, loop = true, openMultiple = false }: AccordionRootProps) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const AccordionRoot = ({ children, orientation = 'vertical', asChild, transitionDuration = 0, transitionTimingFunction = 'linear', customRootClass, loop = true, openMultiple = false, value, defaultValue, onValueChange }: AccordionRootProps) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const accordionRef = useRef<HTMLDivElement | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -35,7 +38,10 @@ const AccordionRoot = ({ children, orientation = 'vertical', asChild, transition | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
accordionRef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
transitionDuration, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
transitionTimingFunction, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
openMultiple | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
openMultiple, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defaultValue, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onValueChange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+41
to
+44
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. Props passed to context, but implementation missing While the props are correctly passed to the context, there's no implementation to handle controlled behavior. The component needs logic to:
Consider implementing the controlled behavior with a useEffect hook: const AccordionRoot = ({ children, orientation = 'vertical', asChild, transitionDuration = 0, transitionTimingFunction = 'linear', customRootClass, loop = true, openMultiple = false, value, defaultValue, onValueChange }: AccordionRootProps) => {
const accordionRef = useRef<HTMLDivElement | null>(null);
const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME);
- const [activeItems, setActiveItems] = useState<(number | string)[]>([]);
+ const [activeItems, setActiveItems] = useState<string[]>(() => {
+ // Initialize from defaultValue if provided
+ if (defaultValue !== undefined) {
+ return Array.isArray(defaultValue) ? defaultValue : [defaultValue];
+ }
+ return [];
+ });
+
+ // Handle controlled mode
+ useEffect(() => {
+ if (value !== undefined) {
+ const newActiveItems = Array.isArray(value) ? value : [value];
+ setActiveItems(newActiveItems);
+ }
+ }, [value]);
+
+ // Create wrapper for setActiveItems that calls onValueChange
+ const handleSetActiveItems = (items: string[]) => {
+ setActiveItems(items);
+ if (onValueChange) {
+ onValueChange(openMultiple ? items : items[0] || '');
+ }
+ }; Also, you'll need to update how 📝 Committable suggestion
Suggested change
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. agreed, implementation missing 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:
Length of output: 3911 @kotAPI I'd be happy to help implement the missing functionality. Based on my analysis, we need to make the following changes:
Here's a complete implementation: // First, update the AccordionContext type in src/components/ui/Accordion/contexts/AccordionContext.tsx
interface AccordionContextType {
rootClass?: string | null;
activeItems: (number | string)[];
setActiveItems: (items: (number | string)[]) => void;
accordionRef?: React.RefObject<HTMLDivElement | null>;
transitionDuration?: number;
transitionTimingFunction?: string;
openMultiple?: boolean;
// Add the new props
value?: string | string[];
defaultValue?: string | string[];
onValueChange?: (value: string | string[]) => void;
}
// Then, update the AccordionRoot component implementation
import React, { useState, useRef, useEffect } from 'react';
// ... other imports
const AccordionRoot = ({
children,
orientation = 'vertical',
asChild,
transitionDuration = 0,
transitionTimingFunction = 'linear',
customRootClass,
loop = true,
openMultiple = false,
value,
defaultValue,
onValueChange
}: AccordionRootProps) => {
const accordionRef = useRef<HTMLDivElement | null>(null);
const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME);
const isControlled = value !== undefined;
// Initialize state from defaultValue if provided
const [activeItems, setActiveItemsState] = useState<(number | string)[]>(() => {
if (defaultValue !== undefined) {
return Array.isArray(defaultValue) ? defaultValue : [defaultValue];
}
return [];
});
// Handle controlled mode
useEffect(() => {
if (isControlled) {
const newActiveItems = Array.isArray(value) ? value : value ? [value] : [];
setActiveItemsState(newActiveItems);
}
}, [value, isControlled]);
// Create wrapper for setActiveItems that calls onValueChange
const setActiveItems = (items: (number | string)[]) => {
if (!isControlled) {
setActiveItemsState(items);
}
if (onValueChange) {
onValueChange(openMultiple ? items : items[0] || '');
}
};
return (
<AccordionContext.Provider
value={{
rootClass,
activeItems,
setActiveItems,
accordionRef,
transitionDuration,
transitionTimingFunction,
openMultiple,
value,
defaultValue,
onValueChange
}}>
<RovingFocusGroup.Root orientation={orientation} loop={loop}>
<RovingFocusGroup.Group >
<Primitive.div className={clsx(`${rootClass}-root`)} ref={accordionRef} asChild={asChild}>
{children}
</Primitive.div>
</RovingFocusGroup.Group>
</RovingFocusGroup.Root>
</AccordionContext.Provider>
);
}; This implementation:
Would you like me to also show how to update other components that might be affected by this change? 🧬 Code Definitions UsedRelevant Code SnippetsFilename:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<RovingFocusGroup.Root orientation={orientation} loop={loop}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<RovingFocusGroup.Group > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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.
Add a key prop to the iterable element
When rendering lists in React, each element should have a unique
key
prop to help React identify which items have changed.Also note that the template literal is unnecessary since
item.id
is already a string.📝 Committable suggestion
🧰 Tools
🪛 Biome (1.9.4)
[error] 29-29: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)