-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b0e7c54
commit 57b487d
Showing
12 changed files
with
155 additions
and
202 deletions.
There are no files selected for viewing
98 changes: 59 additions & 39 deletions
98
packages/libs/react-ui/src/components/Accordion/Accordion.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,79 @@ | ||
import { Accordion, IAccordionProps } from './Accordion'; | ||
import type { IAccordionRootProps, IAccordionSectionProps } from './'; | ||
import { Accordion } from './'; | ||
|
||
import type { Meta, StoryObj } from '@storybook/react'; | ||
import React from 'react'; | ||
|
||
const meta: Meta<{} & IAccordionProps> = { | ||
const generateSection = (index: number): IAccordionSectionProps => ({ | ||
title: <span>Section {index + 1}</span>, | ||
children: <p>This is the content for section {index + 1}</p>, | ||
onOpen: () => console.log(`open section ${index + 1}`), | ||
onClose: () => console.log(`close section ${index + 1}`), | ||
}); | ||
const generateSections = (n: number): IAccordionSectionProps[] => | ||
Array.from({ length: n }, (d, i) => generateSection(i)); | ||
|
||
const sampleSections: IAccordionSectionProps[] = generateSections(5); | ||
|
||
type StoryProps = { sectionCount: number } & IAccordionRootProps; | ||
|
||
const meta: Meta<StoryProps> = { | ||
title: 'Components/Accordion', | ||
parameters: { | ||
controls: { | ||
hideNoControlsWarning: true, | ||
sort: 'requiredFirst', | ||
}, | ||
docs: { | ||
description: { | ||
component: '', | ||
}, | ||
}, | ||
}, | ||
argTypes: { | ||
linked: { | ||
type: 'boolean', | ||
defaultValue: true, | ||
control: { type: 'boolean' }, | ||
description: | ||
'Each section will close the other sections if they are linked', | ||
control: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
sections: { | ||
defaultValue: [], | ||
description: 'Accordion children', | ||
control: { | ||
type: 'array', | ||
}, | ||
sectionCount: { | ||
control: { type: 'range', min: 1, max: sampleSections.length, step: 1 }, | ||
description: 'Adjust sample section items count', | ||
}, | ||
}, | ||
}; | ||
|
||
export default meta; | ||
type Story = StoryObj<{} & IAccordionProps>; | ||
type IStory = StoryObj<StoryProps>; | ||
|
||
export const Dynamic: Story = { | ||
export const Dynamic: IStory = { | ||
name: 'Accordion', | ||
args: { | ||
linked: true, | ||
sections: [ | ||
{ | ||
title: <span>First Section</span>, | ||
children: <p>This is the content for the first section</p>, | ||
onOpen: () => console.log('open first item'), | ||
onClose: () => console.log('close first item'), | ||
}, | ||
{ | ||
title: <span>Second Section</span>, | ||
children: <p>This is the content for the second section</p>, | ||
onOpen: () => console.log('open second item'), | ||
onClose: () => console.log('close second item'), | ||
}, | ||
{ | ||
title: <span>Third Section</span>, | ||
children: <p>This is the content for the third section</p>, | ||
onOpen: () => console.log('open third item'), | ||
onClose: () => console.log('close third item'), | ||
}, | ||
], | ||
linked: false, | ||
sectionCount: 3, | ||
}, | ||
render: ({ linked, sections }) => { | ||
return <Accordion linked={Boolean(linked)} sections={sections} />; | ||
render: ({ linked, sectionCount }) => { | ||
return ( | ||
<Accordion.Root linked={linked}> | ||
{sampleSections | ||
.slice(0, sectionCount) | ||
.map( | ||
( | ||
{ title, children, onOpen, onClose }: IAccordionSectionProps, | ||
index, | ||
) => ( | ||
<Accordion.Section | ||
onOpen={onOpen} | ||
onClose={onClose} | ||
title={title} | ||
key={index} | ||
> | ||
{children} | ||
</Accordion.Section> | ||
), | ||
)} | ||
</Accordion.Root> | ||
); | ||
}, | ||
}; | ||
|
||
export default meta; |
98 changes: 0 additions & 98 deletions
98
packages/libs/react-ui/src/components/Accordion/Accordion.test.tsx
This file was deleted.
Oops, something went wrong.
51 changes: 16 additions & 35 deletions
51
packages/libs/react-ui/src/components/Accordion/Accordion.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,22 @@ | ||
import { AccordionSection, IAccordionSectionProps } from './AccordionSection'; | ||
import useLinked from './useLinked'; | ||
import { IAccordionSectionsProps } from '.'; | ||
|
||
import React, { FC, useState } from 'react'; | ||
import React, { FC, FunctionComponentElement } from 'react'; | ||
|
||
export interface IAccordionProps { | ||
sections: Omit<IAccordionSectionProps, 'isOpen' | 'onToggle'>[]; | ||
export interface IAccordionRootProps { | ||
children?: React.ReactNode; | ||
linked?: boolean; | ||
openSection?: number; | ||
} | ||
|
||
export const Accordion: FC<IAccordionProps> = ({ sections, linked = true }) => { | ||
const [expandedSections, setExpandedSections] = useState<number[]>([]); | ||
const handleOpen = (index: number): void => { | ||
if (linked) setExpandedSections([index]); | ||
else setExpandedSections([...expandedSections, index]); | ||
}; | ||
const handleClose = (index: number): void => { | ||
setExpandedSections(expandedSections.filter((item) => item !== index)); | ||
}; | ||
|
||
const isOpen = (index: number): boolean => expandedSections.includes(index); | ||
|
||
const handleToggle = (index: number): void => { | ||
if (isOpen(index)) handleClose(index); | ||
else handleOpen(index); | ||
}; | ||
|
||
return ( | ||
<div data-testid="kda-accordion-wrapper"> | ||
{sections.map((section, index) => ( | ||
<AccordionSection | ||
{...section} | ||
isOpen={isOpen(index)} | ||
onToggle={() => handleToggle(index)} | ||
key={String(section.title)} | ||
> | ||
{section.children} | ||
</AccordionSection> | ||
))} | ||
</div> | ||
); | ||
export const AccordionRoot: FC<IAccordionRootProps> = ({ | ||
children, | ||
linked, | ||
openSection, | ||
}) => { | ||
if (linked) { | ||
const { setUsingLinked } = useLinked(openSection); | ||
setUsingLinked(true); | ||
} | ||
return <div data-testid="kda-accordion-wrapper">{children}</div>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
packages/libs/react-ui/src/components/Accordion/AccordionSections.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import useLinked from './useLinked'; | ||
import { IAccordionSectionProps } from '.'; | ||
|
||
import React, { FC, FunctionComponentElement } from 'react'; | ||
|
||
export interface IAccordionSectionsProps { | ||
// children?: FunctionComponentElement<IAccordionSectionProps>[]; | ||
children?: React.ReactNode; | ||
linked?: boolean; | ||
openSection?: number; | ||
} | ||
|
||
export const AccordionSections: FC<IAccordionSectionsProps> = ({ | ||
children, | ||
linked, | ||
openSection = 0, | ||
}) => { | ||
return <div data-testid="kda-accordion-sections">{children}</div>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,22 @@ | ||
export { Accordion } from './Accordion'; | ||
export type { IAccordionProps } from './Accordion'; | ||
export type { IAccordionSectionProps } from './AccordionSection'; | ||
import type { IAccordionRootProps } from './Accordion'; | ||
import { AccordionRoot } from './Accordion'; | ||
import type { IAccordionSectionProps } from './AccordionSection'; | ||
import { AccordionSection } from './AccordionSection'; | ||
import type { IAccordionSectionsProps } from './AccordionSections'; | ||
import { AccordionSections } from './AccordionSections'; | ||
|
||
import { FC } from 'react'; | ||
|
||
export { IAccordionRootProps, IAccordionSectionProps, IAccordionSectionsProps }; | ||
|
||
export interface IAccordionProps { | ||
Root: FC<IAccordionRootProps>; | ||
Sections: FC<IAccordionSectionsProps>; | ||
Section: FC<IAccordionSectionProps>; | ||
} | ||
|
||
export const Accordion: IAccordionProps = { | ||
Root: AccordionRoot, | ||
Sections: AccordionSections, | ||
Section: AccordionSection, | ||
}; |
16 changes: 16 additions & 0 deletions
16
packages/libs/react-ui/src/components/Accordion/useLinked.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { useState } from 'react'; | ||
|
||
interface IUseLinkedReturn { | ||
activeSection: number; | ||
setActiveSection: React.Dispatch<React.SetStateAction<number>>; | ||
usingLinked: boolean; | ||
setUsingLinked: React.Dispatch<React.SetStateAction<boolean>>; | ||
} | ||
|
||
const useLinked = (openSection = 0): IUseLinkedReturn => { | ||
const [usingLinked, setUsingLinked] = useState(false); | ||
const [activeSection, setActiveSection] = useState(openSection); | ||
return { activeSection, setActiveSection, usingLinked, setUsingLinked }; | ||
}; | ||
|
||
export default useLinked; |
Oops, something went wrong.