Skip to content

Commit 07cbe24

Browse files
committed
chore: adds colors for global alert
1 parent 5025b93 commit 07cbe24

16 files changed

+511
-202
lines changed

packages/notifications/src/elements/global-alert/GlobalAlert.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import SuccessIcon from '@zendeskgarden/svg-icons/src/16/check-circle-stroke.svg
1414

1515
import { TYPE, IGlobalAlertProps } from '../../types';
1616
import { StyledGlobalAlert, StyledGlobalAlertIcon } from '../../styled';
17-
import { GlobalAlertContext } from './utility';
17+
import { GlobalAlertContext } from '../../utils/useGlobalAlertContext';
1818
import { GlobalAlertButton } from './GlobalAlertButton';
1919
import { GlobalAlertClose } from './GlobalAlertClose';
2020
import { GlobalAlertContent } from './GlobalAlertContent';
@@ -38,8 +38,8 @@ const GlobalAlertComponent = forwardRef<HTMLDivElement, IGlobalAlertProps>(
3838
<GlobalAlertContext.Provider value={useMemo(() => ({ type }), [type])}>
3939
{/* [1] */}
4040
{/* eslint-disable-next-line jsx-a11y/prefer-tag-over-role */}
41-
<StyledGlobalAlert ref={ref} role="status" alertType={type} {...props}>
42-
<StyledGlobalAlertIcon>{icon}</StyledGlobalAlertIcon>
41+
<StyledGlobalAlert ref={ref} role="status" $alertType={type} {...props}>
42+
<StyledGlobalAlertIcon $alertType={type}>{icon}</StyledGlobalAlertIcon>
4343
{props.children}
4444
</StyledGlobalAlert>
4545
</GlobalAlertContext.Provider>

packages/notifications/src/elements/global-alert/GlobalAlertButton.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77

88
import React, { forwardRef } from 'react';
99
import PropTypes from 'prop-types';
10-
1110
import { IGlobalAlertButtonProps } from '../../types';
1211
import { StyledGlobalAlertButton } from '../../styled';
13-
import { useGlobalAlertContext } from './utility';
12+
import { useGlobalAlertContext } from '../../utils/useGlobalAlertContext';
1413

1514
/**
1615
* @extends ButtonHTMLAttributes<HTMLButtonElement>
@@ -22,8 +21,15 @@ export const GlobalAlertButton = forwardRef<HTMLButtonElement, IGlobalAlertButto
2221
return (
2322
<StyledGlobalAlertButton
2423
ref={ref}
25-
alertType={type}
24+
$alertType={type}
2625
{...props}
26+
focusInset={false}
27+
isDanger={false}
28+
isLink={false}
29+
isNeutral={false}
30+
isPill={false}
31+
isStretched={false}
32+
size="small"
2733
isPrimary={!isBasic}
2834
isBasic={isBasic}
2935
/>

packages/notifications/src/elements/global-alert/GlobalAlertClose.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { useText } from '@zendeskgarden/react-theming';
1010
import XStrokeIcon from '@zendeskgarden/svg-icons/src/16/x-stroke.svg';
1111

1212
import { StyledGlobalAlertClose } from '../../styled';
13-
import { useGlobalAlertContext } from './utility';
13+
import { useGlobalAlertContext } from '../../utils/useGlobalAlertContext';
1414

1515
/**
1616
* 1. role='img' on `svg` is valid WAI-ARIA usage in this context.
@@ -28,7 +28,7 @@ export const GlobalAlertClose = forwardRef<
2828
const label = useText(GlobalAlertClose, props, 'aria-label', 'Close');
2929

3030
return (
31-
<StyledGlobalAlertClose ref={ref} alertType={type} {...props}>
31+
<StyledGlobalAlertClose ref={ref} $alertType={type} {...props} size="small">
3232
{/* [1] */}
3333
{/* eslint-disable-next-line jsx-a11y/prefer-tag-over-role */}
3434
<XStrokeIcon role="img" aria-label={label} />

packages/notifications/src/elements/global-alert/GlobalAlertTitle.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ import PropTypes from 'prop-types';
1010

1111
import { IGlobalAlertTitleProps } from '../../types';
1212
import { StyledGlobalAlertTitle } from '../../styled';
13-
import { useGlobalAlertContext } from './utility';
13+
import { useGlobalAlertContext } from '../../utils/useGlobalAlertContext';
1414

