Skip to content

Commit

Permalink
Improve atom HTML element A to handle innerRef forwarding
Browse files Browse the repository at this point in the history
The currently used version of "Gatsby Link" (1) uses the `innerRef` prop
to allow `ref` access to the underlying DOM element (necessary for
animations). In order to wrap animated components the `ref` is
necessary and is therefore now forwarded.

The legacy behavior of "Gatsby Link" is about to change in the future to
the `React.forwardRef` API.
See gatsbyjs/gatsby#9892 for more details.

References:
  (1) https://www.gatsbyjs.org/docs/gatsby-link

Associated epic: GH-69
GH-64
  • Loading branch information
arcticicestudio committed Dec 13, 2018
1 parent 71a309c commit eeaa8f4
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 11 deletions.
39 changes: 32 additions & 7 deletions src/components/atoms/core/HTMLElements/inlineTextSemantics/A.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
import React from "react";
import PropTypes from "prop-types";
import { Link } from "gatsby";
import styled from "styled-components";
import styled, { css } from "styled-components";

import { isRouteInternal } from "utils";

const BaseComponent = styled.a`
const baseStyles = css`
color: inherit;
cursor: pointer;
text-decoration: none;
Expand All @@ -33,28 +33,49 @@ const BaseComponent = styled.a`
}
`;

const BaseComponent = styled.a`
${baseStyles};
`;

const BaseGatsbyLink = styled(Link)`
${baseStyles}
`;

/**
* A dynamic and failsafe component which either renders to a base HTML link `<a>` (anchor) or a "Gatsby Link" based on
* the target/URL type, internal or external, passed to the `to` and `href` props.
*
* Note: The currently used version of "Gatsby Link" uses the `innerRef` prop to allow `ref` access to the underlying
* DOM element (necessary for animations). This legacy behavior is about to change in the future to the
* `React.forwardRef` API.
* See https://github.com/gatsbyjs/gatsby/pull/9892 for more details.
*
* @example <caption>Usage</caption>
* <!-- The target is external so both will render to `<a>` with the `href` prop. -->
* <A href="https://arcticicestudio.github.io/nord">Nord</A>
* <A to="https://arcticicestudio.github.io/nord">Nord</A>
* <!-- The target is internal so both will render to `<Link>` with the `to` prop. -->
* <A to="/blog">Blog</A>
* <A href="/blog">Blog</A>
* <!-- Allow ref access to the underlying "Gatsby Link" DOM element. -->
* const RefLink = React.forwardRef(({children, ...passProps}, ref) => (
* <A innerRef={ref} {...passProps}>
* {children}
* </A>
* );
* <RefLink to="/blog">Blog</RefLink>
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a
* @see https://www.gatsbyjs.org/docs/gatsby-link
* @see https://github.com/gatsbyjs/gatsby/pull/9892
* @since 0.3.0
*/
const A = ({ children, href, to, ...passProps }) =>
const A = ({ children, href, to, linkRef, ...passProps }) =>
isRouteInternal(to) || isRouteInternal(href) ? (
<BaseComponent as={Link} to={to || href} {...passProps}>
<BaseGatsbyLink innerRef={linkRef} to={to || href} {...passProps}>
{children}
</BaseComponent>
</BaseGatsbyLink>
) : (
<BaseComponent href={href || to} {...passProps}>
<BaseComponent ref={linkRef} href={href || to} {...passProps}>
{children}
</BaseComponent>
);
Expand All @@ -66,4 +87,8 @@ A.propTypes = {

A.defaultProps = { to: "" };

export default A;
export default React.forwardRef(({ children, ...passProps }, ref) => (
<A linkRef={ref} {...passProps}>
{children}
</A>
));
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`snapshot renders external URLs with \`href\` prop 1`] = `
<div>
<a
class="sc-bdVaJa ccNLbx"
class="sc-bdVaJa jEake"
href="https://nordtheme.com"
>
Docs
Expand All @@ -14,7 +14,7 @@ exports[`snapshot renders external URLs with \`href\` prop 1`] = `
exports[`snapshot renders external URLs with \`to\` prop 1`] = `
<div>
<a
class="sc-bdVaJa ccNLbx"
class="sc-bdVaJa jEake"
href="https://nordtheme.com"
>
Docs
Expand All @@ -25,7 +25,7 @@ exports[`snapshot renders external URLs with \`to\` prop 1`] = `
exports[`snapshot renders inernal URLs with \`href\` prop 1`] = `
<div>
<a
class="sc-bdVaJa ccNLbx"
class="sc-bwzfXH lhDJTy"
href="/docs"
>
Docs
Expand All @@ -36,7 +36,7 @@ exports[`snapshot renders inernal URLs with \`href\` prop 1`] = `
exports[`snapshot renders inernal URLs with \`to\` prop 1`] = `
<div>
<a
class="sc-bdVaJa ccNLbx"
class="sc-bwzfXH lhDJTy"
href="/docs"
>
Docs
Expand Down

0 comments on commit eeaa8f4

Please sign in to comment.