Skip to content

Commit

Permalink
feat: add site theme switching mechanism (#642)
Browse files Browse the repository at this point in the history
  • Loading branch information
jzempel authored Nov 11, 2024
1 parent b6bc239 commit da8d584
Show file tree
Hide file tree
Showing 46 changed files with 810 additions and 361 deletions.
6 changes: 3 additions & 3 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export default [
'react/destructuring-assignment': 'off',
'react/display-name': 'off',
'react/no-array-index-key': 'off',
'react/no-unknown-property': ['error', { ignore: ['css'] }]
'react/no-unknown-property': ['error', { ignore: ['css'] }],
'react/no-unstable-nested-components': ['error', { allowAsProps: true }]
}
},
{
Expand Down Expand Up @@ -64,8 +65,7 @@ export default [
rules: {
'no-alert': 'off',
'jsx-a11y/img-redundant-alt': 'off',
'n/no-unsupported-features/es-builtins': ['error', { version: '>=20.0.0' }],
'react/no-unstable-nested-components': ['error', { allowAsProps: true }]
'n/no-unsupported-features/es-builtins': ['error', { version: '>=20.0.0' }]
}
}
];
11 changes: 10 additions & 1 deletion gatsby-ssr.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@

import React from 'react';
import { Provider, Layout } from './src/components';
import __html from '!!raw-loader!./utils/color-scheme.js';

export const wrapRootElement = ({ props, element }) => <Provider {...props}>{element}</Provider>;

export const wrapPageElement = ({ props, element }) => <Layout {...props}>{element}</Layout>;

