Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add component level theming (#11691)
Part of [this issue](https://github.com/Shopify/polaris-internal/issues/1513) - Removed `html` from theme classes to remove global theme constraint - Added `ThemeProvider` component - Updated `useTheme` to be context aware of parent themes - Updated `Portal` component to be context aware of parent themes - Initialized a `dark-experimental` theme Example ```tsx function App() { return ( /** Sets the default theme globally on the root HTML element (optional) */ <AppProvider theme="light"> {/* Sets the dark theme on an internal container element */} <ThemeProvider theme="dark-experimental"> {/* ... */} </ThemeProvider> </AppProvider> ) } ``` ## Tophat Note: In web we will be restricting imports of the `ThemeProvider` to only areas that Polaris approves Make sure everything looks the same on spin. The `p-theme-light` class should be added to the top html element https://admin.web.web-xubz.sophie-schneider.us.spin.dev/store/shop1 --------- Co-authored-by: Sophie Schneider <thesophieschneider@gmail.com>
- Loading branch information
1 parent
ca8eb99
commit 1e613de
Showing
18 changed files
with
393 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
'@shopify/polaris': minor | ||
'@shopify/polaris-tokens': minor | ||
--- | ||
|
||
- Added `ThemeProvider` component | ||
- Removed `html` from theme classes to remove global theme constraint | ||
- Updated `useTheme` to be context aware of parent themes | ||
- Updated `Portal` component to be context aware of parent themes | ||
- Initialized a `dark-experimental` theme |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
polaris-react/src/components/ThemeProvider/ThemeProvider.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.themeContainer { | ||
color: var(--p-color-text); | ||
} |
97 changes: 97 additions & 0 deletions
97
polaris-react/src/components/ThemeProvider/ThemeProvider.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import React, {useCallback, useState} from 'react'; | ||
import type {ComponentMeta} from '@storybook/react'; | ||
import { | ||
Frame, | ||
Icon, | ||
TopBar, | ||
Text, | ||
ThemeProvider, | ||
InlineStack, | ||
} from '@shopify/polaris'; | ||
import {HeartIcon, NotificationIcon} from '@shopify/polaris-icons'; | ||
|
||
export default { | ||
component: ThemeProvider, | ||
} as ComponentMeta<typeof ThemeProvider>; | ||
|
||
export function Default() { | ||
const [isHeartMenuOpen, setIsHeartMenuOpen] = useState(true); | ||
|
||
const toggleIsHeartMenuOpen = useCallback( | ||
() => setIsHeartMenuOpen((isHeartMenuOpen) => !isHeartMenuOpen), | ||
[], | ||
); | ||
|
||
const [isNotificationsMenuOpen, setIsNotificationsMenuOpen] = useState(false); | ||
|
||
const toggleIsNotificationsMenuOpen = useCallback( | ||
() => | ||
setIsNotificationsMenuOpen( | ||
(isNotificationsMenuOpen) => !isNotificationsMenuOpen, | ||
), | ||
[], | ||
); | ||
|
||
const heartMenu = ( | ||
<ThemeProvider theme="light"> | ||
<TopBar.Menu | ||
activatorContent={ | ||
<ThemeProvider theme="dark-experimental"> | ||
<span> | ||
<Icon source={HeartIcon} /> | ||
<Text as="span" visuallyHidden> | ||
Light theme popover button | ||
</Text> | ||
</span> | ||
</ThemeProvider> | ||
} | ||
open={isHeartMenuOpen} | ||
onOpen={toggleIsHeartMenuOpen} | ||
onClose={toggleIsHeartMenuOpen} | ||
actions={[ | ||
{ | ||
items: [{content: 'Light theme popover'}], | ||
}, | ||
]} | ||
/> | ||
</ThemeProvider> | ||
); | ||
|
||
const notificationsMenu = ( | ||
<ThemeProvider theme="dark-experimental"> | ||
<TopBar.Menu | ||
activatorContent={ | ||
<span> | ||
<Icon source={NotificationIcon} /> | ||
<Text as="span" visuallyHidden> | ||
Dark theme popover button | ||
</Text> | ||
</span> | ||
} | ||
open={isNotificationsMenuOpen} | ||
onOpen={toggleIsNotificationsMenuOpen} | ||
onClose={toggleIsNotificationsMenuOpen} | ||
actions={[ | ||
{ | ||
items: [{content: 'Dark theme popover'}], | ||
}, | ||
]} | ||
/> | ||
</ThemeProvider> | ||
); | ||
|
||
return ( | ||
<Frame | ||
topBar={ | ||
<TopBar | ||
secondaryMenu={ | ||
<InlineStack> | ||
{heartMenu} | ||
{notificationsMenu} | ||
</InlineStack> | ||
} | ||
/> | ||
} | ||
/> | ||
); | ||
} |
56 changes: 56 additions & 0 deletions
56
polaris-react/src/components/ThemeProvider/ThemeProvider.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import React from 'react'; | ||
import {themeNameDefault, createThemeClassName} from '@shopify/polaris-tokens'; | ||
|
||
import { | ||
ThemeContext, | ||
getTheme, | ||
ThemeNameContext, | ||
} from '../../utilities/use-theme'; | ||
import {classNames} from '../../utilities/css'; | ||
|
||
import styles from './ThemeProvider.module.css'; | ||
|
||
/** | ||
* Allowlist of local themes | ||
* TODO: Replace `as const` with `satisfies ThemeName[]` | ||
*/ | ||
export const themeNamesLocal = ['light', 'dark-experimental'] as const; | ||
|
||
type ThemeNameLocal = typeof themeNamesLocal[number]; | ||
|
||
export const isThemeNameLocal = (name: string): name is ThemeNameLocal => | ||
themeNamesLocal.includes(name as any); | ||
|
||
export interface ThemeProviderProps { | ||
as?: keyof React.ReactHTML; | ||
children: React.ReactNode; | ||
className?: string; | ||
theme?: ThemeNameLocal; | ||
'data-portal-id'?: string; | ||
} | ||
|
||
export function ThemeProvider(props: ThemeProviderProps) { | ||
const { | ||
as: ThemeContainer = 'div', | ||
children, | ||
className, | ||
theme: themeName = themeNameDefault, | ||
} = props; | ||
|
||
return ( | ||
<ThemeNameContext.Provider value={themeName}> | ||
<ThemeContext.Provider value={getTheme(themeName)}> | ||
<ThemeContainer | ||
data-portal-id={props['data-portal-id']} | ||
className={classNames( | ||
createThemeClassName(themeName), | ||
styles.themeContainer, | ||
className, | ||
)} | ||
> | ||
{children} | ||
</ThemeContainer> | ||
</ThemeContext.Provider> | ||
</ThemeNameContext.Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export type {ThemeProviderProps} from './ThemeProvider'; | ||
export {ThemeProvider, isThemeNameLocal} from './ThemeProvider'; |
Oops, something went wrong.