Skip to content

Commit 5e39f90

Browse files
committed
feat(chrome): adds sub-component mapping
1 parent 0061baa commit 5e39f90

File tree

7 files changed

+144
-93
lines changed

7 files changed

+144
-93
lines changed

packages/chrome/demo/stories/ChromeStory.tsx

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,16 @@ import { DEFAULT_THEME } from '@zendeskgarden/react-theming';
3232
import {
3333
Body,
3434
Chrome,
35-
CollapsibleSubNavItem,
3635
Content,
3736
Footer,
38-
FooterItem,
3937
Header,
40-
HeaderItem,
41-
HeaderItemIcon,
42-
HeaderItemText,
43-
HeaderItemWrapper,
4438
IChromeProps,
4539
INavItemProps,
4640
Main,
4741
Nav,
48-
NavItem,
49-
NavItemIcon,
50-
NavItemText,
5142
Sidebar,
5243
SkipNav,
53-
SubNav,
54-
SubNavItem,
55-
SubNavItemText
44+
SubNav
5645
} from '@zendeskgarden/react-chrome';
5746
import { Button } from '@zendeskgarden/react-buttons';
5847
import { IFooterItem, IHeaderItem, INavItem, ISubNavItem } from './types';
@@ -150,13 +139,13 @@ export const ChromeStory: Story<IArgs> = ({
150139
{hasNav && (
151140
<Nav isExpanded={isExpanded} aria-label="Nav">
152141
{hasLogo && (
153-
<NavItem hasLogo product={product}>
154-
<NavItemIcon>{product ? PRODUCT_ICONS[product] : <ProductIcon />}</NavItemIcon>
155-
<NavItemText>Nav Logo</NavItemText>
156-
</NavItem>
142+
<Nav.Item hasLogo product={product}>
143+
<Nav.ItemIcon>{product ? PRODUCT_ICONS[product] : <ProductIcon />}</Nav.ItemIcon>
144+
<Nav.ItemText>Nav Logo</Nav.ItemText>
145+
</Nav.Item>
157146
)}
158147
{navItems.map((item, index) => (
159-
<NavItem
148+
<Nav.Item
160149
key={index}
161150
isCurrent={currentNav === index}
162151
onClick={() => {
@@ -165,43 +154,43 @@ export const ChromeStory: Story<IArgs> = ({
165154
onNavClick({ hasSubNav: item.hasSubNav, hasSidebar: item.hasSidebar });
166155
}}
167156
>
168-
<NavItemIcon>{NAV_ICONS[index] || <NavIcon />}</NavItemIcon>
169-
<NavItemText isWrapped={isWrapped}>{item.text}</NavItemText>
170-
</NavItem>
157+
<Nav.ItemIcon>{NAV_ICONS[index] || <NavIcon />}</Nav.ItemIcon>
158+
<Nav.ItemText isWrapped={isWrapped}>{item.text}</Nav.ItemText>
159+
</Nav.Item>
171160
))}
172161
{hasBrandmark && (
173-
<NavItem hasBrandmark>
174-
<NavItemIcon>
162+
<Nav.Item hasBrandmark>
163+
<Nav.ItemIcon>
175164
<BrandmarkIcon />
176-
</NavItemIcon>
177-
<NavItemText>Brandmark</NavItemText>
178-
</NavItem>
165+
</Nav.ItemIcon>
166+
<Nav.ItemText>Brandmark</Nav.ItemText>
167+
</Nav.Item>
179168
)}
180169
</Nav>
181170
)}
182171
{hasSubNav && (
183172
<SubNav style={{ maxWidth: subNavMaxWidth }}>
184173
{subNavItems.map((item, index) =>
185174
item.items ? (
186-
<CollapsibleSubNavItem key={index} header={item.text}>
175+
<SubNav.CollapsibleItem key={index} header={item.text}>
187176
{item.items.map((subItem, subIndex) => (
188-
<SubNavItem
177+
<SubNav.Item
189178
key={subIndex}
190179
isCurrent={currentSubNav === parseFloat(`${index}.${subIndex}`)}
191180
onClick={() => setCurrentSubNav(parseFloat(`${index}.${subIndex}`))}
192181
>
193-
<SubNavItemText isWrapped={isWrapped}>{subItem}</SubNavItemText>
194-
</SubNavItem>
182+
<SubNav.ItemText isWrapped={isWrapped}>{subItem}</SubNav.ItemText>
183+
</SubNav.Item>
195184
))}
196-
</CollapsibleSubNavItem>
185+
</SubNav.CollapsibleItem>
197186
) : (
198-
<SubNavItem
187+
<SubNav.Item
199188
key={index}
200189
isCurrent={currentSubNav === index}
201190
onClick={() => setCurrentSubNav(index)}
202191
>
203-
<SubNavItemText isWrapped={isWrapped}>{item.text}</SubNavItemText>
204-
</SubNavItem>
192+
<SubNav.ItemText isWrapped={isWrapped}>{item.text}</SubNav.ItemText>
193+
</SubNav.Item>
205194
)
206195
)}
207196
</SubNav>
@@ -210,41 +199,41 @@ export const ChromeStory: Story<IArgs> = ({
210199
{hasHeader && (
211200
<Header isStandalone={!(hasNav || hasSubNav)}>
212201
{hasLogo && (
213-
<HeaderItem hasLogo product={product}>
214-
<HeaderItemIcon>
202+
<Header.Item hasLogo product={product}>
203+
<Header.ItemIcon>
215204
<SupportIcon />
216-
</HeaderItemIcon>
217-
<HeaderItemText>Header Logo</HeaderItemText>
218-
</HeaderItem>
205+
</Header.ItemIcon>
206+
<Header.ItemText>Header Logo</Header.ItemText>
207+
</Header.Item>
219208
)}
220209
{headerItems.map((item, index) =>
221210
item.isWrapper ? (
222-
<HeaderItemWrapper
211+
<Header.ItemWrapper
223212
key={index}
224213
maxX={item.maxX}
225214
maxY={item.maxY}
226215
isRound={item.isRound}
227216
>
228217
{item.hasIcon && (
229-
<HeaderItemIcon>
218+
<Header.ItemIcon>
230219
{HEADER_ICONS[HEADER_ICONS.length - headerItems.length + index] || (
231220
<HeaderIcon />
232221
)}
233-
</HeaderItemIcon>
222+
</Header.ItemIcon>
234223
)}
235-
<HeaderItemText isClipped={item.isClipped}>{item.text}</HeaderItemText>
236-
</HeaderItemWrapper>
224+
<Header.ItemText isClipped={item.isClipped}>{item.text}</Header.ItemText>
225+
</Header.ItemWrapper>
237226
) : (
238-
<HeaderItem key={index} maxX={item.maxX} maxY={item.maxY} isRound={item.isRound}>
227+
<Header.Item key={index} maxX={item.maxX} maxY={item.maxY} isRound={item.isRound}>
239228
{item.hasIcon && (
240-
<HeaderItemIcon>
229+
<Header.ItemIcon>
241230
{HEADER_ICONS[HEADER_ICONS.length - headerItems.length + index] || (
242231
<HeaderIcon />
243232
)}
244-
</HeaderItemIcon>
233+
</Header.ItemIcon>
245234
)}
246-
<HeaderItemText isClipped={item.isClipped}>{item.text}</HeaderItemText>
247-
</HeaderItem>
235+
<Header.ItemText isClipped={item.isClipped}>{item.text}</Header.ItemText>
236+
</Header.Item>
248237
)
249238
)}
250239
</Header>
@@ -271,11 +260,11 @@ export const ChromeStory: Story<IArgs> = ({
271260
<Footer>
272261
{footerItems &&
273262
footerItems.map(({ text, type }, index) => (
274-
<FooterItem key={index}>
263+
<Footer.Item key={index}>
275264
<Button isBasic={type === 'basic'} isPrimary={type === 'primary'}>
276265
{text}
277266
</Button>
278-
</FooterItem>
267+
</Footer.Item>
279268
))}
280269
</Footer>
281270
)}

packages/chrome/demo/stories/CollapsibleSubNavItemStory.tsx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,33 @@
66
*/
77

88
import React, { useState } from 'react';
9-
import { Story } from '@storybook/react';
9+
import { StoryFn } from '@storybook/react';
1010
import { Col, Grid, Row } from '@zendeskgarden/react-grid';
11-
import {
12-
CollapsibleSubNavItem,
13-
ICollapsibleSubNavItemProps,
14-
SubNavItem
15-
} from '@zendeskgarden/react-chrome';
11+
import { SubNav, ICollapsibleSubNavItemProps } from '@zendeskgarden/react-chrome';
1612
import { COLLAPSIBLE_SUB_NAV_ITEM } from './types';
1713

1814
interface IArgs extends ICollapsibleSubNavItemProps {
1915
items: COLLAPSIBLE_SUB_NAV_ITEM[];
2016
}
2117

22-
export const CollapsibleSubNavItemStory: Story<IArgs> = ({ items, ...args }) => {
18+
export const CollapsibleSubNavItemStory: StoryFn<IArgs> = ({ items, ...args }) => {
2319
const [current, setCurrent] = useState<number | undefined>();
2420

2521
return (
2622
<Grid>
2723
<Row>
2824
<Col sm={6}>
29-
<CollapsibleSubNavItem {...args}>
25+
<SubNav.CollapsibleItem {...args}>
3026
{items.map((item, index) => (
31-
<SubNavItem
27+
<SubNav.Item
3228
key={index}
3329
isCurrent={current === index}
3430
onClick={() => setCurrent(index)}
3531
>
3632
{item}
37-
</SubNavItem>
33+
</SubNav.Item>
3834
))}
39-
</CollapsibleSubNavItem>
35+
</SubNav.CollapsibleItem>
4036
</Col>
4137
</Row>
4238
</Grid>

packages/chrome/src/elements/footer/Footer.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,22 @@
77

88
import React, { HTMLAttributes } from 'react';
99
import { StyledFooter } from '../../styled';
10+
import { FooterItem } from './FooterItem';
1011

1112
/**
1213
* @extends HTMLAttributes<HTMLElement>
1314
*/
14-
export const Footer = React.forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>((props, ref) => (
15-
<StyledFooter ref={ref} {...props} />
16-
));
15+
export const FooterComponent = React.forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>(
16+
(props, ref) => <StyledFooter ref={ref} {...props} />
17+
);
1718

18-
Footer.displayName = 'Footer';
19+
FooterComponent.displayName = 'Footer';
20+
21+
/**
22+
* @extends HTMLAttributes<HTMLElement>
23+
*/
24+
export const Footer = FooterComponent as typeof FooterComponent & {
25+
Item: typeof FooterItem;
26+
};
27+
28+
Footer.Item = FooterItem;

packages/chrome/src/elements/header/Header.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,32 @@ import React from 'react';
99
import PropTypes from 'prop-types';
1010
import { IHeaderProps } from '../../types';
1111
import { StyledHeader } from '../../styled';
12+
import { HeaderItem } from './HeaderItem';
13+
import { HeaderItemIcon } from './HeaderItemIcon';
14+
import { HeaderItemText } from './HeaderItemText';
15+
import { HeaderItemWrapper } from './HeaderItemWrapper';
1216

13-
/**
14-
* @extends HTMLAttributes<HTMLElement>
15-
*/
16-
export const Header = React.forwardRef<HTMLElement, IHeaderProps>((props, ref) => (
17+
export const HeaderComponent = React.forwardRef<HTMLElement, IHeaderProps>((props, ref) => (
1718
<StyledHeader ref={ref} {...props} />
1819
));
1920

20-
Header.displayName = 'Header';
21+
HeaderComponent.displayName = 'Header';
2122

22-
Header.propTypes = {
23+
HeaderComponent.propTypes = {
2324
isStandalone: PropTypes.bool
2425
};
26+
27+
/**
28+
* @extends HTMLAttributes<HTMLElement>
29+
*/
30+
export const Header = HeaderComponent as typeof HeaderComponent & {
31+
Item: typeof HeaderItem;
32+
ItemIcon: typeof HeaderItemIcon;
33+
ItemText: typeof HeaderItemText;
34+
ItemWrapper: typeof HeaderItemWrapper;
35+
};
36+
37+
Header.Item = HeaderItem;
38+
Header.ItemIcon = HeaderItemIcon;
39+
Header.ItemText = HeaderItemText;
40+
Header.ItemWrapper = HeaderItemWrapper;

packages/chrome/src/elements/nav/Nav.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import { INavProps } from '../../types';
1111
import { useChromeContext } from '../../utils/useChromeContext';
1212
import { NavContext } from '../../utils/useNavContext';
1313
import { StyledNav } from '../../styled';
14+
import { NavItem } from './NavItem';
15+
import { NavItemIcon } from './NavItemIcon';
16+
import { NavItemText } from './NavItemText';
1417

15-
/**
16-
* @extends HTMLAttributes<HTMLElement>
17-
*/
18-
export const Nav = React.forwardRef<HTMLElement, INavProps>((props, ref) => {
18+
export const NavComponent = React.forwardRef<HTMLElement, INavProps>((props, ref) => {
1919
const { hue, isLight, isDark } = useChromeContext();
2020
const navContextValue = useMemo(() => ({ isExpanded: !!props.isExpanded }), [props.isExpanded]);
2121

@@ -26,8 +26,21 @@ export const Nav = React.forwardRef<HTMLElement, INavProps>((props, ref) => {
2626
);
2727
});
2828

29-
Nav.displayName = 'Nav';
29+
NavComponent.displayName = 'Nav';
3030

31-
Nav.propTypes = {
31+
NavComponent.propTypes = {
3232
isExpanded: PropTypes.bool
3333
};
34+
35+
/**
36+
* @extends HTMLAttributes<HTMLElement>
37+
*/
38+
export const Nav = NavComponent as typeof NavComponent & {
39+
Item: typeof NavItem;
40+
ItemIcon: typeof NavItemIcon;
41+
ItemText: typeof NavItemText;
42+
};
43+
44+
Nav.Item = NavItem;
45+
Nav.ItemIcon = NavItemIcon;
46+
Nav.ItemText = NavItemText;

packages/chrome/src/elements/subnav/SubNav.tsx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,29 @@
88
import React, { HTMLAttributes } from 'react';
99
import { StyledSubNav } from '../../styled';
1010
import { useChromeContext } from '../../utils/useChromeContext';
11+
import { SubNavItem } from './SubNavItem';
12+
import { SubNavItemText } from './SubNavItemText';
13+
import { CollapsibleSubNavItem } from './CollapsibleSubNavItem';
14+
15+
export const SubNavComponent = React.forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>(
16+
(props, ref) => {
17+
const { hue, isLight, isDark } = useChromeContext();
18+
19+
return <StyledSubNav ref={ref} hue={hue} isLight={isLight} isDark={isDark} {...props} />;
20+
}
21+
);
22+
23+
SubNavComponent.displayName = 'SubNav';
1124

1225
/**
1326
* @extends HTMLAttributes<HTMLElement>
1427
*/
15-
export const SubNav = React.forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>((props, ref) => {
16-
const { hue, isLight, isDark } = useChromeContext();
17-
18-
return <StyledSubNav ref={ref} hue={hue} isLight={isLight} isDark={isDark} {...props} />;
19-
});
28+
export const SubNav = SubNavComponent as typeof SubNavComponent & {
29+
Item: typeof SubNavItem;
30+
ItemText: typeof SubNavItemText;
31+
CollapsibleItem: typeof CollapsibleSubNavItem;
32+
};
2033

21-
SubNav.displayName = 'SubNav';
34+
SubNav.Item = SubNavItem;
35+
SubNav.ItemText = SubNavItemText;
36+
SubNav.CollapsibleItem = CollapsibleSubNavItem;

0 commit comments

Comments
 (0)