diff --git a/docs/migration.md b/docs/migration.md index 7bbed356f40..448a6f0f992 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -44,6 +44,20 @@ consider additional positioning prop support on a case-by-case basis. #### @zendeskgarden/react-chrome - Removed `PRODUCT` type export. Use `IHeaderItemProps['product']` instead. +- Renamed `ICollapsibleSubNavItemProps` type export to `ISubNavCollapsibleItemProps`. +- Subcomponent exports have been deprecated and will be removed in a future major version. Update + to subcomponent properties: + - `FooterItem` -> `Footer.Item` + - `HeaderItem` -> `Header.Item` + - `HeaderItemIcon` -> `Header.ItemIcon` + - `HeaderItemText` -> `Header.ItemText` + - `HeaderItemWrapper` -> `Header.ItemWrapper` + - `NavItem` -> `Nav.Item` + - `NavItemIcon` -> `Nav.ItemIcon` + - `NavItemText` -> `Nav.ItemText` + - `CollapsibleSubNavItem` -> `SubNav.CollapsibleItem` + - `SubNavItem` -> `SubNav.Item` + - `SubNavItemText` -> `SubNav.ItemText` #### @zendeskgarden/react-colorpickers diff --git a/packages/chrome/README.md b/packages/chrome/README.md index 974f1480668..bb297d81503 100644 --- a/packages/chrome/README.md +++ b/packages/chrome/README.md @@ -15,41 +15,37 @@ npm install react react-dom styled-components @zendeskgarden/react-theming ```jsx import { ThemeProvider } from '@zendeskgarden/react-theming'; -import { Chrome, Nav, NavItem, ... } from '@zendeskgarden/react-chrome'; +import { Chrome, Nav, SubNav, Body, Header, Content, Main } from '@zendeskgarden/react-chrome'; import ConnectIcon from '@zendeskgarden/icons/src/26/relationshape-connect.svg'; - - Subnav 1 - + + Subnav 1 + ... -
- ... -
+
...
-
- Lorem ipsum... -
+
Lorem ipsum...
-
+; ``` diff --git a/packages/chrome/demo/chrome.stories.mdx b/packages/chrome/demo/chrome.stories.mdx index 9e98b769a23..cd52bb14a27 100644 --- a/packages/chrome/demo/chrome.stories.mdx +++ b/packages/chrome/demo/chrome.stories.mdx @@ -1,28 +1,17 @@ import { Meta, ArgsTable, Canvas, Story, Markdown } from '@storybook/addon-docs'; import { useArgs } from '@storybook/client-api'; import { - Chrome, - CollapsibleSubNavItem, Body, + Chrome, Content, Footer, - FooterItem, Header, - HeaderItem, - HeaderItemIcon, - HeaderItemText, - HeaderItemWrapper, Main, Nav, - NavItem, - NavItemIcon, - NavItemText, Sheet, Sidebar, SkipNav, SubNav, - SubNavItem, - SubNavItemText, PRODUCTS } from '@zendeskgarden/react-chrome'; import { ChromeStory } from './stories/ChromeStory'; @@ -44,27 +33,27 @@ import README from '../README.md'; title="Packages/Chrome/Chrome" component={Chrome} subcomponents={{ - CollapsibleSubNavItem, Body, Content, Footer, - FooterItem, + 'Footer.Item': Footer.Item, Header, - HeaderItem, - HeaderItemIcon, - HeaderItemText, - HeaderItemWrapper, + 'Item.HeaderItem': Header.Item, + 'Item.HeaderItemIcon': Header.ItemIcon, + 'Item.HeaderItemText': Header.ItemText, + 'Item.HeaderItemWrapper': Header.ItemWrapper, Main, Nav, - NavItem, - NavItemIcon, - NavItemText, + 'Nav.Item': Nav.Item, + 'Nav.ItemIcon': Nav.ItemIcon, + 'Nav.ItemText': Nav.ItemText, Sheet, Sidebar, SkipNav, SubNav, - SubNavItem, - SubNavItemText + 'SubNav.CollapsibleItem': SubNav.CollapsibleItem, + 'SubNav.Item': SubNav.Item, + 'SubNav.ItemText': SubNav.ItemText }} /> @@ -108,17 +97,17 @@ import README from '../README.md'; isExpanded: { name: 'Nav isExpanded', table: { category: 'Story' } }, isWrapped: { name: 'Nav/SubNav isWrapped', table: { category: 'Story' } }, hasNav: { name: 'Nav', table: { category: 'Story' } }, - navItems: { name: 'NavItem[]', table: { category: 'Story' } }, + navItems: { name: 'Nav.Item[]', table: { category: 'Story' } }, hasLogo: { name: 'Nav hasLogo', table: { category: 'Story' } }, hasBrandmark: { name: 'Nav hasBrandmark', table: { category: 'Story' } }, hasSubNav: { name: 'SubNav', table: { category: 'Story' } }, - subNavItems: { name: 'SubNavItem[]', table: { category: 'Story' } }, + subNavItems: { name: 'SubNav.Item[]', table: { category: 'Story' } }, subNavMaxWidth: { name: 'SubNav max-width', control: 'number', table: { category: 'Story' } }, hasHeader: { name: 'Header', table: { category: 'Story' } }, - headerItems: { name: 'HeaderItem[]', table: { category: 'Story' } }, + headerItems: { name: 'Header.Item[]', table: { category: 'Story' } }, hasSidebar: { name: 'Sidebar', table: { category: 'Story' } }, hasFooter: { name: 'Footer', table: { category: 'Story' } }, - footerItems: { name: 'FooterItem[]', table: { category: 'Story' } }, + footerItems: { name: 'Footer.Item[]', table: { category: 'Story' } }, product: { name: 'Nav product', control: { type: 'select', options: PRODUCTS }, diff --git a/packages/chrome/demo/stories/ChromeStory.tsx b/packages/chrome/demo/stories/ChromeStory.tsx index 38c5178b1ae..17d9af6be0e 100644 --- a/packages/chrome/demo/stories/ChromeStory.tsx +++ b/packages/chrome/demo/stories/ChromeStory.tsx @@ -32,27 +32,16 @@ import { DEFAULT_THEME } from '@zendeskgarden/react-theming'; import { Body, Chrome, - CollapsibleSubNavItem, Content, Footer, - FooterItem, Header, - HeaderItem, - HeaderItemIcon, - HeaderItemText, - HeaderItemWrapper, IChromeProps, INavItemProps, Main, Nav, - NavItem, - NavItemIcon, - NavItemText, Sidebar, SkipNav, - SubNav, - SubNavItem, - SubNavItemText + SubNav } from '@zendeskgarden/react-chrome'; import { Button } from '@zendeskgarden/react-buttons'; import { IFooterItem, IHeaderItem, INavItem, ISubNavItem } from './types'; @@ -150,13 +139,13 @@ export const ChromeStory: Story = ({ {hasNav && ( )} @@ -183,25 +172,25 @@ export const ChromeStory: Story = ({ {subNavItems.map((item, index) => item.items ? ( - + {item.items.map((subItem, subIndex) => ( - setCurrentSubNav(parseFloat(`${index}.${subIndex}`))} > - {subItem} - + {subItem} + ))} - + ) : ( - setCurrentSubNav(index)} > - {item.text} - + {item.text} + ) )} @@ -210,41 +199,41 @@ export const ChromeStory: Story = ({ {hasHeader && (
{hasLogo && ( - - + + - - Header Logo - + + Header Logo + )} {headerItems.map((item, index) => item.isWrapper ? ( - {item.hasIcon && ( - + {HEADER_ICONS[HEADER_ICONS.length - headerItems.length + index] || ( )} - + )} - {item.text} - + {item.text} + ) : ( - + {item.hasIcon && ( - + {HEADER_ICONS[HEADER_ICONS.length - headerItems.length + index] || ( )} - + )} - {item.text} - + {item.text} + ) )}
@@ -271,11 +260,11 @@ export const ChromeStory: Story = ({
{footerItems && footerItems.map(({ text, type }, index) => ( - + - + ))}
)} diff --git a/packages/chrome/demo/stories/CollapsibleSubNavItemStory.tsx b/packages/chrome/demo/stories/SubNavCollapsibleItem.tsx similarity index 68% rename from packages/chrome/demo/stories/CollapsibleSubNavItemStory.tsx rename to packages/chrome/demo/stories/SubNavCollapsibleItem.tsx index 1dd0fa654af..7c3af150362 100644 --- a/packages/chrome/demo/stories/CollapsibleSubNavItemStory.tsx +++ b/packages/chrome/demo/stories/SubNavCollapsibleItem.tsx @@ -6,37 +6,33 @@ */ import React, { useState } from 'react'; -import { Story } from '@storybook/react'; +import { StoryFn } from '@storybook/react'; import { Col, Grid, Row } from '@zendeskgarden/react-grid'; -import { - CollapsibleSubNavItem, - ICollapsibleSubNavItemProps, - SubNavItem -} from '@zendeskgarden/react-chrome'; +import { SubNav, ICollapsibleSubNavItemProps } from '@zendeskgarden/react-chrome'; import { COLLAPSIBLE_SUB_NAV_ITEM } from './types'; interface IArgs extends ICollapsibleSubNavItemProps { items: COLLAPSIBLE_SUB_NAV_ITEM[]; } -export const CollapsibleSubNavItemStory: Story = ({ items, ...args }) => { +export const SubNavCollapsibleItem: StoryFn = ({ items, ...args }) => { const [current, setCurrent] = useState(); return ( - + {items.map((item, index) => ( - setCurrent(index)} > {item} - + ))} - + diff --git a/packages/chrome/demo/collapsibleSubNavItem.stories.mdx b/packages/chrome/demo/subNavCollapsibleItem.stories.mdx similarity index 73% rename from packages/chrome/demo/collapsibleSubNavItem.stories.mdx rename to packages/chrome/demo/subNavCollapsibleItem.stories.mdx index afa5a507703..b82c61ad3a0 100644 --- a/packages/chrome/demo/collapsibleSubNavItem.stories.mdx +++ b/packages/chrome/demo/subNavCollapsibleItem.stories.mdx @@ -1,11 +1,11 @@ import { Meta, ArgsTable, Canvas, Story, Markdown } from '@storybook/addon-docs'; import { useArgs } from '@storybook/client-api'; import { CollapsibleSubNavItem } from '@zendeskgarden/react-chrome'; -import { CollapsibleSubNavItemStory } from './stories/CollapsibleSubNavItemStory'; +import { SubNavCollapsibleItem } from './stories/SubNavCollapsibleItem'; import { COLLAPSIBLE_SUB_NAV_ITEMS as ITEMS } from './stories/data'; import README from '../README.md'; - + # API @@ -21,7 +21,7 @@ import README from '../README.md'; args={{ header: 'Header', items: ITEMS }} argTypes={{ items: { name: 'children' }, isExpanded: { control: false } }} > - {({ onChange, ...args }) => } + {({ onChange, ...args }) => } @@ -36,7 +36,7 @@ import README from '../README.md'; {args => { const updateArgs = useArgs()[1]; const handleChange = () => updateArgs({ isExpanded: !args.isExpanded }); - return ; + return ; }} diff --git a/packages/chrome/src/elements/footer/Footer.tsx b/packages/chrome/src/elements/footer/Footer.tsx index 1bd456e0752..87c13745748 100644 --- a/packages/chrome/src/elements/footer/Footer.tsx +++ b/packages/chrome/src/elements/footer/Footer.tsx @@ -7,12 +7,22 @@ import React, { HTMLAttributes } from 'react'; import { StyledFooter } from '../../styled'; +import { FooterItem } from './FooterItem'; /** * @extends HTMLAttributes */ -export const Footer = React.forwardRef>((props, ref) => ( - -)); +export const FooterComponent = React.forwardRef>( + (props, ref) => +); -Footer.displayName = 'Footer'; +FooterComponent.displayName = 'Footer'; + +/** + * @extends HTMLAttributes + */ +export const Footer = FooterComponent as typeof FooterComponent & { + Item: typeof FooterItem; +}; + +Footer.Item = FooterItem; diff --git a/packages/chrome/src/elements/header/Header.tsx b/packages/chrome/src/elements/header/Header.tsx index 7478a42b3f9..1c01ed5e0cf 100644 --- a/packages/chrome/src/elements/header/Header.tsx +++ b/packages/chrome/src/elements/header/Header.tsx @@ -9,16 +9,32 @@ import React from 'react'; import PropTypes from 'prop-types'; import { IHeaderProps } from '../../types'; import { StyledHeader } from '../../styled'; +import { HeaderItem } from './HeaderItem'; +import { HeaderItemIcon } from './HeaderItemIcon'; +import { HeaderItemText } from './HeaderItemText'; +import { HeaderItemWrapper } from './HeaderItemWrapper'; -/** - * @extends HTMLAttributes - */ -export const Header = React.forwardRef((props, ref) => ( +export const HeaderComponent = React.forwardRef((props, ref) => ( )); -Header.displayName = 'Header'; +HeaderComponent.displayName = 'Header'; -Header.propTypes = { +HeaderComponent.propTypes = { isStandalone: PropTypes.bool }; + +/** + * @extends HTMLAttributes + */ +export const Header = HeaderComponent as typeof HeaderComponent & { + Item: typeof HeaderItem; + ItemIcon: typeof HeaderItemIcon; + ItemText: typeof HeaderItemText; + ItemWrapper: typeof HeaderItemWrapper; +}; + +Header.Item = HeaderItem; +Header.ItemIcon = HeaderItemIcon; +Header.ItemText = HeaderItemText; +Header.ItemWrapper = HeaderItemWrapper; diff --git a/packages/chrome/src/elements/nav/Nav.tsx b/packages/chrome/src/elements/nav/Nav.tsx index a4c58113d6d..b3e5bc1e054 100644 --- a/packages/chrome/src/elements/nav/Nav.tsx +++ b/packages/chrome/src/elements/nav/Nav.tsx @@ -11,11 +11,11 @@ import { INavProps } from '../../types'; import { useChromeContext } from '../../utils/useChromeContext'; import { NavContext } from '../../utils/useNavContext'; import { StyledNav } from '../../styled'; +import { NavItem } from './NavItem'; +import { NavItemIcon } from './NavItemIcon'; +import { NavItemText } from './NavItemText'; -/** - * @extends HTMLAttributes - */ -export const Nav = React.forwardRef((props, ref) => { +export const NavComponent = React.forwardRef((props, ref) => { const { hue, isLight, isDark } = useChromeContext(); const navContextValue = useMemo(() => ({ isExpanded: !!props.isExpanded }), [props.isExpanded]); @@ -26,8 +26,21 @@ export const Nav = React.forwardRef((props, ref) => { ); }); -Nav.displayName = 'Nav'; +NavComponent.displayName = 'Nav'; -Nav.propTypes = { +NavComponent.propTypes = { isExpanded: PropTypes.bool }; + +/** + * @extends HTMLAttributes + */ +export const Nav = NavComponent as typeof NavComponent & { + Item: typeof NavItem; + ItemIcon: typeof NavItemIcon; + ItemText: typeof NavItemText; +}; + +Nav.Item = NavItem; +Nav.ItemIcon = NavItemIcon; +Nav.ItemText = NavItemText; diff --git a/packages/chrome/src/elements/subnav/SubNav.tsx b/packages/chrome/src/elements/subnav/SubNav.tsx index fcc2280c6a8..f0b3ff0c36d 100644 --- a/packages/chrome/src/elements/subnav/SubNav.tsx +++ b/packages/chrome/src/elements/subnav/SubNav.tsx @@ -8,14 +8,29 @@ import React, { HTMLAttributes } from 'react'; import { StyledSubNav } from '../../styled'; import { useChromeContext } from '../../utils/useChromeContext'; +import { SubNavItem } from './SubNavItem'; +import { SubNavItemText } from './SubNavItemText'; +import { CollapsibleSubNavItem } from './CollapsibleSubNavItem'; + +export const SubNavComponent = React.forwardRef>( + (props, ref) => { + const { hue, isLight, isDark } = useChromeContext(); + + return ; + } +); + +SubNavComponent.displayName = 'SubNav'; /** * @extends HTMLAttributes */ -export const SubNav = React.forwardRef>((props, ref) => { - const { hue, isLight, isDark } = useChromeContext(); - - return ; -}); +export const SubNav = SubNavComponent as typeof SubNavComponent & { + Item: typeof SubNavItem; + ItemText: typeof SubNavItemText; + CollapsibleItem: typeof CollapsibleSubNavItem; +}; -SubNav.displayName = 'SubNav'; +SubNav.Item = SubNavItem; +SubNav.ItemText = SubNavItemText; +SubNav.CollapsibleItem = CollapsibleSubNavItem; diff --git a/packages/chrome/src/index.ts b/packages/chrome/src/index.ts index 229ff7a0e87..23fb88e88f6 100644 --- a/packages/chrome/src/index.ts +++ b/packages/chrome/src/index.ts @@ -5,27 +5,39 @@ * found at http://www.apache.org/licenses/LICENSE-2.0. */ -export { Chrome } from './elements/Chrome'; -export { SkipNav } from './elements/SkipNav'; -export { Body } from './elements/body/Body'; -export { Content } from './elements/body/Content'; -export { Main } from './elements/body/Main'; -export { Sidebar } from './elements/body/Sidebar'; -export { Header } from './elements/header/Header'; +/** @deprecated use `Header.Item` instead */ export { HeaderItem } from './elements/header/HeaderItem'; +/** @deprecated use `Header.ItemIcon` instead */ export { HeaderItemIcon } from './elements/header/HeaderItemIcon'; +/** @deprecated use `Header.ItemText` instead */ export { HeaderItemText } from './elements/header/HeaderItemText'; +/** @deprecated use `Header.ItemWrapper` instead */ export { HeaderItemWrapper } from './elements/header/HeaderItemWrapper'; -export { Footer } from './elements/footer/Footer'; +/** @deprecated use `Footer.Item` instead */ export { FooterItem } from './elements/footer/FooterItem'; -export { Nav } from './elements/nav/Nav'; +/** @deprecated use `Nav.Item` instead */ export { NavItem } from './elements/nav/NavItem'; +/** @deprecated use `Nav.ItemIcon` instead */ export { NavItemIcon } from './elements/nav/NavItemIcon'; +/** @deprecated use `Nav.ItemText` instead */ export { NavItemText } from './elements/nav/NavItemText'; -export { SubNav } from './elements/subnav/SubNav'; +/** @deprecated use `SubNav.Item` instead */ export { SubNavItem } from './elements/subnav/SubNavItem'; +/** @deprecated use `SubNav.ItemText` instead */ export { SubNavItemText } from './elements/subnav/SubNavItemText'; +/** @deprecated use `SubNav.CollapsibleItem` instead */ export { CollapsibleSubNavItem } from './elements/subnav/CollapsibleSubNavItem'; + +export { Chrome } from './elements/Chrome'; +export { SkipNav } from './elements/SkipNav'; +export { Body } from './elements/body/Body'; +export { Content } from './elements/body/Content'; +export { Main } from './elements/body/Main'; +export { Sidebar } from './elements/body/Sidebar'; +export { Header } from './elements/header/Header'; +export { Footer } from './elements/footer/Footer'; +export { Nav } from './elements/nav/Nav'; +export { SubNav } from './elements/subnav/SubNav'; export { Sheet } from './elements/sheet/Sheet'; export {