diff --git a/CHANGELOG.md b/CHANGELOG.md
index 762127b7f3..cbde22b2ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Fixes
- Fix build on Windows @jurokapsiar ([#383](https://github.com/stardust-ui/react/pull/383))
+### Features
+- Export `mergeThemes` @levithomason ([#285](https://github.com/stardust-ui/react/pull/285))
+
+### Documentation
+- Add `Provider` examples @levithomason ([#285](https://github.com/stardust-ui/react/pull/285))
+
## [v0.10.0](https://github.com/stardust-ui/react/tree/v0.10.0) (2018-10-19)
[Compare changes](https://github.com/stardust-ui/react/compare/v0.9.1...v0.10.0)
diff --git a/docs/src/examples/components/Provider/Types/ProviderExample.shorthand.tsx b/docs/src/examples/components/Provider/Types/ProviderExample.shorthand.tsx
new file mode 100644
index 0000000000..a09d4ab1ae
--- /dev/null
+++ b/docs/src/examples/components/Provider/Types/ProviderExample.shorthand.tsx
@@ -0,0 +1,20 @@
+import React from 'react'
+import { Provider } from '@stardust-ui/react'
+
+const theme = { siteVariables: { brand: 'cornflowerblue' } }
+
+const ProviderExampleShorthand = () => (
+
+
+
+ Use the Provider.Consumer to access the theme:
+
+
+
theme.siteVariables.brand = {theme.siteVariables.brand}}
+ />
+
+
+)
+
+export default ProviderExampleShorthand
diff --git a/docs/src/examples/components/Provider/Types/index.tsx b/docs/src/examples/components/Provider/Types/index.tsx
new file mode 100644
index 0000000000..57b5e357df
--- /dev/null
+++ b/docs/src/examples/components/Provider/Types/index.tsx
@@ -0,0 +1,15 @@
+import * as React from 'react'
+import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
+import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'
+
+const Types = () => (
+
+
+
+)
+
+export default Types
diff --git a/docs/src/examples/components/Provider/index.tsx b/docs/src/examples/components/Provider/index.tsx
new file mode 100644
index 0000000000..bb4e2aaa06
--- /dev/null
+++ b/docs/src/examples/components/Provider/index.tsx
@@ -0,0 +1,10 @@
+import * as React from 'react'
+import Types from './Types'
+
+const ProviderExamples = () => (
+
+
+
+)
+
+export default ProviderExamples
diff --git a/src/components/Provider/Provider.tsx b/src/components/Provider/Provider.tsx
index f06d57203d..2c775c4e6f 100644
--- a/src/components/Provider/Provider.tsx
+++ b/src/components/Provider/Provider.tsx
@@ -21,7 +21,7 @@ export interface ProviderProps {
}
/**
- * The Provider passes the CSS in JS renderer and theme down context.
+ * The Provider passes the CSS in JS renderer and theme to your components.
*/
class Provider extends React.Component {
static propTypes = {
diff --git a/src/index.ts b/src/index.ts
index d22c6a8aa5..dbed4569fc 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -118,3 +118,8 @@ export {
export {
default as chatMessageEnterEscBehavior,
} from './lib/accessibility/Behaviors/Chat/chatMessageEnterEscBehavior'
+
+//
+// Utilities
+//
+export { default as mergeThemes } from './lib/mergeThemes'
diff --git a/test/specs/components/Provider/Provider-test.tsx b/test/specs/components/Provider/Provider-test.tsx
new file mode 100644
index 0000000000..4c3b185e0a
--- /dev/null
+++ b/test/specs/components/Provider/Provider-test.tsx
@@ -0,0 +1,12 @@
+import Provider from 'src/components/Provider/Provider'
+import ProviderConsumer from 'src/components/Provider/ProviderConsumer'
+
+describe('Provider', () => {
+ test('is exported', () => {
+ expect(require('src/index.ts').Provider).toEqual(Provider)
+ })
+
+ test('has a ProviderConsumer subcomponent', () => {
+ expect(require('src/index.ts').Provider.Consumer).toEqual(ProviderConsumer)
+ })
+})
diff --git a/test/specs/components/Provider/ProviderConsumer-test.tsx b/test/specs/components/Provider/ProviderConsumer-test.tsx
new file mode 100644
index 0000000000..391630117e
--- /dev/null
+++ b/test/specs/components/Provider/ProviderConsumer-test.tsx
@@ -0,0 +1,74 @@
+import * as React from 'react'
+import { mount } from 'enzyme'
+
+import Provider from 'src/components/Provider/Provider'
+import ProviderConsumer from 'src/components/Provider/ProviderConsumer'
+import { IThemeInput } from 'types/theme'
+
+describe('ProviderConsumer', () => {
+ test('is exported', () => {
+ expect(require('src/index.ts').ProviderConsumer).toEqual(ProviderConsumer)
+ })
+
+ test('is a subcomponent of the Provider', () => {
+ expect(Provider.Consumer).toEqual(ProviderConsumer)
+ })
+
+ describe('render', () => {
+ test('is a callback that receives the prepared theme', () => {
+ expect.assertions(13)
+
+ const inputTheme: IThemeInput = {
+ siteVariables: { a: 'b' },
+ componentVariables: { Button: { color: 'red' } },
+ componentStyles: { Button: { root: { color: 'red' } } },
+ fontFaces: [{ name: 'name', paths: ['path.woff2'], style: { fontWeight: 400 } }],
+ staticStyles: ['body{margin:0;}', { body: { margin: 0 } }],
+ icons: {
+ user: { icon: { content: '\\f1', fontFamily: 'i' } },
+ userFunc: { icon: () => ({ content: '\\f1', fontFamily: 'i' }) },
+ userSvg: { isSvg: true, icon: },
+ userSvgFunc: { isSvg: true, icon: () => },
+ },
+ }
+
+ mount(
+
+ {
+ // siteVariables
+ expect(preparedTheme).toHaveProperty('siteVariables.a', 'b')
+
+ // componentVariables
+ expect(preparedTheme).toHaveProperty('componentVariables.Button')
+ expect(preparedTheme.componentVariables.Button).toBeInstanceOf(Function)
+ expect(preparedTheme.componentVariables.Button()).toMatchObject(
+ inputTheme.componentVariables.Button,
+ )
+
+ // componentStyles
+ expect(preparedTheme).toHaveProperty('componentStyles.Button.root')
+ expect(preparedTheme.componentStyles.Button.root).toBeInstanceOf(Function)
+ expect(preparedTheme.componentStyles.Button.root()).toMatchObject(
+ inputTheme.componentStyles.Button.root,
+ )
+
+ // fontFaces
+ expect(preparedTheme).toHaveProperty('fontFaces')
+ expect(preparedTheme.fontFaces).toMatchObject(inputTheme.fontFaces)
+
+ // staticStyles
+ expect(preparedTheme).toHaveProperty('staticStyles')
+ expect(preparedTheme.staticStyles).toMatchObject(inputTheme.staticStyles)
+
+ // icons
+ expect(preparedTheme).toHaveProperty('icons')
+ expect(preparedTheme.icons).toMatchObject(inputTheme.icons)
+ return null
+ }}
+ />
+ ,
+ )
+ })
+ })
+})