` β `` π
+- `` β `` π
+- `` β `` π
+- `` β `` π
+
+---
+
+
+
+> Primitives can be rendered anywhere
+
+
+
+---
+
+
+
+---
+
+
+
+# Responsive design
+
+
+
+---
+
+
+
+**Prop per breakpoint** vs. **all props are responsive**
+
+
+
+---
+
+
+
+
+```jsx
+
+
+ Pizza
+
+
+```
+
+```jsx
+// breakpoints: [small, medium, large]
+
+ Pizza
+
+```
+
+
+
+
+---
+
+
+
+---
+
+
+
+Now let's compose primitives...
+
+
+
+---
+
+
+
+---
+
+
+
+# Layout Primitives
+
+
+
+---
+
+
+
+
+
+---
+
+
+
+> Primitives to control layout and white space around their children
+
+
+
+---
+
+
+
+# Box
+
+
+
+---
+
+## API design
+
+- Layout (`width`, `height`, etc.)
+- White space (`margin`, `padding`)
+- Colors (`background`, `color`)
+- Borders (`border`, `border-radius`),
+- Shadows (`box-shadow`),
+- HTML elements (`div`, `span`, `section`, ...)
+
+---
+
+
+
+```javascript
+import styled from '@emotion/styled';
+import { layout, space, color, border, boxShadow } from 'styled-system';
+
+export const Box = styled.div(
+ // defaults
+ {
+ minWidth: 0,
+ },
+ // API
+ layout,
+ space,
+ color,
+ border,
+ boxShadow
+);
+```
+
+
+
+---
+
+
+
+---
+
+
+
+> Model API based on CSS knowledge
+
+
+
+---
+
+
+
+# Flex
+
+
+
+---
+
+## Flexbox layout
+
+```jsx
+
+```
+
+---
+
+
+
+---
+
+
+
+# Grid
+
+
+
+---
+
+
+
+---
+
+
+
+# Stack
+
+
+
+---
+
+
+
+---
+
+
+
+# Group
+
+
+
+---
+
+
+
+---
+
+
+
+> Primitives should not have any whitespace around them!
+
+
+
+---
+
+
+
+# Primitives Composition
+
+
+
+---
+
+## API: Composition
+
+- `` β ``
+- `` β ``
+- `` β ``
+
+---
+
+
+
+> Primitives are meant to be composed
+
+
+
+---
+
+
+
+# Patterns
+
+
+
+---
+
+
+
+> A design pattern is the re-usable form of a solution to a design problem.
+
+
+
+---
+
+
+
+---
+
+
+
+---
+
+
+
+# Demo
+
+
+
+---
+
+
+
+---
+
+
+
+---
+
+
+ react-styleguidist}
+ gap={4}
+ />
+
+
+
+
+I have stickers with me. Please go grab one after the talk!
+
+
+
+---
+
+
+
+# Recap
+
+
+
+---
+
+## Recap
+
+1. Components are a common UI language
+1. Components is a better way of writing HTML & CSS
+1. Use design tokens to reduce choice
+1. Use primitive components (Text, Box)
+1. Do not make any assumptions
+1. Use layout primitives to control the white space
+1. Compose complex components using primitives
+
+---
+
+
+
+# The future of UI development
+
+
+
+---
+
+## Building UIs with primitives & patterns
+
+1. Get a ~~static mockup~~ wireframe from a designer
+1. Get data from API endpoint
+1. Assembly UI using primitives or re-use a pattern.
+1. ...
+1. Profit
+
+---
+
+
+
+---
+
+## Links and credits
+
+- https://styled-system.com
+- https://react-styleguidist.js.org
+- https://github.com/sapegin/stack-styled
+- https://github.com/sapegin/react-group
+- https://airbnb.design/sketching-interfaces/
+
+---
+
+
+ https://component-driven.io
+ }
+ >
+
+
+---
+
+
+
+# Thank you and let components be with you!
+
+
+ @okonetchnikov
+ @ComponentDriven
+ andrey@okonet.ru
+
+
+
diff --git a/slides/code/Box-Text.js b/slides/code/Box-Text.js
index 1766ff58..e7d6a20b 100644
--- a/slides/code/Box-Text.js
+++ b/slides/code/Box-Text.js
@@ -15,7 +15,7 @@
borderColor="grey.5"
>
-```
diff --git a/src/exercises/5-Patterns/LoginForm.js b/src/exercises/5-Patterns/LoginForm.js
new file mode 100644
index 00000000..8dd9efd5
--- /dev/null
+++ b/src/exercises/5-Patterns/LoginForm.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import {
+ Box,
+ Button,
+ Flex,
+ Grid,
+ Heading,
+ Input,
+ Link,
+ Stack,
+ Text,
+} from '../../components';
+
+export default () => {
+ return ;
+};
diff --git a/src/exercises/5-Patterns/LoginForm.md b/src/exercises/5-Patterns/LoginForm.md
new file mode 100644
index 00000000..cedb1d7f
--- /dev/null
+++ b/src/exercises/5-Patterns/LoginForm.md
@@ -0,0 +1,3 @@
+```jsx
+
+```
diff --git a/src/exercises/5-Patterns/LoginPage.js b/src/exercises/5-Patterns/LoginPage.js
deleted file mode 100644
index 4e1a9854..00000000
--- a/src/exercises/5-Patterns/LoginPage.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react';
-import Box from '../../components/primitives/Box';
-import Flex from '../../components/primitives/Flex';
-import Heading from '../../components/primitives/Heading';
-import Button from '../../components/primitives/Button';
-import Link from '../../components/primitives/Link';
-import Text from '../../components/primitives/Text';
-import Input from '../../components/primitives/Input';
-
-const LoginPage = () => {
- return ;
-};
-
-export default LoginPage;
diff --git a/src/exercises/5-Patterns/LoginPage.md b/src/exercises/5-Patterns/LoginPage.md
deleted file mode 100644
index fb790041..00000000
--- a/src/exercises/5-Patterns/LoginPage.md
+++ /dev/null
@@ -1,3 +0,0 @@
-```jsx harmony
-
-```
diff --git a/src/exercises/5-Patterns/Readme.md b/src/exercises/5-Patterns/Readme.md
index 2822b394..143cbff7 100644
--- a/src/exercises/5-Patterns/Readme.md
+++ b/src/exercises/5-Patterns/Readme.md
@@ -1,79 +1,31 @@
-## 5.1 Using layout and basic primitive to compose UI patterns
+## 5.1 Creating a login form using primitives
In the previous exercise we learned how to manage whitespace around our primitives. Now it's time to use what we learned and create an application specific component.
-### The result
-
-```jsx noeditor
-import SubscriptionForm from '../../../src/components/patterns/SubscriptionForm';
-
- {}}
- onEmailChange={() => {}}
-/>;
-```
-
-### The task
-
-1. Create a `SubscriptionForm` component using the `Grid` component.
-2. The layout should be responsive and the button should be placed below the input field on a narrow screen.
-
-**Hint:** Use `grid-template-columns` CSS property for responsiveness, like this: `gridTemplateColumns={['1fr', '1fr auto']}`.
-
-
- Solution
-
-```js {"file": "solutions/5.1.js", "static": true}
-```
-
-
-
-## 5.2 Creating a new page using primitives
-
Using `Box` and `Flex` components we can create really complex layouts without writing custom CSS. And since the values for the spacing are coming from our [spacing scale](https://cdds.netlify.com/styleguide/#/Foundation?id=spacing) we can be sure our layouts are consistent across the whole application.
-We can even create full pages. Letβs try to create a new login page four our app.
+Letβs create a login form four our app.
### The result
-```jsx noeditor
-import Box from '../../components/primitives/Box';
-import Flex from '../../components/primitives/Flex';
-import Heading from '../../components/primitives/Heading';
-import Button from '../../components/primitives/Button';
-import Link from '../../components/primitives/Link';
-import Text from '../../components/primitives/Text';
-import Input from '../../components/primitives/Input';
-
-;
+```js noeditor
+import LoginForm from './final/LoginForm';
+
```
### The task
-1. Create a `LoginPage` component.
+1. Create a `LoginForm` component.
+2. Use only primitives for layout, whitespace (`Box`, `Flex`, `Grid`, and `Stack`) and text (`Text`, `Heading`, `Button`, and `Link`).
+3. The layout should be responsive and the labels should be placed above input fields on a narrow screen.
+
+**Hint:** Use arrays for responsiveness, like this: `gridTemplateColumns={['1fr', '1fr auto']}`.
-2. Use only primitives for layout, whitespace (`Box`, `Flex`, `Grid`, and `Stack`) and text (`Text`, `Heading` and `Link`).
Solution
-```js {"file": "solutions/5.2.js", "static": true}
+```js {"file": "./final/LoginForm.js", "static": true}
```
diff --git a/src/exercises/5-Patterns/SubscriptionForm.js b/src/exercises/5-Patterns/SubscriptionForm.js
deleted file mode 100644
index b9058271..00000000
--- a/src/exercises/5-Patterns/SubscriptionForm.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react';
-import Stack from '../../components/primitives/Stack';
-import Box from '../../components/primitives/Box';
-import Button from '../../components/primitives/Button';
-import Input from '../../components/primitives/Input';
-
-const SubscriptionForm = ({
- id,
- onSubmit,
- onEmailChange,
- email,
- loading,
- success,
- error,
-}) => (
-
-);
-
-export default SubscriptionForm;
diff --git a/src/exercises/5-Patterns/SubscriptionForm.md b/src/exercises/5-Patterns/SubscriptionForm.md
deleted file mode 100644
index 11611436..00000000
--- a/src/exercises/5-Patterns/SubscriptionForm.md
+++ /dev/null
@@ -1,3 +0,0 @@
-```jsx harmony
-
-```
diff --git a/src/exercises/5-Patterns/final/LoginForm.js b/src/exercises/5-Patterns/final/LoginForm.js
new file mode 100644
index 00000000..8c25441e
--- /dev/null
+++ b/src/exercises/5-Patterns/final/LoginForm.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import {
+ Heading,
+ Text,
+ Box,
+ Flex,
+ Grid,
+ Input,
+ Link,
+ Button,
+ Stack,
+} from '../../../components';
+
+export default () => {
+ return (
+
+ Login please
+
+
+ Username
+
+
+
+
+
+ Password
+
+
+
+
+
+
+ Log in
+
+
+
+ Forgot your password?
+
+
+
+ );
+};
diff --git a/src/exercises/5-Patterns/solutions/5.1.js b/src/exercises/5-Patterns/solutions/5.1.js
deleted file mode 100644
index 804eae42..00000000
--- a/src/exercises/5-Patterns/solutions/5.1.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/* eslint-disable jsx-a11y/accessible-emoji */
-import React from 'react';
-import Grid from '../../../../src/components/primitives/Grid';
-import Button from '../../../../src/components/primitives/Button';
-import Input from '../../../../src/components/primitives/Input';
-
-const SubscriptionForm = ({
- id,
- onSubmit,
- onEmailChange,
- email,
- loading,
- success,
- error,
-}) => (
-
-
-
- Subscribe
-
-
-);
-
-export default SubscriptionForm;
diff --git a/src/exercises/5-Patterns/solutions/5.2.js b/src/exercises/5-Patterns/solutions/5.2.js
deleted file mode 100644
index 58c5ddd0..00000000
--- a/src/exercises/5-Patterns/solutions/5.2.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import Box from '../../../../components/primitives/Box';
-import Flex from '../../../../components/primitives/Flex';
-import Heading from '../../../../components/primitives/Heading';
-import Button from '../../components/primitives/Button';
-import Link from '../../../../components/primitives/Link';
-import Text from '../../../../components/primitives/Text';
-import Input from '../../../../components/primitives/Input';
-
-const LoginPage = () => {
- return (
-
- );
-};
-
-export default LoginPage;
diff --git a/styleguide.config.js b/styleguide.config.js
index c2c74aaa..e2c4ffbb 100644
--- a/styleguide.config.js
+++ b/styleguide.config.js
@@ -23,6 +23,15 @@ const config = {
pagePerSection: true,
exampleMode: 'expand',
usageMode: 'expand',
+ compilerConfig: {
+ transforms: {
+ // Support for styled-components
+ dangerousTaggedTemplateString: true,
+
+ // "Support" for `import` syntax
+ moduleImport: false,
+ },
+ },
webpackConfig,
updateExample(props, exampleFilePath) {
const { settings, lang } = props;