1
1
import classnames from 'classnames' ;
2
- import { FC , ReactNode , KeyboardEvent , MouseEvent , TouchEvent } from 'react' ;
2
+ import { createRef , FC , ReactNode , KeyboardEvent , MouseEvent , RefObject , TouchEvent , useEffect , useState } from 'react' ;
3
3
import { useLingui } from '@lingui/react' ;
4
+ import { Start } from '@client/ui/icons' ;
4
5
5
6
import Badge from '../general/Badge' ;
6
7
import Size from '../general/Size' ;
7
8
9
+ const useRefTextOverflowed = ( ref : RefObject < HTMLElement > ) => {
10
+ const [ overflowed , setOverflowed ] = useState ( false ) ;
11
+
12
+ useEffect ( ( ) => {
13
+ if ( ref . current ) {
14
+ const { current} = ref ;
15
+ setOverflowed ( current . scrollWidth > current . clientWidth ) ;
16
+ }
17
+ } , [ ref , ref ?. current ?. scrollWidth , ref ?. current ?. clientWidth ] ) ;
18
+
19
+ return overflowed ;
20
+ } ;
21
+
8
22
interface SidebarFilterProps {
23
+ children ?: ReactNode [ ] ;
9
24
name : string ;
10
25
icon ?: ReactNode ;
11
26
isActive : boolean ;
@@ -16,6 +31,7 @@ interface SidebarFilterProps {
16
31
}
17
32
18
33
const SidebarFilter : FC < SidebarFilterProps > = ( {
34
+ children,
19
35
name : _name ,
20
36
icon,
21
37
isActive,
@@ -24,11 +40,32 @@ const SidebarFilter: FC<SidebarFilterProps> = ({
24
40
size,
25
41
handleClick,
26
42
} : SidebarFilterProps ) => {
43
+ const nameSpanRef = createRef < HTMLSpanElement > ( ) ;
44
+ const overflowed = useRefTextOverflowed ( nameSpanRef ) ;
45
+
27
46
const { i18n} = useLingui ( ) ;
28
47
48
+ const [ expanded , setExpanded ] = useState ( false ) ;
49
+
29
50
const classNames = classnames ( 'sidebar-filter__item' , {
30
51
'is-active' : isActive ,
31
52
} ) ;
53
+ const expanderClassNames = classnames ( 'sidebar-filter__expander' , {
54
+ 'is-active' : isActive ,
55
+ expanded : expanded ,
56
+ } ) ;
57
+
58
+ const flexCss = children
59
+ ? {
60
+ display : 'flex' ,
61
+ }
62
+ : { } ;
63
+ const focusCss = {
64
+ ':focus' : {
65
+ outline : 'none' ,
66
+ WebkitTapHighlightColor : 'transparent' ,
67
+ } ,
68
+ } ;
32
69
33
70
let name = _name ;
34
71
if ( name === '' ) {
@@ -48,23 +85,35 @@ const SidebarFilter: FC<SidebarFilterProps> = ({
48
85
49
86
return (
50
87
< li >
51
- < button
52
- className = { classNames }
53
- css = { {
54
- ':focus' : {
55
- outline : 'none' ,
56
- WebkitTapHighlightColor : 'transparent' ,
57
- } ,
58
- } }
59
- type = "button"
60
- onClick = { ( event ) => handleClick ( slug , event ) }
61
- role = "menuitem"
62
- >
63
- { icon }
64
- < span className = "name" > { name } </ span >
65
- < Badge > { count } </ Badge >
66
- { size != null && < Size value = { size } className = "size" /> }
67
- </ button >
88
+ < div css = { flexCss } >
89
+ { children && (
90
+ < button
91
+ className = { expanderClassNames }
92
+ css = { focusCss }
93
+ type = "button"
94
+ onClick = { ( ) => setExpanded ( ! expanded ) }
95
+ role = "switch"
96
+ aria-checked = { expanded }
97
+ >
98
+ < Start />
99
+ </ button >
100
+ ) }
101
+ < button
102
+ className = { classNames }
103
+ css = { focusCss }
104
+ type = "button"
105
+ onClick = { ( event ) => handleClick ( slug , event ) }
106
+ role = "menuitem"
107
+ >
108
+ { icon }
109
+ < span className = "name" ref = { nameSpanRef } title = { overflowed ? name || '' : undefined } >
110
+ { name }
111
+ </ span >
112
+ < Badge > { count } </ Badge >
113
+ { size != null && < Size value = { size } className = "size" /> }
114
+ </ button >
115
+ </ div >
116
+ { children && expanded && < ul className = "sidebar-filter__nested" > { children } </ ul > }
68
117
</ li >
69
118
) ;
70
119
} ;
0 commit comments