Skip to content
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

Accordion #6931

Merged
merged 108 commits into from
Sep 20, 2024
Merged

Accordion #6931

merged 108 commits into from
Sep 20, 2024

Conversation

reidbarber
Copy link
Member

@reidbarber reidbarber commented Aug 22, 2024

Accordion

This implements the Accordion pattern, with an emphasis on individual accordion items as opposed to groups.

Features

  • Implements hidden=until-found
  • Supports additional interactive elements adjacent to Heading (i.e. Menu)
  • Not a collection component

API

React Aria/Stately hooks:

  • useDisclosure
  • useDisclosureState

React Aria components:

  • AccordionItem
    • Heading
      • Button
    • AccordionPanel

RSP v3 components:

  • AccordionGroup
    • AccordionItem
      • AccordionHeader
      • AccordionPanel

Spectrum 2 components:

  • AccordionGroup
    • AccordionItem
      • AccordionHeader
      • AccordionPanel

Examples

RAC

<AccordionItem>
  {({isExpanded}) => (
    <>
      <Header>
        <Heading level={3}>
          <Button slot="trigger">{isExpanded ? '⬇️' : '➡️'} This is an accordion header</Button>
        </Heading>
      </Header>
      <AccordionPanel>
        <p>This is the content of the accordion panel.</p>
      </AccordionPanel>
    </>
  )}
</AccordionItem>

Spectrum 2

<AccordionGroup isQuiet styles={style({width: 384})}>
  <AccordionItem>
    <AccordionHeader>
      Files
    </AccordionHeader>
    <AccordionPanel>
      Files content
    </AccordionPanel>
  </AccordionItem>
  <AccordionItem>
    <AccordionHeader>
      People
    </AccordionHeader>
    <AccordionPanel>
      <TextField label="Name" />
    </AccordionPanel>
  </AccordionItem>
</AccordionGroup>

Additional comments

With regards to an Accordion (or AccordionGroup) wrapper around AccordionItem elements in React Aria, there is no ARIA semantics for that element, and keyboard arrow navigation is listed as optional, so we're going to prioritize the individual AccordionItem element for now but may revisit this in a follow-up. The main benefit would be controlling the expanded items' state at the group level and using Up/Down or Home/End keyboard navigation between item headers.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

@rspbot
Copy link

rspbot commented Aug 23, 2024

@nwidynski
Copy link

nwidynski commented Aug 27, 2024

Hey @reidbarber thanks getting to work on this!

I've got a couple of questions regarding the spec the team chose here and would love to provide some input from our own learnings as we implemented both <Disclosure /> and <Accordion /> pattern using react-aria.

  1. Is there a reason not to follow the <...Trigger/> pattern instead of <AccordionItem>? I could imagine your spec of additional interactive elements inside the <Header /> introducing this constraint?
<DisclosureTrigger isOpen>
  <Heading level={3}>
    <Button />
  </Heading>
  <Disclosure>
    <Text>I am controlled.</Text>
  </Disclosure>
</DisclosureTrigger>
  1. Since the W3C patterns do not collide in their ARIA properties or interactivity, would there be reasoning against re-cycling <Disclosure /> inside <Accordion />, similar to how <Checkbox/> works in both grouped and ungrouped scenario?
const { buttonProps, regionProps } = isNil(ctxState)
  ? // eslint-disable-next-line react-hooks/rules-of-hooks
    useDisclosureTrigger(state)
  : // eslint-disable-next-line react-hooks/rules-of-hooks
    useAccordionItem(props, ctxState, objectRef);
  1. Have you guys considered adding something like useDisclosureAnimation()?
export const useDisclosureAnimation = (
  ...option: AtomicDisclosureAnimationOptions
): AtomicDisclosureAnimation => {
  const [ref, isOpen] = option;

  const previous = useRef(isOpen);
  const [, rerender] = useState({});

  const isAnimating = previous.current !== isOpen;
  const onEnd = useCallback(() => rerender({}), []);
  
  if (isAnimating) previous.current = isOpen;
  
  useAnimation(ref, isAnimating, onEnd);

  return {
    isOpening: isOpen && isAnimating,
    isClosing: !isOpen && isAnimating,
  };
};
  1. Does the team already have an idea how to work in arrow key navigation inside <Accordion />? I suppose it would work similar to the <Tabs /> pattern but i would be very interested in any guidance.

@reidbarber
Copy link
Member Author

@nwidynski Thanks for the input! We are definitely still considering different API options, so I appreciate the comments.

