├── .gitignore ├── .prettierrc ├── README.md ├── deck.mdx ├── netlify.toml ├── onemorething.jpg ├── package-lock.json ├── package.json └── src ├── context.js ├── greeting-loader.js ├── greeting.1.1.js ├── greeting.class.1.1.js ├── greeting.class.1.2.js ├── greeting.class.1.3.js ├── greeting.class.2.1.js ├── greeting.class.3.1.js ├── greeting.class.3.2.js ├── greeting.class.3.3.js ├── greeting.class.4.1.js ├── greeting.class.5.1.js ├── greeting.class.5.2.js ├── greeting.class.5.3.js ├── greeting.class.5.4.js ├── greeting.hooks.1.1.js ├── greeting.hooks.1.2.js ├── greeting.hooks.1.3.js ├── greeting.hooks.1.4.js ├── greeting.hooks.2.1.js ├── greeting.hooks.3.1.js ├── greeting.hooks.3.2.js ├── greeting.hooks.3.3.js ├── greeting.hooks.4.1.js ├── greeting.hooks.4.2.js ├── greeting.hooks.5.1.js ├── greeting.hooks.5.2.js ├── greeting.hooks.5.3.js ├── greeting.hooks.6.1.js ├── greeting.hooks.6.2.js ├── greeting.hooks.6.3.js ├── row.js └── styles.css /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | public 4 | .cache -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "printWidth": 60 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MDX Deck + Code Surfer template 2 | 3 | This project was generated with the `npm init code-surfer-deck` command. 4 | 5 | ## Development 6 | 7 | To run the presentation deck in development mode: 8 | 9 | ```sh 10 | npm start 11 | ``` 12 | 13 | Edit the [`deck.mdx`](deck.mdx) file to get started. 14 | 15 | ## Exporting 16 | 17 | To build the presentation deck: 18 | 19 | ```sh 20 | npm run build 21 | ``` 22 | 23 | For more documentation see [MDX Deck](https://github.com/jxnblk/mdx-deck) and [Code Surfer](https://codesurfer.pomb.us/) 24 | -------------------------------------------------------------------------------- /deck.mdx: -------------------------------------------------------------------------------- 1 | import { Image, Notes, Head } from "mdx-deck"; 2 | import { CodeSurferColumns, Step } from "code-surfer"; 3 | import { 4 | vsDark as classTheme, 5 | nightOwl as hooksTheme, 6 | } from "@code-surfer/themes"; 7 | 8 | import GreetingLoader from "./src/greeting-loader"; 9 | import onemorething from "./onemorething.jpg"; 10 | 11 | export const theme = classTheme; 12 | 13 | 14 | React Hooks Intro 15 | 16 | 17 | This is a copy of [Dan's hooks demo](https://youtu.be/dpw9EHDh2bM?t=1051) from React Conf 18 | 19 | I built it to test [Code Surfer v3](https://codesurfer.pomb.us/) 20 | 21 | --- 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ```jsx file=./src/greeting.1.1.js 30 | ``` 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ```jsx 7 file=./src/greeting.1.1.js 39 | ``` 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ```jsx file=./src/greeting.class.1.1.js 48 | ``` 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | ```jsx file=./src/greeting.class.1.2.js 57 | ``` 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | ```jsx 10:12,15:17,25 file=./src/greeting.class.1.3.js 66 | ``` 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | ```jsx 1:31 file=./src/greeting.class.1.3.js 75 | ``` 76 | 77 | 78 | 79 | 80 | 81 | --- 82 | 83 | But let's take a step back 84 | 85 | --- 86 | 87 | 91 | 92 | 93 | 94 | 95 | 96 | ```jsx file=./src/greeting.1.1.js 97 | ``` 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | ```jsx 5,10 file=./src/greeting.hooks.1.1.js 106 | ``` 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | ```jsx 5 file=./src/greeting.hooks.1.1.js 115 | ``` 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | ```jsx 6,8:10,15[29:55] file=./src/greeting.hooks.1.2.js 124 | ``` 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | ```jsx 5:6 file=./src/greeting.hooks.1.2.js 133 | ``` 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | ```jsx file=./src/greeting.hooks.1.3.js 142 | ``` 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | ```jsx 1[15:40],5 file=./src/greeting.hooks.1.4.js 151 | ``` 152 | 153 | 154 | 155 | 156 | 157 | --- 158 | 159 | 160 | 161 | 162 | 163 | ```jsx file=./src/greeting.class.1.3.js title="Before Hooks" subtitle="A class component with state" 164 | ``` 165 | 166 | ```jsx file=./src/greeting.hooks.1.4.js title="After Hooks" subtitle="A function component with state" 167 | ``` 168 | 169 | 170 | 171 | 172 | 173 | ```jsx 7:9 file=./src/greeting.class.1.3.js title="Before Hooks" subtitle="state has to be an object" 174 | ``` 175 | 176 | ```jsx 5 file=./src/greeting.hooks.1.4.js title="After Hooks" subtitle="state could be anything" 177 | ``` 178 | 179 | 180 | 181 | 182 | 183 | ```jsx 7:12,16,24 file=./src/greeting.class.1.3.js title="Before Hooks" subtitle="we read and update the state using this.state and this.setState" 184 | ``` 185 | 186 | ```jsx 5,8,14[16:27] file=./src/greeting.hooks.1.4.js title="After Hooks" subtitle="the state and the setter are just variables in the function" 187 | ``` 188 | 189 | 190 | 191 | 192 | 193 | ```jsx 1[100],31[100] file=./src/greeting.class.1.3.js title="Before Hooks" 194 | ``` 195 | 196 | ```jsx 1[1:7,15:40],5 file=./src/greeting.hooks.1.4.js title="After Hooks" 197 | ``` 198 | 199 | 200 | 201 | 202 | 203 | --- 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | ```jsx file=./src/greeting.class.1.3.js 212 | ``` 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | ```jsx file=./src/greeting.class.2.1.js 221 | ``` 222 | 223 | 224 | 225 | 226 | 227 | --- 228 | 229 | 233 | 234 | 235 | 236 | 237 | 238 | ```jsx file=./src/greeting.hooks.1.4.js 239 | ``` 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | ```jsx file=./src/greeting.hooks.2.1.js 248 | ``` 249 | 250 | 251 | 252 | 253 | 254 | --- 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | ```jsx file=./src/greeting.class.2.1.js 263 | ``` 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | ```jsx file=./src/greeting.class.3.1.js 272 | ``` 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | ```jsx 30,31,32[20:37],46,47 file=./src/greeting.class.3.2.js 281 | ``` 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | ```jsx file=./src/greeting.class.3.3.js 290 | ``` 291 | 292 | 293 | 294 | 295 | 296 | --- 297 | 298 | 302 | 303 | 304 | 305 | 306 | 307 | ```jsx file=./src/greeting.hooks.2.1.js 308 | ``` 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | ```jsx 1[27:37,40:52],3 file=./src/greeting.hooks.3.1.js 317 | ``` 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | ```jsx 8,19[14:30] file=./src/greeting.hooks.3.2.js 326 | ``` 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | ```jsx file=./src/greeting.hooks.3.3.js 335 | ``` 336 | 337 | 338 | 339 | 340 | 341 | --- 342 | 343 | 344 | 345 | 346 | 347 | ```jsx 30,31,45,46,48,49,51,52 file=./src/greeting.class.3.3.js title="Before Hooks" 348 | ``` 349 | 350 | ```jsx 8,9 file=./src/greeting.hooks.3.3.js title="After Hooks" 351 | ``` 352 | 353 | 354 | 355 | 356 | 357 | --- 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | ```jsx file=./src/greeting.class.3.3.js 366 | ``` 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | ```jsx file=./src/greeting.class.4.1.js 375 | ``` 376 | 377 | 378 | 379 | 380 | 381 | --- 382 | 383 | 387 | 388 | 389 | 390 | 391 | 392 | ```jsx file=./src/greeting.hooks.3.3.js 393 | ``` 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | ```jsx 1,4,5 file=./src/greeting.hooks.4.1.js 402 | ``` 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | ```jsx file=./src/greeting.hooks.4.2.js 411 | ``` 412 | 413 | 414 | 415 | 416 | 417 | --- 418 | 419 | 420 | 421 | 422 | 423 | ```jsx 20:28 file=./src/greeting.class.4.1.js title="Before Hooks" subtitle="We have different lifecycle methods for mount and update" 424 | ``` 425 | 426 | ```jsx 15:17 file=./src/greeting.hooks.4.2.js title="After Hooks" 427 | ``` 428 | 429 | 430 | 431 | 432 | 433 | ```jsx 20:28 file=./src/greeting.class.4.1.js title="Before Hooks" subtitle="we use this.state to access state" 434 | ``` 435 | 436 | ```jsx 15:17 file=./src/greeting.hooks.4.2.js title="After Hooks" subtitle="the effect is inside the function component so we can use the variables from the function scope" 437 | ``` 438 | 439 | 440 | 441 | 442 | 443 | --- 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | ```jsx file=./src/greeting.class.4.1.js 452 | ``` 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | ```jsx file=./src/greeting.class.5.1.js 461 | ``` 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | ```jsx file=./src/greeting.class.5.2.js 470 | ``` 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | ```jsx file=./src/greeting.class.5.3.js 479 | ``` 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | ```jsx file=./src/greeting.class.5.4.js 488 | ``` 489 | 490 | 491 | 492 | 493 | 494 | --- 495 | 496 | 500 | 501 | 502 | 503 | 504 | 505 | ```jsx file=./src/greeting.hooks.4.2.js 506 | ``` 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | ```jsx file=./src/greeting.hooks.5.1.js 515 | ``` 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | ```jsx file=./src/greeting.hooks.5.2.js 524 | ``` 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | ```jsx 20,23:26 file=./src/greeting.hooks.5.3.js 533 | ``` 534 | 535 | 536 | 537 | 538 | 539 | --- 540 | 541 | 542 | 543 | 544 | 545 | ```jsx 22:35 file=./src/greeting.class.5.4.js title="Before Hooks" subtitle="the logic for the different effects is mixed and splitted apart in different methods" 546 | ``` 547 | 548 | ```jsx 15:17,20:26 file=./src/greeting.hooks.5.3.js title="After Hooks" subtitle="the code is separated based on what is doing instead of when it runs" 549 | ``` 550 | 551 | 552 | 553 | 554 | 555 | --- 556 | 557 | 558 | 559 | --- 560 | 561 | 565 | 566 | 567 | 568 | 569 | 570 | ```jsx 1:51 file=./src/greeting.hooks.5.3.js 571 | ``` 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | ```jsx 19:26 file=./src/greeting.hooks.5.3.js 580 | ``` 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | ```jsx file=./src/greeting.hooks.6.1.js 589 | ``` 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | ```jsx file=./src/greeting.hooks.6.2.js 598 | ``` 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | ```jsx 10,11,17:23,28,31:34 file=./src/greeting.hooks.6.2.js 607 | ``` 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | ```jsx 10,11,20,23,31:40 file=./src/greeting.hooks.6.3.js 616 | ``` 617 | 618 | 619 | 620 | 621 | 622 | --- 623 | 624 | 625 | 626 | 627 | 628 | ```jsx 5:77 file=./src/greeting.class.5.4.js 629 | ``` 630 | 631 | ```jsx 9:58 file=./src/greeting.hooks.6.3.js 632 | ``` 633 | 634 | 635 | 636 | 637 | 638 | --- 639 | 640 | [Code Surfer Docs](https://codesurfer.pomb.us/) 641 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | publish = "public/" 3 | command = "npm run build" 4 | 5 | [[redirects]] 6 | from = "/*" 7 | to = "/index.html" 8 | status = 200 -------------------------------------------------------------------------------- /onemorething.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pomber/react-conf-2018-hooks-demo/efe0e4156d98bc1364bc616df6b6c0065dd736c9/onemorething.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "mdx-deck deck.mdx", 6 | "build": "mdx-deck build deck.mdx", 7 | "test": "echo \"there are no tests\"" 8 | }, 9 | "devDependencies": { 10 | "code-surfer": "^3.0.0-beta.1", 11 | "mdx-deck": "3.0.10" 12 | }, 13 | "name": "react-conf-2018-hooks-demo" 14 | } 15 | -------------------------------------------------------------------------------- /src/context.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const theme = { 4 | golden: "theme-golden", 5 | }; 6 | 7 | export const locale = { 8 | rainbow: "🇬🇧", 9 | }; 10 | 11 | export const ThemeContext = React.createContext( 12 | theme.golden 13 | ); 14 | export const LocaleContext = React.createContext( 15 | locale.rainbow 16 | ); 17 | -------------------------------------------------------------------------------- /src/greeting-loader.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { useThemeUI } from "theme-ui"; 4 | 5 | const load = require.context("./", true, /greeting\..*js$/); 6 | 7 | export default function GreetingLoader({ 8 | version = "1.1", 9 | theme, 10 | }) { 11 | const Greeting = load("./greeting." + version + ".js") 12 | .default; 13 | 14 | const { themeUi } = useThemeUI(); 15 | 16 | const t = theme || themeUi; 17 | 18 | if (typeof window == `undefined`) { 19 | return null; 20 | } 21 | 22 | return ( 23 |
34 | 35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /src/greeting.1.1.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | 4 | export default function Greeting(props) { 5 | return ( 6 |
7 | {props.name} 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /src/greeting.class.1.1.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | 4 | export default class Greeting extends React.Component { 5 | render() { 6 | return ( 7 |
8 | {this.props.name} 9 |
10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/greeting.class.1.2.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | 4 | export default class Greeting extends React.Component { 5 | constructor(props) { 6 | super(props); 7 | this.state = { 8 | name: "Mary" 9 | }; 10 | } 11 | 12 | render() { 13 | return ( 14 |
15 | 16 | 17 | 18 |
19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/greeting.class.1.3.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | 4 | export default class Greeting extends React.Component { 5 | constructor(props) { 6 | super(props); 7 | this.state = { 8 | name: "Mary", 9 | }; 10 | this.handleNameChange = this.handleNameChange.bind( 11 | this 12 | ); 13 | } 14 | 15 | handleNameChange(e) { 16 | this.setState({ name: e.target.value }); 17 | } 18 | 19 | render() { 20 | return ( 21 |
22 | 23 | 27 | 28 |
29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/greeting.class.2.1.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | 4 | export default class Greeting extends React.Component { 5 | constructor(props) { 6 | super(props); 7 | this.state = { 8 | name: "Mary", 9 | surname: "Poppins", 10 | }; 11 | this.handleNameChange = this.handleNameChange.bind( 12 | this 13 | ); 14 | this.handleSurnameChange = this.handleSurnameChange.bind( 15 | this 16 | ); 17 | } 18 | 19 | handleNameChange(e) { 20 | this.setState({ name: e.target.value }); 21 | } 22 | 23 | handleSurnameChange(e) { 24 | this.setState({ surname: e.target.value }); 25 | } 26 | 27 | render() { 28 | return ( 29 |
30 | 31 | 35 | 36 | 37 | 41 | 42 |
43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/greeting.class.3.1.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default class Greeting extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | name: "Mary", 10 | surname: "Poppins", 11 | }; 12 | this.handleNameChange = this.handleNameChange.bind( 13 | this 14 | ); 15 | this.handleSurnameChange = this.handleSurnameChange.bind( 16 | this 17 | ); 18 | } 19 | 20 | handleNameChange(e) { 21 | this.setState({ name: e.target.value }); 22 | } 23 | 24 | handleSurnameChange(e) { 25 | this.setState({ surname: e.target.value }); 26 | } 27 | 28 | render() { 29 | return ( 30 |
31 | 32 | 36 | 37 | 38 | 42 | 43 |
44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/greeting.class.3.2.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default class Greeting extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | name: "Mary", 10 | surname: "Poppins", 11 | }; 12 | this.handleNameChange = this.handleNameChange.bind( 13 | this 14 | ); 15 | this.handleSurnameChange = this.handleSurnameChange.bind( 16 | this 17 | ); 18 | } 19 | 20 | handleNameChange(e) { 21 | this.setState({ name: e.target.value }); 22 | } 23 | 24 | handleSurnameChange(e) { 25 | this.setState({ surname: e.target.value }); 26 | } 27 | 28 | render() { 29 | return ( 30 | 31 | {theme => ( 32 |
33 | 34 | 38 | 39 | 40 | 44 | 45 |
46 | )} 47 |
48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/greeting.class.3.3.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default class Greeting extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | name: "Mary", 10 | surname: "Poppins", 11 | }; 12 | this.handleNameChange = this.handleNameChange.bind( 13 | this 14 | ); 15 | this.handleSurnameChange = this.handleSurnameChange.bind( 16 | this 17 | ); 18 | } 19 | 20 | handleNameChange(e) { 21 | this.setState({ name: e.target.value }); 22 | } 23 | 24 | handleSurnameChange(e) { 25 | this.setState({ surname: e.target.value }); 26 | } 27 | 28 | render() { 29 | return ( 30 | 31 | {theme => ( 32 |
33 | 34 | 38 | 39 | 40 | 44 | 45 | 46 | {locale => ( 47 | {locale} 48 | )} 49 | 50 |
51 | )} 52 |
53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/greeting.class.4.1.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default class Greeting extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | name: "Mary", 10 | surname: "Poppins", 11 | }; 12 | this.handleNameChange = this.handleNameChange.bind( 13 | this 14 | ); 15 | this.handleSurnameChange = this.handleSurnameChange.bind( 16 | this 17 | ); 18 | } 19 | 20 | componentDidMount() { 21 | document.title = 22 | this.state.name + " " + this.state.surname; 23 | } 24 | 25 | componentDidUpdate() { 26 | document.title = 27 | this.state.name + " " + this.state.surname; 28 | } 29 | 30 | handleNameChange(e) { 31 | this.setState({ name: e.target.value }); 32 | } 33 | 34 | handleSurnameChange(e) { 35 | this.setState({ surname: e.target.value }); 36 | } 37 | 38 | render() { 39 | return ( 40 | 41 | {theme => ( 42 |
43 | 44 | 48 | 49 | 50 | 54 | 55 | 56 | {locale => ( 57 | {locale} 58 | )} 59 | 60 |
61 | )} 62 |
63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/greeting.class.5.1.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default class Greeting extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | name: "Mary", 10 | surname: "Poppins", 11 | width: window.innerWidth, 12 | }; 13 | this.handleNameChange = this.handleNameChange.bind( 14 | this 15 | ); 16 | this.handleSurnameChange = this.handleSurnameChange.bind( 17 | this 18 | ); 19 | } 20 | 21 | componentDidMount() { 22 | document.title = 23 | this.state.name + " " + this.state.surname; 24 | } 25 | 26 | componentDidUpdate() { 27 | document.title = 28 | this.state.name + " " + this.state.surname; 29 | } 30 | 31 | handleNameChange(e) { 32 | this.setState({ name: e.target.value }); 33 | } 34 | 35 | handleSurnameChange(e) { 36 | this.setState({ surname: e.target.value }); 37 | } 38 | 39 | render() { 40 | return ( 41 | 42 | {theme => ( 43 |
44 | 45 | 49 | 50 | 51 | 55 | 56 | 57 | {locale => ( 58 | {locale} 59 | )} 60 | 61 |
62 | )} 63 |
64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/greeting.class.5.2.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default class Greeting extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | name: "Mary", 10 | surname: "Poppins", 11 | width: window.innerWidth, 12 | }; 13 | this.handleNameChange = this.handleNameChange.bind( 14 | this 15 | ); 16 | this.handleSurnameChange = this.handleSurnameChange.bind( 17 | this 18 | ); 19 | } 20 | 21 | componentDidMount() { 22 | document.title = 23 | this.state.name + " " + this.state.surname; 24 | } 25 | 26 | componentDidUpdate() { 27 | document.title = 28 | this.state.name + " " + this.state.surname; 29 | } 30 | 31 | handleNameChange(e) { 32 | this.setState({ name: e.target.value }); 33 | } 34 | 35 | handleSurnameChange(e) { 36 | this.setState({ surname: e.target.value }); 37 | } 38 | 39 | render() { 40 | return ( 41 | 42 | {theme => ( 43 |
44 | 45 | 49 | 50 | 51 | 55 | 56 | 57 | {locale => ( 58 | {locale} 59 | )} 60 | 61 | {this.state.width} 62 |
63 | )} 64 |
65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/greeting.class.5.3.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default class Greeting extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | name: "Mary", 10 | surname: "Poppins", 11 | width: window.innerWidth, 12 | }; 13 | this.handleNameChange = this.handleNameChange.bind( 14 | this 15 | ); 16 | this.handleSurnameChange = this.handleSurnameChange.bind( 17 | this 18 | ); 19 | this.handleResize = this.handleResize.bind(this); 20 | } 21 | 22 | componentDidMount() { 23 | document.title = 24 | this.state.name + " " + this.state.surname; 25 | window.addEventListener("resize", this.handleResize); 26 | } 27 | 28 | componentDidUpdate() { 29 | document.title = 30 | this.state.name + " " + this.state.surname; 31 | } 32 | 33 | handleNameChange(e) { 34 | this.setState({ name: e.target.value }); 35 | } 36 | 37 | handleSurnameChange(e) { 38 | this.setState({ surname: e.target.value }); 39 | } 40 | 41 | handleResize() { 42 | this.setState({ width: window.innerWidth }); 43 | } 44 | 45 | render() { 46 | return ( 47 | 48 | {theme => ( 49 |
50 | 51 | 55 | 56 | 57 | 61 | 62 | 63 | {locale => ( 64 | {locale} 65 | )} 66 | 67 | {this.state.width} 68 |
69 | )} 70 |
71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/greeting.class.5.4.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default class Greeting extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | name: "Mary", 10 | surname: "Poppins", 11 | width: window.innerWidth, 12 | }; 13 | this.handleNameChange = this.handleNameChange.bind( 14 | this 15 | ); 16 | this.handleSurnameChange = this.handleSurnameChange.bind( 17 | this 18 | ); 19 | this.handleResize = this.handleResize.bind(this); 20 | } 21 | 22 | componentDidMount() { 23 | document.title = 24 | this.state.name + " " + this.state.surname; 25 | window.addEventListener("resize", this.handleResize); 26 | } 27 | 28 | componentDidUpdate() { 29 | document.title = 30 | this.state.name + " " + this.state.surname; 31 | } 32 | 33 | componentWillUnmount() { 34 | window.removeEventListener("resize", this.handleResize); 35 | } 36 | 37 | handleNameChange(e) { 38 | this.setState({ name: e.target.value }); 39 | } 40 | 41 | handleSurnameChange(e) { 42 | this.setState({ surname: e.target.value }); 43 | } 44 | 45 | handleResize() { 46 | this.setState({ width: window.innerWidth }); 47 | } 48 | 49 | render() { 50 | return ( 51 | 52 | {theme => ( 53 |
54 | 55 | 59 | 60 | 61 | 65 | 66 | 67 | {locale => ( 68 | {locale} 69 | )} 70 | 71 | {this.state.width} 72 |
73 | )} 74 |
75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/greeting.hooks.1.1.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | 4 | export default function Greeting(props) { 5 | const name = ??? 6 | 7 | return ( 8 |
9 | 10 | 11 | 12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/greeting.hooks.1.2.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | 4 | export default function Greeting(props) { 5 | const name = ??? 6 | const setName = ??? 7 | 8 | function handleNameChange(e) { 9 | setName(e.target.value); 10 | } 11 | 12 | return ( 13 |
14 | 15 | 16 | 17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/greeting.hooks.1.3.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Row from "./row"; 3 | 4 | export default function Greeting(props) { 5 | const [name, setName] = ??? 6 | 7 | function handleNameChange(e) { 8 | setName(e.target.value); 9 | } 10 | 11 | return ( 12 |
13 | 14 | 15 | 16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/greeting.hooks.1.4.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import Row from "./row"; 3 | 4 | export default function Greeting(props) { 5 | const [name, setName] = useState("Mary"); 6 | 7 | function handleNameChange(e) { 8 | setName(e.target.value); 9 | } 10 | 11 | return ( 12 |
13 | 14 | 15 | 16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/greeting.hooks.2.1.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import Row from "./row"; 3 | 4 | export default function Greeting(props) { 5 | const [name, setName] = useState("Mary"); 6 | const [surname, setSurname] = useState("Poppins"); 7 | 8 | function handleNameChange(e) { 9 | setName(e.target.value); 10 | } 11 | 12 | function handleSurnameChange(e) { 13 | setSurname(e.target.value); 14 | } 15 | 16 | return ( 17 |
18 | 19 | 20 | 21 | 22 | 26 | 27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /src/greeting.hooks.3.1.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext } from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default function Greeting(props) { 6 | const [name, setName] = useState("Mary"); 7 | const [surname, setSurname] = useState("Poppins"); 8 | 9 | function handleNameChange(e) { 10 | setName(e.target.value); 11 | } 12 | 13 | function handleSurnameChange(e) { 14 | setSurname(e.target.value); 15 | } 16 | 17 | return ( 18 |
19 | 20 | 21 | 22 | 23 | 27 | 28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/greeting.hooks.3.2.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext } from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default function Greeting(props) { 6 | const [name, setName] = useState("Mary"); 7 | const [surname, setSurname] = useState("Poppins"); 8 | const theme = useContext(ThemeContext); 9 | 10 | function handleNameChange(e) { 11 | setName(e.target.value); 12 | } 13 | 14 | function handleSurnameChange(e) { 15 | setSurname(e.target.value); 16 | } 17 | 18 | return ( 19 |
20 | 21 | 22 | 23 | 24 | 28 | 29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/greeting.hooks.3.3.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext } from "react"; 2 | import Row from "./row"; 3 | import { ThemeContext, LocaleContext } from "./context"; 4 | 5 | export default function Greeting(props) { 6 | const [name, setName] = useState("Mary"); 7 | const [surname, setSurname] = useState("Poppins"); 8 | const theme = useContext(ThemeContext); 9 | const locale = useContext(LocaleContext); 10 | 11 | function handleNameChange(e) { 12 | setName(e.target.value); 13 | } 14 | 15 | function handleSurnameChange(e) { 16 | setSurname(e.target.value); 17 | } 18 | 19 | return ( 20 |
21 | 22 | 23 | 24 | 25 | 29 | 30 | {locale} 31 |
32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/greeting.hooks.4.1.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | useState, 3 | useContext, 4 | useEffect, 5 | } from "react"; 6 | import Row from "./row"; 7 | import { ThemeContext, LocaleContext } from "./context"; 8 | 9 | export default function Greeting(props) { 10 | const [name, setName] = useState("Mary"); 11 | const [surname, setSurname] = useState("Poppins"); 12 | const theme = useContext(ThemeContext); 13 | const locale = useContext(LocaleContext); 14 | 15 | function handleNameChange(e) { 16 | setName(e.target.value); 17 | } 18 | 19 | function handleSurnameChange(e) { 20 | setSurname(e.target.value); 21 | } 22 | 23 | return ( 24 |
25 | 26 | 27 | 28 | 29 | 33 | 34 | {locale} 35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /src/greeting.hooks.4.2.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | useState, 3 | useContext, 4 | useEffect, 5 | } from "react"; 6 | import Row from "./row"; 7 | import { ThemeContext, LocaleContext } from "./context"; 8 | 9 | export default function Greeting(props) { 10 | const [name, setName] = useState("Mary"); 11 | const [surname, setSurname] = useState("Poppins"); 12 | const theme = useContext(ThemeContext); 13 | const locale = useContext(LocaleContext); 14 | 15 | useEffect(() => { 16 | document.title = name + " " + surname; 17 | }); 18 | 19 | function handleNameChange(e) { 20 | setName(e.target.value); 21 | } 22 | 23 | function handleSurnameChange(e) { 24 | setSurname(e.target.value); 25 | } 26 | 27 | return ( 28 |
29 | 30 | 31 | 32 | 33 | 37 | 38 | {locale} 39 |
40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/greeting.hooks.5.1.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | useState, 3 | useContext, 4 | useEffect, 5 | } from "react"; 6 | import Row from "./row"; 7 | import { ThemeContext, LocaleContext } from "./context"; 8 | 9 | export default function Greeting(props) { 10 | const [name, setName] = useState("Mary"); 11 | const [surname, setSurname] = useState("Poppins"); 12 | const theme = useContext(ThemeContext); 13 | const locale = useContext(LocaleContext); 14 | 15 | useEffect(() => { 16 | document.title = name + " " + surname; 17 | }); 18 | 19 | const [width, setWidth] = useState(window.innerWidth); 20 | 21 | function handleNameChange(e) { 22 | setName(e.target.value); 23 | } 24 | 25 | function handleSurnameChange(e) { 26 | setSurname(e.target.value); 27 | } 28 | 29 | return ( 30 |
31 | 32 | 33 | 34 | 35 | 39 | 40 | {locale} 41 | {width} 42 |
43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/greeting.hooks.5.2.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | useState, 3 | useContext, 4 | useEffect, 5 | } from "react"; 6 | import Row from "./row"; 7 | import { ThemeContext, LocaleContext } from "./context"; 8 | 9 | export default function Greeting(props) { 10 | const [name, setName] = useState("Mary"); 11 | const [surname, setSurname] = useState("Poppins"); 12 | const theme = useContext(ThemeContext); 13 | const locale = useContext(LocaleContext); 14 | 15 | useEffect(() => { 16 | document.title = name + " " + surname; 17 | }); 18 | 19 | const [width, setWidth] = useState(window.innerWidth); 20 | useEffect(() => { 21 | const handleResize = () => setWidth(window.innerWidth); 22 | window.addEventListener("resize", handleResize); 23 | }); 24 | 25 | function handleNameChange(e) { 26 | setName(e.target.value); 27 | } 28 | 29 | function handleSurnameChange(e) { 30 | setSurname(e.target.value); 31 | } 32 | 33 | return ( 34 |
35 | 36 | 37 | 38 | 39 | 43 | 44 | {locale} 45 | {width} 46 |
47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /src/greeting.hooks.5.3.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | useState, 3 | useContext, 4 | useEffect, 5 | } from "react"; 6 | import Row from "./row"; 7 | import { ThemeContext, LocaleContext } from "./context"; 8 | 9 | export default function Greeting(props) { 10 | const [name, setName] = useState("Mary"); 11 | const [surname, setSurname] = useState("Poppins"); 12 | const theme = useContext(ThemeContext); 13 | const locale = useContext(LocaleContext); 14 | 15 | useEffect(() => { 16 | document.title = name + " " + surname; 17 | }); 18 | 19 | const [width, setWidth] = useState(window.innerWidth); 20 | useEffect(() => { 21 | const handleResize = () => setWidth(window.innerWidth); 22 | window.addEventListener("resize", handleResize); 23 | return () => { 24 | window.removeEventListener("resize", handleResize); 25 | }; 26 | }); 27 | 28 | function handleNameChange(e) { 29 | setName(e.target.value); 30 | } 31 | 32 | function handleSurnameChange(e) { 33 | setSurname(e.target.value); 34 | } 35 | 36 | return ( 37 |
38 | 39 | 40 | 41 | 42 | 46 | 47 | {locale} 48 | {width} 49 |
50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /src/greeting.hooks.6.1.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | useState, 3 | useContext, 4 | useEffect, 5 | } from "react"; 6 | import Row from "./row"; 7 | import { ThemeContext, LocaleContext } from "./context"; 8 | 9 | export default function Greeting(props) { 10 | const [name, setName] = useState("Mary"); 11 | const [surname, setSurname] = useState("Poppins"); 12 | const theme = useContext(ThemeContext); 13 | const locale = useContext(LocaleContext); 14 | const width = useWindowWidth(); 15 | 16 | useEffect(() => { 17 | document.title = name + " " + surname; 18 | }); 19 | 20 | function handleNameChange(e) { 21 | setName(e.target.value); 22 | } 23 | 24 | function handleSurnameChange(e) { 25 | setSurname(e.target.value); 26 | } 27 | 28 | return ( 29 |
30 | 31 | 32 | 33 | 34 | 38 | 39 | {locale} 40 | {width} 41 |
42 | ); 43 | } 44 | 45 | function useWindowWidth() { 46 | const [width, setWidth] = useState(window.innerWidth); 47 | useEffect(() => { 48 | const handleResize = () => setWidth(window.innerWidth); 49 | window.addEventListener("resize", handleResize); 50 | return () => { 51 | window.removeEventListener("resize", handleResize); 52 | }; 53 | }); 54 | return width; 55 | } 56 | -------------------------------------------------------------------------------- /src/greeting.hooks.6.2.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | useState, 3 | useContext, 4 | useEffect, 5 | } from "react"; 6 | import Row from "./row"; 7 | import { ThemeContext, LocaleContext } from "./context"; 8 | 9 | export default function Greeting(props) { 10 | const [name, setName] = useState("Mary"); 11 | const [surname, setSurname] = useState("Poppins"); 12 | const theme = useContext(ThemeContext); 13 | const locale = useContext(LocaleContext); 14 | const width = useWindowWidth(); 15 | useDocumentTitle(name + " " + surname); 16 | 17 | function handleNameChange(e) { 18 | setName(e.target.value); 19 | } 20 | 21 | function handleSurnameChange(e) { 22 | setSurname(e.target.value); 23 | } 24 | 25 | return ( 26 |
27 | 28 | 29 | 30 | 31 | 35 | 36 | {locale} 37 | {width} 38 |
39 | ); 40 | } 41 | 42 | function useDocumentTitle(title) { 43 | useEffect(() => { 44 | document.title = title; 45 | }); 46 | } 47 | 48 | function useWindowWidth() { 49 | const [width, setWidth] = useState(window.innerWidth); 50 | useEffect(() => { 51 | const handleResize = () => setWidth(window.innerWidth); 52 | window.addEventListener("resize", handleResize); 53 | return () => { 54 | window.removeEventListener("resize", handleResize); 55 | }; 56 | }); 57 | return width; 58 | } 59 | -------------------------------------------------------------------------------- /src/greeting.hooks.6.3.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | useState, 3 | useContext, 4 | useEffect, 5 | } from "react"; 6 | import Row from "./row"; 7 | import { ThemeContext, LocaleContext } from "./context"; 8 | 9 | export default function Greeting(props) { 10 | const name = useFormInput("Mary"); 11 | const surname = useFormInput("Poppins"); 12 | const theme = useContext(ThemeContext); 13 | const locale = useContext(LocaleContext); 14 | const width = useWindowWidth(); 15 | useDocumentTitle(name.value + " " + surname.value); 16 | 17 | return ( 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | {locale} 26 | {width} 27 |
28 | ); 29 | } 30 | 31 | function useFormInput(initialValue) { 32 | const [value, setValue] = useState(initialValue); 33 | function handleChange(e) { 34 | setValue(e.target.value); 35 | } 36 | return { 37 | value, 38 | onChange: handleChange, 39 | }; 40 | } 41 | 42 | function useDocumentTitle(title) { 43 | useEffect(() => { 44 | document.title = title; 45 | }); 46 | } 47 | 48 | function useWindowWidth() { 49 | const [width, setWidth] = useState(window.innerWidth); 50 | useEffect(() => { 51 | const handleResize = () => setWidth(window.innerWidth); 52 | window.addEventListener("resize", handleResize); 53 | return () => { 54 | window.removeEventListener("resize", handleResize); 55 | }; 56 | }); 57 | return width; 58 | } 59 | -------------------------------------------------------------------------------- /src/row.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./styles.css"; 3 | 4 | const Row = props => ( 5 |
6 | {props.label} 7 | {props.children} 8 |
9 | ); 10 | 11 | export default Row; 12 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* From https://github.com/donycisneros/react-hooks-demo */ 2 | 3 | @import url("https://fonts.googleapis.com/css?family=Playfair+Display:400,900i"); 4 | 5 | section { 6 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", 7 | "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", 8 | "Droid Sans", "Helvetica Neue", sans-serif; 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | width: 360px; 12 | padding: 30px; 13 | background-color: #d1dae0; 14 | border-bottom: 4px solid #abb5b8; 15 | box-shadow: 8px 8px 0px 0px #000000; 16 | text-align: initial; 17 | font-size: 1.5rem; 18 | max-width: 90%; 19 | } 20 | .row:not(:first-child) { 21 | margin-top: 25px; 22 | } 23 | .row-title, 24 | section input { 25 | font-weight: bold; 26 | color: #696969; 27 | padding-left: 8px; 28 | } 29 | section input { 30 | border: none; 31 | font-size: 2.5rem; 32 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", 33 | "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", 34 | "Droid Sans", "Helvetica Neue", sans-serif; 35 | } 36 | .row-content { 37 | font-size: 2.5rem; 38 | font-weight: bold; 39 | color: #000000; 40 | display: block; 41 | width: 100%; 42 | margin-top: 15px; 43 | } 44 | .row-content input, 45 | .row-content input:focus { 46 | padding: 7px; 47 | color: #000000; 48 | border-radius: 8px; 49 | width: 100%; 50 | outline: none; 51 | } 52 | .row-content input { 53 | background-color: transparent; 54 | } 55 | .row-content input:focus { 56 | background-color: #a0aaad; 57 | } 58 | .row-content input:focus::selection { 59 | background: #fff3a3; 60 | } 61 | .row-content input:focus::-moz-selection { 62 | background: #fff3a3; 63 | } 64 | 65 | /*========== Theme Golden ==========*/ 66 | 67 | .theme-golden { 68 | font-family: "Playfair Display", serif; 69 | background: #ffc42b; 70 | border-top: 2px solid #ffd979; 71 | border-bottom-color: #b48700; 72 | } 73 | .theme-golden .row, 74 | .theme-golden .row-content input { 75 | font-family: "Playfair Display", serif; 76 | text-align: center; 77 | } 78 | .theme-golden .row-content input { 79 | font-style: italic; 80 | } 81 | .theme-golden .row-content input:focus { 82 | background-color: #b68b1b; 83 | } 84 | .theme-golden .row-content input:focus::selection { 85 | background: #ffea98; 86 | } 87 | .theme-golden .row-content input:focus::-moz-selection { 88 | background: #ffea98; 89 | } 90 | .theme-golden .row { 91 | position: relative; 92 | z-index: 1; 93 | } 94 | .theme-golden .row:before { 95 | border-top: 1px solid #d4990d; 96 | content: ""; 97 | margin: 0 auto; 98 | position: absolute; 99 | top: 15%; 100 | left: 0; 101 | right: 0; 102 | bottom: 0; 103 | width: 95%; 104 | z-index: -1; 105 | } 106 | .theme-golden .row-title { 107 | color: #936508; 108 | background: #ffc42b; 109 | padding: 0 7px; 110 | } 111 | 112 | /*========== Media Queries ==========*/ 113 | 114 | @media (max-width: 415px) { 115 | .theme-golden { 116 | max-width: 90vw; 117 | margin: 0 auto; 118 | } 119 | section input { 120 | font-size: 1.2rem; 121 | } 122 | } 123 | 124 | @media (max-width: 900px) { 125 | section { 126 | font-size: 1rem; 127 | padding: 15px; 128 | } 129 | .row-content, 130 | section input { 131 | font-size: 1.2rem; 132 | } 133 | .row-content { 134 | margin-top: 1px; 135 | } 136 | .row:not(:first-child) { 137 | margin-top: 2px; 138 | } 139 | section input { 140 | padding: 0 7px 2px; 141 | } 142 | } 143 | --------------------------------------------------------------------------------