Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9680566

Browse files
committed
feat(CAccordion): improve accessibility; allow passing or overriding class names for all subcomponents.
1 parent0acd718 commit9680566

16 files changed

+585
-92
lines changed

‎packages/coreui-react/src/components/accordion/CAccordion.tsx

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,78 @@ import React, { createContext, forwardRef, HTMLAttributes, useState } from 'reac
22
importPropTypesfrom'prop-types'
33
importclassNamesfrom'classnames'
44

5+
import{mergeClassNames}from'../../utils'
6+
57
exportinterfaceCAccordionPropsextendsHTMLAttributes<HTMLDivElement>{
68
/**
7-
* The active item key.
9+
* Determines which accordion item is currently active (expanded) by default.
10+
* Accepts a number or string corresponding to the `itemKey` of the desired accordion item.
11+
*
12+
*@example
13+
* <CAccordion activeItemKey="1">...</CAccordion>
814
*/
915
activeItemKey?:number|string
16+
1017
/**
11-
* Make accordion items stay open when another item is opened
18+
* When set to `true`, multiple accordion items within the React Accordion can be open simultaneously.
19+
* This is ideal for scenarios where users need to view multiple sections at once without collapsing others.
20+
*
21+
*@default false
22+
*
23+
*@example
24+
* <CAccordion alwaysOpen>...</CAccordion>
1225
*/
1326
alwaysOpen?:boolean
27+
1428
/**
15-
* A string of all className you want applied to the base component.
29+
* Allows you to apply custom CSS classes to the React Accordion for enhanced styling and theming.
30+
*
31+
*@example
32+
* <CAccordion className="my-custom-accordion">...</CAccordion>
1633
*/
1734
className?:string
35+
1836
/**
19-
* Removes the default background-color, some borders, and some rounded corners to render accordions edge-to-edge with their parent container.
37+
* Allows overriding or extending the default CSS class names used in the component.
38+
*
39+
* - `ACCORDION`: Base class for the accordion component.
40+
* - `ACCORDION_FLUSH`: Class applied when the `flush` prop is set to true, ensuring an edge-to-edge layout.
41+
*
42+
* Use this prop to customize the styles of specific parts of the accordion.
43+
*
44+
*@example
45+
* const customClasses = {
46+
* ACCORDION: 'custom-accordion',
47+
* ACCORDION_FLUSH: 'custom-accordion-flush'
48+
* }
49+
* <CAccordion customClassNames={customClasses}>...</CAccordion>
50+
*/
51+
customClassNames?:Partial<typeofACCORDION_CLASS_NAMES>
52+
53+
/**
54+
* When `flush` is set to `true`, the React Accordion renders edge-to-edge with its parent container,
55+
* creating a seamless and modern look ideal for minimalist designs.
56+
*
57+
*@default false
58+
*
59+
*@example
60+
* <CAccordion flush>...</CAccordion>
2061
*/
2162
flush?:boolean
2263
}
2364

