6
6
*/
7
7
8
8
import React from 'react' ;
9
+ import { createPortal } from 'react-dom' ;
10
+ import { StyleSheetManager } from 'styled-components' ;
11
+
9
12
import { StoryFn } from '@storybook/react' ;
10
13
import LeafIcon from '@zendeskgarden/svg-icons/src/16/leaf-stroke.svg' ;
11
14
import CartIcon from '@zendeskgarden/svg-icons/src/16/shopping-cart-stroke.svg' ;
12
15
import { Grid } from '@zendeskgarden/react-grid' ;
13
16
import { IMenuProps , Item , ItemGroup , Separator , Menu } from '@zendeskgarden/react-dropdowns' ;
17
+ import { IGardenTheme , ThemeProvider } from '@zendeskgarden/react-theming' ;
14
18
import { IconButton } from '@zendeskgarden/react-buttons' ;
15
19
import { ButtonType , IItem , Items } from './types' ;
16
20
@@ -29,50 +33,77 @@ interface IArgs extends IMenuProps {
29
33
label : string ;
30
34
}
31
35
32
- export const MenuStory : StoryFn < IArgs > = ( { button, items, label, ...args } ) => (
33
- < Grid >
34
- < Grid . Row justifyContent = "center" style = { { height : 800 } } >
35
- < Grid . Col alignSelf = "center" textAlign = "center" >
36
- < div style = { { display : 'inline-block' , position : 'relative' , width : 200 } } >
37
- < Menu
38
- { ...args }
39
- button = {
40
- button === 'string'
41
- ? label
42
- : /* eslint-disable-next-line react/no-unstable-nested-components */
43
- props => (
44
- < IconButton { ...props } aria-label = { label } >
45
- < LeafIcon />
46
- </ IconButton >
47
- )
48
- }
49
- >
50
- { items . map ( item => {
51
- if ( 'items' in item ) {
52
- return (
53
- < ItemGroup
54
- legend = { item . legend }
55
- aria-label = { item [ 'aria-label' ] }
56
- key = { item . legend || item [ 'aria-label' ] }
57
- type = { item . type }
58
- icon = { item . icon ? < CartIcon /> : undefined }
59
- >
60
- { item . items . map ( groupItem => (
61
- < MenuItem key = { groupItem . value } { ...groupItem } />
62
- ) ) }
63
- </ ItemGroup >
64
- ) ;
65
- }
36
+ const Portal = ( { children, target } : any ) => {
37
+ if ( ! target ) return null ;
38
+
39
+ return createPortal ( children , target ) ;
40
+ } ;
41
+
42
+ export const MenuStory : StoryFn < IArgs > = ( { button, items, label, ...args } ) => {
43
+ const ref = React . useRef < any > ( null ) ;
44
+ const [ document , setDocument ] = React . useState ( undefined ) ;
45
+
46
+ React . useEffect ( ( ) => {
47
+ if ( ref . current && ! ref . current . shadowRoot ) {
48
+ const shadowRoot = ref . current ?. attachShadow ( { mode : 'open' } ) ;
66
49
67
- if ( 'isSeparator' in item ) {
68
- return < Separator key = { item . value } /> ;
69
- }
50
+ setDocument ( shadowRoot ) ;
51
+ }
52
+ } , [ ] ) ;
70
53
71
- return < MenuItem key = { item . value } { ...item } /> ;
72
- } ) }
73
- </ Menu >
74
- </ div >
75
- </ Grid . Col >
76
- </ Grid . Row >
77
- </ Grid >
78
- ) ;
54
+ return (
55
+ < div ref = { ref } >
56
+ < Portal target = { document } >
57
+ < StyleSheetManager target = { document } >
58
+ < ThemeProvider theme = { ( theme : IGardenTheme ) => ( { ...theme , document } ) } >
59
+ < Grid >
60
+ < Grid . Row justifyContent = "center" style = { { height : 800 } } >
61
+ < Grid . Col alignSelf = "center" textAlign = "center" >
62
+ < div style = { { display : 'inline-block' , position : 'relative' , width : 200 } } >
63
+ < Menu
64
+ { ...args }
65
+ button = {
66
+ button === 'string'
67
+ ? label
68
+ : /* eslint-disable-next-line react/no-unstable-nested-components */
69
+ props => (
70
+ < IconButton { ...props } aria-label = { label } >
71
+ < LeafIcon />
72
+ </ IconButton >
73
+ )
74
+ }
75
+ >
76
+ { items . map ( item => {
77
+ if ( 'items' in item ) {
78
+ return (
79
+ < ItemGroup
80
+ legend = { item . legend }
81
+ aria-label = { item [ 'aria-label' ] }
82
+ key = { item . legend || item [ 'aria-label' ] }
83
+ type = { item . type }
84
+ icon = { item . icon ? < CartIcon /> : undefined }
85
+ >
86
+ { item . items . map ( groupItem => (
87
+ < MenuItem key = { groupItem . value } { ...groupItem } />
88
+ ) ) }
89
+ </ ItemGroup >
90
+ ) ;
91
+ }
92
+
93
+ if ( 'isSeparator' in item ) {
94
+ return < Separator key = { item . value } /> ;
95
+ }
96
+
97
+ return < MenuItem key = { item . value } { ...item } /> ;
98
+ } ) }
99
+ </ Menu >
100
+ </ div >
101
+ </ Grid . Col >
102
+ </ Grid . Row >
103
+ </ Grid >
104
+ </ ThemeProvider >
105
+ </ StyleSheetManager >
106
+ </ Portal >
107
+ </ div >
108
+ ) ;
109
+ } ;
0 commit comments