Skip to content

Commit

Permalink
fix(deps) resolve yarn warnings regarding unmet peer dependencies for…
Browse files Browse the repository at this point in the history
… Redwood projects (#8874)

Running `yarn install` in a Redwood project results in a wall of
information, most of which are warnings about peer dependencies and
unmet dependency version requirements. We (framework authors) put up
with it but that's not the case for developers — best case they find the
output warnings annoying (and hopefully don't miss important errors);
worst case it turns people away from using Redwood.

Some, but not all, warnings are from Redwood packages. Many are
upstream. At this time, there is no known negative impact from these
dependency warnings — i.e. ideally they would all be resolved, but doing
so has diminishing returns and is an ongoing maintenance consideration.
This PR silences warnings that are considered acceptable and resolves
those that are not. (Note: contributions are welcome for anyone who'd
like to completely resolve these warnings!)

Lastly, warnings != errors. This PR does not touch errors (if/when
applicable).

Here's what `yarn install` will look like with changes from this PR

![yarn-install](https://github.com/redwoodjs/redwood/assets/2951/278d2f36-a5e8-430d-8179-f6a8899d3227)

Nice, right?!? 🤯

There are two cases of warnings handled by this PR.

Case 1) [YN0002 -
MISSING_PEER_DEPENDENCY](https://yarnpkg.com/advanced/error-codes#yn0002---missing_peer_dependency)
This PR silences these warnings using yarnrc `logFilters`.

Important: devs can still inspect these warnings via `yarn explain
peer-requirements` or by managing their projects' `logFilters` config.

Case 2) [YN0060 -
INCOMPATIBLE_PEER_DEPENDENCY](https://yarnpkg.com/advanced/error-codes#yn0060---incompatible_peer_dependency)
Because this can only be resolved via the parent package, this PR moves
the necessary package code into the respective Redwood Package, thus
properly fixing the incompatibility.

This PR breaks a CSS import in the a11y Template
`layout.tsx.a11yTemplate`, which is used when anyone generates a layout
component with the `--skipLink` command option: `yarn redwood generate
layout <name> --skipLink`

```diff
// web/src/layouts/MyLayout/MyLayout.{jsx|tsx}

import { SkipNavLink, SkipNavContent } from '@redwoodjs/router'
-import '@reach/skip-nav/styles.css'
+import '@redwoodjs/router/skip-nav.css'
```

- [x] Update redwoodjs/docs/a11y
- [ ] Codemode for layout component import change (might not be
necessary as find+replace would work just fine)

---------

Co-authored-by: Dominic Saadi <[email protected]>
  • Loading branch information
2 people authored and redwood-bot committed Feb 8, 2024
1 parent 5a52156 commit ed07722
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 34 deletions.
4 changes: 2 additions & 2 deletions docs/docs/a11y.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ yarn rw g layout main --skipLink

```jsx title="web/src/layouts/MainLayout/MainLayout.js"
import { SkipNavLink, SkipNavContent } from '@redwoodjs/router'
import '@reach/skip-nav/styles.css'
import '@redwoodjs/router/skip-nav.css'

const MainLayout = ({ children }) => {
return (
Expand All @@ -122,7 +122,7 @@ export default MainLayout
```

`SkipNavLink` renders a link that remains hidden till focused and `SkipNavContent` renders a div as the target for the link.
For more on these components, see [Reach UI's docs](https://reach.tech/skip-nav/#reach-skip-nav).
The code for these components comes from Reach UI. For more details, see [Reach UI's docs](https://reach.tech/skip-nav/#reach-skip-nav).

One thing you'll probably want to do is change the URL the skip link sends the user to when activated.
You can do that by changing the `contentId` and `id` props of `SkipNavLink` and `SkipNavContent` respectively:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`JavaScript: includes skip link when --skipLink is set to true 1`] = `
"import { SkipNavLink, SkipNavContent } from '@redwoodjs/router'
import '@reach/skip-nav/styles.css'
import '@redwoodjs/router/skip-nav.css'
/**
* since the main content isn't usually the first thing in the document,
Expand Down Expand Up @@ -109,7 +109,7 @@ describe('AppLayout', () => {

exports[`TypeScript: includes skip link when --skipLink is set to true 1`] = `
"import { SkipNavLink, SkipNavContent } from '@redwoodjs/router'
import '@reach/skip-nav/styles.css'
import '@redwoodjs/router/skip-nav.css'
/**
* since the main content isn't usually the first thing in the document,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SkipNavLink, SkipNavContent } from '@redwoodjs/router'
import '@reach/skip-nav/styles.css'
import '@redwoodjs/router/skip-nav.css'

/**
* since the main content isn't usually the first thing in the document,
Expand Down
3 changes: 1 addition & 2 deletions packages/forms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"dependencies": {
"@babel/runtime-corejs3": "7.23.9",
"core-js": "3.35.1",
"graphql": "16.8.1",
"pascalcase": "1.0.0",
"react-hook-form": "7.49.3"
},
Expand All @@ -38,15 +39,13 @@
"@types/pascalcase": "1.0.3",
"@types/react": "18.2.37",
"@types/react-dom": "18.2.15",
"graphql": "16.8.1",
"nodemon": "3.0.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.3.3",
"vitest": "1.2.2"
},
"peerDependencies": {
"graphql": "16.8.1",
"react": "18.2.0"
},
"gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1"
Expand Down
4 changes: 2 additions & 2 deletions packages/router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
"dist",
"skip-nav.css"
],
"scripts": {
"build": "yarn build:js && yarn build:types",
Expand All @@ -25,7 +26,6 @@
},
"dependencies": {
"@babel/runtime-corejs3": "7.23.9",
"@reach/skip-nav": "0.18.0",
"@redwoodjs/auth": "6.0.7",
"core-js": "3.35.1"
},
Expand Down
33 changes: 33 additions & 0 deletions packages/router/skip-nav.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Original code source https://github.com/reach/reach-ui
* https://github.com/reach/reach-ui/blob/dev/packages/skip-nav/styles.css
*/

:root {
--reach-skip-nav: 1;
}

[data-reach-skip-nav-link] {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
position: absolute;
}

[data-reach-skip-nav-link]:focus {
padding: 1rem;
position: fixed;
top: 10px;
left: 10px;
background: white;
z-index: 1;
width: auto;
height: auto;
clip: auto;
}


4 changes: 2 additions & 2 deletions packages/router/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export * from './useMatch'

export { parseSearch, getRouteRegexAndParams, matchPath } from './util'

export { SkipNavLink, SkipNavContent } from './skipNav'

/**
* A more specific interface is created in `.redwood/types/includes/web-routerRoutes`
* when the site is built, which will describe all known routes.
Expand All @@ -37,7 +39,5 @@ export { parseSearch, getRouteRegexAndParams, matchPath } from './util'
// Keep this in index.ts so it can be extended with declaration merging
export interface AvailableRoutes {}

export { SkipNavLink, SkipNavContent } from '@reach/skip-nav'

// Used by packages/internal/src/generate/templates/web-routerRoutes.d.ts.template
export * from './routeParamsTypes'
166 changes: 166 additions & 0 deletions packages/router/src/skipNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// Original Code Source https://github.com/reach/reach-ui
// Moving here to resolve unmet peer dependency issues related to React 18
// If resolved, should consider reverting to @reach/skip-nav
// See: https://github.com/reach/reach-ui/issues/916

import * as React from 'react'

////////////////////////////////////////////////////////////////////////////////

// Original Code Source @reach/polymorphic
// https://github.com/reach/reach-ui/blob/dev/packages/polymorphic/src/reach-polymorphic.ts

type Merge<P1 = {}, P2 = {}> = Omit<P1, keyof P2> & P2

type ForwardRefExoticComponent<E, OwnProps> = React.ForwardRefExoticComponent<
Merge<
E extends React.ElementType ? React.ComponentPropsWithRef<E> : never,
OwnProps & { as?: E }
>
>

interface ForwardRefComponent<
IntrinsicElementString,
OwnProps = {}
/*
* Extends original type to ensure built in React types play nice with
* polymorphic components still e.g. `React.ElementRef` etc.
*/
> extends ForwardRefExoticComponent<IntrinsicElementString, OwnProps> {
/*
* When `as` prop is passed, use this overload. Merges original own props
* (without DOM props) and the inferred props from `as` element with the own
* props taking precendence.
*
* We explicitly avoid `React.ElementType` and manually narrow the prop types
* so that events are typed when using JSX.IntrinsicElements.
*/
<As = IntrinsicElementString>(
props: As extends ''
? { as: keyof JSX.IntrinsicElements }
: As extends React.ComponentType<infer P>
? Merge<P, OwnProps & { as: As }>
: As extends keyof JSX.IntrinsicElements
? Merge<JSX.IntrinsicElements[As], OwnProps & { as: As }>
: never
): React.ReactElement | null
}

////////////////////////////////////////////////////////////////////////////////

// Original Code Source @reach/skip-nav
// https://github.com/reach/reach-ui/blob/dev/packages/skip-nav/src/reach-skip-nav.tsx

// The user may want to provide their own ID (maybe there are multiple nav
// menus on a page a use might want to skip at various points in tabbing?).
const defaultId = 'reach-skip-nav'

/**
* SkipNavLink
*
* Renders a link that remains hidden until focused to skip to the main content.
*
* @see Docs https://reach.tech/skip-nav#skipnavlink
*/
const SkipNavLink = React.forwardRef(function SkipNavLink(
{ as: Comp = 'a', children = 'Skip to content', contentId, ...props },
forwardedRef
) {
const id = contentId || defaultId
return (
<Comp
{...props}
ref={forwardedRef}
href={`#${id}`}
// TODO: Remove in 1.0 (kept for back compat)
data-reach-skip-link=""
data-reach-skip-nav-link=""
>
{children}
</Comp>
)
}) as ForwardRefComponent<'a', SkipNavLinkProps>

/**
* @see Docs https://reach.tech/skip-nav#skipnavlink-props
*/
interface SkipNavLinkProps {
/**
* Allows you to change the text for your preferred phrase or localization.
*
* @see Docs https://reach.tech/skip-nav#skipnavlink-children
*/
children?: React.ReactNode
/**
* An alternative ID for `SkipNavContent`. If used, the same value must be
* provided to the `id` prop in `SkipNavContent`.
*
* @see Docs https://reach.tech/skip-nav#skipnavlink-contentid
*/
contentId?: string
}

SkipNavLink.displayName = 'SkipNavLink'

////////////////////////////////////////////////////////////////////////////////

/**
* SkipNavContent
*
* Renders a div as the target for the link.
*
* @see Docs https://reach.tech/skip-nav#skipnavcontent
*/
const SkipNavContent = React.forwardRef(function SkipNavContent(
{ as: Comp = 'div', id: idProp, ...props },
forwardedRef
) {
const id = idProp || defaultId
return (
<Comp
{...props}
ref={forwardedRef}
id={id}
data-reach-skip-nav-content=""
/>
)
}) as ForwardRefComponent<'div', SkipNavContentProps>

/**
* @see Docs https://reach.tech/skip-nav#skipnavcontent-props
*/
interface SkipNavContentProps {
/**
* You can place the `SkipNavContent` element as a sibling to your main
* content or as a wrapper.
*
* Keep in mind it renders a `div`, so it may mess with your CSS depending on
* where it’s placed.
*
* @example
* <SkipNavContent />
* <YourMainContent />
* // vs.
* <SkipNavContent>
* <YourMainContent/>
* </SkipNavContent>
*
* @see Docs https://reach.tech/skip-nav#skipnavcontent-children
*/
children?: React.ReactNode
/**
* An alternative ID. If used, the same value must be provided to the
* `contentId` prop in `SkipNavLink`.
*
* @see Docs https://reach.tech/skip-nav#skipnavcontent-id
*/
id?: string
}

SkipNavContent.displayName = 'SkipNavContent'

////////////////////////////////////////////////////////////////////////////////
// Exports

export type { SkipNavContentProps, SkipNavLinkProps }
export { SkipNavLink, SkipNavContent }
23 changes: 0 additions & 23 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7292,27 +7292,6 @@ __metadata:
languageName: node
linkType: hard

"@reach/polymorphic@npm:0.18.0":
version: 0.18.0
resolution: "@reach/polymorphic@npm:0.18.0"
peerDependencies:
react: ^16.8.0 || 17.x
checksum: dfde6dc901005f92e16f0e3601f0c659b70ee14d91e612cd68c9a918744fd94de30e8065d73663b72964225d3476f377c650daf2ac1e256de61df9ee386aabdc
languageName: node
linkType: hard

"@reach/skip-nav@npm:0.18.0":
version: 0.18.0
resolution: "@reach/skip-nav@npm:0.18.0"
dependencies:
"@reach/polymorphic": "npm:0.18.0"
peerDependencies:
react: ^16.8.0 || 17.x
react-dom: ^16.8.0 || 17.x
checksum: 30e3d4c568093e170b9e80ee42764a080c0a15ab3f9c7edf78dcc6ebd92f156799dba0f544757b84401806765f60fe527c869ef86d5323c0a7a3bdccf1a68f85
languageName: node
linkType: hard

"@react-email/render@npm:0.0.10":
version: 0.0.10
resolution: "@react-email/render@npm:0.0.10"
Expand Down Expand Up @@ -8304,7 +8283,6 @@ __metadata:
typescript: "npm:5.3.3"
vitest: "npm:1.2.2"
peerDependencies:
graphql: 16.8.1
react: 18.2.0
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -8604,7 +8582,6 @@ __metadata:
"@babel/cli": "npm:7.23.9"
"@babel/core": "npm:^7.22.20"
"@babel/runtime-corejs3": "npm:7.23.9"
"@reach/skip-nav": "npm:0.18.0"
"@redwoodjs/auth": "npm:6.0.7"
"@types/react": "npm:18.2.37"
"@types/react-dom": "npm:18.2.15"
Expand Down

0 comments on commit ed07722

Please sign in to comment.