Is there a reason not to follow the <...Trigger/> pattern instead of <AccordionItem>?

I think the main reason is that we want to support additional interactive elements adjacent to the accordion header, and that pattern usually means the entire first child is the trigger.

would there be reasoning against re-cycling <Disclosure /> inside <Accordion />

We haven't given much thought into including a disclosure component, but as it seems like a simple subset of accordion features, I think we could consider having accordion build on top it, maybe at the hook level.

Have you guys considered adding something like useDisclosureAnimation()

This looks great! I think we definitely want to include these states.

Does the team already have an idea how to work in arrow key navigation inside <Accordion />?

Arrow key navigation between items is optional in ARIA, so we're still considering options for this.

Copy link
Member

@LFDanLu LFDanLu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some initial comments, but I think overall the api makes sense. Might be a bit odd to have a AccordionItem only for RAC without a container Accordion element, but the wrapping container doesn't seem to have much of a purpose so it might be ok. If we feel like that might be confusing, we could change it from "Item" so that it doesn't sound like it is a collection element

packages/@react-aria/accordion/src/useAccordionItem.ts Outdated Show resolved Hide resolved
packages/@react-aria/accordion/src/useAccordionItem.ts Outdated Show resolved Hide resolved
packages/@react-aria/accordion/src/useAccordionItem.ts Outdated Show resolved Hide resolved
packages/@react-spectrum/accordion/src/Accordion.tsx Outdated Show resolved Hide resolved
packages/@react-stately/accordion/package.json Outdated Show resolved Hide resolved
Comment on lines 29 to 34
<AccordionHeader>
Your files
</AccordionHeader>
<AccordionPanel>
files
</AccordionPanel>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed that if you flip the order of these that the panel renders about the header when opened. This is probably fine if we want to just enforce the order that these elements are provided to the AccordionItem but otherwise we might need to use a flex container + order?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For react spectrum i think enforcing the order is a good idea

packages/react-aria-components/src/Accordion.tsx Outdated Show resolved Hide resolved
packages/react-aria-components/src/Accordion.tsx Outdated Show resolved Hide resolved
Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add react-stately/accordion to the ts strict config

packages/@react-aria/accordion/src/useAccordionItem.ts Outdated Show resolved Hide resolved
Comment on lines 29 to 34
<AccordionHeader>
Your files
</AccordionHeader>
<AccordionPanel>
files
</AccordionPanel>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For react spectrum i think enforcing the order is a good idea

packages/@react-spectrum/accordion/src/Accordion.tsx Outdated Show resolved Hide resolved
packages/@react-spectrum/accordion/src/Accordion.tsx Outdated Show resolved Hide resolved
@@ -0,0 +1,128 @@
/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking, but recommendation for building a mutually exclusive AccordionGroup with arrow key navigation would be something like this?

function AccordionGroup() {
  let [openIndex, setOpenIndex] = useState(0);
  let focusManager = useFocusManager({accept: (node) => {
    return node.getAttribute('data-accordion-trigger-g1') === true;
  }});
  return (
    <div onKeyDown={(e) => {
      if (e.key === 'ArrowDown') {
        focusManager.focusNext();
        e.preventDefault();
      } else if (e.key === 'ArrowUp') {
        focusManager.focusPrevious();
        e.preventDefault();
      }
    }}>
      <AccordionItem isOpen={openIndex === 0} onOpenChange={val => val && setOpenIndex(0)}>
        {({isOpen}) => (
          <>
            <Header>
              <Heading level={3}>
                <Button slot="trigger" data-accordion-trigger-g1>{isOpen ? '⬇️' : '➡️'} Item 1</Button>
              </Heading>
            </Header>
            <AccordionPanel>
              <p>Content for panel 1.</p>
            </AccordionPanel>
          </>
        )}
      </AccordionItem>
      <AccordionItem isOpen={openIndex === 1} onOpenChange={val => val && setOpenIndex(1)}>
        {({isOpen}) => (
          <>
            <Header>
              <Heading level={3}>
                <Button slot="trigger" data-accordion-trigger-g1>{isOpen ? '⬇️' : '➡️'} Item 2</Button>
              </Heading>
            </Header>
            <AccordionPanel>
              <p>Panel 2's content.</p>
            </AccordionPanel>
          </>
        )}
      </AccordionItem>
    </div>
  );
}

export const AccordionGroupExample = {
  render: () => <FocusScope><AccordionGroup /></FocusScope>
};

@rspbot
Copy link

rspbot commented Sep 5, 2024

@reidbarber reidbarber changed the title WIP: Accordion Accordion Sep 5, 2024
@rspbot
Copy link

