15 |
16 |
17 |
18 | My page
19 |
20 |
21 | Welcome!
22 | This is a button
23 |
24 | `,
25 | }}
26 | />
27 |
28 | HTML includes a large set of built-in UI elements, such as `` (paragraph) and ``. We typically customize these by embedding other kinds of code in our HTML: CSS code lets us add custom styles, and JavaScript code lets us add interactivity.
29 |
30 | > If you're familiar with XML, then HTML should feel very similar, although it has some unusual special cases.
31 |
32 | ## Document type
33 |
34 | Every HTML file should start with a **document type declaration**, or DOCTYPE for short. The DOCTYPE specifies which _version_ of the HTML language the file uses. The browser looks at this to decide how to parse the rest of the HTML and render the page.
35 |
36 | Most HTML features are backwards compatible, but some aren't, so it's important to specify this so that your page renders correctly now and in the future.
37 |
38 | ## Head
39 |
40 | The `` element contains _metadata_ about the page. Elements in the head don't actually show up in the UI, but instead inform the browser how to render the page.
41 |
42 | The head may also include references to other resources that the browser should download in order to display the page, such as CSS and JavaScript code.
43 |
44 | At minimum, the `` should contain a `` element, which will set the title of the browser window for that page.
45 |
46 | ## Body
47 |
48 | The ` ` contains a hierarchy of UI elements that the browser renders. In the next section, we'll look at a variety of these elements in more depth.
49 |
--------------------------------------------------------------------------------
/pages/html_and_css/accessibility.mdx:
--------------------------------------------------------------------------------
1 | ## WAI-ARIA
2 |
3 | WAI-ARIA (Web Accessibility Initiative – Accessible Rich Internet Applications) is the specification for accessibility standards on the web. For more detail, see: https://www.w3.org/WAI/standards-guidelines/aria/
4 |
5 | This standard added a variety of HTML element attributes to help make our websites more accessible. Many of these attributes have the prefix `aria`, such as `aria-label`. For more detail on the available attributes, see:
6 | https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques
7 |
8 | ## Semantic HTML
9 |
10 | The best way to make our page accessible is by using "semantic" HTML elements. Instead of using only `div` and `span` elements and styling them with CSS (which is sometimes easier), we should use elements like `img` and `button` where appropriate, and reset their built-in styles as needed.
11 |
12 | Semantic elements have built-in behaviors that users already understand, and screenreaders often know how to interpret them without any special `aria` attributes.
13 |
14 | ## Roles
15 |
16 | If we can't use semantic elements for some reason (e.g. we want to design a custom widget, rather than using a built-in one), we should check if there's a built-in `role` we can use. The `role` attribute tells assistive devices what kind of widget an element is, e.g. image, button, checkbox, dropdown, tree, etc.
17 |
18 | By providing a `role` and a variety of `aria` attributes, we can usually create something accessible.
19 |
20 | ### Example: Images
21 |
22 | To display an image, we can use an `img` element, or a `div` with a `background-image` set via CSS.
23 |
24 | In some ways, the `div` is more flexible and easier to style. We can even make it accessible to screenreaders by adding a `role` and `aria-label`. However, it will still be missing some default browser behavior (right click to save or open in a new tab).
25 |
26 |
32 |
33 |
34 | My Title
35 |
42 |
43 |
44 |
45 | Img element (try right clicking):
46 |
47 |
48 |
49 | Div (right click is missing options):
50 |
51 |
52 |
53 | `,
54 | }}
55 | />
56 |
57 | ### Example: Links and buttons
58 |
59 |
64 |
65 |
66 | My Title
67 |
68 |
69 |
72 |
73 |
74 | Button: Wikipedia
75 |
76 |
77 |
78 | Span: Wikipedia
79 |
80 |
87 |
88 | `,
89 | }}
90 | />
91 |
92 | ## Keyboard Navigation
93 |
94 | The first place to start when supporting keyboard navigation is making sure we're using semantic elements. Elements like `button` support keyboard navigation out-of-the-box.
95 |
96 | If we want to implement custom navigation, we'll usually start with the `tabindex` HTML attribute, which lets us specify that an element is be focusable.
97 |
98 | Beyond that, we'll often need to use JavaScript to handle key press events.
99 |
--------------------------------------------------------------------------------
/pages/html_and_css/advanced_selectors.mdx:
--------------------------------------------------------------------------------
1 | ## Combinators
2 |
3 | We can combine CSS selectors using **combinators**. These are analogous to operators, like `+` or `-`, in other programming languages.
4 |
5 | ### Descendant combinator
6 |
7 |
13 |
14 |
15 |
16 | My page
17 |
22 |
23 |
24 | Welcome!
25 |
26 | I'm in main
27 |
28 | I'm nested in a section in main
29 |
30 |
31 |
32 | `,
33 | }}
34 | />
35 |
36 | ### Child combinator
37 |
38 |
44 |
45 |
46 |
47 | My page
48 |
53 |
54 |
55 | Welcome!
56 |
57 | I'm in main
58 |
59 | I'm nested in a section in main
60 |
61 |
62 |
63 | `,
64 | }}
65 | />
66 |
67 | ## Pseudo-classes
68 |
69 | These represent either element state or location in the document.
70 |
71 |
77 |
78 |
79 |
80 | My page
81 |
89 |
90 |
91 | Try clicking me!
92 |
93 | `,
94 | }}
95 | />
96 |
97 | If we use margins for spacing in lists, it's common to remove the margin from the last element.
98 |
99 |
105 |
106 |
107 |
108 | My page
109 |
122 |
123 |
124 |
125 | Apples
126 | Cherries
127 | Oranges
128 | Peaches
129 | Pears
130 |
131 |
132 | `,
133 | }}
134 | />
135 |
136 | ## Pseudo-elements
137 |
138 | We can insert a new HTML element in our UI using the CSS `::before` and `::after` pseudo-elements. These are often used for adding decorations around other elements.
139 |
140 |
146 |
147 |
148 |
149 | My page
150 |
168 |
169 |
170 | A quote!
171 |
172 | `,
173 | }}
174 | />
175 |
176 |
177 |
--------------------------------------------------------------------------------
/pages/html_and_css/box_model.mdx:
--------------------------------------------------------------------------------
1 | ## What is the Box Model?
2 |
3 | Every HTML is rendered within a rectangular "box". The box model describes the layout for this box.
4 |
5 | ## Width and height
6 |
7 | The most direct way to specify the size of a box is through the `width` and `height` CSS styles.
8 |
9 | We can use hardcoded values, e.g. `300px`, or a variety of other values like percents, e.g. `50%`.
10 |
11 | If we don't specify a width/height, these styles default to `auto`. Using `auto` sets the width or height to the "intrinsic content size" of the box (i.e. big enough to fit its content).
12 |
13 |
19 |
20 | ## Padding, margin, and border
21 |
22 | Each element/box can have a **border**. We can add spacing _outside_ the border with **margin**, or inside the border with **padding**.
23 |
24 |
31 |
32 | ### Specifying a different size on each side
33 |
34 | We can use separate CSS styles to specify different margins/borders/paddings for each side.
35 |
36 | For example:
37 |
38 |
46 |
47 | ### Shorthand syntax
48 |
49 | There's a shorthand syntax for combining different margin and padding sizes in the same line. We can specify up to 4 values, going clockwise from the top: top, right, bottom, and left. If we only specify 2 values, then they will represent: vertical, horizonal.
50 |
51 |
57 |
58 | ## Content box vs. border box
59 |
60 | We can use two different algorithms for calculating box dimensions. We specify which algorithm to use via the `box-sizing` style.
61 |
62 | The two options are:
63 |
64 | - `content-box` - The width/height don't include padding or border width
65 | - `border-box` - The width/height include padding and border width
66 |
67 |
76 |
77 | > Try changing `content-box` to `border-box` and see what happens!
78 |
79 | Generally, `border-box` is a little easier to use, and most developers set it on every element (we can use this CSS to do so: `* { box-sizing: border-box; }`).
80 |
81 | ## Position
82 |
83 | We can use `position: relative` along with `top/right/bottom/left` to move a box without affect the layout of anything around it.
84 |
85 |
92 |
93 | We `position: absolute`, on the other hand, removes the box from the regular page layout and sets the position relative to the box's nearest ancestor that also sets a `position`.
94 |
95 |
104 |
--------------------------------------------------------------------------------
/pages/html_and_css/browser_dev_tools.mdx:
--------------------------------------------------------------------------------
1 | The browser's built-in developer tools let us inspect the HTML of _any_ webpage. This is extremely useful for debugging our layout and styles.
2 |
3 | ## Debugging styles
4 |
5 | A few common techniques:
6 |
7 | - We often add temporary styles to individual elements to see what they would look like
8 | - We check the computed box model diagram to see why the dimensions of an element look a certain way
9 | - We can look up a computed style for an element and then jump to the source CSS file or style tag where it's defined
10 |
--------------------------------------------------------------------------------
/pages/html_and_css/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "order": [
3 | "elements",
4 | "styling",
5 | "box_model",
6 | "browser_dev_tools",
7 | "flexbox",
8 | "advanced_selectors",
9 | "units",
10 | "responsive_design",
11 | "accessibility",
12 | "css_variables",
13 | "limitations",
14 | "projects",
15 | "resources"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/pages/html_and_css/css_variables.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: CSS Variables
3 | ---
4 |
5 | All modern browsers support CSS **custom properties**, also known as CSS variables.
6 |
7 | ## Declaring variables
8 |
9 | All variables must be declared in a CSS rule, i.e. within curly braces.
10 |
11 | To declare a top-level variable that can be used anywhere, we typically use the `:root` pseudo-class. In an HTML page, this refers to the HTML element.
12 |
13 | Any CSS value can be stored in a variable: sizes (with units), colors, shorthand properties (e.g. `1px solid blue` for a border), etc.
14 |
15 |
21 |
22 |
23 |
24 | My page
25 |
39 |
40 |
41 | Hello, world!
42 | Hello, world!
43 |
44 | `,
45 | }}
46 | />
47 |
48 | ## Shadowing variables
49 |
50 | Any CSS rule can redeclare a variable to a different value. An HTML element will use the variable declared on the nearest ancestor.
51 |
52 |
58 |
59 |
60 |
61 | My page
62 |
79 |
80 |
81 | Hello, world!
82 | Hello, world!
83 |
84 | Hello, world!
85 | Hello, world!
86 |
87 |
88 | `,
89 | }}
90 | />
91 |
92 | ## Fallback values
93 |
94 | We can also provide a fallback value when using `var`, in case our variable isn't defined.
95 |
96 | In this example, we don't declare a `--primary-color` in the root. This means that our `h1` and `button` outside of the `section` will use the fallback value, since `--primary-color` isn't defined.
97 |
98 |
104 |
105 |
106 |
107 | My page
108 |
122 |
123 |
124 | Hello, world!
125 | Hello, world!
126 |
127 | Hello, world!
128 | Hello, world!
129 |
130 |
131 | `,
132 | }}
133 | />
134 |
--------------------------------------------------------------------------------
/pages/html_and_css/elements.mdx:
--------------------------------------------------------------------------------
1 | ## Element Syntax
2 |
3 | HTML describes a hierarchy of **elements** that make up a webpage. Each element can be configured using **attributes**, and may contain nested **content** (text or other elements) within.
4 |
5 | ### Regular elements
6 |
7 | Suppose we wanted to use the `main` element, and set its `class` attribute to the value `"my-content"`. Here's how we would write it:
8 |
9 | ',
41 | ],
42 | },
43 | //'\n',
44 | { id: 'Content', value: ['Hello, world!'] },
45 | //'\n',
46 | {
47 | id: 'Closing tag',
48 | value: [
49 | '',
50 | {
51 | id: 'tag2',
52 | label: 'Tag name',
53 | style: { color: '#2e9f74' },
54 | value: ['main'],
55 | },
56 | '>',
57 | ],
58 | },
59 | ],
60 | },
61 | ]}
62 | />
63 |
64 | > Hover or tap to highlight the different parts of the diagram above.
65 |
66 | ### Void elements
67 |
68 | Some elements must not contain any content - these are called **void elements**. In this case, a closing tag is not allowed. The opening tag may end in either `>`, or `/>` like XML.
69 |
70 | ',
102 | ],
103 | },
104 | ],
105 | },
106 | ]}
107 | />
108 |
109 | > An up-to-date list of all void elements can be found here: https://github.com/wooorm/html-void-elements
110 |
111 |
112 |
113 | ### Entity references
114 |
115 | The characters `<`, `>`,`"`,`'` and `&` are reserved, since they're used by the HTML syntax to define elements and attributes. We can use special escape sequences starting with `&` to insert these as text within an element's content.
116 |
117 | For example, if we want to write a `<` character, we could use the following HTML:
118 |
119 |
125 |
126 |
127 |
128 | My page
129 |
130 |
131 | A less-than symbol: <
132 |
133 | `,
134 | }}
135 | />
136 |
137 | Here are the characters we _have to_ use entity references to write.
138 |
139 | | Character | Entity reference |
140 | | --------- | ---------------- |
141 | | `<` | `<` |
142 | | `>` | `>` |
143 | | `"` | `"` |
144 | | `'` | `'` |
145 | | `&` | `&` |
146 |
147 | There are many other entity references that exist mainly for historic reasons: UTF-8 wasn't always widely supported, so there had to be a way to represent other characters within ASCII.
148 |
149 | ## `` elements
150 |
151 | The following are a few of the most common elements used in the `head` of a document.
152 |
153 | ### `style`
154 |
155 | We can use a `style` element to style our page with CSS:
156 |
157 |
163 |
164 |
165 |
166 | My page
167 |
172 |
173 |
174 | Hello, world!
175 |
176 | `,
177 | }}
178 | />
179 |
180 | ### `link`
181 |
182 | We can also link to external CSS files using the `link` element, e.g.: ` `.
183 |
184 | > Note that `link` is a void element, so we must _not_ include a closing tag.
185 |
186 | ### `script`
187 |
188 | Script elements let us run JavaScript to add interactivity to our page.
189 |
190 |
196 |
197 |
198 |
199 | My page
200 |
207 |
208 |
209 | Click me!
210 |
211 | `,
212 | }}
213 | />
214 |
215 | We can link to external JavaScript files using the `src` attribute of a `script` element, e.g. ``.
216 |
217 | > The `script` tag is _not_ a void element, so we _must_ include a closing tag.
218 |
219 | Note that script tags may also be used in the `body`, and that the location of the script tag _does matter_. A script in the `head` will run before the `body` is constructed and the UI is presented to the user - so some parts of the document may not be accessible via JavaScript yet.
220 |
221 | ## `` elements
222 |
223 | Now, let's look at some of the most common `body` elements.
224 |
225 | ### Block vs. inline
226 |
227 | Most elements are either **block** or **inline** elements. Block elements are rendered on their own line, while inline elements render on the same line, so long as they fit within their parent element (think a paragraph with word-wrapping).
228 |
229 | The most general-purpose block element is the `div` and the most general-purpose inline element is the `span`.
230 |
231 |
237 |
238 |
239 |
240 | My page
241 |
242 |
243 | Block
244 | Block
245 | Block
246 | Inline
247 | Inline
248 | Inline
249 | Block
250 |
251 | `,
252 | }}
253 | />
254 |
255 | Note that block elements cannot be nested inside inline elements.
256 |
257 | We can change an element from block to inline or vice versa using the CSS declaration `display: block` or `display: inline`.
258 |
259 | > Technically, as of HTML5, elements are now grouped into [content categories](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories) rather than "block" or "inline", which are purely presentational. However, most developers still refer to elements as "block" or "inline", and the mental model is essentially the same.
260 |
261 | > Here's a complete list of [block elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements#elements) and [inline elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements#list_of_inline_elements)
262 |
263 | ### Semantic HTML
264 |
265 | The elements `div` and `span` do not have any semantic meaning or built-in styles. However, many elements do, and we should try to use these whenever possible.
266 |
267 | Here are a handful of common elements:
268 |
269 | - Sections: `main`, `nav`, `header`, `footer`, `section`
270 | - Headings: `h1`, `h2`, `h3`, `h4`, `h5`, `h6`
271 | - Inline styles: `strong`, `em`
272 | - Navigation: `a`
273 | - Embedded content: `img`, `video`, `svg`, `audio`
274 | - Lists: `ul`, `ol`, `li`
275 | - Forms: `form`, `label`, `input`, `select`, `option`, `textarea`, `button`
276 |
277 | Although we could make many webpages using just `div` and `span` elements, we should try to use semantic elements - semantic elements often come with built-in styles or behaviors that users expect, and assistive technologies like screenreaders use them to navigate the page.
278 |
279 | ## Validating HTML
280 |
281 | Browsers almost never throw errors, however, it's still a good idea to write valid HTML so that all browsers display your page the same way.
282 |
283 | You can check that your HTML is valid here: https://validator.w3.org/#validate_by_input (or programatically here: https://validator.w3.org/docs/api.html)
284 |
285 | Your text editor will usually guide you in the right direction through autocomplete.
286 |
--------------------------------------------------------------------------------
/pages/html_and_css/flexbox.mdx:
--------------------------------------------------------------------------------
1 | Flexbox is an alternate layout algorithm we can use.
2 |
3 | ## CSS Properties
4 |
5 | The first property we need to consider is `flex-direction`, which defines the **main axis** and **cross axis** of our layout. After this, we can use `justify-content` to distribute elements along the main axis, and `align-items` to align elements along the cross axis.
6 |
7 |
29 | Child 1
30 | ,
31 |
42 | Child 2
43 | ,
44 |
55 | Child 3
56 | ,
57 | ]}
58 | />
59 |
60 | ## Comparisons with other layout systems
61 |
62 | - **UIStackView on iOS**: https://dabbott.github.io/webdev-projects/cheatsheets/uistackview-flexbox.html
63 |
--------------------------------------------------------------------------------
/pages/html_and_css/limitations.mdx:
--------------------------------------------------------------------------------
1 | ## HTML
2 |
3 | A few challenges we typically encounter when using HTML directly:
4 |
5 | - **Reusability**: while there are some ways we can reuse HTML snippets, such as template tags and web components, they typically rely heavily on JavaScript, and even then are somewhat cumbersome to use directly.
6 | - **Browser differences**: since different browsers may implement the web standards at different times or have different bugs, we need to double check whether we can use newer features (see https://caniuse.com/) and test on multiple platforms
7 | - **Screen reader differences**: just like how browsers have differences, so do screen readers. We similarly need to test with multiple screenreaders (see https://webaim.org/projects/screenreadersurvey8/ for which to test with)
8 |
9 | ## CSS
10 |
11 | A few challenges we typically encounter when using CSS directly:
12 |
13 | - **Encapsulation**: Since CSS is global, we need to enforce naming conventions across our team (e.g. http://getbem.com/introduction/). Otherwise, our CSS files can quickly grow in size and complexity until it's practically impossible to make changes without breaking something.
14 | - **Vendor prefixing**: If we want to use newer CSS features, we need to add browser-specific features to property names. This is a hassle to do manually (fortunately there are tools that can do this automatically)
15 | - **CSS Resets**: Often we want our website to look the same on different browsers. This means we'll want to "reset" each browser's default styles to something standard. A few common options: https://meyerweb.com/eric/tools/css/reset/, https://necolas.github.io/normalize.css/.
16 |
--------------------------------------------------------------------------------
/pages/html_and_css/projects.mdx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/pages/html_and_css/projects.mdx
--------------------------------------------------------------------------------
/pages/html_and_css/projects/blog_project.mdx:
--------------------------------------------------------------------------------
1 | import html from '../../../examples/files/html_and_css/blog.html'
2 | import css from '../../../examples/files/html_and_css/blog._css'
3 |
4 | ## Finished Project
5 |
6 |
15 |
16 | ## Steps
17 |
18 | 1. Create or open an HTML file. Add a ``, ``, ``, and ``.
19 |
20 | 1. Add a `
38 |
39 |
40 |
41 |
42 | `,
43 | }}
44 | />
45 |
46 | Here's an example where we use a media query to change the root font size - and since all headings have rem-based font sizes by default, they all resize!
47 |
48 |
54 |
55 |
56 |
57 | My page
58 |
73 |
74 |
75 | Heading 1
76 | Heading 2
77 | Heading 3
78 |
79 | `,
80 | }}
81 | />
82 |
--------------------------------------------------------------------------------
/pages/html_and_css/styling.mdx:
--------------------------------------------------------------------------------
1 | ## CSS
2 |
3 | CSS, or Cascading Style Sheets, is a language for customizing the styles of HTML elements. CSS lets us "select" which element we want to style, and then apply any number of style properties, such as `font-size` or `background-color`. There are _hundreds_ of properties, but only around 30 or so that we use enough to memorize. Usually a quick Google search for what you're trying to do will bring up the CSS property you need.
4 |
5 | To use CSS, we embed a CSS **stylesheet** inside a `
26 |
27 |
28 | Welcome!
29 |
30 | `,
31 | }}
32 | />
33 |
34 | ## Syntax
35 |
36 | A stylesheet may contain any number of rules. Each rule has the following syntax:
37 |
38 |
86 |
87 | ## Where to put styles
88 |
89 | Stylesheets can be embedded, external, or inline. So far, we've seen embedded styles (they're _embedded_ within an HTML page).
90 |
91 | ### External styles
92 |
93 | To use an external stylesheet, we link to it using a ` ` element in the `head`: e.g. ` `. This is useful since stylesheets can be reused between HTML files this way.
94 |
95 | ### Inline styles
96 |
97 | With both embedded and external styles, all rules are _global_! Inline styles, on the other hand, are applied to a single HTML element. This can be useful for prototyping and for passing variables to CSS. However, this tends to be verbose and hard to maintain, so we tend not to do it often in production code.
98 |
99 |
105 |
106 |
107 |
108 | My page
109 |
110 |
111 | Inline styles!
112 |
113 | `,
114 | }}
115 | />
116 |
117 | ## Selectors
118 |
119 | The selector is the part of the rule that lets us choose which HTML element(s) our rule should target.
120 |
121 | The 3 most common selectors are: tag, id, and class.
122 |
123 | ### Tag selector
124 |
125 | We use the tag selector to target _every element_ with any given tag name.
126 |
127 | In this example, we target every `p` element.
128 |
129 |
135 |
136 |
137 |
138 | My page
139 |
144 |
145 |
146 | Hello
147 | World
148 | !
149 |
150 | `,
151 | }}
152 | />
153 |
154 | ### Class selector
155 |
156 | We use the class selector to target every element with a specific `class` attribute. This gives us more granular control than the tag selector, since we can decide which elements the CSS rule should apply to. We can also apply the same class to elements with different tag names.
157 |
158 | The class selector has a `.` prefix followed by value of the `class` attribute we want to target.
159 |
160 |
166 |
167 |
168 |
169 | My page
170 |
175 |
176 |
177 | Hello
178 | World
179 | !
180 |
181 | `,
182 | }}
183 | />
184 |
185 | ### Id selector
186 |
187 | We use the id selector to target one element with a specific `id` attribute. This gives us even more granular control than the class selector. We often want to use this when we know we'll only have one instance of a given element.
188 |
189 | The id selector has a `#` prefix followed by the value of the `id` attribute we want to target.
190 |
191 |
197 |
198 |
199 |
200 | My page
201 |
206 |
207 |
208 | Hello
209 | World
210 | !
211 |
212 | `,
213 | }}
214 | />
215 |
216 | ## Cascading
217 |
218 | The **cascade** is the algorithm that browsers use to determine the precedence of declarations when multiple declarations target the same element.
219 |
220 | We're allowed to have any number of CSS rules target the same element. For example, consider the element `Welcome!
`. We might have a selector for `#my-example`, `.my-paragraph`, _and_ `p` all at the same time. We could even have multiple rules with the selector `p`. How will these rules applied to the `p`?
221 |
222 | First, if two rules with the same selector exist, whichever comes later in the stylesheet wins. In the following example, we have two rules with a `color` declaration that both use the `p` selector - in this case, the one that comes later in the style tag wins, so the paragraph is green.
223 |
224 |
230 |
231 |
232 |
233 | My page
234 |
242 |
243 |
244 | Welcome!
245 |
246 | `,
247 | }}
248 | />
249 |
250 | ## Specificity
251 |
252 | In general, more specific rules take precedence over more generic rules.
253 |
254 | For ids, classes, and tags: the `#id` selector is the most specific, `.class` is less specific, and `tag` is the most generic. Even if a `.class` element comes later in the file, an `#id` will tag precedence.
255 |
256 |
262 |
263 |
264 |
265 | My page
266 |
277 |
278 |
279 | Welcome!
280 |
281 | `,
282 | }}
283 | />
284 |
285 | ## Targeting multiple elements
286 |
287 | If we want to reuse the same declarations for multiple selectors, there's shorter syntax to do so. This is common for applying styles to all elements of a certain category, e.g. headings, or for resetting browser-default styles.
288 |
289 |
295 |
296 |
297 |
298 | My page
299 |
304 |
305 |
306 | Heading 1
307 | Heading 2
308 | Heading 3
309 |
310 | `,
311 | }}
312 | />
313 |
314 | ## Using multiple classes
315 |
316 | We can apply multiple classes to the same element. This gives us more flexibility to mix-and-match different styles.
317 |
318 |
324 |
325 |
326 |
327 | My page
328 |
336 |
337 |
338 | Heading 1
339 | Heading 2
340 | Heading 3
341 |
342 | `,
343 | }}
344 | />
345 |
--------------------------------------------------------------------------------
/pages/html_and_css/units.mdx:
--------------------------------------------------------------------------------
1 | ## Pixels
2 |
3 | Pixels are convenient because they're always consistent: no matter where a `px` is used, it always means the same thing. However, this means that we can't easily scale _all_ of our font sizes at once in certain contexts (e.g. the user wants to increase the font size) - we have to go through and set a new `px` value anywhere we use `px`.
4 |
5 |
11 |
12 |
13 |
14 | My page
15 |
26 |
27 |
28 | Heading 1
29 | Heading 2
30 | Heading 3
31 |
32 | `,
33 | }}
34 | />
35 |
36 | ## Ems & Rems
37 |
38 | The units `em` are relative to the parent's font size, while `rem` are relatively to the root font size (the size set on the `html` element).
39 |
40 |
46 |
47 |
48 |
49 | My page
50 |
64 |
65 |
66 | Heading 1
67 | Heading 2
68 | Heading 3
69 |
70 | `,
71 | }}
72 | />
73 |
74 | ### When to use Ems and Rems?
75 |
76 | These units are most commonly used for fonts and spacing. We should use them anywhere we may want a large portion of our site to scale up or down.
77 |
78 | ## Supporting system font size
79 |
80 | It's common to set the root font size to a percent, which then is based on the browser-provided default font size. The user may increase or decrease their font size across all their webpages through their system or browser settings, and we can use this approach to respect their preference.
81 |
82 | Many websites use `62.5%` as the root font size - since the default browser font size is typically `16px`, this means the root font size is `10px`, which can make the math easier when converting from design mockups (e.g. a `40px` font size or spacing value in a mockup from a designer would be `4rem`).
83 |
84 |
90 |
91 |
92 |
93 | My page
94 |
108 |
109 |
110 | Heading 1
111 | Heading 2
112 | Heading 3
113 |
114 | `,
115 | }}
116 | />
117 |
--------------------------------------------------------------------------------
/pages/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Web Development Express
3 | subtitle: A guide to web development
4 | ---
5 |
6 | ## About this guide
7 |
8 | This guide accompanies my 8-day web development class. The class schedule is roughly:
9 |
10 | - Day 1-2: HTML & CSS
11 | - Day 3-4: TypeScript
12 | - Day 5-8: React
13 |
14 | Feel free to play with the examples in this guide if you want another look at what I went over during the class.
15 |
--------------------------------------------------------------------------------
/pages/intro_slides.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import SpectacleSlideshow from '../components/SpectacleSlideshow'
3 |
4 | const introSlides = require('!!babel-loader!spectacle-mdx-loader!../slides/intro.mdx')
5 |
6 | const slides = introSlides.default.map((slide, index, list) => {
7 | return {
8 | sectionName: `Intro`,
9 | SlideComponent: slide,
10 | NotesComponent: introSlides.notes[index],
11 | }
12 | })
13 |
14 | export default () =>
15 |
--------------------------------------------------------------------------------
/pages/playgrounds.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import EditorConsole from '../components/EditorConsole'
3 |
4 | export default function Playgrounds() {
5 | return
6 | }
7 |
--------------------------------------------------------------------------------
/pages/react.mdx:
--------------------------------------------------------------------------------
1 | For React, I'll be referring to my React guide, https://www.react.express/
2 |
--------------------------------------------------------------------------------
/pages/schedule.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | Heading1,
4 | Heading3,
5 | List,
6 | VerticalSpacer,
7 | UnorderedList,
8 | HorizontalSpacer,
9 | } from 'react-guidebook'
10 | import styled from 'styled-components'
11 |
12 | const Container = styled.div({
13 | height: '100vh',
14 | display: 'flex',
15 | alignItems: 'stretch',
16 | justifyContent: 'center',
17 | overflow: 'hidden',
18 | padding: '100px 40px',
19 | background: `linear-gradient(135deg, #607d8b, #251542)`,
20 | })
21 |
22 | const Inner = styled.div({
23 | flex: '1 1 0',
24 | maxWidth: '1200px',
25 | margin: '0 auto',
26 | display: 'flex',
27 | alignItems: 'stretch',
28 | justifyContent: 'center',
29 | flexDirection: 'column',
30 | })
31 |
32 | const Title = styled.h1(({ theme }) => ({
33 | ...theme.textStyles.title,
34 | display: 'inline-block', // So the gradient doesn't extend beyond the text
35 | backgroundColor: theme.colors.title.left, // Fallback
36 | backgroundImage: `linear-gradient(45deg, ${theme.colors.title.left}, ${theme.colors.title.right})`,
37 | backgroundSize: '100%',
38 | backgroundRepeat: 'repeat',
39 | WebkitBackgroundClip: 'text',
40 | WebkitTextFillColor: 'transparent',
41 | MozBackgroundClip: 'text',
42 | MozTextFillColor: 'transparent',
43 | backgroundClip: 'text',
44 | textFillColor: 'transparent',
45 | whiteSpace: 'pre',
46 | }))
47 |
48 | const Section = styled.section(({ theme }) => ({
49 | flex: '1 1 0',
50 | padding: '30px 40px',
51 | background: 'white',
52 | borderRadius: '4px',
53 | // border: `1px solid ${theme.colors.textDecorativeLight}`,
54 | boxShadow: '0 2px 8px rgba(0,0,0,0.2), 0 4px 20px rgba(0,0,0,0.1)',
55 | // width: '33%',
56 | }))
57 |
58 | const StyledUnorderedList = styled(UnorderedList)({
59 | paddingLeft: '30px',
60 | })
61 |
62 | const StyledHeading = styled(Heading3)({
63 | marginBottom: '6px',
64 | marginTop: '16px',
65 | background: 'rgba(0,0,0,0.05)',
66 | display: 'inline-block',
67 | padding: '0 10px',
68 | borderRadius: '2px',
69 | })
70 |
71 | const ListItem = styled(List)({
72 | fontSize: '1.1rem',
73 | })
74 |
75 | const Row = styled.div({
76 | flex: '1 1 0',
77 | display: 'flex',
78 | flexDirection: 'row',
79 | })
80 |
81 | const Chunk = styled.div({
82 | flex: '1 1 0',
83 | })
84 |
85 | export default function BoxModelDiagramPage() {
86 | return (
87 |
88 |
89 |
96 |
97 | {'Day 1-2: HTML & CSS'}
98 |
99 |
100 | Day 1
101 |
102 | Elements
103 | Styling
104 | Box Model
105 | Browser Dev Tools
106 |
107 |
108 |
109 | Day 2
110 |
111 | Flexbox
112 | Advanced Selectors
113 | Units
114 | Responsive Design
115 | Accessibility
116 | Limitations
117 |
118 |
119 |
120 |
121 |
122 |
123 |
128 | {'Day 3-4: TypeScript'}
129 |
130 |
131 |
132 | Day 3
133 |
134 | TypeScript Overview
135 | Type Declarations
136 | Type Refinement
137 | DOM
138 |
139 |
140 |
141 | Day 4
142 |
143 | Tools
144 | Imports and Exports
145 | Events
146 | Equality
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
159 | {'Day 5-8: React'}
160 |
161 |
162 |
163 | Day 5 - Fundamentals
164 |
165 | {'JSX, Elements & Components'}
166 | {'Props & Children'}
167 | Styling
168 | Conditional Rendering
169 | {'Lists & Keys'}
170 |
171 |
172 |
173 | Day 6 - Hooks
174 |
175 | Hooks
176 | Rules of hooks
177 | Built-in hooks
178 | Custom hooks
179 |
180 |
181 |
182 | Day 7 - Data
183 |
184 | XHR
185 | Promises
186 | Async/Await
187 | Suspense
188 | Working with Contexts
189 |
190 |
191 |
192 | Day 8 - Production-readiness
193 |
194 | Performance
195 | Devtools
196 | Lifecycle
197 | Patterns
198 | Testing
199 |
200 |
201 |
202 |
203 |
204 |
205 | )
206 | }
207 |
--------------------------------------------------------------------------------
/pages/slides.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import SpectacleSlideshow from '../components/SpectacleSlideshow'
3 |
4 | const introSlides = require('!!babel-loader!spectacle-mdx-loader!../slides/index.mdx')
5 |
6 | const slides = introSlides.default.map((slide, index) => {
7 | return {
8 | sectionName: ``,
9 | SlideComponent: slide,
10 | NotesComponent: introSlides.notes[index],
11 | }
12 | })
13 |
14 | export default () =>
15 |
--------------------------------------------------------------------------------
/pages/syntax_diagram.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { parseQueryParameters, parseUrl, useRouter } from 'react-guidebook'
3 | import styled from 'styled-components'
4 | import SyntaxDiagram, { Token } from '../components/SyntaxDiagram'
5 |
6 | const Container = styled.div({
7 | height: '100vh',
8 | display: 'flex',
9 | alignItems: 'center',
10 | justifyContent: 'center',
11 | overflow: 'hidden',
12 | })
13 |
14 | function getTokens(fragment: string): Token[] | undefined {
15 | const data = parseQueryParameters(fragment).data
16 |
17 | if (!data) return
18 |
19 | return JSON.parse(data).tokens
20 | }
21 |
22 | export default function SyntaxDiagramPage() {
23 | const router = useRouter()
24 | const { fragment } = parseUrl(router.clientPath)
25 | const tokens = getTokens(fragment) || []
26 |
27 | return (
28 |
29 |
30 |
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/pages/typescript.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: TypeScript
3 | ---
4 |
5 | ## Web browsers run JavaScript
6 |
7 | JavaScript is the only language that web browsers can run natively.
8 |
9 | JavaScript is weakly-typed, so the following code is valid:
10 |
11 |
20 |
21 | ## TypeScript to the rescue
22 |
23 | TypeScript is a superset of JavaScript that supports type annotations.
24 |
25 | The above code is no longer valid:
26 |
27 |
36 |
37 | ## How TypeScript works
38 |
39 | Type annotations are stripped out during a build step.
40 |
41 | Because of this, there may be no way to tell the type of your variables at runtime. E.g. in the example below, there's no way to tell that the `rect` object is a `Rectangle` at runtime, since `Rectangle` doesn't exist in the compiled code.
42 |
43 |
62 |
63 | TODO: Mention sourcemaps
64 |
65 | ## Comparisons with other languages
66 |
67 | - **Swift**: https://dabbott.github.io/webdev-projects/cheatsheets/swift-typescript.html
68 |
69 | > Go through cheatsheet up to anonymous functions
70 |
71 | ## TypeScript Playground
72 |
73 | You can play with TypeScript in the playground on the TypeScript docs here: https://www.typescriptlang.org/play
74 |
--------------------------------------------------------------------------------
/pages/typescript/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "order": [
3 | "type_declarations",
4 | "type_refinement",
5 | "dom",
6 | "imports_and_exports",
7 | "events",
8 | "equality",
9 | "immutability",
10 | "context",
11 | "tools"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/pages/typescript/context.mdx:
--------------------------------------------------------------------------------
1 | See https://www.typescript.express/functions/context
2 |
--------------------------------------------------------------------------------
/pages/typescript/dom.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: DOM
3 | ---
4 |
5 | The DOM or "Document Object Model" is an in-memory representation of an HTML page.
6 |
7 | We can use TypeScript to read and modify the UI of a webpage using the DOM.
8 |
9 | ## Accessing elements
10 |
11 | We typically use `document.querySelector` or `document.querySelectorAll` to grab a reference to existing elements in our HTML document. We can then modify them using DOM APIs.
12 |
13 |
20 |
21 |
22 |
23 | My page
24 |
25 |
26 | Change background!
27 |
28 |
34 | `,
35 | }}
36 | />
37 |
38 | ## Creating elements
39 |
40 |
50 |
--------------------------------------------------------------------------------
/pages/typescript/equality.mdx:
--------------------------------------------------------------------------------
1 | See https://www.typescript.express/syntax/equality
2 |
3 | See https://www.typescript.express/syntax/logical_operators
4 |
--------------------------------------------------------------------------------
/pages/typescript/events.mdx:
--------------------------------------------------------------------------------
1 | ## Event loop
2 |
3 | The event loop is queue of functions. When a program starts, the engine evaluates all JavaScript code. Then the engine goes "idle" until new "events" (functions) are added to the event loop. New events may be inserted into the event loop at any time, either by our code or the JavaScript environment (usually in response to I/O), which are then executed in sequence. We use callback functions to perform actions as a result of events.
4 |
5 | ## setTimeout
6 |
7 | To set a one-off timer, we use `setTimeout`.
8 |
9 |
16 |
17 |
18 |
19 | My page
20 |
21 | Waiting...
22 |
27 | `,
28 | }}
29 | />
30 |
31 | ## setInterval
32 |
33 | To set a repeating timer, we use `setInterval`.
34 |
35 |
42 |
43 |
44 |
45 | My page
46 |
47 | Waiting...
48 |
53 | `,
54 | }}
55 | />
56 |
57 | ## Click events
58 |
59 | Events bubble up from inner to outer elements. We can prevent this by calling `event.stopPropagation()`.
60 |
61 | If we want to add multiple events, we can use `element.addEventListener` instead of assigning directly to the event handler, e.g. `outer.addEventListener('click', () => { ... })`.
62 |
63 | Most global events can be assigned to the `document` object.
64 |
65 |
72 |
73 |
74 |
75 | My page
76 |
86 |
87 |
88 |
91 |
92 |
108 | `,
109 | }}
110 | />
111 |
112 | ## Capture and bubble phases
113 |
114 | 
115 |
116 | > From: https://developer.salesforce.com/blogs/developer-relations/2017/08/depth-look-lightning-component-events.html
117 |
118 | The third parameter to `addEventListener` can bind events to the capture phase, e.g. `outer.addEventListener('click', () => { ... }, true)`.
119 |
--------------------------------------------------------------------------------
/pages/typescript/immutability.mdx:
--------------------------------------------------------------------------------
1 | Most of the time, we use mutable objects and arrays, but we often want to treat them as if they were immutable - instead of mutating them, we make a clone and modify the clone.
2 |
3 | We typically do this through "spread" syntax:
4 |
5 | See: https://www.typescript.express/syntax/spread
6 |
7 | We sometimes do this for deeply nested objects, cloning each intermediate object/array.
8 |
--------------------------------------------------------------------------------
/pages/typescript/imports_and_exports.mdx:
--------------------------------------------------------------------------------
1 | See https://www.typescript.express/modules/imports_and_exports
2 |
--------------------------------------------------------------------------------
/pages/typescript/projects.mdx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/pages/typescript/projects.mdx
--------------------------------------------------------------------------------
/pages/typescript/projects/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "order": ["todo_list", "drawing"]
3 | }
4 |
--------------------------------------------------------------------------------
/pages/typescript/projects/drawing.mdx:
--------------------------------------------------------------------------------
1 | ## Completed Example
2 |
3 |
22 |
23 | ## Steps
24 |
25 | Starting from the starter code...
26 |
27 | 1. Refactor our path drawing code by extracting out a separate function to create a path:
28 |
29 | ```ts
30 | function convertToPath(shape: Shape): Path2D {
31 | const path = new Path2D()
32 |
33 | // ...
34 |
35 | return path
36 | }
37 | ```
38 |
39 | After this, use `context.fill(path)` and `context.stroke(path)` to draw the path.
40 |
41 | 2. Implement the pencil tool.
42 |
43 | 3. Add one or more of the following features:
44 |
45 | - **Keyboard Shortcuts**
46 |
47 | Pressing "r" should activate the rectangle tool, "o" should activate ellipse, and "p" or "v" should activate pencil.
48 |
49 | > Hint: use the `onkeypress` event, and set the `checked` property of the input elements
50 |
51 | - **Eraser Tool**
52 |
53 | When the eraser tool is active, dragging should remove any shape under the mouse.
54 |
55 | > Hint: use the canvas APIs `context.isPointInPath` and `context.isPointInStroke` to determine the shape under the mouse
56 |
57 | - **Move Tool (hardest)**
58 |
59 | When the move tool is active, dragging should move the top shape under the mouse.
60 |
61 | > Hint: use the canvas APIs `context.isPointInPath` and `context.isPointInStroke` to determine the shape under the mouse
62 |
--------------------------------------------------------------------------------
/pages/typescript/projects/todo_list.mdx:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/pages/typescript/resources.mdx:
--------------------------------------------------------------------------------
1 | Swift \* TypeScript cheatsheet: https://dabbott.github.io/webdev-projects/cheatsheets/swift-typescript.html
2 |
3 | TypeScript Playground: https://www.typescriptlang.org/play
4 |
--------------------------------------------------------------------------------
/pages/typescript/tools.mdx:
--------------------------------------------------------------------------------
1 | ## Setting up a new project
2 |
3 | - We use `node` and `yarn` to manage dependencies and build the project
4 |
5 | ```bash
6 | yarn init
7 | ```
8 |
9 | - `package.json`
10 | - dependencies
11 | - devDependencies
12 | - Add typescript compiler
13 |
14 | ```bash
15 | yarn add -D typescript
16 | ```
17 |
18 | - `tsc`
19 | - 1:1 file mapping - ts to plain js
20 | - For node (server-side) code, we're done here
21 | - `tsconfig.json`
22 |
23 | ```json
24 | {
25 | "compilerOptions": {
26 | "strict": true,
27 | "target": "es2018",
28 | "outDir": "./lib",
29 | "rootDir": "./src",
30 | "lib": ["ESNext", "DOM"],
31 | "sourceMap": true
32 | },
33 | "exclude": ["node_modules"]
34 | }
35 | ```
36 |
37 | - Run individual files with `node`
38 |
39 | - `node lib/foo.js`
40 |
41 | - Bundler: `webpack`, `parcel`, etc
42 |
43 |
54 |
--------------------------------------------------------------------------------
/pages/typescript/type_declarations.mdx:
--------------------------------------------------------------------------------
1 | ## `type` keyword
2 |
3 | Most types are declared with the `type` keyword.
4 |
5 | Unlike most languages, _literal values_ can be used as types.
6 |
7 |
16 |
17 | ## Type inference
18 |
19 | Variables are declared with `let`, and constants are declared with `const`. Note that the inferred types are different.
20 |
21 |
28 |
29 | ## Object types
30 |
31 | Objects are used both like like _dictionaries_, with arbitrary fields but values of the same type, and like _structs_, with named fields and values of different types.
32 |
33 | Note that this distinction only exists at compile-time. At run-time, all objects are dictionary-like, supporting arbitrary fields and values.
34 |
35 | ### "Dictionary-like" objects
36 |
37 |
48 |
49 | ### "Struct-like" objects
50 |
51 | These objects have a set of defined property names and values.
52 |
53 | Note that type declarations look _a lot_ like literal values, and it's common to accidentally confuse types and values.
54 |
55 |
69 |
70 | ## Classes
71 |
72 | These are about the same as Swift in terms of both syntax and semantics.
73 |
74 | ## Interfaces
75 |
76 | These are about the same as Swift protocols.
77 |
78 | Note that when defining objects, `type` and `interface` are almost interchangeable - https://microsoft.github.io/TypeScript-New-Handbook/everything/#interface-vs-alias. Using one or the other mostly comes down to personal preference and whatever pattern has been established in the codebase.
79 |
80 | 42
91 | }`}
92 | />
93 |
94 | TypeScript doesn't support default implementations or protocol extensions (without very non-ideomatic prototype extension).
95 |
96 | ## Unions
97 |
98 | We're allowed to make unions out of any types.
99 |
100 |
107 |
108 | ### Discriminated Unions
109 |
110 | These are analogous to Swift's enums with associated data.
111 |
112 | Note that we typically use the property `type` as the "discriminant", but we can use any arbitrary type.
113 |
114 |
137 |
138 | ### Enums
139 |
140 | TypeScript supports enums, but unions are much more common:
141 |
142 | - Enums can't have associated data
143 | - Enums can't have methods or static members
144 | - Converting to/from an enum is a hassle
145 |
146 |
157 |
158 | ## Intersection types
159 |
160 | This works both with object types and interfaces.
161 |
162 |
171 |
--------------------------------------------------------------------------------
/pages/typescript/type_refinement.mdx:
--------------------------------------------------------------------------------
1 | - Big difference from Swift: TypeScript does a lot of type refinement automatically
2 | - Can be confusing at first, types in VSCode might not be what you expect
3 |
4 |
15 |
--------------------------------------------------------------------------------
/public/static/devin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/public/static/devin.jpg
--------------------------------------------------------------------------------
/public/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/public/static/favicon.ico
--------------------------------------------------------------------------------
/public/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/public/static/favicon.png
--------------------------------------------------------------------------------
/public/static/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/public/static/logo.png
--------------------------------------------------------------------------------
/public/static/logo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/public/static/logo@2x.png
--------------------------------------------------------------------------------
/public/static/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/public/static/preview.png
--------------------------------------------------------------------------------
/public/static/quotes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dabbott/webdev-express/1a394c10d1bb8afafd2b712400f1f489f9871393/public/static/quotes.png
--------------------------------------------------------------------------------
/slides/index.mdx:
--------------------------------------------------------------------------------
1 | # React Native
2 |
3 | - [Intro](/intro_slides)
4 | - [JavaScript & JSX](/javascript/slides)
5 | - [React](/react/slides)
6 | - [Core Components](/core_components/slides)
7 | - [App Development](/app/slides)
8 |
--------------------------------------------------------------------------------
/slides/intro.mdx:
--------------------------------------------------------------------------------
1 | ## React
2 |
3 | React is a JavaScript library for building user interfaces.
4 |
5 | - Declarative
6 | - Component-based
7 | - _"Learn Once, Write Anywhere"_
8 |
9 | ---
10 |
11 | ## Declarative
12 |
13 | We define the _current state_ of the UI and let React figure out _how_ to render it.
14 |
15 | React figures out how to call `view.addView`/`view.addSubview` for us.
16 |
17 | > React figures out the optimal way to update the UI.
18 |
19 | Similar to SwiftUI & Jetpack Compose
20 |
21 | ---
22 |
23 | ## Component-based
24 |
25 | - Components are encapsulated
26 | - Everything is a component - no view controllers or fragments
27 | - Written entirely in JavaScript - no storyboards or layout files
28 |
29 | ---
30 |
31 | ## _Learn Once, Write Anywhere_
32 |
33 | If you learn JavaScript and React, you can write:
34 |
35 | - Mobile apps (React Native)
36 | - Websites (React DOM)
37 | - Desktop apps (React Native Windows / React Native macOS)
38 | - VR apps (React 360)
39 | - ...and more!
40 |
41 | > The React library is the same for each. We pair it with platform-specific API bindings.
42 |
43 | ---
44 |
45 | ## Reference
46 |
47 | All slides available online: [reactnative.express/slides](https://www.reactnative.express/slides)
48 |
--------------------------------------------------------------------------------
/styles/slidesTheme.ts:
--------------------------------------------------------------------------------
1 | import { slidesTheme } from 'react-guidebook'
2 |
3 | export default slidesTheme
4 |
--------------------------------------------------------------------------------
/styles/theme.ts:
--------------------------------------------------------------------------------
1 | import { defaultTheme } from 'react-guidebook'
2 |
3 | defaultTheme.colors.primary = 'rgb(62,195,18)'
4 | defaultTheme.colors.title.right = 'rgb(189,255,36)'
5 | defaultTheme.colors.textDecorativeLight = 'rgb(114,189,117)'
6 | defaultTheme.colors.selectedBackground = 'rgb(244,250,242)'
7 |
8 | // defaultTheme.sizes.tableOfContentsWidth = 160
9 |
10 | export default defaultTheme
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "strictNullChecks": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "noEmit": true,
11 | "esModuleInterop": true,
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "jsx": "preserve"
17 | },
18 | "exclude": ["node_modules", "examples"],
19 | "include": [
20 | "next-env.d.ts",
21 | "custom.d.ts",
22 | "guidebook.d.ts",
23 | "**/*.ts",
24 | "**/*.tsx"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/utils/search.js:
--------------------------------------------------------------------------------
1 | import * as Guidebook from 'react-guidebook'
2 | import guidebook from '../guidebook'
3 |
4 | let searchDocuments = []
5 | let searchIndexPromise = undefined
6 |
7 | export const searchPages = (query) => {
8 | if (!searchIndexPromise) {
9 | searchIndexPromise = Promise.all([
10 | import('../searchIndex'),
11 | import('flexsearch'),
12 | ]).then(([{ indexData, documents }, { default: FlexSearch }]) => {
13 | searchDocuments = documents
14 | const search = new FlexSearch()
15 | search.import(indexData)
16 | return search
17 | })
18 | }
19 |
20 | return searchIndexPromise.then((searchIndex) =>
21 | Guidebook.searchPages(guidebook, searchIndex, searchDocuments, query)
22 | )
23 | }
24 |
25 | export const searchTextMatch = (id, query) =>
26 | Guidebook.searchTextMatch(guidebook, searchDocuments, id, query)
27 |
--------------------------------------------------------------------------------
/utils/serialize.ts:
--------------------------------------------------------------------------------
1 | // MIT License
2 | // https://github.com/pravdomil/React-Serialize
3 |
4 | import React from 'react'
5 |
6 | /**
7 | * Serialize React element to JSON string
8 | */
9 | export function serialize(element: React.ReactNode): string {
10 | function replacer(this: any, key: string, value: any) {
11 | switch (key) {
12 | case '_owner':
13 | case '_store':
14 | case 'ref':
15 | case 'key':
16 | return
17 | case 'mdxType':
18 | case 'originalType':
19 | return
20 | case 'type':
21 | if (this.props.originalType) {
22 | return this.props.originalType
23 | }
24 |
25 | if (typeof value === 'string') {
26 | return value
27 | }
28 | if (value === React.Fragment) {
29 | return '<>'
30 | }
31 | return value.displayName || value.name
32 | default:
33 | return value
34 | }
35 | }
36 |
37 | return JSON.stringify(element, replacer)
38 | }
39 |
40 | type Options = {
41 | components?: Record
42 | reviver?: (
43 | type: any,
44 | props: Record,
45 | key: number | undefined,
46 | components: Record
47 | ) => {
48 | type: any
49 | props: Record
50 | key: number | undefined
51 | components: Record
52 | }
53 | }
54 |
55 | /**
56 | * Deserialize JSON string to React element
57 | */
58 | export function deserialize(data: string | object, options?: Options) {
59 | if (typeof data === 'string') {
60 | data = JSON.parse(data)
61 | }
62 | if (data instanceof Object) {
63 | return deserializeElement(data, options)
64 | }
65 | throw new Error('Deserialization error: incorrect data type')
66 | }
67 |
68 | function deserializeElement(
69 | element: any,
70 | options: Options = {},
71 | key?: number
72 | ): React.ReactNode {
73 | let { components = {}, reviver } = options
74 |
75 | if (typeof element !== 'object') {
76 | return element
77 | }
78 |
79 | if (element === null) {
80 | return element
81 | }
82 |
83 | if (element instanceof Array) {
84 | return element.map((el, i) => deserializeElement(el, options, i))
85 | }
86 |
87 | // Now element has following shape { type: string, props: object }
88 |
89 | let { type, props } = element
90 |
91 | if (typeof type !== 'string') {
92 | throw new Error('Deserialization error: element type must be string')
93 | }
94 |
95 | if (type === '<>') {
96 | type = React.Fragment
97 | } else {
98 | type = components[type] || type.toLowerCase()
99 | }
100 |
101 | if (props.children) {
102 | props = { ...props, children: deserializeElement(props.children, options) }
103 | }
104 |
105 | if (reviver) {
106 | ;({ type, props, key, components } = reviver(type, props, key, components))
107 | }
108 |
109 | return React.createElement(type, { ...props, key })
110 | }
111 |
--------------------------------------------------------------------------------