Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

(docs) - Post-release update (#605)

* fix min-height on article and offset markdown links to allow for fixed header

* relocate target pseudo selector to mdx.js

* Edit Introduction, Getting Started, and Queries

* Edit Mutations, Document Caching, and Errors

* Fix some non-American typos

* Close sidebar on background click

* Add missing sub-page links to index pages

* Add rel="external" to external links

* Add anchor links to headings

* Fix lint errors

Co-authored-by: Phil Pluckthun <phil@kitten.sh>

authored by

Will Golledge
Phil Pluckthun
and committed by
GitHub
f1a6267a 5409c462

+177 -84
+9 -8
docs/README.md
··· 7 7 8 8 `urql` is an implementation of a GraphQL client, built to be both easy to use for newcomers to 9 9 GraphQL, as well as extensible, to grow to support dynamic single-app applications and highly 10 - customised GraphQL infrastructure. In short, `urql` prioritizes usability and adaptability. 10 + customized GraphQL infrastructure. In short, `urql` prioritizes usability and adaptability. 11 11 12 12 As you're adopting GraphQL, `urql` becomes your primary data layer and can handle content-heavy 13 13 pages through ["Document Caching"](./basics/document-caching.md) as well as dynamic and data-heavy 14 - pages through ["Normalized Caching"](./graphcache/normalized-caching.md). 14 + apps through ["Normalized Caching"](./graphcache/normalized-caching.md). 15 15 16 16 ## Constituent Parts 17 17 18 - `urql` can be understood as a collection of connected parts and packages. When you [get 18 + `urql` can be understood as a collection of connected parts and packages. When you [first get 19 19 started](./basics/getting-started.md) you'll only need to install a single package for your 20 20 framework of choice. We're then able to declaratively send GraphQL requests to our API. 21 21 22 - All framework packages — like `urql` and `@urql/preact` — wrap the core package, which we can 23 - imagine as the brain of `urql` with most of its logic. 22 + All framework packages — like `urql`, `@urql/preact`, and `@urql/svelte` — wrap the [core 23 + package](./concepts/core-package.md), which we can imagine as the brain of `urql` with most of its 24 + logic. 24 25 25 26 As we progress with implementing `urql` into our application, we're later able to extend it by 26 27 adding ["addon packages", which we call _Exchanges_](./concepts/exchanges.md) ··· 34 35 guide](./basics/getting-started.md) and usage patterns for our framework of choice. 35 36 - **Main Concepts** then explains more about how `urql` functions, what it's made up of, and covers 36 37 the main aspects of the `Client` and GraphQL clients in general, on the ["Philosophy" 37 - page](./concepts/philosophy.md) 38 + page](./concepts/philosophy.md). 38 39 - **Advanced** covers all more uncommon use-cases and contains guides that we won't need immediately 39 40 when we get started with `urql`. 40 41 - **Graphcache** documents one of the most important addons to `urql`, which adds ["Normalized 41 42 Caching" support](./graphcache/normalized-caching.md) to the `Client` and enables more complex 42 43 use-cases, smarter caching, and more dynamic apps to function. 43 - - **Showcase** aims to list some companies that use `urql`, third-party packages, and other helpful 44 - resources, like tutorials or guides. 44 + - **Showcase** aims to list users of `urql`, third-party packages, and other helpful resources, 45 + like tutorials and guides. 45 46 - **API** contains a detailed list of all helpers, utilities, components, and other parts of each of 46 47 `urql`'s packages, which may contain all details of each part and package. 47 48
+4 -4
docs/advanced/README.md
··· 9 9 catch-all chapter of various use-cases that can only be covered after [the "Concepts" 10 10 chapter.](../concepts/README.md) 11 11 12 - - **Subscriptions** covers how to use `useSubscription` and how to set up GraphQL subscriptions with 12 + - [**Subscriptions**](./subscriptions.md) covers how to use `useSubscription` and how to set up GraphQL subscriptions with 13 13 `urql`. 14 - - **Server-side Rendering** guides us through how to set up server-side rendering and rehydration. 15 - - **Auto-populate Mutations** presents the `populateExchange` addon which can make it easier to 14 + - [**Server-side Rendering**](./server-side-rendering.md) guides us through how to set up server-side rendering and rehydration. 15 + - [**Auto-populate Mutations**](./auto-populate-mutations.md) presents the `populateExchange` addon which can make it easier to 16 16 update normalized data after mutations. 17 - - **Testing** covers how to test components that use `urql` particularly in React. 17 + - [**Testing**](./testing.md) covers how to test components that use `urql` particularly in React.
+6 -6
docs/advanced/server-side-rendering.md
··· 12 12 ## The SSR Exchange 13 13 14 14 The `ssrExchange` has two functions. On the server-side it's able to gather all results as they're 15 - being fetched, which can then be serialised and sent to the client. On the client-side it's able to 16 - use these serialised results to rehydrate and render the application without refetching this data. 15 + being fetched, which can then be serialized and sent to the client. On the client-side it's able to 16 + use these serialized results to rehydrate and render the application without refetching this data. 17 17 18 18 To start out with the `ssrExchange` we have to add the exchange to our `Client`: 19 19 ··· 28 28 29 29 const isServerSide = typeof window === 'undefined'; 30 30 31 - // The `ssrExchange` must be initialised with `isClient` and `initialState` 31 + // The `ssrExchange` must be initialized with `isClient` and `initialState` 32 32 const ssr = ssrExchange({ 33 33 isClient: !isServerSide, 34 34 initialState: !isServerSide ? window.__URQL_DATA__ : undefined, ··· 44 44 }); 45 45 ``` 46 46 47 - The `ssrExchange` must be initialised with the `isClient` and `initialState` options. The `isClient` 47 + The `ssrExchange` must be initialized with the `isClient` and `initialState` options. The `isClient` 48 48 option tells the exchange whether it's on the server- or client-side. In our example we use `typeof window` to determine this, but in Webpack environments you may also be able to use `process.browser`. 49 49 50 - The `initialState` option should be set to the serialised data you retrieve on your server-side. 51 - This data may be retrieved using methods on `ssrExchange()`. You can retrive the serialised data 50 + The `initialState` option should be set to the serialized data you retrieve on your server-side. 51 + This data may be retrieved using methods on `ssrExchange()`. You can retrive the serialized data 52 52 after server-side rendering using `ssr.extractData()`: 53 53 54 54 ```js
+1 -1
docs/api/graphcache.md
··· 200 200 cache.resolveFieldByKey({ __typename: 'Query' }, cache.keyOfField('todo', { id: 1 })); // 'Todo:1' 201 201 ``` 202 202 203 - This specialised method is likely only going to be useful in combination with 203 + This specialized method is likely only going to be useful in combination with 204 204 [`cache.inspectFields`](#inspectfields). 205 205 206 206 ### inspectFields
+6 -6
docs/basics/README.md
··· 8 8 In this chapter we'll explain the basics of `urql` and how to get started with using it without any 9 9 prior knowledge. It's split into multiple pages that are best read in order. 10 10 11 - - **Getting started** covers how to install the package and set it up. 12 - - **Queries** explains how to write your first GraphQL queries with `urql`. 13 - - **Mutations** follows up with how to define mutations. 14 - - **Document Caching** explains the default cache mechanism of `urql`, as opposed to the [Normalized 15 - Cache](../graphcache/normalized-caching.md) which is not the default. 16 - - **Errors** contains information on error handling in `urql`. 11 + - [**Getting started**](./getting-started.md) covers how to install the package for your framework of choice and set it up. 12 + - [**Queries**](./queries.md) explains how to write your first GraphQL queries with `urql`. 13 + - [**Mutations**](./mutations.md) follows up with how to define GraphQL mutations. 14 + - [**Document Caching**](./document-caching.md) explains the default cache mechanism of `urql`, as opposed to the opt-in 15 + [Normalized Cache](../graphcache/normalized-caching.md). 16 + - [**Errors**](./errors.md) contains information on error handling in `urql`. 17 17 18 18 After reading "Basics" you may want to [read the "Concepts" chapter of the 19 19 documentation](../concepts/README.md) as it explains the motivation and architecture that drives
+13 -10
docs/basics/document-caching.md
··· 11 11 This works like the cache in a browser. `urql` creates a key for each request that is sent based on 12 12 a query and its variables. 13 13 14 + The default _document caching_ logic is implemented in the default `cacheExchange`. We'll learn more 15 + about ["Exchanges" on a later page.](../concepts/exchanges.md) 16 + 14 17 ## Operation Keys 15 18 16 19 ![Keys for GraphQL Requests](../assets/urql-operation-keys.png) 17 20 18 - Once a result comes in it's cached indefinitely by their key. This means that each unique request 21 + Once a result comes in it's cached indefinitely by its key. This means that each unique request 19 22 can have exactly one cached result. 20 23 21 - However, we also need to invalidate the cache result so new requests for the same data can be 22 - sent when we know that some results are outdated. A result may be outdated because a mutation has 23 - been executed on data that has been queried previously. 24 + However, we also need to invalidate the cached results so that requests are sent again and updated, 25 + when we know that some results are out-of-date. With document caching we assume that a result may 26 + be invalidated by a mutation that executes on data that has been queried previously. 24 27 25 - In GraphQL the client can request additional type information on a query by adding the `__typename` 26 - field. This field return the name of the type of a piece of data in a requests, and we use it 27 - to detect commonalities and data dependencies between queries and mutations. 28 + In GraphQL the client can request additional type information by adding the `__typename` field to a 29 + query's _selection set_. This field returns the name of the type for an object in the results, and 30 + we use it to detect commonalities and data dependencies between queries and mutations. 28 31 29 32 ![Document Caching](../assets/urql-document-caching.png) 30 33 31 - When we send a mutation that contains types that another query's results contains as well, that 32 - query's result is removed from the cache. 34 + In short, when we send a mutation that contains types that another query's results contains as well, 35 + that query's result is removed from the cache. 33 36 34 37 This is an aggressive form of cache invalidation. However, it works well for content-driven sites, 35 - although it doesn't deal with normalized data or IDs. 38 + while it doesn't deal with normalized data or IDs. 36 39 37 40 ## Request Policies 38 41
+1 -1
docs/basics/errors.md
··· 6 6 # Error handling 7 7 8 8 When we use a GraphQL API there are two kinds of errors we may encounter: Network Errors and GraphQL 9 - Errors from the API. Since it's common to encounter either of them in development, there's a 9 + Errors from the API. Since it's common to encounter either of them, there's a 10 10 [`CombinedError`](../api/core.md#combinederror-class) class that can hold and abstract either. 11 11 12 12 We may encounter a `CombinedError` when using `urql` wherever an `error` may be returned, typically
+14 -14
docs/basics/getting-started.md
··· 7 7 8 8 In the ["Introduction"](./README.md) we read how `urql` consists of multiple constituent parts that 9 9 make up a GraphQL client. Hence there are multiple packages — one for each framework we officially 10 - support — that you'll get started with. 10 + support — that we'll get started with on this page. 11 11 12 12 ## React & Preact 13 13 14 - This "Getting Started" guide covers how to install and set up `urql` and the Client, for React and 15 - Preact. Since the `urql` and `@urql/preact` packages share most of their API one-to-one, when 16 - reading the documentation on React, all examples are essentially the same, except that we'll use the 17 - `@urql/preact` package instead of the `urql` package for Preact. 14 + This "Getting Started" guide covers how to install and set up `urql` and the `Client`, for React and 15 + Preact. Since the `urql` and `@urql/preact` packages share most of their API and are used in the 16 + same way, when reading the documentation on React, all examples are essentially the same, except 17 + that we'd want to use the `@urql/preact` package instead of the `urql` package for Preact. 18 18 19 19 ### Installation 20 20 ··· 27 27 npm install --save urql graphql 28 28 ``` 29 29 30 - To use urql with Preact, we have to install `@urql/preact` instead of `urql` and import from 30 + To use `urql` with Preact, we have to install `@urql/preact` instead of `urql` and import from 31 31 that package instead. Otherwise all examples for Preact will be the same. 32 32 33 33 Most libraries related to GraphQL also need the `graphql` package to be installed as a peer 34 - dependency, so that they can adapt to your specific versioning requirements, which is why we'll need 35 - to install `graphql` as well. 34 + dependency, so that they can adapt to your specific versioning requirements. That's why we'll need 35 + to install `graphql` alongside `urql`. 36 36 37 - Both the `urql` packages and `graphql` follow [semantic versioning](https://semver.org) and `urql` 38 - packages will define a range of compatible versions of `graphql`. Watch out for breaking changes in 39 - the future however, in which case your package manager may warn you about `graphql` being out of the 40 - defined peer dependency range. 37 + Both the `urql` and `graphql` packages follow [semantic versioning](https://semver.org) and all 38 + `urql` packages will define a range of compatible versions of `graphql`. Watch out for breaking 39 + changes in the future however, in which case your package manager may warn you about `graphql` being 40 + out of the defined peer dependency range. 41 41 42 42 ### Setting up the `Client` 43 43 ··· 55 55 At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started. 56 56 57 57 Another common option is `fetchOptions`. This option allows us to customize the options that will be 58 - passed to `fetch` when a request is sent to the given API `url`. We may pass in an object or a 59 - function returning an object to this option. 58 + passed to `fetch` when a request is sent to the given API `url`. We may pass in an options object or 59 + a function returning an options object. 60 60 61 61 In the following example we'll add a token to each `fetch` request that our `Client` sends to our 62 62 GraphQL API.
+4 -3
docs/basics/mutations.md
··· 11 11 12 12 ## React & Preact 13 13 14 - This guide covers how to query data with React and Preact, which share almost the same API. 14 + This guide covers how to send mutations in React and Preact, which share almost the same API. 15 15 16 16 Both libraries offer a `useMutation` hook and a `Mutation` component. The latter accepts the same 17 17 parameters but we won't cover it in this guide. [Look it up in the API docs if you prefer ··· 19 19 20 20 ### Sending a mutation 21 21 22 - Let's pick up an example in an imaginary todo items GraphQL API and dive into an example! 23 - We'll set up a mutation that _updates_ a todo item. 22 + Let's again pick up an example with an imaginary GraphQL API for todo items, and dive into an 23 + example! We'll set up a mutation that _updates_ a todo item's title. 24 24 25 25 ```jsx 26 26 const UpdateTodo = ` 27 27 mutation ($id: ID!, $title: String!) { 28 28 updateTodo (id: $id, title: $title) { 29 29 id 30 + title 30 31 } 31 32 } 32 33 `;
+24 -18
docs/basics/queries.md
··· 18 18 19 19 ### Run a first query 20 20 21 - For the following examples imagine we are querying data from a GraphQL API that contains todo items 22 - Let's dive right into an example! 21 + For the following examples, we'll imagine that we're querying data from a GraphQL API that contains 22 + todo items. Let's dive right into it! 23 23 24 24 ```jsx 25 25 import { useQuery } from 'urql'; ··· 53 53 }; 54 54 ``` 55 55 56 - Here we have implemented our first GraphQL query to fetch todos. We see that using `useQuery` 57 - accepts options — in this case we've set `query` to our GraphQL query — and returns a tuple — an 58 - array that contains a result and a reexecute function. 56 + Here we have implemented our first GraphQL query to fetch todos. We see that `useQuery` accepts 57 + options and returns a tuple. In this case we've set the `query` option to our GraphQL query. The 58 + tuple we then get in return is an array that contains a result object and a re-execute function. 59 59 60 - The result contains several properties. The `fetching` field indicates whether we're currently loading 61 - data, `data` contains the actual `data` from the API's result, and `error` is set when either the 62 - request to the API has failed or when our result contained some `GraphQLError`s, which 60 + The result object contains several properties. The `fetching` field indicates whether we're currently 61 + loading data, `data` contains the actual `data` from the API's result, and `error` is set when either 62 + the request to the API has failed or when our API result contained some `GraphQLError`s, which 63 63 we'll get into later on the ["Errors" page](./errors.md). 64 64 65 65 ### Variables 66 66 67 - Typically we'll also need to pass variables to our queries, for instance What if we are dealing with 68 - pagination? For this purpose the `useQuery` hook also accepts a `variables` option, which we can use 67 + Typically we'll also need to pass variables to our queries, for instance, if we are dealing with 68 + pagination. For this purpose the `useQuery` hook also accepts a `variables` option, which we can use 69 69 to supply variables to our query. 70 70 71 71 ```jsx ··· 89 89 ``` 90 90 91 91 As when we're sending GraphQL queries manually using `fetch`, the variables will be attached to the 92 - `POST` request that is sent to our GraphQL API. 92 + `POST` request body that is sent to our GraphQL API. 93 93 94 - Whenever the `variables` (or the `query`) option on 95 - the `useQuery` hook changes `fetching` will return to being `true` and a new request will be sent to 96 - our API, unless a result has already been cached previously. 94 + Whenever the `variables` (or the `query`) option on the `useQuery` hook changes `fetching` will 95 + switch to `true` and a new request will be sent to our API, unless a result has already been cached 96 + previously. 97 97 98 98 ### Pausing `useQuery` 99 99 100 - In some cases we may want `useQuery` to execute a query when a precondition has been met. For 101 - instance, we may be building a form and want validation to only take place when a field has been 102 - filled out. 100 + In some cases we may want `useQuery` to execute a query when a pre-condition has been met, and not 101 + execute the query otherwise. For instance, we may be building a form and want a validation query to 102 + only take place when a field has been filled out. 103 + 104 + Since hooks in React can't just be commented out, the `useQuery` hook accepts a `pause` option that 105 + temporarily _freezes_ all changes and stops requests. 103 106 104 107 In the previous example we've defined a query with mandatory arguments. The `$from` and `$limit` 105 108 variables have been defined to be non-nullable `Int!` values. 106 109 107 110 Let's pause the query we've just 108 111 written to not execute when these variables are empty, to prevent `null` variables from being 109 - executed. We can do this by means of the `pause` option. 112 + executed. We can do this by means of setting the `pause` option to `true`: 110 113 111 114 ```jsx 112 115 const Todos = ({ from, limit }) => { ··· 149 152 150 153 For this reason there's another field on results, `result.stale`, which indicates that the cached 151 154 result is either outdated or that another request is being sent in the background. 155 + 156 + Request policies aren't specific to `urql`'s React API, but are a common feature in its core. [You 157 + can learn more about request policies on the API docs.](../api/core.md#requestpolicy) 152 158 153 159 ### Reexecuting Queries 154 160
+4 -4
docs/concepts/README.md
··· 10 10 11 11 Each page goes a little further in explaning a core concept of `urql`. 12 12 13 - - **Philosophy** gives a quick overview of the different aspects of GraphQL clients and `urql` in 13 + - [**Philosophy**](./philosophy.md) gives a quick overview of the different aspects of GraphQL clients and `urql` in 14 14 particular, which shines a light on why you may want to use `urql`. 15 - - **Stream Pattern** explains the inner working of `urql`, which is _stream-based_, also known as 15 + - [**Stream Pattern**](./stream-patterns.md) explains the inner working of `urql`, which is _stream-based_, also known as 16 16 Observable patterns in JS. 17 - - **Core Package** defines why a shared package exists that contains the main logic of `urql`, and 17 + - [**Core Package**](./core-package.md) defines why a shared package exists that contains the main logic of `urql`, and 18 18 how we can use it directly in Node.js. 19 - - **Exchanges** finally introduces _Exchanges_ and how to write extensions or addons and use them 19 + - [**Exchanges**](./exchanges.md) finally introduces _Exchanges_ and how to write extensions or addons and use them 20 20 in `urql`. 21 21 22 22 Finally, some _Exchanges_ are covered in different sections of the documentation, like
+13
packages/site/src/assets/anchor.js
··· 1 + import React from 'react'; 2 + 3 + const SvgAnchor = props => ( 4 + <svg viewBox="0 0 16 16" {...props}> 5 + <path 6 + fill="currentColor" 7 + fillRule="evenodd" 8 + d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z" 9 + /> 10 + </svg> 11 + ); 12 + 13 + export default SvgAnchor;
+5
packages/site/src/assets/anchor.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg viewBox="0 0 16 16" version="1.1"> 3 + <path fill="currentColor" fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path> 4 + </svg> 5 +
+49 -1
packages/site/src/components/mdx.js
··· 7 7 import Highlight, { Prism } from 'prism-react-renderer'; 8 8 import nightOwlLight from 'prism-react-renderer/themes/nightOwlLight'; 9 9 10 + import AnchorSvg from '../assets/anchor'; 10 11 import { relative } from './sidebar'; 11 12 12 13 const getLanguage = className => { ··· 223 224 return <Link to={relative(from, to)}>{children}</Link>; 224 225 } 225 226 226 - return <a href={href}>{children}</a>; 227 + return ( 228 + <a rel="external" href={href}> 229 + {children} 230 + </a> 231 + ); 232 + }; 233 + 234 + const HeadingText = styled.h1` 235 + &:target:before { 236 + content: ''; 237 + display: block; 238 + height: 1.5em; 239 + margin: -1.5em 0 0; 240 + } 241 + `; 242 + 243 + const AnchorLink = styled.a` 244 + display: inline-block; 245 + color: ${p => p.theme.colors.accent}; 246 + padding-right: 0.5rem; 247 + width: 2rem; 248 + 249 + @media ${({ theme }) => theme.media.sm} { 250 + margin-left: -2rem; 251 + display: none; 252 + 253 + ${HeadingText}:hover > & { 254 + display: inline-block; 255 + } 256 + } 257 + `; 258 + 259 + const AnchorIcon = styled(AnchorSvg)` 260 + height: 100%; 261 + `; 262 + 263 + const Header = tag => ({ id, children }) => { 264 + return ( 265 + <HeadingText as={tag} id={id}> 266 + <AnchorLink href={`#${id}`}> 267 + <AnchorIcon /> 268 + </AnchorLink> 269 + {children} 270 + </HeadingText> 271 + ); 227 272 }; 228 273 229 274 const components = { ··· 236 281 th: TableHeader, 237 282 td: TableCell, 238 283 a: MdLink, 284 + h1: HeadingText, 285 + h2: Header('h2'), 286 + h3: Header('h3'), 239 287 }; 240 288 241 289 export const MDXComponents = ({ children }) => (
+7 -1
packages/site/src/components/navigation.js
··· 6 6 export const SidebarContainer = styled.div` 7 7 display: ${p => (p.hidden ? 'none' : 'block')}; 8 8 position: absolute; 9 + left: 0; 10 + right: 0; 11 + bottom: 0; 12 + min-height: 100%; 9 13 10 14 @media ${({ theme }) => theme.media.sm} { 11 15 display: block; ··· 73 77 } 74 78 `; 75 79 76 - export const ChevronItem = styled(ChevronIcon)` 80 + export const ChevronItem = styled(ChevronIcon).attrs(() => ({ 81 + 'aria-hidden': 'true', 82 + }))` 77 83 display: inline-block; 78 84 color: inherit; 79 85 vertical-align: baseline;
+2 -2
packages/site/src/components/sidebar.js
··· 59 59 return { pathname }; 60 60 }; 61 61 62 - export const SidebarStyling = ({ children, sidebarOpen }) => { 62 + export const SidebarStyling = ({ children, sidebarOpen, closeSidebar }) => { 63 63 const basepath = useBasepath() || ''; 64 64 const homepage = basepath ? `/${basepath}/` : '/'; 65 65 66 66 return ( 67 67 <> 68 68 <SideBarStripes /> 69 - <SidebarContainer hidden={!sidebarOpen}> 69 + <SidebarContainer hidden={!sidebarOpen} onClick={closeSidebar}> 70 70 <SidebarWrapper> 71 71 <HeroLogoLink to={homepage}> 72 72 <HeroLogo />
+1 -1
packages/site/src/screens/docs/article.js
··· 21 21 id: 'page-content', 22 22 }))` 23 23 flex: 1; 24 - min-height: 100vh; 24 + min-height: calc(100vh - ${p => p.theme.layout.header}); 25 25 background: ${p => p.theme.colors.bg}; 26 26 padding: ${p => p.theme.spacing.md}; 27 27
+4 -1
packages/site/src/screens/docs/header.js
··· 13 13 width: 100%; 14 14 z-index: 1; 15 15 16 + box-sizing: border-box; 17 + height: ${p => p.theme.layout.header}; 18 + 16 19 background: ${p => p.theme.colors.bg}; 17 20 border-bottom: 1px solid ${p => p.theme.colors.border}; 18 21 padding: 0 ${p => p.theme.spacing.md}; ··· 21 24 22 25 const Wrapper = styled.div` 23 26 width: 100%; 27 + height: 100%; 24 28 max-width: ${p => p.theme.layout.page}; 25 29 margin: 0 auto; 26 - height: ${p => p.theme.layout.header}; 27 30 padding-top: 2px; 28 31 display: flex; 29 32 flex-direction: row;
+10 -3
packages/site/src/screens/docs/index.js
··· 1 - import React, { useState } from 'react'; 1 + import React, { useState, useCallback } from 'react'; 2 2 import styled from 'styled-components'; 3 3 4 4 import Article, { ArticleStyling } from './article'; ··· 38 38 const Docs = ({ isLoading, children }) => { 39 39 const [sidebarOpen, setSidebarOpen] = useState(false); 40 40 41 + const closeSidebar = useCallback(() => { 42 + setSidebarOpen(false); 43 + }, [setSidebarOpen]); 44 + 41 45 return ( 42 46 <> 43 47 <Header /> ··· 49 53 {/* load just the styles if Suspense fallback in use */} 50 54 {isLoading ? ( 51 55 <> 52 - <SidebarStyling sidebarOpen={sidebarOpen} /> 56 + <SidebarStyling 57 + sidebarOpen={sidebarOpen} 58 + closeSidebar={closeSidebar} 59 + /> 53 60 <ArticleStyling>{children}</ArticleStyling> 54 61 </> 55 62 ) : ( 56 63 <> 57 - <Sidebar sidebarOpen={sidebarOpen} /> 64 + <Sidebar sidebarOpen={sidebarOpen} closeSidebar={closeSidebar} /> 58 65 <Article>{children}</Article> 59 66 </> 60 67 )}