1515
/**
1616
* @extends HTMLAttributes<HTMLDivElement>
1717
*/
18-
export const GlobalAlertTitle = forwardRef<HTMLDivElement, IGlobalAlertTitleProps>((props, ref) => {
19-
const { type } = useGlobalAlertContext();
18+
export const GlobalAlertTitle = forwardRef<HTMLDivElement, IGlobalAlertTitleProps>(
19+
({ isRegular, ...props }, ref) => {
20+
const { type } = useGlobalAlertContext();
2021

21-
return <StyledGlobalAlertTitle alertType={type} ref={ref} {...props} />;
22-
});
22+
return <StyledGlobalAlertTitle $alertType={type} $isRegular={isRegular} ref={ref} {...props} />;
23+
}
24+
);
2325

2426
GlobalAlertTitle.displayName = 'GlobalAlert.Title';
2527

packages/notifications/src/styled/global-alert/StyledGlobalAlert.spec.tsx

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

88
import React from 'react';
9-
import { render } from 'garden-test-utils';
10-
import { DEFAULT_THEME, getColorV8 } from '@zendeskgarden/react-theming';
9+
import { getRenderFn } from 'garden-test-utils';
10+
import { DEFAULT_THEME, PALETTE } from '@zendeskgarden/react-theming';
1111

12-
import { TYPE } from '../../types';
12+
import { Type } from '../../types';
1313
import { StyledGlobalAlert } from './StyledGlobalAlert';
1414