65+
exportconstACCORDION_CLASS_NAMES={
66+
/**
67+
* Base class for the accordion container.
68+
*/
69+
ACCORDION:'accordion',
70+
71+
/**
72+
* Applied when the `flush` prop is enabled.
73+
*/
74+
ACCORDION_FLUSH:'accordion-flush',
75+
}
76+
2477
exportinterfaceCAccordionContextProps{
2578
_activeItemKey?:number|string
2679
alwaysOpen?:boolean
@@ -30,12 +83,24 @@ export interface CAccordionContextProps {
3083
exportconstCAccordionContext=createContext({}asCAccordionContextProps)
3184

3285
exportconstCAccordion=forwardRef<HTMLDivElement,CAccordionProps>(
33-
({ children, activeItemKey, alwaysOpen=false, className, flush, ...rest},ref)=>{
86+
(
87+
{ children, activeItemKey, alwaysOpen=false, className, customClassNames, flush, ...rest},
88+
ref,
89+
)=>{
3490
const[_activeItemKey,setActiveKey]=useState(activeItemKey)
3591

92+
const_classNames=mergeClassNames<typeofACCORDION_CLASS_NAMES>(
93+
ACCORDION_CLASS_NAMES,
94+
customClassNames,
95+
)
96+
3697
return(
3798
<div
38-
className={classNames('accordion',{'accordion-flush':flush},className)}
99+
className={classNames(
100+
_classNames.ACCORDION,
101+
{[_classNames.ACCORDION_FLUSH]:flush},
102+
className,
103+
)}
39104
{...rest}
40105
ref={ref}
41106
>

‎packages/coreui-react/src/components/accordion/CAccordionBody.tsx

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,60 @@ import classNames from 'classnames'
55
import{CAccordionItemContext}from'./CAccordionItem'
66

77
import{CCollapse}from'./../collapse/CCollapse'
8+
import{mergeClassNames}from'../../utils'
89

910
exportinterfaceCAccordionBodyPropsextendsHTMLAttributes<HTMLDivElement>{
1011
/**
11-
* A string of all className you want applied to the base component.
12+
* Allows you to apply custom CSS classes to the React Accordion Body for enhanced styling and theming.
13+
*
14+
*@example
15+
* <CAccordionBody className="custom-accordion-body">...</CAccordionBody>
1216
*/
1317
className?:string
18+
19+
/**
20+
* Allows overriding or extending the default CSS class names used in the accordion body component.
21+
* Accepts a partial object matching the shape of `ACCORDION_BODY_CLASS_NAMES`, which includes:
22+
*
23+
* - `ACCORDION_COLLAPSE`: Base class for the collapse container in the accordion body.
24+
* - `ACCORDION_BODY`: Base class for the main content container inside the accordion body.
25+
*
26+
* Use this prop to customize the styles of specific parts of the accordion body.
27+
*
28+
*@example
29+
* const customClasses = {
30+
* ACCORDION_COLLAPSE: 'custom-collapse-class',
31+
* ACCORDION_BODY: 'custom-body-class',
32+
* }
33+
* <CAccordionBody customClassNames={customClasses}>...</CAccordionBody>
34+
*/
35+
customClassNames?:Partial<typeofACCORDION_BODY_CLASS_NAMES>
36+
}
37+
38+
exportconstACCORDION_BODY_CLASS_NAMES={
39+
/**
40+
* Used for managing collapsible behavior in the accordion body.
41+
*/
42+
ACCORDION_COLLAPSE:'accordion-collapse',
43+
44+
/**
45+
* Styles the main content container inside the accordion.
46+
*/
47+
ACCORDION_BODY:'accordion-body',
1448
}
1549

1650
exportconstCAccordionBody=forwardRef<HTMLDivElement,CAccordionBodyProps>(
17-
({ children, className, ...rest},ref)=>{
18-
const{ visible}=useContext(CAccordionItemContext)
51+
({ children, className, customClassNames, ...rest},ref)=>{
52+
const{ id, visible}=useContext(CAccordionItemContext)
53+
54+
const_classNames=mergeClassNames<typeofACCORDION_BODY_CLASS_NAMES>(
55+
ACCORDION_BODY_CLASS_NAMES,
56+
customClassNames,
57+
)
1958

2059
return(
21-
<CCollapseclassName="accordion-collapse"visible={visible}>
22-
<divclassName={classNames('accordion-body',className)}{...rest}ref={ref}>
60+
<CCollapseid={id}className={_classNames.ACCORDION_COLLAPSE}visible={visible}>
61+
<divclassName={classNames(_classNames.ACCORDION_BODY,className)}{...rest}ref={ref}>
2362
{children}
2463
</div>
2564
</CCollapse>

‎packages/coreui-react/src/components/accordion/CAccordionButton.tsx

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,46 @@ import classNames from 'classnames'
44

55
import{CAccordionItemContext}from'./CAccordionItem'
66

7+
import{mergeClassNames}from'../../utils'
8+
79
exportinterfaceCAccordionButtonPropsextendsHTMLAttributes<HTMLButtonElement>{
810
/**
9-
*A string of all className you want applied tothebase component.
11+
*Styles the clickable element intheaccordion header.
1012
*/
1113
className?:string
14+
15+
/**
16+
* Allows overriding or extending the default CSS class names used in the accordion button component.
17+
* Accepts a partial object matching the shape of `CLASS_NAMES`, which includes:
18+
*
19+
* - `ACCORDION_BUTTON`: Base class for the accordion button.
20+
*
21+
* Use this prop to customize the styles of the accordion button.
22+
*
23+
*@example
24+
* const customClasses = {
25+
* ACCORDION_BUTTON: 'custom-button-class',
26+
* }
27+
* <CAccordionButton customClassNames={customClasses}>...</CAccordionButton>
28+
*/
29+
customClassNames?:Partial<typeofCLASS_NAMES>
30+
}
31+
32+
exportconstCLASS_NAMES={
33+
ACCORDION_BUTTON:'accordion-button',
1234
}
1335

1436
exportconstCAccordionButton=forwardRef<HTMLButtonElement,CAccordionButtonProps>(
15-
({ children, className, ...rest},ref)=>{
16-
const{ visible, setVisible}=useContext(CAccordionItemContext)
37+
({ children, className, customClassNames, ...rest},ref)=>{
38+
const{ id, visible, setVisible}=useContext(CAccordionItemContext)
39+
const_classNames=mergeClassNames<typeofCLASS_NAMES>(CLASS_NAMES,customClassNames)
1740

1841
return(
1942
<button
2043
type="button"
21-
className={classNames('accordion-button',{collapsed:!visible},className)}
22-
aria-expanded={!visible}
44+
className={classNames(_classNames.ACCORDION_BUTTON,{collapsed:!visible},className)}
45+
aria-controls={id}
46+
aria-expanded={visible}
2347
onClick={()=>setVisible(!visible)}
2448
{...rest}
2549
ref={ref}

‎packages/coreui-react/src/components/accordion/CAccordionHeader.tsx

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,53 @@ import PropTypes from 'prop-types'
33
importclassNamesfrom'classnames'
44

55
import{CAccordionButton}from'./CAccordionButton'
6+
import{mergeClassNames}from'../../utils'
67

78
exportinterfaceCAccordionHeaderPropsextendsHTMLAttributes<HTMLDivElement>{
89
/**
910
* A string of all className you want applied to the base component.
1011
*/
1112
className?:string
13+
/**
14+
* Allows overriding or extending the default CSS class names used in the accordion header component.
15+
* Accepts a partial object matching the shape of `ACCORDION_HEADER_CLASS_NAMES`, which includes:
16+
*
17+
* - `ACCORDION_HEADER`: Base class for the accordion header container.
18+
* - `ACCORDION_BUTTON`: Class applied to the button within the accordion header.
19+
*
20+
* Use this prop to customize the styles of specific parts of the accordion header.
21+
*
22+
*@example
23+
* const customClasses = {
24+
* ACCORDION_HEADER: 'custom-header-class',
25+
* ACCORDION_BUTTON: 'custom-button-class',
26+
* }
27+
* <CAccordionHeader customClassNames={customClasses}>...</CAccordionHeader>
28+
*/
29+
customClassNames?:Partial<typeofACCORDION_HEADER_CLASS_NAMES>
30+
}
31+
32+
exportconstACCORDION_HEADER_CLASS_NAMES={
33+
/**
34+
* Styles the header container of an accordion item.
35+
*/
36+
ACCORDION_HEADER:'accordion-header',
37+
38+
/**
39+
* Styles the clickable element in the accordion header.
40+
*/
41+
ACCORDION_BUTTON:'accordion-button',
1242
}
1343

1444
exportconstCAccordionHeader=forwardRef<HTMLDivElement,CAccordionHeaderProps>(
15-
({ children, className, ...rest},ref)=>{
45+
({ children, className, customClassNames, ...rest},ref)=>{
46+
const_classNames=mergeClassNames<typeofACCORDION_HEADER_CLASS_NAMES>(
47+
ACCORDION_HEADER_CLASS_NAMES,
48+
customClassNames,
49+
)
1650
return(
17-
<divclassName={classNames('accordion-header',className)}{...rest}ref={ref}>
18-
<CAccordionButton>{children}</CAccordionButton>
51+
<divclassName={classNames(_classNames.ACCORDION_HEADER,className)}{...rest}ref={ref}>
52+
<CAccordionButtonclassName={_classNames.ACCORDION_HEADER}>{children}</CAccordionButton>
1953
</div>
2054
)
2155
},

‎packages/coreui-react/src/components/accordion/CAccordionItem.tsx

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ import React, {
44
HTMLAttributes,
55
useContext,
66
useEffect,
7+
useId,
78
useRef,
89
useState,
910
}from'react'
1011
importPropTypesfrom'prop-types'
1112
importclassNamesfrom'classnames'
1213

1314
import{CAccordionContext}from'./CAccordion'
15+
import{mergeClassNames}from'../../utils'
1416

1517
exportinterfaceCAccordionItemContextProps{
18+
id:string
1619
setVisible:(a:boolean)=>void
1720
visible?:boolean
1821
}
@@ -24,19 +27,49 @@ export interface CAccordionItemProps extends HTMLAttributes<HTMLDivElement> {
2427
* A string of all className you want applied to the base component.
2528
*/
2629
className?:string
30+
31+
/**
32+
* Allows overriding or extending the default CSS class names used in the accordion item component.
33+
* Accepts a partial object matching the shape of `ACCORDION_ITEM_CLASS_NAMES`, which includes:
34+
*
35+
* - `ACCORDION_ITEM`: Base class for an individual accordion item.
36+
*
37+
* Use this prop to customize the styles of specific parts of the accordion item.
38+
*
39+
*@example
40+
* const customClasses = {
41+
* ACCORDION_ITEM: 'custom-item-class',
42+
* }
43+
* <CAccordionItem customClassNames={customClasses}>...</CAccordionItem>
44+
*/
45+
customClassNames?:Partial<typeofACCORDION_ITEM_CLASS_NAMES>
46+
2747
/**
2848
* Item key.
2949
*/
3050
itemKey?:number|string
3151
}
3252

53+
exportconstACCORDION_ITEM_CLASS_NAMES={
54+
/**
55+
* Base class for an individual accordion item.
56+
*/
57+
ACCORDION_ITEM:'accordion-item',
58+
}
59+
3360
exportconstCAccordionItem=forwardRef<HTMLDivElement,CAccordionItemProps>(
34-
({ children, className, itemKey, ...rest},ref)=>{
61+
({ children, className, customClassNames, itemKey, ...rest},ref)=>{
62+
constid=useId()
3563
const_itemKey=useRef(itemKey??Math.random().toString(36).slice(2,11))
3664

3765
const{ _activeItemKey, alwaysOpen, setActiveKey}=useContext(CAccordionContext)
3866
const[visible,setVisible]=useState(Boolean(_activeItemKey===_itemKey.current))
3967

68+
const_classNames=mergeClassNames<typeofACCORDION_ITEM_CLASS_NAMES>(
69+
ACCORDION_ITEM_CLASS_NAMES,
70+
customClassNames,
71+
)
72+
4073
useEffect(()=>{
4174
!alwaysOpen&&visible&&setActiveKey(_itemKey.current)
4275
},[visible])
@@ -46,8 +79,8 @@ export const CAccordionItem = forwardRef<HTMLDivElement, CAccordionItemProps>(
4679
},[_activeItemKey])
4780

4881
return(
49-
<divclassName={classNames('accordion-item',className)}{...rest}ref={ref}>
50-
<CAccordionItemContext.Providervalue={{ setVisible, visible}}>
82+
<divclassName={classNames(_classNames.ACCORDION_ITEM,className)}{...rest}ref={ref}>
83+
<CAccordionItemContext.Providervalue={{id,setVisible, visible}}>
5184
{children}
5285
</CAccordionItemContext.Provider>
5386
</div>

‎packages/coreui-react/src/utils/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import getRTLPlacement from './getRTLPlacement'
44
importgetTransitionDurationFromElementfrom'./getTransitionDurationFromElement'
55
importisInViewportfrom'./isInViewport'
66
importisRTLfrom'./isRTL'
7+
importmergeClassNamesfrom'./mergeClassNames'
78

89
export{
910
executeAfterTransition,
@@ -12,4 +13,5 @@ export {
1213
getTransitionDurationFromElement,
1314
isInViewport,
1415
isRTL,
16+
mergeClassNames,
1517
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp