Skip to content

Commit

Permalink
Add Theming (#1454)
Browse files Browse the repository at this point in the history
* Add ThemeProvider

* Add initial types

* Forgot default export

* Add colors to theme

* Fix types

* Allow ThemeProvider to update theme on instance

* Merge incoming theme

* Add theming to Button

* Move button colors to context

* Add theming for Checkbox

* Make buttongroup themeable

* Make header themeable

* Make badge themeable

* Pull correct references from theme for components

* Make avatar themeable

* Export lodash.merge from config

* Make Divider themeable

* Remove theme from avatar(doesn't need)

* Make card themeable

* Make Icon themeable

* Make Input themeable

* Make ListItem themeable

* Make overlay themeable

* Make PricingCard themeable, color no longer required prop

* Make Rating themeable

* Use error color from theme for Input

* Properly theme Input (add instance methods)

* Make SearchBar themeable

* Make Slider themeable

* Make SocialIcon themeable

* Use right theming variables

* Make Text themeable

* Make Tile themeable

* Make Tooltip themeable

* Update components to use withTheme

* Prettier avatar

* fix: PricingCard normalizeText import

* fix: Input errorProps and labelProps propType

* fix(types): Add Badge to theme

* fix: ThemeText component correctly

* fix: Use colors from colors file

* fix(Tile): Correct imports for BackgroundImage

* fix(types): Typo for Tooltip theme

* test: Update Text tests for the new theme

* test: Update Badge tests for the new theme

* test: Update CheckBox tests for the new theme

* test: Update Icon tests for the new theme

* test: Update Button tests for the new theme

* test: Update SocialIcon tests for the new theme

* test: Update Divider tests for the new theme

* test(CheckBox): Use correct test prop

* test: Update ButtonGroup tests for the new theme

* test: Update Card tests for the new theme

* test: Update Tile tests for the new theme

* test: Update FeaturedTile tests for the new theme

* fix(Button): Typo, should be StyleSheet.flatten

* test: Update PricingCard tests for the new theme

* test: Update Slider tests for the new theme

* test: Update Header tests for the new theme

* test: Update Rating tests for the new theme

* test: Update Overlay tests for the new theme

* test: Update ListItem tests for the new theme

* test: Update Input tests for the new theme

* test: Update SearchBar tests for the new theme

* test: Update Tooltip tests for the new theme

* test: Add test for ThemeProvider

* test(Icon): Add test for using values from theme

* style(tests): One line default import with object import

* chore: Update yarn.lock

* feat(theme): Pass updateTheme through the hoc

* feat(theme): Export withTheme HOC

* docs: Add documentation on theming

* feat(theme): Make ThemeProvider usage optional

* docs(theme): Add component instructions

[ci-skip]

* feat(theme): Make withTheme work with refs

* test: Input and SearchBar now use withTheme HOC

* style: Remove flow type from file

[ci skip]

* fix(types): Correct return type for withTheme
  • Loading branch information
iRoachie committed Oct 10, 2018
1 parent 78f961f commit e9750c8
Show file tree
Hide file tree
Showing 87 changed files with 9,076 additions and 6,168 deletions.
258 changes: 249 additions & 9 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,258 @@ id: customization
title: Customization
---

Congrats! You've installed React Native Elements and your immediate question goes something like this:
Congrats! You've installed React Native Elements and your immediate question
goes something like this:

> So umm, how I do change how it looks?
Great question! A UI Kit wouldn't be that useful if the apps everyone built looked the same right? For this case
React Native Elements provide a number of props on each component to enable you to style them how you want.
Great question! A UI Kit wouldn't be that useful if the apps everyone built
looked the same right? For this case React Native Elements provide a number of
props on each component to enable you to style them how you want.

### Containers
## Component Styles

_Every_ component from React Native Elements has a container around it. The container is just a traditional `<View />` from
react native that has some styling on it. This default styling prevents components from colliding with each other.
If you want to change how two components react to each on the screen your first stop should be the `containerStyle` prop.
_Every_ component from React Native Elements has a container around it. The
container is just a traditional `<View />` from react native that has some
styling on it. This default styling prevents components from colliding with each
other. If you want to change how two components react to each on the screen your
first stop should be the `containerStyle` prop.

Similar to `containerStyle`, components may provide their custom style props like `buttonStyle`, `titleStyle` etc.
Always refer to the component doc to find out which style props the component provides.
Similar to `containerStyle`, components may provide their custom style props
like `buttonStyle`, `titleStyle` etc. Always refer to the documentation for the
component to find out which style props it provides.

## Theming

While component styles are great for single use, you may want to have the same
styling for every instance of a component. For example, you may want all your
buttons to be blue or have the same font. Here are some ways to reuse styles
with React Native Elements.

### Using Composition

With this approach, we create one component with the styles we want and use that
instead of the built-in component.

```jsx
import React from 'react';
import { Button } from 'react-native-elements';

const RaisedButton = props => <Button raised {...props} />;

// Your App
const App = () => {
return <RaisedButton title="Yea" />;
};
```

If we want to use a button that's raised in our app, we can use `RaisedButton`
instead of using `Button`. This component still accepts all the props from the
normal `Button` just that it has the `raised` prop set by default.

### Using ThemeProvider

The previous solution works great for only one component, but imagine having to
do this for every component you want custom styles for. That could get a bit
tedious to manage. Thankfully, there's a better way to do this. React Native
Elements ships with a 3 utilities for large-scale theming.

Firstly you'll want to set up your `ThemeProvider`.

```jsx
import { ThemeProvider, Button } from 'react-native-elements';

const theme = {
Button: {
raised: true,
},
};

// Your App
const App = () => {
return (
<ThemeProvider theme={theme}>
<Button title="My Button" />
<Button title="My 2nd Button" />
</ThemeProvider>
);
};
```

The example above acheives the same goals as the first example — apply the same
styles to multiple instances of `Button` in the app. However this example
applies the `raised` prop to every instance of `Button` inside the component
tree under `ThemeProvider`. Both of these buttons will have the `raised` prop
set to true.

This is extremely convenient and is made possible through
[React's Context API](https://reactjs.org/docs/context.html).

---

### Order of Styles

What happens now if we want a `Button` that isn't raised? To do that we have to
the understand the order in which styles are applied.

> Internal > Theme > External
#### Internal

Internal components styles are the styles which are defined in the component
file. These are applied first.

#### Theme

Theme styles are the values that are set by the ThemeProvider If present, these
are applied second.

```jsx
import { ThemeProvider, Button } from 'react-native-elements';

const theme = {
Button: {
titleStyle: {
color: 'red',
},
},
};

const App = () => {
return (
<ThemeProvider theme={theme}>
<Card title="My Button" />
</ThemeProvider>
);
};
```

This will override the white color for the title set in the component's style.

#### External

External styles are the styles which are set through the component props. These
are applied last and have the highest precendence.

```jsx
import { ThemeProvider, Button } from 'react-native-elements';

const theme = {
Button: {
titleStyle: {
color: 'red',
},
},
};

const App = () => {
return (
<ThemeProvider theme={theme}>
<Card title="My Button" titleStyle={{ color: 'pink' }} />
</ThemeProvider>
);
};
```

This will override both the white color for the title set in the component's
style as well as the red color set in the theme.

> Remember if you want to override the values set in the theme you can always
> use component props.
---

### The Theme Object

By default, the theme object looks like this. You can add whatever values you
want to the theme, and they will be merged with the default.

```tsx
interface theme {
colors: {
primary;
secondary;
grey0;
grey1;
grey2;
grey3;
grey4;
grey5;
greyOutline;
searchBg;
error;
divider;
};
}
```

Setting styles in the theme is as simple as using the name of the component, as
a key and the props you want to change as the value.

```jsx
import { ThemeProvider } from 'react-native-elements';

const theme = {
Avatar: {
rounded: true,
},
Badge: {
textStyle: { fontSize: 30 },
},
};

...

<ThemeProvider theme={theme}>
```

---

### Using the theme in your own components

You may want to make use of the theming utilities in your own components. For
this you can use the `withTheme` HOC exported from this library. It adds two
props to the component it wraps - `theme` and `updateTheme`.

```jsx
import React from 'react';
import { Text } from 'react-native';
import { withTheme } from 'react-native-elements';

function MyComponent(props) {
const { colors, updateTheme } = props.theme;
return <Text style={{ color: colors.primary }}>Yo!</Text>;
}

export default withTheme(MyComponent);
```

The `updateTheme` merges the theme passed in with the current theme.

```jsx
const theme = {
colors: {
primary: 'pink',
},
};

// We can update the primary color
updateTheme({ colors: { primary: 'red' } });
```

Don't want to wrap your components? You can use the `ThemeConsumer` component
which uses render props!

```jsx
import React from 'react';
import { Text } from 'react-native';
import { ThemeConsumer } from 'react-native-elements';

const MyComponent = () => (
<ThemeConsumer>
{({ theme }) => (
<Text style={{ color: theme.colors.primary }}>Yo!</Text>;
)}
</ThemeConsumer>
)
```
29 changes: 28 additions & 1 deletion docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,31 @@ id: overview
title: Overview
---

This section of the documentation describes the props and examples for all the components from React Native Elements.
This section of the documentation describes the props and examples for all the
components from React Native Elements.

## Using React Native Elements

The components in this library have a single theme running through them. From
one central location, we can update the colours used in all components. While
this was great for the developers of the library, the actual users also needed a
way to use this feature.

But why stop at colours? Why not allow the props of every component to be
defined in one central place? And so the idea behind theming with React Native
Elements was born!

```jsx
import { Button, ThemeProvider } from 'react-native-elements';

const MyApp = () => {
return (
<ThemeProvider>
<Button title="Hey!" />
</ThemeProvider>
);
};
```

To customize the theme, or use it within your own components, be sure to check
the docs on [Customization](customization.md).
20 changes: 10 additions & 10 deletions docs/pricing.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,29 @@ outer component styling (optional)

specify pricing information style

| Type | Default |
| :------------: | :-----------------------------------------------: |
| style (object) | none |
| Type | Default |
| :------------: | :-----: |
| style (object) | none |

---

### `pricingStyle`

specify pricing text style

| Type | Default |
| :------------: | :------------------------------------------------------------: |
| style (object) | none |
| Type | Default |
| :------------: | :-----: |
| style (object) | none |

---

### `titleStyle`

specify title text style

| Type | Default |
| :------------: | :-------------------------------------------------------------: |
| style (object) | none |
| Type | Default |
| :------------: | :-----: |
| style (object) | none |

---

Expand Down Expand Up @@ -128,7 +128,7 @@ pricing information (optional)

### `color`

color scheme for button & title (required)
color scheme for button & title

| Type | Default |
| :----: | :-----: |
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@
"logo": "https://opencollective.com/react-native-elements/logo.txt"
},
"dependencies": {
"lodash.merge": "^4.6.1",
"lodash.times": "^4.3.2",
"opencollective-postinstall": "^2.0.0",
"prop-types": "^15.5.8"
},
"devDependencies": {
"@types/react": "^16.4.16",
"@types/react-native": "^0.57.4",
"babel": "^6.23.0",
"babel-core": "^6.23.1",
Expand All @@ -46,8 +48,8 @@
"babel-loader": "^6.3.2",
"babel-preset-react-native": "4.0.0",
"codecov": "^2.1.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.6.0",
"enzyme-to-json": "^3.3.4",
"eslint": "^3.17.1",
"eslint-plugin-react": "^6.10.0",
Expand Down

0 comments on commit e9750c8

Please sign in to comment.