Skip to content

Commit 8bc7bfc

Browse files
feat: added types for Accordion, AccordionItem, AccordionSkeleton, SkeletonText (#13875)
* chore: added name to contributor list * refactor: changed file ext to .tsx for accordion and skeleton text * refactor: using context for accordion instead of cloning children * feat: added types for SkeletonText component * fix: added type to props parameter for SkeletonText * feat: added types to accordion components * fix: linting err in SkeletonText component * fix: reverted default prop type deletion * Update packages/react/src/components/Accordion/AccordionItem.tsx * refactor: renamed variable and removed v10 interface from accordion --------- Co-authored-by: Andrea N. Cardona <cardona.n.andrea@gmail.com>
1 parent 4f3787a commit 8bc7bfc

9 files changed

Lines changed: 265 additions & 47 deletions

File tree

.all-contributorsrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,15 @@
11491149
"code"
11501150
]
11511151
},
1152+
{
1153+
"login": "SunnyJohal",
1154+
"name": "Sunny Johal",
1155+
"avatar_url": "https://avatars.githubusercontent.com/u/19283532?v=4",
1156+
"profile": "https://github.com/SunnyJohal",
1157+
"contributions": [
1158+
"code"
1159+
]
1160+
},
11521161
{
11531162
"login": "sjbeatle",
11541163
"name": "Steven Black",

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ check out our [Contributing Guide](/.github/CONTRIBUTING.md) and our
237237
<td align="center"><a href="https://github.com/gerzonc"><img src="https://avatars.githubusercontent.com/u/36211892?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gerzon</b></sub></a><br /><a href="https://github.com/carbon-design-system/carbon/commits?author=gerzonc" title="Code">💻</a></td>
238238
<td align="center"><a href="https://github.com/guidari"><img src="https://avatars.githubusercontent.com/u/52183462?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Guilherme Datilio Ribeiro</b></sub></a><br /><a href="https://github.com/carbon-design-system/carbon/commits?author=guidari" title="Code">💻</a> <a href="https://github.com/carbon-design-system/carbon/commits?author=guidari" title="Documentation">📖</a> <a href="#a11y-guidari" title="Accessibility">️️️️♿️</a> <a href="https://github.com/carbon-design-system/carbon/pulls?q=is%3Apr+reviewed-by%3Aguidari" title="Reviewed Pull Requests">👀</a></td>
239239
<td align="center"><a href="https://github.com/kubijo"><img src="https://avatars.githubusercontent.com/u/11244314?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kubijo</b></sub></a><br /><a href="https://github.com/carbon-design-system/carbon/commits?author=kubijo" title="Code">💻</a></td>
240+
<td align="center"><a href="https://github.com/SunnyJohal"><img src="https://avatars.githubusercontent.com/u/19283532?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sunny Johal</b></sub></a><br /><a href="https://github.com/carbon-design-system/carbon/commits?author=SunnyJohal" title="Code">💻</a></td>
240241
<td align="center"><a href="http://www.steveblackonline.com/"><img src="https://avatars.githubusercontent.com/u/7853451?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Steven Black</b></sub></a><br /><a href="https://github.com/carbon-design-system/carbon/commits?author=sjbeatle" title="Code">💻</a> <a href="#a11y-sjbeatle" title="Accessibility">️️️️♿️</a></td>
241242
</tr>
242243
<tr>

packages/react/src/components/Accordion/Accordion.Skeleton.js renamed to packages/react/src/components/Accordion/Accordion.Skeleton.tsx

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,43 @@ import { ChevronRight } from '@carbon/icons-react';
1212
import SkeletonText from '../SkeletonText';
1313
import { usePrefix } from '../../internal/usePrefix';
1414

15+
interface AccordionSkeletonProps {
16+
/**
17+
* Specify the alignment of the accordion heading
18+
* title and chevron.
19+
*/
20+
align?: 'start' | 'end';
21+
22+
/**
23+
* Specify an optional className to add.
24+
*/
25+
className?: string;
26+
27+
/**
28+
* Set number of items to render.
29+
*/
30+
count?: number;
31+
32+
/**
33+
* Specify whether an individual AccordionItem should
34+
* be flush, default is false.
35+
*/
36+
isFlush?: boolean;
37+
38+
/**
39+
* `false` to not display the first item opened.
40+
*/
41+
open?: boolean;
42+
}
43+
1544
function AccordionSkeleton({
16-
align,
45+
align = 'end',
1746
className,
18-
count,
47+
count = 4,
1948
isFlush,
20-
open,
49+
open = true,
2150
...rest
22-
}) {
51+
}: AccordionSkeletonProps) {
2352
const prefix = usePrefix();
2453
const classes = cx(`${prefix}--accordion`, `${prefix}--skeleton`, className, {
2554
[`${prefix}--accordion--${align}`]: align,

packages/react/src/components/Accordion/Accordion.js renamed to packages/react/src/components/Accordion/Accordion.tsx

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,40 @@
88
import cx from 'classnames';
99
import { usePrefix } from '../../internal/usePrefix';
1010
import PropTypes from 'prop-types';
11-
import React from 'react';
11+
import React, { PropsWithChildren } from 'react';
12+
import { AccordionProvider } from './AccordionProvider';
13+
14+
interface AccordionProps {
15+
/**
16+
* Specify the alignment of the accordion heading
17+
* title and chevron. Defaults to `end`.
18+
*/
19+
align?: 'start' | 'end';
20+
21+
/**
22+
* Specify an optional className to be applied to
23+
* the container node.
24+
*/
25+
className?: string;
26+
27+
/**
28+
* Specify whether an individual AccordionItem
29+
* should be disabled.
30+
*/
31+
disabled?: boolean;
32+
33+
/**
34+
* Specify whether Accordion text should be flush,
35+
* default is `false`, does not work with `align="start"`.
36+
*/
37+
isFlush?: boolean;
38+
39+
/**
40+
* Specify the size of the Accordion. Currently
41+
* supports the following: `sm`, `md`, `lg`
42+
*/
43+
size?: 'sm' | 'md' | 'lg';
44+
}
1245

1346
function Accordion({
1447
align = 'end',
@@ -18,7 +51,7 @@ function Accordion({
1851
isFlush = false,
1952
size,
2053
...rest
21-
}) {
54+
}: PropsWithChildren<AccordionProps>) {
2255
const prefix = usePrefix();
2356

2457
const className = cx(`${prefix}--accordion`, customClassName, {
@@ -27,14 +60,13 @@ function Accordion({
2760
[`${prefix}--layout--size-${size}`]: size,
2861
[`${prefix}--accordion--flush`]: isFlush && align !== 'start',
2962
});
63+
3064
return (
31-
<ul className={className} {...rest}>
32-
{disabled
33-
? React.Children.toArray(children).map((child) => {
34-
return React.cloneElement(child, { disabled });
35-
})
36-
: children}
37-
</ul>
65+
<AccordionProvider disabled={disabled}>
66+
<ul className={className} {...rest}>
67+
{children}
68+
</ul>
69+
</AccordionProvider>
3870
);
3971
}
4072

packages/react/src/components/Accordion/AccordionItem.js renamed to packages/react/src/components/Accordion/AccordionItem.tsx

Lines changed: 105 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,128 @@
44
* This source code is licensed under the Apache-2.0 license found in the
55
* LICENSE file in the root directory of this source tree.
66
*/
7-
87
import { ChevronRight } from '@carbon/icons-react';
98
import cx from 'classnames';
109
import PropTypes from 'prop-types';
11-
import React, { useState } from 'react';
10+
import React, {
11+
AnimationEventHandler,
12+
AriaAttributes,
13+
KeyboardEvent,
14+
MouseEventHandler,
15+
PropsWithChildren,
16+
ReactElement,
17+
ReactNode,
18+
useContext,
19+
useState,
20+
} from 'react';
1221
import { Text } from '../Text';
1322
import { match, keys } from '../../internal/keyboard';
1423
import { useId } from '../../internal/useId';
1524
import deprecate from '../../prop-types/deprecate';
1625
import { usePrefix } from '../../internal/usePrefix';
26+
import { AccordionContext } from './AccordionProvider';
27+
28+
interface AccordionItemProps {
29+
/**
30+
* Specify an optional className to be
31+
* applied to the container node.
32+
*/
33+
className?: string;
34+
35+
/**
36+
* Specify whether an individual `AccordionItem` should
37+
* be disabled (overrides the parent accordion state). If undefined,
38+
* this value will be managed by the parent Accordion.
39+
*/
40+
disabled?: boolean;
41+
42+
/**
43+
* The handler of the massaged `click` event.
44+
*/
45+
onClick?: MouseEventHandler<HTMLLIElement>;
46+
47+
/**
48+
* The handler of the massaged `click` event on
49+
* the heading.
50+
*/
51+
onHeadingClick?: ({
52+
isOpen,
53+
event,
54+
}: {
55+
isOpen: boolean;
56+
event: Parameters<MouseEventHandler<HTMLButtonElement>>[0];
57+
}) => void;
58+
59+
/**
60+
* `true` to open the expand.
61+
*/
62+
open?: boolean;
63+
64+
/**
65+
* @deprecated This prop has been deprecated and will be
66+
* removed in the next major release of Carbon. Use the
67+
* `renderToggle` prop instead.
68+
*/
69+
renderExpando?: (
70+
props: PropsWithChildren<AccordionToggleProps>
71+
) => ReactElement;
72+
73+
/**
74+
* The callback function to render the expand button.
75+
* Can be a React component class.
76+
*/
77+
renderToggle?: (
78+
props: PropsWithChildren<AccordionToggleProps>
79+
) => ReactElement;
1780

18-
const defaultRenderToggle = (props) => <button type="button" {...props} />;
81+
/**
82+
* The accordion title.
83+
*/
84+
title?: ReactNode;
85+
86+
/**
87+
* The callback function to run on the `onAnimationEnd`
88+
* event for the list item.
89+
*/
90+
handleAnimationEnd?: AnimationEventHandler<HTMLLIElement>;
91+
}
92+
93+
interface AccordionToggleProps {
94+
'aria-controls'?: AriaAttributes['aria-controls'];
95+
'aria-expanded'?: AriaAttributes['aria-expanded'];
96+
className?: string;
97+
disabled?: boolean;
98+
onClick?: MouseEventHandler<HTMLButtonElement>;
99+
onKeyDown?: (event: KeyboardEvent<HTMLButtonElement>) => void;
100+
type?: 'button';
101+
}
102+
103+
const defaultRenderToggle = (props: AccordionToggleProps) => (
104+
<button type="button" {...props} />
105+
);
19106

20107
function AccordionItem({
21108
children,
22-
className: customClassName,
23-
iconDescription, // eslint-disable-line
109+
className: customClassName = '',
24110
open = false,
25111
onHeadingClick,
26112
renderExpando = defaultRenderToggle, // remove renderExpando in next major release
27113
renderToggle,
28114
title = 'title',
29-
disabled,
115+
disabled: controlledDisabled,
116+
handleAnimationEnd,
30117
...rest
31-
}) {
118+
}: PropsWithChildren<AccordionItemProps>) {
32119
const [isOpen, setIsOpen] = useState(open);
33120
const [prevIsOpen, setPrevIsOpen] = useState(open);
34121
const [animation, setAnimation] = useState('');
122+
const accordionState = useContext(AccordionContext);
123+
124+
const disabledIsControlled = typeof controlledDisabled === 'boolean';
125+
const disabled = disabledIsControlled
126+
? controlledDisabled
127+
: accordionState.disabled;
128+
35129
const id = useId('accordion-item');
36130
const prefix = usePrefix();
37131
const className = cx({
@@ -70,15 +164,15 @@ function AccordionItem({
70164
}
71165
}
72166

73-
function handleAnimationEnd(event) {
74-
if (rest.handleAnimationEnd) {
75-
rest.handleAnimationEnd(event);
167+
function onAnimationEnd(event) {
168+
if (handleAnimationEnd) {
169+
handleAnimationEnd(event);
76170
}
77171
setAnimation('');
78172
}
79173

80174
return (
81-
<li className={className} {...rest} onAnimationEnd={handleAnimationEnd}>
175+
<li className={className} {...rest} onAnimationEnd={onAnimationEnd}>
82176
<Toggle
83177
disabled={disabled}
84178
aria-controls={id}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright IBM Corp. 2016, 2023
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
import React, { PropsWithChildren, createContext } from 'react';
8+
9+
type AccordionProviderProp = {
10+
/**
11+
* Global setting to disable all AccordionItems
12+
* within the Accordion. Individual AccordionItems can be
13+
* disabled by passing the `disabled` prop to the AccordionItem.
14+
*/
15+
disabled: boolean;
16+
};
17+
18+
export const AccordionContext = createContext({ disabled: false });
19+
20+
export const AccordionProvider = ({
21+
disabled,
22+
children,
23+
}: PropsWithChildren<AccordionProviderProp>) => {
24+
return (
25+
<AccordionContext.Provider value={{ disabled }}>
26+
{children}
27+
</AccordionContext.Provider>
28+
);
29+
};
File renamed without changes.

0 commit comments

Comments
 (0)