1515
describe('StyledGlobalAlert', () => {
16-
it.each(TYPE)('renders "%s" type', type => {
17-
const { container } = render(<StyledGlobalAlert alertType={type} />);
16+
it.each<{ mode: 'light' | 'dark'; type: Type; color: string }>([
17+
{ mode: 'light', type: 'success', color: PALETTE.green[700] },
18+
{ mode: 'dark', type: 'success', color: PALETTE.green[700] },
19+
{ mode: 'light', type: 'error', color: PALETTE.red[700] },
20+
{ mode: 'dark', type: 'error', color: PALETTE.red[700] },
21+
{ mode: 'light', type: 'warning', color: PALETTE.yellow[300] },
22+
{ mode: 'dark', type: 'warning', color: PALETTE.yellow[300] },
23+
{ mode: 'light', type: 'info', color: PALETTE.blue[300] },
24+
{ mode: 'dark', type: 'info', color: PALETTE.blue[300] }
25+
])('renders $mode mode $type background color', ({ mode, type, color }) => {
26+
const { container } = getRenderFn(mode)(<StyledGlobalAlert $alertType={type} />);
27+
28+
expect(container.firstChild).toHaveStyleRule('background-color', color);
29+
});
30+
31+
it.each<{ mode: 'light' | 'dark'; type: Type; color: string }>([
32+
{ mode: 'light', type: 'success', color: PALETTE.green[100] },
33+
{ mode: 'dark', type: 'success', color: PALETTE.green[100] },
34+
{ mode: 'light', type: 'error', color: PALETTE.red[100] },
35+
{ mode: 'dark', type: 'error', color: PALETTE.red[100] },
36+
{ mode: 'light', type: 'warning', color: PALETTE.yellow[800] },
37+
{ mode: 'dark', type: 'warning', color: PALETTE.yellow[800] },
38+
{ mode: 'light', type: 'info', color: PALETTE.blue[800] },
39+
{ mode: 'dark', type: 'info', color: PALETTE.blue[800] }
40+
])('renders $mode mode $type foreground color', ({ mode, type, color }) => {
41+
const { container } = getRenderFn(mode)(<StyledGlobalAlert $alertType={type} />);
42+
43+
expect(container.firstChild).toHaveStyleRule('color', color);
44+
});
45+
46+
it.each<{ mode: 'light' | 'dark'; type: Type; color: string }>([
47+
{ mode: 'light', type: 'success', color: PALETTE.green[800] },
48+
{ mode: 'dark', type: 'success', color: PALETTE.green[800] },
49+
{ mode: 'light', type: 'error', color: PALETTE.red[800] },
50+
{ mode: 'dark', type: 'error', color: PALETTE.red[800] },
51+
{ mode: 'light', type: 'warning', color: PALETTE.yellow[400] },
52+
{ mode: 'dark', type: 'warning', color: PALETTE.yellow[400] },
53+
{ mode: 'light', type: 'info', color: PALETTE.blue[400] },
54+
{ mode: 'dark', type: 'info', color: PALETTE.blue[400] }
55+
])('renders $mode mode $type border color', ({ mode, type, color }) => {
56+
const { container } = getRenderFn(mode)(<StyledGlobalAlert $alertType={type} />);
1857

1958
expect(container.firstChild).toHaveStyleRule(
20-
'background-color',
21-
{
22-
success: getColorV8(DEFAULT_THEME.colors.successHue, 600, DEFAULT_THEME),
23-
error: getColorV8(DEFAULT_THEME.colors.dangerHue, 600, DEFAULT_THEME),
24-
warning: getColorV8(DEFAULT_THEME.colors.warningHue, 300, DEFAULT_THEME),
25-
info: getColorV8(DEFAULT_THEME.colors.primaryHue, 200, DEFAULT_THEME)
26-
}[type]
59+
'box-shadow',
60+
`0 ${DEFAULT_THEME.borderWidths.sm} ${DEFAULT_THEME.borderWidths.sm} ${color}`
2761
);
2862
});
2963
});

packages/notifications/src/styled/global-alert/StyledGlobalAlert.ts

Lines changed: 116 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,145 @@
77

88
import styled, { css, ThemeProps, DefaultTheme } from 'styled-components';
99
import {
10-
getColorV8,
1110
DEFAULT_THEME,
1211
retrieveComponentStyles,
1312
getLineHeight,
14-
focusStyles
13+
focusStyles,
14+
getColor
1515
} from '@zendeskgarden/react-theming';
1616

1717
import { IGlobalAlertProps } from '../../types';
1818

19-
const COMPONENT_ID = 'notifications.global-alert';
19+
const COMPONENT_ID = 'notifications.global_alert';
2020

2121
interface IStyledGlobalAlertProps {
22-
alertType: IGlobalAlertProps['type'];
22+
$alertType: IGlobalAlertProps['type'];
2323
}
2424

25+
const lightDarkOptions = (lightOffset: number, darkOffset: number) => ({
26+
light: { offset: lightOffset },
27+
dark: { offset: darkOffset }
28+
});
29+
2530
/**
2631
* 1. Shifting :focus-visible from LVHFA order to preserve `color` on hover
2732
*/
28-
const colorStyles = (props: ThemeProps<DefaultTheme> & IStyledGlobalAlertProps) => {
33+
const colorStyles = ({ theme, $alertType }: ThemeProps<DefaultTheme> & IStyledGlobalAlertProps) => {
2934
let borderColor;
3035
let backgroundColor;
3136
let foregroundColor;
3237
let anchorHoverColor;
3338
let anchorActiveColor;
34-
let focusColor;
35-
36-
switch (props.alertType) {
37-
case 'success':
38-
borderColor = getColorV8('successHue', 700, props.theme);
39-
backgroundColor = getColorV8('successHue', 600, props.theme);
40-
foregroundColor = getColorV8('successHue', 100, props.theme);
41-
anchorHoverColor = props.theme.palette.white;
42-
anchorActiveColor = props.theme.palette.white;
43-
focusColor = 'successHue';
39+
let focusVariable;
40+
41+
switch ($alertType) {
42+
case 'success': {
43+
borderColor = getColor({
44+
variable: 'border.successEmphasis',
45+
...lightDarkOptions(100, 200),
46+
theme
47+
});
48+
backgroundColor = getColor({
49+
variable: 'background.successEmphasis',
50+
dark: { offset: 100 },
51+
theme
52+
});
53+
foregroundColor = getColor({
54+
variable: 'foreground.success',
55+
...lightDarkOptions(-600, -300),
56+
theme
57+
});
58+
focusVariable = 'foreground.successEmphasis';
4459
break;
45-
46-
case 'error':
47-
borderColor = getColorV8('dangerHue', 700, props.theme);
48-
backgroundColor = getColorV8('dangerHue', 600, props.theme);
49-
foregroundColor = getColorV8('dangerHue', 100, props.theme);
50-
anchorHoverColor = props.theme.palette.white;
51-
anchorActiveColor = props.theme.palette.white;
52-
focusColor = 'dangerHue';
60+
}
61+
case 'error': {
62+
borderColor = getColor({
63+
variable: 'border.dangerEmphasis',
64+
...lightDarkOptions(100, 200),
65+
theme
66+
});
67+
backgroundColor = getColor({
68+
variable: 'background.dangerEmphasis',
69+
dark: { offset: 100 },
70+
theme
71+
});
72+
foregroundColor = getColor({
73+
variable: 'foreground.danger',
74+
...lightDarkOptions(-600, -300),
75+
theme
76+
});
77+
focusVariable = 'foreground.dangerEmphasis';
5378
break;
54-
55-
case 'warning':
56-
borderColor = getColorV8('warningHue', 400, props.theme);
57-
backgroundColor = getColorV8('warningHue', 300, props.theme);
58-
foregroundColor = getColorV8('warningHue', 800, props.theme);
59-
anchorHoverColor = getColorV8('warningHue', 900, props.theme);
60-
anchorActiveColor = getColorV8('warningHue', 1000, props.theme);
61-
focusColor = 'warningHue';
79+
}
80+
case 'warning': {
81+
borderColor = getColor({
82+
variable: 'border.warningEmphasis',
83+
...lightDarkOptions(-300, -200),
84+
theme
85+
});
86+
backgroundColor = getColor({
87+
variable: 'background.warningEmphasis',
88+
...lightDarkOptions(-400, -300),
89+
theme
90+
});
91+
const fgVariable = 'foreground.warning';
92+
foregroundColor = getColor({
93+
variable: fgVariable,
94+
...lightDarkOptions(100, 400),
95+
theme
96+
});
97+
anchorHoverColor = getColor({
98+
variable: fgVariable,
99+
...lightDarkOptions(200, 500),
100+
theme
101+
});
102+
anchorActiveColor = getColor({
103+
variable: fgVariable,
104+
...lightDarkOptions(300, 600),
105+
theme
106+
});
107+
focusVariable = fgVariable;
62108
break;
63-
64-
case 'info':
65-
borderColor = getColorV8('primaryHue', 300, props.theme);
66-
backgroundColor = getColorV8('primaryHue', 200, props.theme);
67-
foregroundColor = getColorV8('primaryHue', 700, props.theme);
68-
anchorHoverColor = getColorV8('primaryHue', 800, props.theme);
69-
anchorActiveColor = getColorV8('primaryHue', 900, props.theme);
70-
focusColor = 'primaryHue';
109+
}
110+
case 'info': {
111+
borderColor = getColor({
112+
variable: 'border.primaryEmphasis',
113+
...lightDarkOptions(-300, -200),
114+
theme
115+
});
116+
backgroundColor = getColor({
117+
variable: 'background.primaryEmphasis',
118+
...lightDarkOptions(-400, -300),
119+
theme
120+
});
121+
const fgVariable = 'foreground.primary';
122+
foregroundColor = getColor({
123+
variable: fgVariable,
124+
...lightDarkOptions(100, 200),
125+
theme
126+
});
127+
anchorHoverColor = getColor({
128+
variable: fgVariable,
129+
...lightDarkOptions(200, 300),
130+
theme
131+
});
132+
anchorActiveColor = getColor({
133+
variable: fgVariable,
134+
...lightDarkOptions(300, 400),
135+
theme
136+
});
137+
focusVariable = fgVariable;
71138
break;
139+
}
140+
}
141+
142+
if (['success', 'error'].includes($alertType)) {
143+
anchorHoverColor = theme.palette.white;
144+
anchorActiveColor = theme.palette.white;
72145
}
73146

74147
// Apply a border without affecting the element's size
75-
const boxShadow = `0 ${props.theme.borderWidths.sm} ${props.theme.borderWidths.sm} ${borderColor}`;
148+
const boxShadow = `0 ${theme.borderWidths.sm} ${theme.borderWidths.sm} ${borderColor}`;
76149

77150
/* stylelint-disable selector-no-qualifying-type */
78151
return css`
@@ -85,8 +158,8 @@ const colorStyles = (props: ThemeProps<DefaultTheme> & IStyledGlobalAlertProps)
85158
86159
/* [1] */
87160
${focusStyles({
88-
theme: props.theme,
89-
color: { hue: focusColor, shade: props.alertType === 'info' ? 600 : 800 },
161+
theme,
162+
color: { variable: focusVariable },
90163
styles: { color: 'inherit' }
91164
})}
92165
@@ -119,7 +192,7 @@ const sizeStyles = (props: ThemeProps<DefaultTheme>) => {
119192
export const StyledGlobalAlert = styled.div.attrs({
120193
'data-garden-id': COMPONENT_ID,
121194
'data-garden-version': PACKAGE_VERSION
122-
})`
195+
})<IStyledGlobalAlertProps>`
123196
display: flex;
124197
flex-wrap: nowrap;
125198
overflow: auto;

0 commit comments

Comments
 (0)