rspbot commented Sep 18, 2024

packages/@react-aria/accordion/src/useAccordion.ts Outdated Show resolved Hide resolved
packages/@react-spectrum/s2/src/Accordion.tsx Outdated Show resolved Hide resolved
packages/@react-spectrum/s2/src/Accordion.tsx Outdated Show resolved Hide resolved
packages/@react-spectrum/s2/src/Accordion.tsx Outdated Show resolved Hide resolved
@rspbot
Copy link

rspbot commented Sep 19, 2024

@rspbot
Copy link

rspbot commented Sep 19, 2024

@rspbot
Copy link

rspbot commented Sep 19, 2024

devongovett
devongovett previously approved these changes Sep 19, 2024
@rspbot
Copy link

rspbot commented Sep 19, 2024

Copy link
Member

@LFDanLu LFDanLu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

behavior looks good, just one other dep that I think we can get rid of

@@ -39,8 +39,10 @@
"dependencies": {
"@internationalized/date": "^3.5.5",
"@internationalized/string": "^3.2.3",
"@react-aria/accordion": "3.0.0-alpha.33",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove this dep now? Noticed it in @react-spectrum/accordion's package json too

Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy for anything else to be follow up

@rspbot
Copy link

rspbot commented Sep 20, 2024

@rspbot
Copy link

rspbot commented Sep 20, 2024

## API Changes

react-aria-components

/react-aria-components:Disclosure

+Disclosure {
+  children?: ReactNode | ((DisclosureRenderProps & {
+    defaultChildren: ReactNode | undefined
+})) => ReactNode
+  className?: string | ((DisclosureRenderProps & {
+    defaultClassName: string | undefined
+})) => string
+  defaultExpanded?: boolean
+  isDisabled?: boolean
+  isExpanded?: boolean
+  onExpandedChange?: (boolean) => void
+  onHoverChange?: (boolean) => void
+  onHoverEnd?: (HoverEvent) => void
+  onHoverStart?: (HoverEvent) => void
+  slot?: string | null
+  style?: CSSProperties | ((DisclosureRenderProps & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

/react-aria-components:DisclosurePanel

+DisclosurePanel {
+  children: ReactNode
+  className?: string | (({
+  
+} & {
+    defaultClassName: string | undefined
+})) => string
+  role?: 'group' | 'region' = 'group'
+  style?: CSSProperties | (({
+  
+} & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

/react-aria-components:DisclosureStateContext

+DisclosureStateContext {
+  UNTYPED
+}

/react-aria-components:DisclosureContext

+DisclosureContext {
+  UNTYPED
+}

/react-aria-components:DisclosureProps

+DisclosureProps {
+  children?: ReactNode | ((DisclosureRenderProps & {
+    defaultChildren: ReactNode | undefined
+})) => ReactNode
+  className?: string | ((DisclosureRenderProps & {
+    defaultClassName: string | undefined
+})) => string
+  defaultExpanded?: boolean
+  isDisabled?: boolean
+  isExpanded?: boolean
+  onExpandedChange?: (boolean) => void
+  onHoverChange?: (boolean) => void
+  onHoverEnd?: (HoverEvent) => void
+  onHoverStart?: (HoverEvent) => void
+  slot?: string | null
+  style?: CSSProperties | ((DisclosureRenderProps & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

/react-aria-components:DisclosurePanelProps

+DisclosurePanelProps {
+  children: ReactNode
+  className?: string | (({
+  
+} & {
+    defaultClassName: string | undefined
+})) => string
+  role?: 'group' | 'region' = 'group'
+  style?: CSSProperties | (({
+  
+} & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

@react-spectrum/accordion

/@react-spectrum/accordion:Accordion

-Accordion <T extends {}> {
+Accordion {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
   bottom?: Responsive<DimensionValue>
-  children: CollectionChildren<{}>
-  defaultExpandedKeys?: Iterable<Key>
-  disabledKeys?: Iterable<Key>
+  children: React.ReactNode
   end?: Responsive<DimensionValue>
-  expandedKeys?: Iterable<Key>
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
   isHidden?: Responsive<boolean>
-  items?: Iterable<{}>
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minWidth?: Responsive<DimensionValue>
-  onExpandedChange?: (Set<Key>) => any
   order?: Responsive<number>
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   start?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/accordion:Item

-Item <T> {
-  props: ItemProps<T>
-  returnVal: undefined
-}

/@react-spectrum/accordion:SpectrumAccordionProps

-SpectrumAccordionProps <T> {
+SpectrumAccordionProps {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
   bottom?: Responsive<DimensionValue>
-  children: CollectionChildren<T>
-  defaultExpandedKeys?: Iterable<Key>
-  disabledKeys?: Iterable<Key>
+  children: React.ReactNode
   end?: Responsive<DimensionValue>
-  expandedKeys?: Iterable<Key>
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
   isHidden?: Responsive<boolean>
-  items?: Iterable<T>
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minWidth?: Responsive<DimensionValue>
-  onExpandedChange?: (Set<Key>) => any
   order?: Responsive<number>
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   start?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/accordion:Disclosure

+Disclosure {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: [ReactElement<SpectrumDisclosureHeaderProps>, ReactElement<SpectrumDisclosurePanelProps>]
+  className?: string | ((DisclosureRenderProps & {
+    defaultClassName: string | undefined
+})) => string
+  defaultExpanded?: boolean
+  id?: string
+  isDisabled?: boolean
+  isExpanded?: boolean
+  onExpandedChange?: (boolean) => void
+  onHoverChange?: (boolean) => void
+  onHoverEnd?: (HoverEvent) => void
+  onHoverStart?: (HoverEvent) => void
+  slot?: string | null
+  style?: CSSProperties | ((DisclosureRenderProps & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

/@react-spectrum/accordion:DisclosureHeader

+DisclosureHeader {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: React.ReactNode
+  id?: string
+  level?: number = 3
+}

/@react-spectrum/accordion:DisclosurePanel

+DisclosurePanel {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: React.ReactNode
+  className?: string | (({
+  
+} & {
+    defaultClassName: string | undefined
+})) => string
+  id?: string
+  role?: 'group' | 'region' = 'group'
+  style?: CSSProperties | (({
+  
+} & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

/@react-spectrum/accordion:SpectrumDisclosureProps

+SpectrumDisclosureProps {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: [ReactElement<SpectrumDisclosureHeaderProps>, ReactElement<SpectrumDisclosurePanelProps>]
+  className?: string | ((DisclosureRenderProps & {
+    defaultClassName: string | undefined
+})) => string
+  defaultExpanded?: boolean
+  id?: string
+  isDisabled?: boolean
+  isExpanded?: boolean
+  onExpandedChange?: (boolean) => void
+  onHoverChange?: (boolean) => void
+  onHoverEnd?: (HoverEvent) => void
+  onHoverStart?: (HoverEvent) => void
+  slot?: string | null
+  style?: CSSProperties | ((DisclosureRenderProps & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

/@react-spectrum/accordion:SpectrumDisclosurePanelProps

+SpectrumDisclosurePanelProps {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: React.ReactNode
+  className?: string | (({
+  
+} & {
+    defaultClassName: string | undefined
+})) => string
+  id?: string
+  role?: 'group' | 'region' = 'group'
+  style?: CSSProperties | (({
+  
+} & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

/@react-spectrum/accordion:SpectrumDisclosureHeaderProps

+SpectrumDisclosureHeaderProps {
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: React.ReactNode
+  id?: string
+  level?: number = 3
+}

@react-spectrum/s2

/@react-spectrum/s2:Accordion

+Accordion {
+  UNSAFE_className?: string
+  UNSAFE_style?: CSSProperties
+  children: React.ReactNode
+  density?: 'compact' | 'regular' | 'spacious' = "regular"
+  id?: string
+  isDisabled?: boolean
+  isQuiet?: boolean
+  size?: 'S' | 'M' | 'L' | 'XL' = "M"
+  slot?: string | null
+  styles?: StylesPropWithHeight
+}

/@react-spectrum/s2:AccordionContext

+AccordionContext {
+  UNTYPED
+}

/@react-spectrum/s2:DisclosureHeader

+DisclosureHeader {
+  UNSAFE_className?: string
+  UNSAFE_style?: CSSProperties
+  children: React.ReactNode
+  id?: string
+  level?: number = 3
+}

/@react-spectrum/s2:Disclosure

+Disclosure {
+  UNSAFE_className?: string
+  UNSAFE_style?: CSSProperties
+  children: [ReactElement<DisclosureHeaderProps>, ReactElement<DisclosurePanelProps>]
+  className?: string | ((DisclosureRenderProps & {
+    defaultClassName: string | undefined
+})) => string
+  defaultExpanded?: boolean
+  density?: 'compact' | 'regular' | 'spacious' = "regular"
+  id?: string
+  isDisabled?: boolean
+  isExpanded?: boolean
+  isQuiet?: boolean
+  onExpandedChange?: (boolean) => void
+  onHoverChange?: (boolean) => void
+  onHoverEnd?: (HoverEvent) => void
+  onHoverStart?: (HoverEvent) => void
+  size?: 'S' | 'M' | 'L' | 'XL' = "M"
+  slot?: string | null
+  style?: CSSProperties | ((DisclosureRenderProps & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+  styles?: StylesProp
+}

/@react-spectrum/s2:DisclosurePanel

+DisclosurePanel {
+  UNSAFE_className?: string
+  UNSAFE_style?: CSSProperties
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: React.ReactNode
+  className?: string | (({
+  
+} & {
+    defaultClassName: string | undefined
+})) => string
+  id?: string
+  role?: 'group' | 'region' = 'group'
+  style?: CSSProperties | (({
+  
+} & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

/@react-spectrum/s2:DisclosureContext

+DisclosureContext {
+  UNTYPED
+}

/@react-spectrum/s2:AccordionProps

+AccordionProps {
+  UNSAFE_className?: string
+  UNSAFE_style?: CSSProperties
+  children: React.ReactNode
+  density?: 'compact' | 'regular' | 'spacious' = "regular"
+  id?: string
+  isDisabled?: boolean
+  isQuiet?: boolean
+  size?: 'S' | 'M' | 'L' | 'XL' = "M"
+  slot?: string | null
+  styles?: StylesPropWithHeight
+}

/@react-spectrum/s2:DisclosureProps

+DisclosureProps {
+  UNSAFE_className?: string
+  UNSAFE_style?: CSSProperties
+  children: [ReactElement<DisclosureHeaderProps>, ReactElement<DisclosurePanelProps>]
+  className?: string | ((DisclosureRenderProps & {
+    defaultClassName: string | undefined
+})) => string
+  defaultExpanded?: boolean
+  density?: 'compact' | 'regular' | 'spacious' = "regular"
+  id?: string
+  isDisabled?: boolean
+  isExpanded?: boolean
+  isQuiet?: boolean
+  onExpandedChange?: (boolean) => void
+  onHoverChange?: (boolean) => void
+  onHoverEnd?: (HoverEvent) => void
+  onHoverStart?: (HoverEvent) => void
+  size?: 'S' | 'M' | 'L' | 'XL' = "M"
+  slot?: string | null
+  style?: CSSProperties | ((DisclosureRenderProps & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+  styles?: StylesProp
+}

/@react-spectrum/s2:DisclosurePanelProps

+DisclosurePanelProps {
+  UNSAFE_className?: string
+  UNSAFE_style?: CSSProperties
+  aria-describedby?: string
+  aria-details?: string
+  aria-label?: string
+  aria-labelledby?: string
+  children: React.ReactNode
+  className?: string | (({
+  
+} & {
+    defaultClassName: string | undefined
+})) => string
+  id?: string
+  role?: 'group' | 'region' = 'group'
+  style?: CSSProperties | (({
+  
+} & {
+    defaultStyle: CSSProperties
+})) => CSSProperties | undefined
+}

@react-aria/disclosure

/@react-aria/disclosure:useDisclosure

+useDisclosure {
+  props: AriaDisclosureProps
+  state: DisclosureState
+  ref?: RefObject<Element | null>
+  returnVal: undefined
+}

/@react-aria/disclosure:DisclosureAria

+DisclosureAria {
+  buttonProps: AriaButtonProps
+  contentProps: HTMLAttributes<HTMLElement>
+}

/@react-aria/disclosure:AriaDisclosureProps

+AriaDisclosureProps {
+  defaultExpanded?: boolean
+  isDisabled?: boolean
+  isExpanded?: boolean
+  onExpandedChange?: (boolean) => void
+}

@react-stately/disclosure

/@react-stately/disclosure:useDisclosureState

+useDisclosureState {
+  props: DisclosureProps
+  returnVal: undefined
+}

/@react-stately/disclosure:DisclosureState

+DisclosureState {
+  collapse: () => void
+  expand: () => void
+  isExpanded: boolean
+  setExpanded: (boolean) => void
+  toggle: () => void
+}

/@react-stately/disclosure:DisclosureProps

+DisclosureProps {
+  defaultExpanded?: boolean
+  isExpanded?: boolean
+  onExpandedChange?: (boolean) => void
+}

@reidbarber reidbarber merged commit 9421c14 into main Sep 20, 2024
29 checks passed
@reidbarber reidbarber deleted the accordionitem branch September 20, 2024 17:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants