Skip to content

Commit

Permalink
feat(ui): embed cool features into ui and update readme (#2583)
Browse files Browse the repository at this point in the history
* feat(ui): embed cool features into ui and update readme

* feat(ui): typo
  • Loading branch information
UnbearableBear authored Apr 7, 2020
1 parent 304c9bf commit e97765a
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 51 deletions.
3 changes: 1 addition & 2 deletions packages/code-du-travail-frontend/pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import App from "next/app";
import getConfig from "next/config";
import * as Sentry from "@sentry/browser";

import { GlobalStyles } from "@socialgouv/react-ui";
import { GlobalStyles, ThemeProvider } from "@socialgouv/react-ui";

import ErrorPage from "./_error";

import { initPiwik } from "../src/piwik";
import { initializeSentry } from "../src/sentry";

import { ThemeProvider } from "../src/layout/ThemeProvider.js";
import { A11y } from "../src/a11y";

import HeadBandAlert from "../src/common/HeadBandAlert";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import {
Modal,
Title,
theme,
useTheme,
} from "@socialgouv/react-ui";

import { useTheme } from "../layout/ThemeProvider.js";

export const AccessibilityModal = ({ children: renderProp }) => {
const [isModalVisible, setModalVisibility] = useState(false);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import React from "react";
import { render, wait } from "@testing-library/react";
import { render } from "@testing-library/react";
import { Button } from "@socialgouv/react-ui";
import {
BLACK_AND_WHITE_STORAGE_KEY,
ThemeProvider,
} from "../../layout/ThemeProvider";
import { AccessibilityModal } from "../AccessibilityModal";

describe("<AccessibilityModal />", () => {
Expand Down Expand Up @@ -35,26 +31,6 @@ describe("<AccessibilityModal />", () => {
expect(baseElement).toMatchSnapshot();
});

it("has a checked checkbox if the localstorage has correct value set to true", async () => {
localStorage.setItem(BLACK_AND_WHITE_STORAGE_KEY, JSON.stringify(true));
const { getByText } = render(
<ThemeProvider>
<AccessibilityModal>
{(openModal) => (
<Button onClick={openModal}>texte dans le bouton</Button>
)}
</AccessibilityModal>
</ThemeProvider>
);
const button = getByText(/texte dans le bouton/i);
button.click();
await wait(() => {
const checkboxLabel = getByText(/noir et blanc/i);
const input = checkboxLabel.querySelector("input");
expect(input.hasAttribute("checked")).toBeTruthy();
});
});

it("closes the modal", async () => {
const { getByText, getByTitle, queryByLabelText } = render(
<AccessibilityModal>
Expand Down
75 changes: 71 additions & 4 deletions packages/react-ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ https://socialgouv-react-ui.netlify.com/

Build is automatically triggered by netlify everytime a changed is pushed to the master branch.

## Usage
## Using components

```js
This one is pretty straightforward

```js
import { Component, AnotherComponent } from "@socialgouv/react-ui"

const App = (
Expand All @@ -18,15 +19,81 @@ const App = (
)
```

## Theming
## Providing a theme

React UI is a themed UI. In order to make it work in your project, you must provide it with a theme.

### Basic option

```js
import { ThemeProvider } from "styled-components";
import { theme } from "../../src/theme";

const { colors } = theme;

export default class MyApp extends App {
render() {
const { children } = this.props;
return (
<ThemeProvider theme={colors}>
<>{children}</>
</ThemeProvider>
);
}
};
```

All you need is to wrap your root component inside the styled component's theme provider and give is a set of colors.

Here, colors are React UI ones, but you can pick others. Simply follow the structure of the exported `colors` item here: [./src/theme.js](https://github.com/SocialGouv/code-du-travail-numerique/blob/master/packages/react-ui/src/theme.js)

### Simpler option

If you don't wish to use you own colors, you can also do:

```js
import { ThemeProvider } from "@socialgouv/react-ui";

// This is an example for next.js
export default class MyApp extends App {
render() {
const { children } = this.props;
return (
<ThemeProvider>
<>{children}</>
</ThemeProvider>
);
}
};
```

With this approach, you also benefit from the theme hook which implements a theme swap feature. You will toggle from the basic theme to the black and white one. Simply do the following:

```js
import { useTheme } from "@socialgouv/react-ui";

...

const { currentTheme, toggleTheme } = useTheme();

...

toggleTheme();
```

Make sure you don't call `toggleTheme` inside the render of a component otherwise you'll get the dreaded infinite rendering loop.

## Using colors and variables

When you wish to set a color, please do not use the color variable from the theme in the `@socialgouv/react-ui` package.
Use the `theme` prop provided by styled-components.

Not OK: ~~`color: ${theme.colors.paragraph};`~~<br />
OK: `color: ${({theme }) => theme.paragraph};`

Otherwise, the color won't change when the theme is dynamically modified. For eveything else, using the `themr.js` file is always the right thing to do: <br />
Otherwise, the color won't change when the theme is dynamically modified. For eveything else, using the `theme.js` file is always the right thing to do.

While contributing to the project, for example, you should do:
``` js
import { box, spacings } from "../theme";
const P = styled.p`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,57 @@
import React, { useState, useContext, useEffect, useMemo } from "react";
import { ThemeProvider as StyledThemeProvider } from "styled-components";
import { theme } from "@socialgouv/react-ui";

import { useLocalStorage } from "../lib/useLocalStorage";
import { blackAndWhiteColors, colors } from "./theme";

export const BLACK_AND_WHITE_STORAGE_KEY = "blackAndWhiteTheme";

const { colors, blackAndWhiteColors } = theme;

const ThemeContext = React.createContext({
currentTheme: colors,
toggleTheme: () => {},
});

const isBlackAndWhiteTheme = () => {
if (typeof window !== "undefined") {
return (
window.localStorage &&
Boolean(
window.localStorage.getItem(BLACK_AND_WHITE_STORAGE_KEY) === "true"
)
);
}
return false;
};

const setBlackAndWhiteTheme = (value) => {
if (typeof window !== "undefined") {
window.localStorage &&
window.localStorage.setItem(BLACK_AND_WHITE_STORAGE_KEY, value);
}
};

export const ThemeProvider = (props) => {
const [isBlackAndWhiteTheme, setBlackAndWhiteTheme] = useLocalStorage(
BLACK_AND_WHITE_STORAGE_KEY,
false
);
const [currentTheme, setCurrentTheme] = useState(colors);

useEffect(() => {
if (isBlackAndWhiteTheme) {
if (isBlackAndWhiteTheme()) {
setCurrentTheme(blackAndWhiteColors);
}
}, [isBlackAndWhiteTheme]);
}, [currentTheme]);

const api = useMemo(
() => ({
currentTheme,
toggleTheme: () => {
if (currentTheme === colors) {
setCurrentTheme(blackAndWhiteColors);
setBlackAndWhiteTheme(true);
setBlackAndWhiteTheme("true");
} else {
setCurrentTheme(colors);
setBlackAndWhiteTheme(false);
setBlackAndWhiteTheme("false");
}
},
}),
[currentTheme, setBlackAndWhiteTheme]
[currentTheme]
);

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import React from "react";
import React, { useEffect } from "react";
import { render } from "@testing-library/react";
import { ThemeProvider, useTheme } from "../ThemeProvider";
import {
BLACK_AND_WHITE_STORAGE_KEY,
ThemeProvider,
useTheme,
} from "./ThemeProvider";

const checkFunction = jest.fn();

const DummyComponent = () => {
const { currentTheme, toggleTheme } = useTheme();
if (typeof currentTheme === "object" && typeof toggleTheme === "function") {
checkFunction();
}
useEffect(() => {
if (typeof currentTheme === "object" && typeof toggleTheme === "function") {
checkFunction();
toggleTheme();
}
}, []);
return null;
};

Expand All @@ -21,5 +28,6 @@ describe("<ThemeProvider />", () => {
</ThemeProvider>
);
expect(checkFunction).toHaveBeenCalled();
expect(localStorage.getItem(BLACK_AND_WHITE_STORAGE_KEY)).toBe("true");
});
});
3 changes: 3 additions & 0 deletions packages/react-ui/src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import * as keyframes from "./keyframes";
import * as theme from "./theme";

// Theme Provider
export { ThemeProvider, useTheme } from "./ThemeProvider";

// Layout
export { Container } from "./layout/Container";
export { Section } from "./layout/Section";
Expand Down

0 comments on commit e97765a

Please sign in to comment.