- 💿 Open up the app and show all the features
- 💿 Build a little todo list from scratch
- normal forms
- ship it, it works and the UX is fine
- iterate to useFetcher to show why you'd bring it in
- useFetcher is the thing that turns your remix app from a "website" to a "web app", if you're into that terminology.
- still just forms!
- progressive enhancement is about two things
- how the app goes from basic functionality to fancy
- progressive enhancement is about two things
- normal forms
- how the developer is able to iterate their code from basic to fancy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useLocation, useTransition } from "@remix-run/react"; | |
import * as React from "react"; | |
/** | |
* An enhanced `<details>` component that's intended to be used as a menu (a bit | |
* like a menu-button). | |
*/ | |
export let DetailsMenu = React.forwardRef< | |
HTMLDetailsElement, | |
React.ComponentPropsWithRef<"details"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import localforage from "localforage"; | |
import { matchSorter } from "match-sorter"; | |
import sortBy from "sort-by"; | |
export async function getContacts(query) { | |
await fakeNetwork(`getContacts:${query}`); | |
let contacts = await localforage.getItem("contacts"); | |
if (!contacts) contacts = []; | |
if (query) { | |
contacts = matchSorter(contacts, query, { keys: ["first", "last"] }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html { | |
box-sizing: border-box; | |
} | |
*, | |
*:before, | |
*:after { | |
box-sizing: inherit; | |
} | |
body { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// TODO: make `pages` optional and measure the div when unspecified, this will | |
// allow more normal document flow and make it easier to do both mobile and | |
// desktop. | |
import { | |
createContext, | |
useCallback, | |
useContext, | |
useEffect, | |
useMemo, | |
useRef, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import fsp from "fs/promises"; | |
import invariant from "tiny-invariant"; | |
import path from "path"; | |
/** | |
* Fetches the contents of a file in a repository or from your local disk. | |
* | |
* @param ref The GitHub ref, use `"local"` for local docs development | |
* @param filepath The filepath inside the repo (including "docs/") | |
* @returns The text of the file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import "./index.css"; | |
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import { | |
DataBrowserRouter, | |
Route, | |
useLoaderData, | |
Form, | |
useNavigation, | |
} from "react-router-dom"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/routes | |
/__landing.tsx -> (layout: __landing.*) | |
/__landing.index.tsx -> / | |
/__landing.company.tsx -> /company | |
/__landing.company.team.tsx -> /company/team | |
/__landing.company.careers.tsx -> /company/careers | |
/__landing.docs.doc.$.tsx -> /docs/* | |
/__auth.tsx -> (layout: _auth.*) | |
/__auth.login.tsx -> /login | |
/__auth.signup.tsx -> /signup |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function useIsPendingPathname(to) { | |
let { location } = useTransition(); | |
let { pathname } = useResolvedPath(to); | |
return location?.pathname === pathname; | |
} | |
function useIsSlowTransition(ms = 300) { | |
let transition = useTransition(); | |
let [isSlow, setIsSlow] = useState(false); |