Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(rna): theming docs #3060

Merged
merged 7 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions docs/src/components/Layout/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,19 +184,16 @@ const SecondaryNav = (props) => {
))}
</ExpanderItem>

{/* React Native does not yet support theming */}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woot!

{isReactNative ? null : (
<ExpanderItem
title={<ExpanderTitle Icon={MdOutlineAutoAwesome} text="Theming" />}
value="theming"
>
{theming.map(({ label, ...rest }) => (
<NavLink key={label} {...rest} onClick={props.onClick}>
{label}
</NavLink>
))}
</ExpanderItem>
)}
<ExpanderItem
title={<ExpanderTitle Icon={MdOutlineAutoAwesome} text="Theming" />}
value="theming"
>
{theming.map(({ label, ...rest }) => (
<NavLink key={label} {...rest} onClick={props.onClick}>
{label}
</NavLink>
))}
</ExpanderItem>

{/* Flutter and React Native don't have guides at this time */}
{isFlutter || isReactNative ? null : (
Expand Down
4 changes: 2 additions & 2 deletions docs/src/data/links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ export const theming: ComponentNavItem[] = [
{
href: '/theming',
label: 'Overview',
platforms: ['react', 'vue', 'angular', 'flutter'],
platforms: ['react', 'vue', 'angular', 'flutter', 'react-native'],
},
{
href: '/theming/responsive',
Expand Down Expand Up @@ -530,7 +530,7 @@ export const theming: ComponentNavItem[] = [
{
href: '/theming/dark-mode',
label: 'Dark mode',
platforms: ['react', 'vue', 'angular', 'flutter'],
platforms: ['react', 'vue', 'angular', 'flutter', 'react-native'],
},
{
href: '/theming/css-variables',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,3 @@ The Authenticator has an option to hide the sign up page including the `Create A
<Fragment>
{({ platform }) => import(`./hidesignup.default.${platform}.mdx`)}
</Fragment>

<Example>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this since it was rendering the React web authenticator

<Authenticator hideSignUp={true} />
</Example>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

## Styling

### Theme Provider

You can update the style of the Authenticator by wrapping it with a [ThemeProvider](/react-native/theming). Then create a [theme object](/react-native/theming#theme-structure), with all your font customizations.

```jsx file=../../../../../../../examples/react-native/src/features/Authenticator/Theming/Example.tsx
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is a good idea so we can test the example even if we aren't rendering it in the docs

```

> If you have TypeScript enabled, all the object keys will be present when creating the [theme object](/react-native/theming#theme-structure). This will help speed up your development time while creating themes.

### Dark mode

Amplify UI comes with a default dark mode implementation

```jsx file=../../../../../../../examples/react-native/src/features/Authenticator/Theming/DarkMode.tsx
```

[Learn more about dark mode](/react-native/theming/dark-mode)
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export async function getStaticProps() {
{({ platform }) => import(`./formfields/form-fields.${platform}.mdx`)}
</Fragment>

<Fragment useCommonWebContent platforms={['web', 'flutter']}>
<Fragment useCommonWebContent platforms={['web','react-native']}>
{({ platform }) => import(`./customization.styling.${platform}.mdx`)}
</Fragment>

Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/[platform]/theming/dark-mode/index.page.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Dark Mode
metaDescription: Dark Mode uses a darker color palette for all screens, making foreground content stand out against darker backgrounds.
supportedFrameworks: react|angular|vue|flutter
supportedFrameworks: react|angular|vue|flutter|react-native
dbanksdesign marked this conversation as resolved.
Show resolved Hide resolved
---

import { Fragment } from '@/components/Fragment';
Expand Down
101 changes: 101 additions & 0 deletions docs/src/pages/[platform]/theming/dark-mode/react-native.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Alert, Tabs, TabItem } from '@aws-amplify/ui-react';
import { Example, ExampleCode } from '@/components/Example';

## Overview

Amplify UI supports color modes/schemes, like Dark Mode, through theme overrides. Amplify UI Theme Overrides let you define different theme styles in different contexts, such as color mode.

## ThemeProvider

The `ThemeProvider` accepts a `colorMode` prop which can be `light`, `dark`, or `system`.

<Alert role="none" variation="warning">

If you have multiple `ThemeProvider`s in your application, make sure to store `colorMode` in the application's state or context and pass it to each `ThemeProvider` or else some parts of your app won't have the right color mode applied. Also, because the theme uses CSS variables which are inherited, your application can have some weird behavior with nested themes and color modes.

</Alert>

## Default Dark Mode

Amplify UI comes with a default dark mode that you can use. Import the `defaultDarkModeOverride` and add it to the overrides array in your theme.

If you want to honor your users' operating system preference for color mode, you can send the `useColorScheme` hook from React Native to the `colorMode` prop on the `ThemeProvider`.

```jsx
import * as React from 'react';
import { useColorScheme } from 'react-native';
import { defaultDarkModeOverride, ThemeProvider } from '@aws-amplify/ui-react';
dbanksdesign marked this conversation as resolved.
Show resolved Hide resolved

const theme = {
overrides: [defaultDarkModeOverride],
};

export const DefaultDarkMode = () => {
const colorMode = useColorScheme();

return (
<ThemeProvider theme={theme} colorMode={colorMode}>
{/* ... */}
</ThemeProvider>
);
};
```

You can also control the color mode in your application as well by keeping a state variable that is either `'light'` or `'dark'`.

```jsx
import * as React from 'react';
import { Pressable, Text } from 'react-native';
import { ThemeProvider } from '@aws-amplify/ui-react-native';

const theme = {
overrides: [defaultDarkModeOverride],
};

export const CustomDarkModeExample = () => {
const [colorMode, setColorMode] = React.useState('light');

return (
// Note: color mode overrides are scoped to the ThemeProvider
// if you use multiple providers
<ThemeProvider theme={theme} colorMode={colorMode}>
<Pressable onPress={() => setColorMode(colorMode === 'light' ? 'dark' : 'light')}>
<Text>Change theme</Text>
</Pressable>
</ThemeProvider>
);
};
```

## Custom dark mode

You can create your own dark mode override as well. The dark mode override will be applied when `colorMode` on the `ThemeProvider` is set to `dark`.

```jsx
const theme = {
overrides: [
{
colorMode: 'dark',
tokens: {
colors: {
font: {
primary: '{colors.pink.100}',
secondary: '{colors.pink.90}',
tertiary: '{colors.pink.80}',
},
background: {
primary: '{colors.purple.10}',
secondary: '{colors.purple.20}',
tertiary: '{colors.purple.40}',
},
border: {
primary: '{colors.pink.60}',
secondary: '{colors.pink.40}',
tertiary: '{colors.pink.20}',
},
},
},
},
],
};
```
2 changes: 1 addition & 1 deletion docs/src/pages/[platform]/theming/index.page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Overview
metaTitle: Theming
metaDescription: A Theme is a structured collection of design decisions that change the appearance of a UI library. An Amplify UI theme is a structured object of design tokens, breakpoints, and overrides.
supportedFrameworks: react|angular|vue|flutter
supportedFrameworks: react|angular|vue|flutter|react-native
---

import { Fragment } from '@/components/Fragment';
Expand Down
101 changes: 101 additions & 0 deletions docs/src/pages/[platform]/theming/theming.react-native.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
A Theme is a structured collection of design decisions that change the appearance of a UI library. An Amplify UI theme is a structured object of [design tokens](#design-tokens) and [overrides](#overrides).


## Getting started

Wrap your application in a `ThemeProvider` and pass in a `Theme` object

```jsx
import { ThemeProvider } from '@aws-amplify/ui-react-native';

const theme = {
tokens: {
colors: {
font: {
primary: 'black'
}
}
}
}

export default function App() {
return (
<ThemeProvider theme={theme}>
{/* ... */}
</ThemeProvider>
)
}
```

## Theme Structure

### Design Tokens

Amplify UI uses [Design Tokens](https://www.designtokens.org/) for storing design decisions and is the primary way to theme the components.

Amplify UI follows the [System UI Theme Specification](https://system-ui.com/theme/) with some modifications. The System UI Theme Specification outlines top-level namespaces for categorizing design token types. For example, colors go under the `colors` namespace. This specification is used by [Stitches](https://stitches.dev/docs/tokens), [Chakra-UI](https://chakra-ui.com/docs/styled-system/theme), and [Evergreen](https://evergreen.segment.com/introduction/theming).

You can define as much or as little as you like in your theme. A simple might define the brand colors and not much else

```javascript
const theme = {
tokens: {
colors: {
brand: {
primary: {
10: '{colors.pink.10}',
20: '{colors.pink.20}',
40: '{colors.pink.40}',
60: '{colors.pink.60}',
80: '{colors.pink.80}',
90: '{colors.pink.90}',
100: '{colors.pink.100}',
}
}
}
}
}
```

A full theme would look like this:

```javascript
const theme = {
tokens: {
colors: {},
fontSizes: {},
}
}
```

### Overrides

An override is a collection of design tokens that should take precedence in certain situations, like dark mode. Overrides are built into the theme configuration, but kept separate, so that token references and values can be resolved at runtime.

```javascript
const theme = {
tokens: {
colors: {
white: '#fff',
black: '#000',
background: {
// This will resolve to #fff in light mode
// and #000 in dark mode because of the override below
primary: '{colors.white}'
},
font: {
primary: '{colors.black}'
}
}
},
overrides: [{
colorMode: 'dark',
tokens: {
colors: {
white: '#000',
black: '#fff'
}
}
}]
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';

import {
Authenticator,
defaultDarkModeOverride,
ThemeProvider,
} from '@aws-amplify/ui-react-native';
import { Amplify } from 'aws-amplify';

import config from './aws-exports';
import { useColorScheme } from 'react-native';
dbanksdesign marked this conversation as resolved.
Show resolved Hide resolved

Amplify.configure(config);

function App() {
const colorMode = useColorScheme();
return (
<ThemeProvider
colorMode={colorMode}
theme={{
tokens: {
colors: {
brand: {
primary: {
10: '{colors.pink.10}',
20: '{colors.pink.20}',
40: '{colors.pink.40}',
60: '{colors.pink.60}',
80: '{colors.pink.80}',
90: '{colors.pink.90}',
100: '{colors.pink.100}',
},
},
},
},
overrides: [defaultDarkModeOverride],
}}
>
<Authenticator.Provider>
<Authenticator></Authenticator>
dbanksdesign marked this conversation as resolved.
Show resolved Hide resolved
</Authenticator.Provider>
</ThemeProvider>
);
}

export default App;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

import { Authenticator, ThemeProvider } from '@aws-amplify/ui-react-native';
import { Amplify } from 'aws-amplify';

import config from './aws-exports';

Amplify.configure(config);

function App() {
return (
<ThemeProvider
theme={{
tokens: {
colors: {
brand: {
primary: {
10: '{colors.pink.10}',
20: '{colors.pink.20}',
40: '{colors.pink.40}',
60: '{colors.pink.60}',
80: '{colors.pink.80}',
90: '{colors.pink.90}',
100: '{colors.pink.100}',
},
},
},
},
}}
>
<Authenticator.Provider>
<Authenticator></Authenticator>
dbanksdesign marked this conversation as resolved.
Show resolved Hide resolved
</Authenticator.Provider>
</ThemeProvider>
);
}

export default App;