Skip to content

Commit f1ee833

Browse files
authored
feat(chrome): new light/dark mode colors (#1849)
1 parent b947599 commit f1ee833

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+748
-649
lines changed

packages/chrome/demo/chrome.stories.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ import README from '../README.md';
9494
footerItems: { name: 'Footer.Item[]', table: { category: 'Story' } },
9595
product: {
9696
name: 'Nav product',
97-
control: { type: 'select', options: PRODUCTS },
97+
control: { type: 'select' },
98+
options: PRODUCTS,
9899
table: { category: 'Story' }
99100
},
100101
isSheetOpen: { name: 'isOpen', table: { category: 'Sheet' } },

packages/chrome/demo/stories/ChromeStory.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export const ChromeStory: Story<IArgs> = ({
156156
{hasLogo && (
157157
<Header.Item hasLogo product={product}>
158158
<Header.ItemIcon>
159-
<SupportIcon />
159+
{product ? PRODUCT_ICONS[product] : <ProductIcon />}
160160
</Header.ItemIcon>
161161
<Header.ItemText>Header Logo</Header.ItemText>
162162
</Header.Item>

packages/chrome/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"sideEffects": false,
2222
"types": "dist/typings/index.d.ts",
2323
"dependencies": {
24+
"@zendeskgarden/react-buttons": "^9.0.0-next.15",
2425
"dom-helpers": "^5.2.1",
2526
"polished": "^4.3.1",
2627
"prop-types": "^15.5.7",

packages/chrome/src/elements/Chrome.spec.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,12 @@ describe('Chrome', () => {
3737
const { container } = render(<Chrome hue={PALETTE.green[100]} />);
3838

3939
expect(container.firstChild).toHaveAttribute('data-test-light', 'true');
40-
expect(container.firstChild).toHaveAttribute('data-test-dark', 'false');
4140
});
4241

4342
it('applies dark styling if hue is above luminance threshold', () => {
4443
const { container } = render(<Chrome hue={PALETTE.green[800]} />);
4544

4645
expect(container.firstChild).toHaveAttribute('data-test-light', 'false');
47-
expect(container.firstChild).toHaveAttribute('data-test-dark', 'true');
4846
});
4947
});
5048
});

packages/chrome/src/elements/Chrome.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import React, { useMemo, useEffect, useContext } from 'react';
99
import PropTypes from 'prop-types';
1010
import { ThemeContext } from 'styled-components';
1111
import { readableColor } from 'polished';
12-
import { getColorV8, useDocument } from '@zendeskgarden/react-theming';
12+
import { DEFAULT_THEME, getColor, useDocument } from '@zendeskgarden/react-theming';
1313
import { IChromeProps } from '../types';
1414
import { ChromeContext } from '../utils/useChromeContext';
1515
import { StyledChrome } from '../styled';
@@ -19,10 +19,10 @@ import { StyledChrome } from '../styled';
1919
*/
2020
export const Chrome = React.forwardRef<HTMLDivElement, IChromeProps>(
2121
({ hue, isFluid, ...props }, ref) => {
22-
const theme = useContext(ThemeContext);
22+
const theme = useContext(ThemeContext) || DEFAULT_THEME;
2323
const isLightMemoized = useMemo(() => {
2424
if (hue) {
25-
const backgroundColor = getColorV8(hue, 600, theme);
25+
const backgroundColor = getColor({ theme, hue });
2626
const LIGHT_COLOR = 'white';
2727

2828
/* prevent this expensive computation on every render */
@@ -35,11 +35,10 @@ export const Chrome = React.forwardRef<HTMLDivElement, IChromeProps>(
3535
return false;
3636
}, [hue, theme]);
3737

38-
const isLight = hue ? isLightMemoized : false;
39-
const isDark = hue ? !isLightMemoized : false;
38+
const isLight = hue ? isLightMemoized : undefined;
4039
const chromeContextValue = useMemo(
41-
() => ({ hue: hue || 'chromeHue', isLight, isDark }),
42-
[hue, isLight, isDark]
40+
() => ({ hue: hue || 'chromeHue', isLight }),
41+
[hue, isLight]
4342
);
4443
const environment = useDocument(theme);
4544

@@ -63,7 +62,7 @@ export const Chrome = React.forwardRef<HTMLDivElement, IChromeProps>(
6362

6463
return (
6564
<ChromeContext.Provider value={chromeContextValue}>
66-
<StyledChrome ref={ref} {...props} data-test-light={isLight} data-test-dark={isDark} />
65+
<StyledChrome ref={ref} {...props} data-test-light={isLight} />
6766
</ChromeContext.Provider>
6867
);
6968
}

packages/chrome/src/elements/header/HeaderItem.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ describe('HeaderItem', () => {
6363
it('renders correct color if no product is provided', () => {
6464
const { container } = render(<HeaderItem hasLogo />);
6565

66-
expect(container.firstChild).toHaveStyleRule('color', 'inherit');
66+
expect(container.firstChild).toHaveStyleRule('color', PALETTE.grey[900]);
6767
});
6868
});
6969
});

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

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,7 @@
55
* found at http://www.apache.org/licenses/LICENSE-2.0.
66
*/
77

8-
import React, {
9-
Children,
10-
cloneElement,
11-
isValidElement,
12-
PropsWithChildren,
13-
SVGAttributes,
14-
ReactSVGElement
15-
} from 'react';
16-
import { DefaultTheme, ThemeProps } from 'styled-components';
8+
import React, { PropsWithChildren, SVGAttributes } from 'react';
179
import { StyledHeaderItemIcon } from '../../styled';
1810

1911
/**
@@ -24,19 +16,6 @@ import { StyledHeaderItemIcon } from '../../styled';
2416
export const HeaderItemIcon = ({
2517
children,
2618
...props
27-
}: PropsWithChildren<SVGAttributes<SVGElement>>) => {
28-
const element = Children.only(children) as ReactSVGElement;
29-
30-
if (isValidElement(element)) {
31-
const Icon = ({
32-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
33-
theme,
34-
...iconProps
35-
}: ThemeProps<DefaultTheme> & SVGAttributes<SVGElement>) =>
36-
cloneElement<SVGAttributes<SVGElement>, SVGElement>(element, { ...props, ...iconProps });
37-
38-
return <StyledHeaderItemIcon as={Icon} {...props} />;
39-
}
40-
41-
return null;
42-
};
19+
}: PropsWithChildren<SVGAttributes<SVGElement>>) => (
20+
<StyledHeaderItemIcon {...props}>{children}</StyledHeaderItemIcon>
21+
);

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

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

88
import React, { useMemo } from 'react';
9+
import { ThemeProvider } from 'styled-components';
910
import PropTypes from 'prop-types';
1011
import { INavProps } from '../../types';
1112
import { useChromeContext } from '../../utils/useChromeContext';
@@ -17,13 +18,20 @@ import { NavItemText } from './NavItemText';
1718
import { NavList } from './NavList';
1819

1920
export const NavComponent = React.forwardRef<HTMLElement, INavProps>((props, ref) => {
20-
const { hue, isLight, isDark } = useChromeContext();
21+
const { hue, isLight } = useChromeContext();
2122
const navContextValue = useMemo(() => ({ isExpanded: !!props.isExpanded }), [props.isExpanded]);
2223

2324
return (
24-
<NavContext.Provider value={navContextValue}>
25-
<StyledNav ref={ref} {...props} hue={hue} isLight={isLight} isDark={isDark} />
26-
</NavContext.Provider>
25+
<ThemeProvider
26+
theme={parentTheme => ({
27+
...parentTheme,
28+
colors: { ...parentTheme.colors, base: isLight ? 'light' : 'dark' }
29+
})}
30+
>
31+
<NavContext.Provider value={navContextValue}>
32+
<StyledNav ref={ref} {...props} hue={hue} />
33+
</NavContext.Provider>
34+
</ThemeProvider>
2735
);
2836
});
2937

packages/chrome/src/elements/nav/NavItem.spec.tsx

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import React from 'react';
99
import { render } from 'garden-test-utils';
10-
import { PALETTE, getColorV8, DEFAULT_THEME } from '@zendeskgarden/react-theming';
10+
import { PALETTE } from '@zendeskgarden/react-theming';
1111
import { Chrome } from '../Chrome';
1212
import { Nav } from './Nav';
1313
import { PRODUCTS, Product } from '../../types';
@@ -83,7 +83,7 @@ describe('NavItem', () => {
8383
it('renders correct opacity if used as brandmark', () => {
8484
const { container } = render(<Nav.Item hasBrandmark />);
8585

86-
expect(container.firstChild).toHaveStyleRule('opacity', '0.3');
86+
expect(container.firstChild).toHaveStyleRule('opacity', '0.32');
8787
});
8888

8989
it('renders correct opacity if used as logo', () => {
@@ -99,35 +99,41 @@ describe('NavItem', () => {
9999
</Nav.List>
100100
);
101101

102-
expect(getByTestId('item')).toHaveStyleRule('opacity', '1');
102+
expect(getByTestId('item')).toHaveStyleRule('opacity', '1', {
103+
modifier: '&[aria-current="true"]'
104+
});
103105
});
104106
});
105107

106108
describe('Hover Color', () => {
107109
it('renders correct color with dark hue', () => {
108110
const { getByTestId } = render(
109111
<Chrome hue="black">
110-
<Nav.List>
111-
<Nav.Item data-test-id="item" />
112-
</Nav.List>
112+
<Nav>
113+
<Nav.List>
114+
<Nav.Item data-test-id="item" />
115+
</Nav.List>
116+
</Nav>
113117
</Chrome>
114118
);
115119

116-
expect(getByTestId('item')).toHaveStyleRule('background-color', 'rgba(0,0,0,0.1)', {
120+
expect(getByTestId('item')).toHaveStyleRule('background-color', 'rgba(0,0,0,0.08)', {
117121
modifier: '&:hover'
118122
});
119123
});
120124

121125
it('renders correct color with light hue', () => {
122126
const { getByTestId } = render(
123127
<Chrome hue="white">
124-
<Nav.List>
125-
<Nav.Item data-test-id="item" />
126-
</Nav.List>
128+
<Nav>
129+
<Nav.List>
130+
<Nav.Item data-test-id="item" />
131+
</Nav.List>
132+
</Nav>
127133
</Chrome>
128134
);
129135

130-
expect(getByTestId('item')).toHaveStyleRule('background-color', 'rgba(255,255,255,0.1)', {
136+
expect(getByTestId('item')).toHaveStyleRule('background-color', 'rgba(255,255,255,0.08)', {
131137
modifier: '&:hover'
132138
});
133139
});
@@ -137,40 +143,49 @@ describe('NavItem', () => {
137143
it('renders correct color by default', () => {
138144
const { getByTestId } = render(
139145
<Chrome>
140-
<Nav.List>
141-
<Nav.Item isCurrent data-test-id="item" />
142-
</Nav.List>
146+
<Nav>
147+
<Nav.List>
148+
<Nav.Item isCurrent data-test-id="item" />
149+
</Nav.List>
150+
</Nav>
143151
</Chrome>
144152
);
145153

146-
expect(getByTestId('item')).toHaveStyleRule(
147-
'background-color',
148-
getColorV8('chromeHue', 500, DEFAULT_THEME)
149-
);
154+
expect(getByTestId('item')).toHaveStyleRule('background-color', PALETTE.kale[700], {
155+
modifier: '&[aria-current="true"]'
156+
});
150157
});
151158

152159
it('renders correct color with dark hue', () => {
153160
const { getByTestId } = render(
154161
<Chrome hue="black">
155-
<Nav.List>
156-
<Nav.Item isCurrent data-test-id="item" />
157-
</Nav.List>
162+
<Nav>
163+
<Nav.List>
164+
<Nav.Item isCurrent data-test-id="item" />
165+
</Nav.List>
166+
</Nav>
158167
</Chrome>
159168
);
160169

161-
expect(getByTestId('item')).toHaveStyleRule('background-color', 'rgba(255,255,255,0.4)');
170+
expect(getByTestId('item')).toHaveStyleRule('background-color', 'rgba(255,255,255,0.4)', {
171+
modifier: '&[aria-current="true"]'
172+
});
162173
});
163174

164175
it('renders correct color with light hue', () => {
165176
const { getByTestId } = render(
166177
<Chrome hue="white">
167-
<Nav.List>
168-
<Nav.Item isCurrent data-test-id="item" />
169-
</Nav.List>
178+
<Nav>
179+
<Nav.List>
180+
<Nav.Item isCurrent data-test-id="item" />
181+
</Nav.List>
182+
</Nav>
170183
</Chrome>
171184
);
172185

173-
expect(getByTestId('item')).toHaveStyleRule('background-color', 'rgba(0,0,0,0.4)');
186+
expect(getByTestId('item')).toHaveStyleRule('background-color', 'rgba(0,0,0,0.4)', {
187+
modifier: '&[aria-current="true"]'
188+
});
174189
});
175190
});
176191

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

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,15 @@ import { useNavListContext } from '../../utils/useNavListContext';
2424
* @extends ButtonHTMLAttributes<HTMLButtonElement>
2525
*/
2626
export const NavItem = React.forwardRef<HTMLButtonElement, INavItemProps>(
27-
({ hasLogo, hasBrandmark, product, ...other }, ref) => {
28-
const { hue, isLight, isDark } = useChromeContext();
27+
({ hasLogo, hasBrandmark, product, isCurrent, ...other }, ref) => {
28+
const { hue } = useChromeContext();
2929
const { isExpanded } = useNavContext();
3030
const navListContext = useNavListContext();
31-
const ariaCurrent = other.isCurrent || undefined;
32-
3331
const hasList = navListContext?.hasList;
3432
let retVal;
3533

3634
if (hasLogo) {
37-
retVal = (
38-
<StyledLogoNavItem
39-
ref={ref}
40-
isDark={isDark}
41-
isLight={isLight}
42-
product={product}
43-
aria-current={ariaCurrent}
44-
{...other}
45-
/>
46-
);
35+
retVal = <StyledLogoNavItem ref={ref} hue={hue} product={product} {...other} />;
4736
} else if (hasBrandmark) {
4837
retVal = <StyledBrandmarkNavItem ref={ref} {...other} />;
4938
} else {
@@ -53,9 +42,7 @@ export const NavItem = React.forwardRef<HTMLButtonElement, INavItemProps>(
5342
ref={ref}
5443
isExpanded={isExpanded}
5544
hue={hue}
56-
isDark={isDark}
57-
isLight={isLight}
58-
aria-current={ariaCurrent}
45+
aria-current={isCurrent || undefined}
5946
{...other}
6047
/>
6148
);

0 commit comments

Comments
 (0)