-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(Theme): add theme package * feat(themes): add zone support * refactor(theme): update props and add docs * chore(styles): update style order * feat(carbon-react): add Theme, useTheme to exports Co-authored-by: Josh Black <[email protected]> Co-authored-by: Andrea N. Cardona <[email protected]>
- Loading branch information
1 parent
20bd64b
commit a67867c
Showing
7 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
packages/carbon-react/src/components/Theme/Theme-story.scss
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,16 @@ | ||
// | ||
// Copyright IBM Corp. 2018, 2018 | ||
// | ||
// This source code is licensed under the Apache-2.0 license found in the | ||
// LICENSE file in the root directory of this source tree. | ||
// | ||
|
||
@use '@carbon/styles/scss/themes'; | ||
@use '@carbon/styles/scss/theme'; | ||
@use '@carbon/styles/scss/zone'; | ||
|
||
.theme-section { | ||
padding: 1rem; | ||
background: theme.$background; | ||
color: theme.$text-primary; | ||
} |
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,85 @@ | ||
import { Story, Props, Source, Preview } from '@storybook/addon-docs/blocks'; | ||
|
||
# Theme | ||
|
||
[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/carbon-react/src/components/Theme) | ||
|
||
<!-- prettier-ignore-start --> | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
## Table of Contents | ||
|
||
- [Overview](#overview) | ||
- [`useTheme`](#usetheme) | ||
- [Component API](#component-api) | ||
- [Theme as](#theme-as) | ||
- [Feedback](#feedback) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- prettier-ignore-end --> | ||
|
||
## Overview | ||
|
||
The `Theme` component allows you to specify the theme for a page, or a portion | ||
of a page. It is most often used to implement inline theming in order to specify | ||
what theme a section of the page should render with. | ||
|
||
The `Theme` component accepts a `theme` prop which allows you to specify the | ||
theme. This value is propagated to the entire sub-tree of components and can be | ||
accessed by any child component using the `useTheme` hook. | ||
|
||
```jsx | ||
<Theme theme="g100"> | ||
<ChildComponent /> | ||
</Theme> | ||
``` | ||
The `Theme` component will render a wrapper element on which all of the values | ||
of the given theme will be applied as CSS Custom Properties. These CSS Custom | ||
Properties can be accessed directly, or you can use the Sass Variables provided | ||
in the styles from the Carbon Design System to refer to these properties in your | ||
styles. | ||
### `useTheme` | ||
The `useTheme` hook allows you to access the current theme in a component. This | ||
can be useful if you need to conditionally render something based on the theme. | ||
For example, if you have an illustration that needs to be rendered differently | ||
in a light or dark theme. | ||
You can use this hook in any component by calling `useTheme`: | ||
```jsx | ||
function ExampleComponent() { | ||
const { theme } = useTheme(); | ||
if (theme === 'g100') { | ||
// ... | ||
} | ||
} | ||
``` | ||
|
||
## Component API | ||
|
||
<Props /> | ||
|
||
### Theme as | ||
|
||
You can configure the base element rendered by `Theme` using the `as` prop. For | ||
example, if you would like the `Theme` component to render as a `section` you | ||
could write the following: | ||
|
||
```jsx | ||
<Theme as="section" theme="g100"> | ||
<ChildComponent /> | ||
</Theme> | ||
``` | ||
|
||
Similarly, you can provide any custom component to the `as` prop which the | ||
`Theme` component will use. | ||
|
||
## Feedback | ||
|
||
Help us improve this component by providing feedback, asking questions on Slack, | ||
or updating this file on | ||
[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/carbon-react/src/components/Theme/Theme.mdx). |
96 changes: 96 additions & 0 deletions
96
packages/carbon-react/src/components/Theme/Theme.stories.js
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,96 @@ | ||
/** | ||
* Copyright IBM Corp. 2016, 2018 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import './Theme-story.scss'; | ||
import React from 'react'; | ||
import { Theme, useTheme } from '../Theme'; | ||
import mdx from './Theme.mdx'; | ||
|
||
export default { | ||
title: 'Components/Theme', | ||
component: Theme, | ||
parameters: { | ||
controls: { | ||
hideNoControlsWarning: true, | ||
}, | ||
docs: { | ||
page: mdx, | ||
}, | ||
}, | ||
argTypes: { | ||
as: { | ||
table: { | ||
disable: true, | ||
}, | ||
}, | ||
children: { | ||
table: { | ||
disable: true, | ||
}, | ||
}, | ||
theme: { | ||
defaultValue: 'g10', | ||
}, | ||
}, | ||
}; | ||
|
||
export const Default = () => { | ||
return ( | ||
<> | ||
<Theme theme="g100"> | ||
<section className="theme-section"> | ||
<p>g100 theme</p> | ||
</section> | ||
</Theme> | ||
<Theme theme="g90"> | ||
<section className="theme-section"> | ||
<p>g90 theme</p> | ||
</section> | ||
</Theme> | ||
<Theme theme="g10"> | ||
<section className="theme-section"> | ||
<p>g10 theme</p> | ||
</section> | ||
</Theme> | ||
<Theme theme="white"> | ||
<section className="theme-section"> | ||
<p>white theme</p> | ||
</section> | ||
</Theme> | ||
</> | ||
); | ||
}; | ||
|
||
export const UseTheme = () => { | ||
function Example() { | ||
const { theme } = useTheme(); | ||
return <div className="theme-section">The current theme is: {theme}</div>; | ||
} | ||
|
||
return ( | ||
<div> | ||
<Example /> | ||
<Theme theme="g100"> | ||
<Example /> | ||
</Theme> | ||
</div> | ||
); | ||
}; | ||
|
||
UseTheme.storyName = 'useTheme'; | ||
|
||
const PlaygroundStory = (args) => { | ||
return ( | ||
<Theme {...args}> | ||
<section className="theme-section"> | ||
<p>{args.theme} theme</p> | ||
</section> | ||
</Theme> | ||
); | ||
}; | ||
|
||
export const Playground = PlaygroundStory.bind({}); |
40 changes: 40 additions & 0 deletions
40
packages/carbon-react/src/components/Theme/__tests__/Theme-test.js
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,40 @@ | ||
/** | ||
* Copyright IBM Corp. 2016, 2018 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import React from 'react'; | ||
import { Theme, useTheme } from '../../Theme'; | ||
import { screen, render } from '@testing-library/react'; | ||
|
||
describe('Theme', () => { | ||
it('should render the children passed in as a prop', () => { | ||
render( | ||
<Theme> | ||
<span data-testid="test">test</span> | ||
</Theme> | ||
); | ||
|
||
expect(screen.getByTestId('test')).toBeInTheDocument(); | ||
}); | ||
|
||
it('should set the theme in context', () => { | ||
function TestComponent({ id }) { | ||
const { theme } = useTheme(); | ||
return <span data-testid={id}>{theme}</span>; | ||
} | ||
render( | ||
<Theme theme="white"> | ||
<TestComponent id="default" /> | ||
<Theme theme="g100"> | ||
<TestComponent id="nested" /> | ||
</Theme> | ||
</Theme> | ||
); | ||
|
||
expect(screen.getByTestId('default')).toHaveTextContent('white'); | ||
expect(screen.getByTestId('nested')).toHaveTextContent('g100'); | ||
}); | ||
}); |
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,80 @@ | ||
/** | ||
* Copyright IBM Corp. 2016, 2018 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import cx from 'classnames'; | ||
|
||
const ThemeContext = React.createContext({ | ||
theme: 'white', | ||
}); | ||
|
||
/** | ||
* Specify the theme to be applied to a page, or a region in a page | ||
*/ | ||
export function Theme({ | ||
as: BaseComponent = 'div', | ||
children, | ||
className: customClassName, | ||
theme, | ||
...rest | ||
}) { | ||
const className = cx(customClassName, { | ||
'bx--white': theme === 'white', | ||
'bx--g10': theme === 'g10', | ||
'bx--g90': theme === 'g90', | ||
'bx--g100': theme === 'g100', | ||
}); | ||
const value = React.useMemo(() => { | ||
return { | ||
theme, | ||
}; | ||
}, [theme]); | ||
|
||
return ( | ||
<ThemeContext.Provider value={value}> | ||
<BaseComponent {...rest} className={className}> | ||
{children} | ||
</BaseComponent> | ||
</ThemeContext.Provider> | ||
); | ||
} | ||
|
||
Theme.propTypes = { | ||
/** | ||
* Specify a custom component or element to be rendered as the top-level | ||
* element in the component | ||
*/ | ||
as: PropTypes.oneOfType([ | ||
PropTypes.func, | ||
PropTypes.string, | ||
PropTypes.elementType, | ||
]), | ||
|
||
/** | ||
* Provide child elements to be rendered inside of `Theme` | ||
*/ | ||
children: PropTypes.node, | ||
|
||
/** | ||
* Provide a custom class name to be used on the outermost element rendered by | ||
* the component | ||
*/ | ||
className: PropTypes.string, | ||
|
||
/** | ||
* Specify the theme | ||
*/ | ||
theme: PropTypes.oneOf(['white', 'g10', 'g90', 'g100']), | ||
}; | ||
|
||
/** | ||
* Get access to the current theme | ||
*/ | ||
export function useTheme() { | ||
return React.useContext(ThemeContext); | ||
} |
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 |
---|---|---|
|
@@ -204,3 +204,5 @@ export { | |
Grid, | ||
Column, | ||
} from './components/Grid'; | ||
|
||
export { Theme, useTheme } from './components/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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// Copyright IBM Corp. 2018, 2018 | ||
// | ||
// This source code is licensed under the Apache-2.0 license found in the | ||
// LICENSE file in the root directory of this source tree. | ||
// | ||
|
||
@use 'sass:map'; | ||
@use 'sass:meta'; | ||
@use './config'; | ||
@use './themes'; | ||
@use './theme'; | ||
@use './utilities/custom-property'; | ||
|
||
/// Specify a Map of zones where the key will be used as part of the selector | ||
/// and the value will be a map used to emit CSS Custom Properties for all color | ||
/// values | ||
$zones: ( | ||
white: themes.$white, | ||
g10: themes.$g10, | ||
g90: themes.$g90, | ||
g100: themes.$g100, | ||
) !default; | ||
|
||
@each $name, $theme in $zones { | ||
.#{config.$prefix}--#{'' + $name} { | ||
@each $key, $value in $theme { | ||
@if type-of($value) == color { | ||
@include custom-property.declaration($key, $value); | ||
} | ||
} | ||
} | ||
} |