export const onRenderBody = ({ setHtmlAttributes, setHeadComponents, setPostBodyComponents }) => {
export const onRenderBody = ({
setHtmlAttributes,
setHeadComponents,
setPreBodyComponents,
setPostBodyComponents
}) => {
setHtmlAttributes({ lang: 'en' });

const version = 2;
Expand All @@ -25,6 +31,9 @@ export const onRenderBody = ({ setHtmlAttributes, setHeadComponents, setPostBody
/>
]);

/* eslint-disable-next-line react/no-danger */
setPreBodyComponents([<script key="color-scheme-js" dangerouslySetInnerHTML={{ __html }} />]);

setPostBodyComponents([
<script
key="docsearch-js"
Expand Down
121 changes: 121 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"postinstall": "husky",
"lint": "npm run lint:js && npm run lint:css && npm run lint:md",
"lint:css": "stylelint 'src/**/*.{js,ts,tsx}'",
"lint:js": "eslint ./",
"lint:js": "eslint ./ --max-warnings 0",
"lint:md": "markdownlint ./*.md src/**/*.mdx",
"prepare": "git submodule update --depth 1 --init && npm run build",
"start": "gatsby develop --open",
Expand Down Expand Up @@ -106,6 +106,7 @@
"react": "18.3.1",
"react-dom": "18.3.1",
"react-dropzone": "14.3.5",
"react-hydration-provider": "2.1.0",
"react-is": "18.3.1",
"react-markdown": "9.0.1",
"react-window": "1.8.10",
Expand Down
56 changes: 42 additions & 14 deletions src/components/MarkdownProvider/components/BestPractice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { math } from 'polished';
import { GatsbyImage, IGatsbyImageData } from 'gatsby-plugin-image';
import { Well } from '@zendeskgarden/react-notifications';
import { Grid } from '@zendeskgarden/react-grid';
import { getColor, getColorV8, mediaQuery } from '@zendeskgarden/react-theming';
import { getColor, mediaQuery, StyledBaseIcon } from '@zendeskgarden/react-theming';
import { ReactComponent as XStrokeIcon } from '@zendeskgarden/svg-icons/src/16/x-stroke.svg';
import { ReactComponent as CheckLgStrokeIcon } from '@zendeskgarden/svg-icons/src/16/check-lg-stroke.svg';
import { ReactComponent as AlertErrorStrokeIcon } from '@zendeskgarden/svg-icons/src/16/alert-error-stroke.svg';
Expand Down Expand Up @@ -52,15 +52,39 @@ const StyledImgContainer = styled.div`
`;

interface IStyledCaptionProps {
hue: string;
type: 'success' | 'warning' | 'danger';
}

const StyledCaption = styled(p => <Well isRecessed {...p} />).attrs<IStyledCaptionProps>(p => ({
const getVariable = (type: IStyledCaptionProps['type'], isBorder?: boolean) => {
let retVal;

if (isBorder) {
if (type === 'success') {
retVal = 'border.successEmphasis';
} else if (type === 'warning') {
retVal = 'border.warningEmphasis';
} else if (type === 'danger') {
retVal = 'border.dangerEmphasis';
}
} else if (type === 'success') {
retVal = 'foreground.success';
} else if (type === 'warning') {
retVal = 'foreground.warning';
} else if (type === 'danger') {
retVal = 'foreground.danger';
}

return retVal;
};

const StyledCaption = styled(p => <Well {...p} />).attrs<IStyledCaptionProps>(p => ({
forwardedAs: p.tag
}))<IStyledCaptionProps>`
border: none;
border-top: ${p => `${p.theme.borders.md} ${getColorV8(p.hue, 500, p.theme)}`};
border-top: ${p =>
`${p.theme.borders.md} ${getColor({ theme: p.theme, variable: getVariable(p.type, true /* isBorder */) })}`};
border-radius: 0;
background-color: ${p => getColor({ theme: p.theme, variable: 'background.subtle' })};
padding-bottom: ${p => p.theme.space.base * 7}px;
color: ${({ theme }) => getColor({ variable: 'foreground.default', theme })};
Expand All @@ -71,7 +95,8 @@ const StyledCaption = styled(p => <Well isRecessed {...p} />).attrs<IStyledCapti
& > li:not(:first-child) {
margin-top: ${p => p.theme.space.xs};
border-top: ${p => `${p.theme.borders.sm} ${getColorV8('neutralHue', 300, p.theme)}`};
border-top: ${p =>
`${p.theme.borders.sm} ${getColor({ theme: p.theme, variable: 'border.default' })}`};
padding-top: ${p => p.theme.space.xs};
}
}
Expand All @@ -85,7 +110,7 @@ const StyledTitle = styled(p => <Well.Title {...p} />).attrs(p => ({ forwardedAs
display: flex;
align-items: center;
margin-left: -${p => math(`${p.theme.iconSizes.md} + ${p.theme.space.xs}`)};
color: ${p => getColorV8(p.hue, 600, p.theme)};
color: ${p => getColor({ theme: p.theme, variable: getVariable(p.type) })};
& + p,
& + ul {
Expand All @@ -97,17 +122,20 @@ const StyledTitle = styled(p => <Well.Title {...p} />).attrs(p => ({ forwardedAs
}
`;

interface ICaptionProps extends PropsWithChildren {
hue: string;
const StyledIcon = styled(StyledBaseIcon)`
color: ${p => getColor({ theme: p.theme, variable: getVariable(p.type) })};
`;

interface ICaptionProps extends PropsWithChildren, IStyledCaptionProps {
title: string;
icon: ReactNode;
imageSource?: string | IGatsbyImageData;
}

const Caption: React.FC<ICaptionProps> = props => (
<StyledCaption tag={props.imageSource ? 'figcaption' : undefined} hue={props.hue}>
<StyledTitle tag="strong" hue={props.hue}>
{props.icon}
<StyledCaption tag={props.imageSource ? 'figcaption' : undefined} type={props.type}>
<StyledTitle tag="strong" type={props.type}>
<StyledIcon type={props.type}>{props.icon}</StyledIcon>
{props.title}
</StyledTitle>
{props.children}
Expand Down Expand Up @@ -164,15 +192,15 @@ const Section: React.FC<ISectionProps> = props => {
};

export const Do: React.FC<ISectionProps> = props => (
<Section {...props} title="Do this" hue="successHue" icon={<CheckLgStrokeIcon />} />
<Section {...props} title="Do this" type="success" icon={<CheckLgStrokeIcon />} />
);

export const Dont: React.FC<ISectionProps> = props => (
<Section {...props} title="Not this" hue="dangerHue" icon={<XStrokeIcon />} />
<Section {...props} title="Not this" type="danger" icon={<XStrokeIcon />} />
);

export const Caution: React.FC<ISectionProps> = props => (
<Section {...props} title="Caution" hue="warningHue" icon={<AlertErrorStrokeIcon />} />
<Section {...props} title="Caution" type="warning" icon={<AlertErrorStrokeIcon />} />
);

interface IBestPracticesProps extends PropsWithChildren {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { ReactComponent as DarkStroke } from '@zendeskgarden/svg-icons/src/16/mo
import { ReactComponent as DarkFill } from '@zendeskgarden/svg-icons/src/16/moon-fill.svg';
import { ReactComponent as CodeSandboxIcon } from './assets/codesandbox-icon.svg';
import { retrieveCodesandboxParameters } from './utils/retrieveCodesandboxParameters';
import { copyToClipboard } from './utils/copyToClipboard';

const ModeIcon = ({
parentTheme,
Expand Down Expand Up @@ -101,7 +100,8 @@ export const CodeExample: React.FC<ICodeExampleProps> = ({ children, code }) =>
}, [code]);

const handleCopy = () => {
copyToClipboard(code);
/* eslint-disable-next-line n/no-unsupported-features/node-builtins */
navigator.clipboard.writeText(code);
addToast(({ close }) => (
<Notification type="success">
<Notification.Title>Code copied</Notification.Title>
Expand Down
Loading

0 comments on commit da8d584

Please sign in to comment.