@newrelic/gatsby-theme-newrelic
Version:
[](https://opensource.newrelic.com/oss-category/#community-project)
1,293 lines (1,002 loc) • 118 kB
Markdown
[](https://opensource.newrelic.com/oss-category/#community-project)
# `gatsby-theme-newrelic`
This theme contains contains common configuration and shared components used
across New Relic Gatsby sites. It is primarily used on the
[developer](https://developer.newrelic.com) and [open source
websites](https://opensource.newrelic.com).
<!-- TOC GFM -->
- [`gatsby-theme-newrelic`](#gatsby-theme-newrelic)
- [Installation](#installation)
- [Configuration](#configuration)
- [Site metadata](#site-metadata)
- [Options](#options)
- [`sitemap`](#sitemap)
- [`newrelic`](#newrelic)
- [`robots`](#robots)
- [`relatedResources`](#relatedresources)
- [`resolveEnv`](#resolveenv)
- [`i18n`](#i18n)
- [`layout`](#layout)
- [`prism`](#prism)
- [`splitio`](#splitio)
- [`signup`](#signup)
- [Environment-specific configuration](#environment-specific-configuration)
- [`newRelicRequestingServicesHeader`](#newRelicRequestingServicesHeader)
- [Layouts](#layouts)
- [Components](#components)
- [`Banner`](#banner)
- [`Button`](#button)
- [`Callout`](#callout)
- [`CodeBlock`](#codeblock)
- [`Collapser`](#collapser)
- [`CollapserGroup`](#collapsergroup)
- [`ContributingGuidelines`](#contributingguidelines)
- [`CreateIssueButton`](#createissuebutton)
- [`DarkModeToggle`](#darkmodetoggle)
- [`Dropdown`](#dropdown)
- [`Dropdown.Toggle`](#dropdowntoggle)
- [`Dropdown.Menu`](#dropdownmenu)
- [`Dropdown.MenuItem`](#dropdownmenuitem)
- [`ExternalLink`](#externallink)
- [`EditPageButton`](#editpagebutton)
- [`FeatherSVG`](#feathersvg)
- [`GitHubIssueButton`](#githubissuebutton)
- [Environment information](#environment-information)
- [`GlobalFooter`](#globalfooter)
- [`GlobalHeader`](#globalheader)
- [`HamburgerMenu`](#hamburgermenu)
- [`Icon`](#icon)
- [Available icons](#available-icons)
- [Shadowing icons](#shadowing-icons)
- [`Layout`](#layout-1)
- [`Layout.Content`](#layoutcontent)
- [`Layout.Footer`](#layoutfooter)
- [`Layout.Main`](#layoutmain)
- [`Layout.PageTools`](#layoutpagetools)
- [`Layout.Sidebar`](#layoutsidebar)
- [`Link`](#link)
- [`MarkdownContainer`](#markdowncontainer)
- [`MDX`](#mdx)
- [Using `MDX`](#using-mdx)
- [Default components](#default-components)
- [`MDXCodeBlock`](#mdxcodeblock)
- [`Navigation`](#navigation)
- [`NavItem`](#navitem)
- [`Page`](#page)
- [`NewRelicLogo`](#newreliclogo)
- [Overlay](#overlay)
- [`PageTools`](#pagetools)
- [`PageTools.Section`](#pagetoolssection)
- [`PageTools.Title`](#pagetoolstitle)
- [Portal](#portal)
- [`RelatedResources`](#relatedresources-1)
- [`SearchInput`](#searchinput)
- [`SkewedContainer`](#skewedcontainer)
- [`SEO`](#seo)
- [`Side`](#side)
- [`SideBySide`](#sidebyside)
- [`SimpleFeedback`](#simplefeedback)
- [`Spinner`](#spinner)
- [`Skeleton`](#skeleton)
- [`SplitColorButton`](#splitcolorbutton)
- [`Steps`](#steps)
- [`Step`](#step)
- [`Surface`](#surface)
- [`Table`](#table)
- [`TableOfContents`](#tableofcontents)
- [`Tag`](#tag)
- [`TagList`](#taglist)
- [`Terminal`](#terminal)
- [`TextHighlight`](#texthighlight)
- [`Video`](#video)
- [MDX Component variants](#mdx-component-variants)
- [Hooks](#hooks)
- [`useActiveHash`](#useactivehash)
- [`useClipboard`](#useclipboard)
- [`useFormattedCode`](#useformattedcode)
- [`useHasMounted`](#usehasmounted)
- [`useInstrumentedHandler`](#useinstrumentedhandler)
- [`useKeyPress`](#usekeypress)
- [`useLayout`](#uselayout)
- [`useLocale`](#uselocale)
- [`useNavigation`](#usenavigation)
- [`useQueryParams`](#usequeryparams)
- [`useScrollFreeze`](#usescrollfreeze)
- [`useSyncedRef`](#usesyncedref)
- [`useThemeTranslation`](#usethemetranslation)
- [`useTimeout`](#usetimeout)
- [`useUserId`](#useuserid)
- [`usePrevious`](#useprevious)
- [`useWarning`](#usewarning)
- [I18n](#i18n-1)
- [Announcements](#announcements)
- [Utils](#utils)
- [`formatCode`](#formatcode)
- [`addPageAction`](#addPageAction)
- [Testing](#testing)
- [Mocking `ReactDOM.createPortal` for snapshot testing](#mocking-reactdomcreateportal-for-snapshot-testing)
<!-- /TOC -->
## Installation
`gatsby-theme-newrelic` uses [Emotion](https://emotion.sh) for styling and
depends on its packages. To install this package, add the
`@newrelic/gatsby-theme-newrelic` package and required Emotion packages.
npm:
```sh
npm install @newrelic/gatsby-theme-newrelic @emotion/core @emotion/styled @mdx-js/mdx @mdx-js/react @splitsoftware/splitio-react gatsby-plugin-mdx
```
yarn:
```sh
yarn add @newrelic/gatsby-theme-newrelic @emotion/core @emotion/styled @mdx-js/mdx @mdx-js/react @splitsoftware/splitio-react gatsby-plugin-mdx
```
## Configuration
You can configure `gatsby-theme-newrelic` using the following configuration
options:
```js
// gatsby-config.js
module.exports = {
siteMetadata: {
siteUrl: 'https://developer.newrelic.com',
repository: 'https://github.com/newrelic/gatsby-theme-newrelic',
branch: 'main',
utmSource: 'developer-site',
},
plugins: [
{
resolve: '@newrelic/gatsby-theme-newrelic',
options: {
sitemap: true,
layout: {
contentPadding: '2rem',
maxWidth: '1600px',
},
newrelic: {
configs: {
staging: {
instrumentationType: 'proAndSPA',
accountId: '1234',
trustKey: '1',
agentID: '1234',
licenseKey: 'your-license-key',
applicationID: '1234',
},
production: {
instrumentationType: 'proAndSPA',
accountId: '1234',
trustKey: '1',
agentID: '1234',
licenseKey: 'your-license-key',
applicationID: '12345',
},
},
},
i18n: {
translationsPath: `${__dirname}/src/i18n/translations`,
additionalLocales: ['jp'],
}
robots: {
policy: [{ userAgent: '*', allow: '/' }],
},
splitio: {
core: {
authorizationKey: 'my-auth-key',
},
},
relatedResources: {
labels: {
'https://my.website': 'my-website'
},
}
},
},
],
};
```
### Site metadata
`gatsby-theme-newrelic` makes use of several `siteMetadata` options. While these
are optional, they are highly recommended.
- `siteUrl`: Production URL for the site (e.g. `https://developer.newrelic.com`)
- `repository`: The URL for the public GitHub repository hosting the source code
for the site.
- `branch`: The mainline branch for use when constructing "Edit this page" links (defaults to `main`).
to various mediums within New Relic.
- `contributingUrl`: The URL where a user can find contributing guidelines for
the site. If this is not specified, it defaults to the `CONTRIBUTING.md` file
in the repo and branch specified in the `siteMetadata`. If the `repository` is
not specified, this will return `null`. Set this value to `null` to disable
the default behavior.
### Options
#### `sitemap`
Toggles the automatic creation of a sitemap. Set this value to
`false` to disable sitemaps.
**Default:** `true`
#### `newrelic`
Configuration for
[`gatsby-plugin-newrelic`](https://github.com/newrelic/gatsby-plugin-newrelic).
For more details on the available configuration options, visit [the
documentation](https://github.com/newrelic/gatsby-plugin-newrelic).
**Default:** `null`
#### `robots`
Configuration for
[`gatsby-plugin-robots-txt`](https://www.gatsbyjs.org/packages/gatsby-plugin-robots-txt/).
These options will be shallow merged with the default value. For more details on
the available configuration options, visit [the
documentation.](https://www.gatsbyjs.org/packages/gatsby-plugin-robots-txt/)
**Default**: `{ policy: [{ userAgent: '*', allow: '/' }] }`
#### `relatedResources`
Optional configuration for related resources used in the right rail. Currently
only `Mdx` nodes are supported.
The related resources component is controlled by specific front matter slugs
that are defined on a page by setting the front matter for `resources`. If no
resources are available in the page front matter, the component will backfill
use the related resource items using Swiftype. See the `swiftype` options below
for more information on customizing the search behavior.
In short, the order of priority for populating content is driven by:
1. Resources defined via the `resources` front matter item.
2. Resources defined from executing a Swiftype search for the page.
**Options:**
- `labels` _(object)_: Map of URLs to their label. This is used to match
results displayed in the right rail with the label in the tag displayed
underneath the link. Use this to add additional labels not covered by the
default set of labels.
- `swiftype` _(object | false)_: Configuration used for fetching results from
Swiftype for an `Mdx` node. Set this to `false` (the default) to disable
fetching related resources through Swiftype. If this is disabled, related
resources can only be sourced via front matter. If enabled, this takes the
following configuration:
- `resultsPath` _(string)_ **required**: Path to the file where Swiftype
results will be stored. If the `refetch` option is set to `false` (the
default), this file will be used to read related resource values for each
`Mdx` node. This file is only written to when `refetch` is set to `true`.
- `refetch` _(boolean)_: Determines whether to refetch results from Swiftype
for every `Mdx` node during a build. It's a good idea to only set this on a
special build (e.g. a build that happens on a cron job) so that Swiftype is
not searched on development or every build on the site.
- **Default**: `false`
- `engineKey` _(string)_ **required**: Swiftype's engine key used to fetch
results from a Swiftype search engine.
- `getSlug` _(function)_: Function to get the slug for an `Mdx` node.
Useful if the slug is set from something other than the filesystem. By
default, this will use the `createFilePath` helper to generate the slug for
the `Mdx` node. This function should accept an object as its only argument
with a key of `node` (i.e. `getSlug: ({ node }) => { /* do something */ }`)
- `filter` _(function)_: Function to determine whether Swfitype should be
queried for the `Mdx` node. Useful if you only need to get related resources
for a subset of nodes on the site. By default, all `Mdx` nodes are fetched.
This function should accept an object as its only argument with a key of
`node` and a key of `slug` (i.e. `filter: ({ node, slug }) => { /* do something */ }`).
- `getParams` _(function)_: Function that allows you to specify additional
params passed to Swiftype when running a search query. Useful if you want to
provide additional filters or field boosts. This function should accept an
object as its only argument with a key of `node` and a key of `slug`.
- `limit` _(integer)_: The limit of related resources that should be fetched
from Swiftype.
- **Default**: `5`
#### `resolveEnv`
Optional function to determine the environment. Useful to provide a fine-tuned
environment name for environment-specific configuration.
**Default**:
```js
const defaultResolveEnv = () =>
process.env.GATSBY_NEWRELIC_ENV ||
process.env.GATSBY_ACTIVE_ENV ||
process.env.NODE_ENV ||
'development';
```
#### `i18n`
Optional configuration for internationalization (i18n).
- `additionalLocales`: Additional supported for languages other than English
(the default language). Currently supports `jp`.
- `translationsPath`: The directory path where the translations will be stored.
- `i18nextOptions`: Additional options to pass into
[`i18next`](https://www.i18next.com/) that will override the defaults.
These values are used to generate locale-specific pages and to populate a dropdown in the `<GlobalHeader />` component.
**Example**
```js
{
i18n: {
additionalLocales: ['jp'];
}
}
```
#### `layout`
Configuration for the layout.
**Options:**
- `maxWidth` _(string)_: Sets the max width of the layout. Accepts any CSS
sizing value (e.g. `1280px`).
- `contentPadding` _(string)_: Sets the padding value for the content. Accepts
any CSS sizing value (e.g. `2rem`)
**Default**: `{ maxWidth: null, contentPadding: null }`
Layout configuration is available in the GraphQL schema which can be queried
within the `Site` type. This is useful when you have other layout elements that
need to use the layout configuration.
```graphql
query {
site {
layout {
maxWidth
contentPadding
}
}
}
```
These values are also available as global CSS variables. You can access them as:
- `maxWidth`: `var(--site-max-width)`
- `contentPadding`: `var(--site-content-padding)`
#### `prism`
Configuration for the [prismjs](https://prismjs.com/) library. This library
powers the syntax highlighting used in the [`CodeBlock`](#codeblock) component.
**Options:**
- `languages` _([string])_: Configure additional languages used for syntax highlighting.
These languages will be appended to the list of default supported languages in
the theme. For a full list of supported languages, visit the [prism
documentation](https://prismjs.com/#supported-languages).
Default supported languages:
- `css`
- `graphql`
- `hcl`
- `javascript`
- `json`
- `jsx`
- `ruby`
- `shell`
- `sql`
- `sass`
- `scss`
**Example:** Add `swift` as a supported language
```js
module.exports = {
plugins: [
{
resolve: '@newrelic/gatsby-theme-newrelic',
options: {
prism: {
languages: ['swift'],
},
},
},
],
};
```
#### `splitio`
Configuration for using [split.io](https://split.io) with the Gatsby site. For
more information on all the available configuration options, visit the [split.io
SDK docs](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#configuration).
**Default:**
```js
const DEFAULT_CONFIG = {
core: {
trafficType: 'user',
},
};
```
**NOTE:** The `core.key` configuration option is generated by the theme and
#### `signup`
Required configuration for using the `<SignUpModal />` in the `<GlobalHeader />` component. If the `GlobalHeader` is not being used, this configuration is not required.
```javascript
module.exports = {
plugins: [
{
resolve: '@newrelic/gatsby-theme-newrelic',
options: {
signup: {
environment: process.env.ENVIRONMENT || 'staging',
signupUrl: '<signup receiver url>',
reCaptchaToken: '<token value>',
},
},
},
],
};
```
##### Environment-specific configuration
Use the `env` option to define environment-specific configuration. The
environment configuration will be merged with the top-level configuration.
```js
module.exports = {
plugins: [
{
resolve: '@newrelic/gatsby-theme-newrelic',
options: {
splitio: {
core: {
trafficType: 'user',
},
env: {
development: {
core: {
authorizationKey: 'my-development-key',
},
},
production: {
core: {
authorizationKey: 'my-prod-key',
},
},
},
},
},
},
],
};
```
The `env` key will be taken from `process.env.GATSBY_ACTIVE_ENV` first (see
[Gatsby environment
variables](https://www.gatsbyjs.com/docs/environment-variables/) for more
information on this variable), falling back to `process.env.NODE_ENV`. When this
is not available, then it defaults to `development`.
You can resolve the `env` by using the `resolveEnv` function:
```js
module.exports = {
plugins: [
{
resolve: '@newrelic/gatsby-theme-newrelic',
options: {
splitio: {
// ...
resolveEnv: () => process.env.BUILD_ENV,
},
},
},
],
};
```
#### `newRelicRequestingServicesHeader`
Configure the name reported to NerdGraph in the `NewRelic-Requesting-Services` header.
The value should be formatted like a slug, dash-separated and all lowercase, like `'io-website'`.
This header is only used in the call to check the current user's logged in status.
Currently, the `useLoggedIn` hook is the only place this is used.
If this isn't configured, nrBrowserAgent won't include the `loggedIn` field on any events, and `useLoggedIn().loggedIn` will always be `null`.
### Layouts
This theme supports Layout components in a similar way to Gatsby `V1` through the [`gatsby-plugin-layout`](https://www.gatsbyjs.com/plugins/gatsby-plugin-layout/). This plugin allows you to persist the layout between page changes, as well as state.
To start using this layout functionality create a component at `src/layouts/index.jsx`, then the plugin will automatically inject the component into your pages.
## Components
### `Banner`
Used to add a marketing banner to a page.
```js
import { Banner } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ---------- | -------- | -------- | ------- | ---------------------------------------------------------- |
| `children` | node | yes | | Content to be displayed in the banner. |
| `onClose` | function | yes | | Handler called when the user clicks on the "close" button. |
| `visible` | boolean | yes | | Determines if the banner is visible to the user or not |
**Example**
```jsx
<Banner visible={visible} onClose={() => setVisible(false)}>
<h1>Hello, World!</h1>
</Banner>
```
### `Button`
Styled buttons used to draw emphasis on clickable actions.
```js
import { Button } from '@newrelic/gatsby-theme-newrelic'`
```
**Props**
| Prop | Type | Required | Default | Description |
| ------- | ------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| variant | enum | yes | | Configures the variant of the button. Must be one of `Button.VARIANT.LINK`, `Button.VARIANT.PRIMARY`, `Button.OUTLINE`, or `Button.VARIANT.NORMAL` |
| size | enum | no | | Configures the size of the button. Can be configured to `Button.SIZE.SMALL` |
| as | React element | no | `button` | Render the button as a different base element. Useful when you want to style links as buttons. |
Additional props are forwarded to the underlying element specified by the `as`
prop.
**Examples**
```js
<Button variant={Button.VARIANT.PRIMARY} onClick={() => console.log('Hello')}>
Say hello
</Button>
```
Render a link as a button
```js
import { Link } from '@newrelic/gatsby-theme-newrelic';
// ...
<Button as={Link} to="/page-2" variant={Button.VARIANT.PRIMARY}>
Page 2
</Button>;
```
### `Callout`
Callouts direct your attention to information of special importance or to information that doesn't fit smoothly into the main text.
- Caution: Screams at you that this could cause a crash or cost you data loss beyond the task at hand.
- Important: Urges awareness that this could impair the task at hand or cost you time if you ignore the text.
- Tip: Whispers to you that this is nice to know, like a shortcut, best practice, or reminder.
```js
import { Callout } from '@newrelic/gatsby-theme-newrelic'`
```
**Props**
| Prop | Type | Required | Default | Description |
| ----------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `className` | string | no | | Adds a `className` to the callout. Useful if you need to position the callout within its parent element. |
| `variant` | enum | yes | | Configures the variant of the callout. Must be one of `Callout.VARIANT.CAUTION`, `Callout.VARIANT.IMPORTANT`, `Callout.VARIANT.TIP`, `Callout.VARIANT.COURSE` |
| `title` | enum | no | | Set the title text. Defaults to variant name. You may hide the title by passing `null` as the value. |
**Examples**
```js
<Callout variant={Callout.VARIANT.CAUTION}>Be careful!</Callout>
```
Hide the title
```js
<Callout variant={Callout.VARIANT.CAUTION} title={null}>
Be careful!
</Callout>
```
### `CodeBlock`
Used when rendering code blocks on a page.
```js
import { CodeBlock } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ------------------ | ------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `autoFormat` | boolean | no | `true`\* | Determines whether to auto format the code using prettier. `true` will force code formatting to occur. `false` will force disable code formatting. If left empty, code formatting will only run on a subset of supported languages (see below) |
| `children` | string | yes | | The code to be rendered in the code block |
| `className` | string | no | | Adds a `className` to the outer container of the code block. Useful if you need to position the code block within its parent element. |
| `components` | object | no | | Swap out the elements used when rendering various elements of the code block. See the "Configurable components" guide below to learn more about this prop. |
| `copyable` | boolean | no | `true` | Determines whether to render a copy button for the content inside the code block. |
| `fileName` | string | no | | The file name associated with the code rendered by the code block. Useful if the code block is used as part of tutorial. |
| `formatOptions` | object | no | | Configuration options given to the [`formatCode`](#formatcode) utility function to auto-format the code block. |
| `highlightedLines` | string | no | | Specifies which lines in the code block should be highlighted. See the examples below on for information on how to format this string. |
| `language` | string | no | | Configures the language used for syntax highlighting. Must match one of the languages or its aliases from [`prismjs`](https://prismjs.com/#supported-languages). To learn more about configuring supported languages, visit the [`prism` configuration section](#prism). |
| `lineNumbers` | boolean | no | `false` | Determines whether to show line numbers inside the code block. |
| `live` | boolean | no | `false` | Determines whether the code block is live-editable or not. Useful when used in conjunction with the `preview` option, though not required. |
| `preview` | boolean | no | `false` | Determines whether a live preview is displayed using the value in the code block. Useful in conjunction with the `live` option to allow the user to edit the code snippet. |
| `scope` | object | no | | Configures the variables available as globals for the live preview. By default, only `React` is injected. To find out more about how the `scope` prop works, visit the [`react-live` documentation](https://github.com/FormidableLabs/react-live#how-does-the-scope-work). |
**Auto code formatting**
Out of the box, the `CodeBlock` component will use prettier to format code for a
subset of languages. These include:
- `jsx`/`javascript`
- `html`
- `graphql`
- `json`
- `css`/`sass`/`scss`
To force formatting for another language, set the `autoFormat` prop value to
`true`. To force disable code formatting, set the `autoFormat` prop value to
`false`.
**NOTE:** If you choose to force enable code formatting for a language not
listed above, you may need to use the `formatOptions` prop to set the proper
[`plugins`](https://prettier.io/docs/en/browser.html#plugins).
**Configurable components**
The `CodeBlock` is a component made up of several underlying components.
There are cases where the default components may not be suitable for the needs
of the site. The `components` prop allows you to specify your own custom
components in place of the defaults to tailor component rendering for that
component.
Each custom component is given all the props that would otherwise be passed to
the default component. It is **highly recommended** to use the props given to
the custom component.
The following components can be customized:
**`Preview`**
By default, the built-in `Preview` component uses the `LivePreview` component
from [`react-live`](https://github.com/FormidableLabs/react-live). Overriding
this component may be useful if you need to, for example, render the preview
inside of a shadow DOM root element which allows style isolation without
polluting the global CSS namespace.
It is **highly recommended** that you render the `LivePreview` component within
your custom component. It will be very difficult to see the live preview
otherwise.
| Prop | Type | Description |
| ----------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `className` | `string` | Includes the default styles for the preview pane. Forward this prop to the root of your custom component to maintain a consistent style. |
**Examples**
```jsx
const codeExample = `
import React from 'react'
const Button = (props) => (
<button className='button' {...props} />
)
`;
const Documentation = () => (
<CodeBlock language="jsx" fileName="src/components/Button.js">
{codeExample}
</CodeBlock>
);
```
Line highlighting
```js
const codeExample = `
import React from 'react'
import PropTypes from 'prop-types'
const Button = (props) => (
<button className='button' {...props}>
{props.children}
</button>
)
Button.propTypes = {
children: PropTypes.element
}
export default Button
`;
const Documentation = () => (
/*
* Highlight multiple lines by comma-separating the line numbers.
* Include a range of lines by using a `-` between the line numbers.
*/
<CodeBlock language="jsx" highlightedLines="1,6,10-12">
{codeExample}
</CodeBlock>
);
```
Custom Preview component
```jsx
import { LivePreview } from 'react-live';
import root from 'react-shadow';
const styles = `
.button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
font-size: 0.875rem;
background: none;
cursor: pointer;
}
`;
// This component will be used in place of the default `Preview` component in
// the `CodeBlock`. Here we are using the shadow DOM to provide style isolation
// for the `button` class defined by the CSS in the `styles` variable above.
const CustomPreview = ({ className }) => (
<root.div>
<style type="text/css">{styles}</style>
<LivePreview className={className} />
</root.div>
);
// The button implementation we will be using when rendering the live preview,
// provided via the `scope` prop.
const Button = ({ children, ...props }) => (
<button className="button">{children}</button>
);
const codeSample = `
<Button>Click me</Button>
`;
const Documentation = () => (
<CodeBlock
preview={true}
components={{ Preview: CustomPreview }}
scope={{ Button }}
>
{codeSample}
</CodeBlock>
);
```
### `Collapser`
This element is used to reveal or hide content associated with it. Use in
conjunction with a [`CollapserGroup`](#collapsergroup) when using multiple
`Collapser`s in tandom.
```js
import { Collapser } from '@newrelic/gatsby-theme-newrelic'`
```
**Props**
| Prop | Type | Required | Default | Description |
| ------------- | ----------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `children` | node | yes | | The content that will be hidden or revealed when the user interacts with the `Collapser`. |
| `defaultOpen` | boolean | yes | false | Determines if the `Collapser` should default to its open state. |
| `id` | string | no | | An HTML `id` attribute that will be attached to the `Collapser` `title`. Useful if you want to deep link to the `Collapser`. |
| `title` | string \| React element | yes | | The text that will be rendered on the interactive button used to toggle the open state on the `Collapser`. |
**Examples**
```js
import { Collapser } from '@newrelic/gatsby-theme-newrelic';
<Collapser title="The Ruby Agent API">
This is some information about the Ruby Agent. You'll have to interact with
the Collapser to see me.
</Collapser>;
```
**Multiple collapsers**
```js
import { Collapser, CollapserGroup } from '@newrelic/gatsby-theme-newrelic';
<CollapserGroup>
<Collapser title="Collapser 1">
The first collapser! I will be hidden by default.
</Collapser>
<Collapser title="Collapser 2" defaultOpen>
The second collapser! The user will see this content by default.
</Collapser>
</CollapserGroup>;
```
### `CollapserGroup`
Used in conjunction with multiple `Collapser`s to group them together.
```js
import { Collapser, CollapserGroup } from '@newrelic/gatsby-theme-newrelic'`
```
**Props**
| Prop | Type | Required | Default | Description |
| ----------- | ------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------ |
| `className` | string | no | | Adds a `className` to the collapser group. Useful if you need to position the collapser group within its parent element. |
| `children` | React element | yes | | The set of `Collapser` elements that will be rendered as part of the `CollapserGroup`. |
**Examples**
```js
import { Collapser, CollapserGroup } from '@newrelic/gatsby-theme-newrelic';
<CollapserGroup>
<Collapser title="Collapser 1">
The first collapser! I will be hidden by default.
</Collapser>
<Collapser title="Collapser 2" defaultOpen>
The second collapser! The user will see this content by default.
</Collapser>
</CollapserGroup>;
```
### `ContributingGuidelines`
Used to display contributing information for the current page. This is meant to
be used as a section inside of the [`PageTools`](#pagetools) component.
To ensure this component leverages its full potential, please ensure the
following [`siteMetadata`](#site-metadata) fields are configured:
- `branch`
- `contributingUrl`
- `repository`
**NOTE:** If the `contributingUrl` is not configured, it will use the default
value as specified in the [`siteMetadata`](#site-metadata) section.
```js
import { ContributingGuidelines } from '@newrelic/gatsby-theme-newrelic'`
```
**Props**
| Prop | Type | Required | Default | Description |
| ------------------ | ------ | -------- | ------- | ------------------------------------------------------------------------------------------- |
| `fileRelativePath` | string | no | | The relative file path of the current page. This will be used by the "Edit this page" link. |
| `pageTitle` | string | no | | The title of the current page for use in a new GitHub issue. |
**Examples**
```js
<PageTools>
<ContributingGuidelines fileRelativePath="src/pages/index.js" />
</PageTools>
```
### `CreateIssueButton`
Pre-defined [`GitHubIssueButton`](#githubissuebutton) used specifically for the
"Create issue" button in the [`ContributingGuidelines`](#contributingguidelines)
and [`GlobalFooter`](#globalfooter) components.
```js
import { CreateIssueButton } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ----------- | ------ | -------- | ------- | --------------------------------------------------------------------------------------------------- |
| `pageTitle` | string | no | | Title of the page where the user clicked the "Create issue" button. Used to pre-populate the issue. |
All other props are forwarded to [`Button`](#button) component.
**Example**
```jsx
import { Button, CreateIssueButton } from '@newrelic/gatsby-theme-newrelic';
<CreateIssueButton
pageTitle="Demo"
size={Button.SIZE.SMALL}
variant={Button.VARIANT.OUTLINE}
/>;
```
### `DarkModeToggle`
Used in combination with [`use-dark-mode`](https://www.npmjs.com/package/use-dark-mode), is an icon
which sets a users' webpage to display either the light or dark theme
```js
import { DarkModeToggle } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ----------- | -------- | -------- | ------- | ----------------------------------------------------------------- |
| `className` | string | no | | Optional className that can be added to the component |
| `onClick` | function | no | | Addional functionality that can be added to the toggle if desired |
| `size` | string | no | | Size of the icon, must denote unit (e.g., `px`, `rem`, `etc`) |
**Example**
```js
// Fake tracking function just for an example
const trackUsage = (event) => {
track(event);
};
<DarkModeToggle
className="dark-mode-toggle"
onClick={trackUsage}
size="0.875rem"
/>;
```
### `Dropdown`
Used in combination with [`Dropdown.Toggle`](#dropdowntoggle), [`Dropdown.Menu`](#dropdownmenu), and [`Dropdown.MenuItem`](#dropdownmenuitem) to create a dropdown.
```js
import { Dropdown } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ---------- | ---- | -------- | ------- | ---------------------------------------------------------------------------- |
| `align` | enum | no | "left" | The position of the menu arrow. Must be either `left`, `right`, or `center`. |
| `children` | node | yes | | Components used for the dropdown. |
```jsx
import { DropDown, Button } from '@newrelic/gatsby-theme-newrelic';
const Example = (
<Dropdown align="right">
<Dropdown.Toggle variant={Button.VARIANT.NORMAL}>Menu</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.MenuItem>Item 1</Dropdown.MenuItem>
<Dropdown.MenuItem>Item 2</Dropdown.MenuItem>
<Dropdown.MenuItem>Item 3</Dropdown.MenuItem>
</Dropdown.Menu>
</Dropdown>
);
```
#### `Dropdown.Toggle`
Used within a [`Dropdown`](#dropdown) component to render a button that can toggle whether or not the dropdown menu is visible.
**Props**
| Prop | Type | Required | Default | Description |
| ---------- | ---- | -------- | ------- | -------------------------------------------------------------------- |
| `size` | enum | no | | The `size` prop for the underlying [`Button`](#button) component. |
| `variant` | enum | yes | | The `variant` prop for the underlying [`Button`](#button) component. |
| `children` | node | no | | Content used to render the toggle |
#### `Dropdown.Menu`
Used within a [`Dropdown`](#dropdown) component to render the _menu_ that is shown when the dropdown is open.
**Props**
| Props | Type | Required | Default | Description |
| ---------- | ---- | -------- | ------- | -------------------------------------------------------------------------------------------- |
| `children` | node | yes | | Content rendered inside the dropdown menu. Should consist of `Dropdown.MenuItem` components. |
#### `Dropdown.MenuItem`
Used within a [`Dropdown.Menu`](#dropdownmenu) component (within a [`Dropdown`](#dropdown) component) to render an individual dropdown menu item.
**Props**
| Props | Type | Required | Default | Description |
| ---------- | -------- | -------- | ------- | ------------------------------------------------------------------------------- |
| `href` | string | no | | A path that, if supplied, will be used as a [`Link`](#link). |
| `onClick` | function | no | | An optional click event handler that is triggerd when the component is clicked. |
| `children` | node | yes | | Content for the `MenuItem`. |
### `ExternalLink`
Used to render links that navigate outside of the website. This component is a
shortcut on top of the `target="_blank"` and `rel="noopener noreferrer"`
attributes and provides no out-of-the-box styling.
```js
import { ExternalLink } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
All props are forwarded to the underlying `a` tag with the exception of the
`target` and `rel` props.
**Example**
```js
<ExternalLink href="https://newrelic.com">Link to New Relic</ExternalLink>
```
### `EditPageButton`
Button used to link to the current page in GitHub. Used for the "Edit page"
button in the [`ContributingGuidelines`](#contributingguidelines) and
[`GlobalFooter`](#globalfooter) components.
```js
import { EditPageButton } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ------------------ | --------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `fileRelativePath` | string | yes | | Relative filepath of the current page. |
| `instrumentation` | Instrumentation | yes | | Config for the component instrumentation when the button is clicked. See the values below for a desciption on what is allowed. |
All other props are forwarded to [`Button`](#button) component.
```ts
type Instrumentation = {
component: string;
};
```
**Instrumentation**
The following fields are available for instrumentation:
- `component` _(string)_ **required** - The name of the component where this
button is used. Helps to understand where in the site the button is clicked.
**Example**
```jsx
import { Button, EditPageButton } from '@newrelic/gatsby-theme-newrelic';
<EditPageButton
fileRelativePath="src/content/docs/apm.mdx"
size={Button.SIZE.SMALL}
variant={Button.VARIANT.OUTLINE}
instrumentation={{ component: 'ContributingGuidelines' }}
/>;
```
### `FeatherSVG`
SVG wrapper for [feather icons](https://feathericons.com/). This is useful when
[shadowing feather icons](#shadowing-icons) to ensure all feather icons have
consistent props/styles applied to them.
**NOTE:** When using this component, you should to spread all props to it.
```js
import { FeatherSVG } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ---------- | ---- | -------- | ------- | ------------------------------------------ |
| `children` | node | yes | | The "guts" of the feather `svg` definition |
Additional props are forwarded to the `svg` tag.
**Example**
```jsx
const ChevronDownIcon = (props) => (
<FeatherSVG {...props}>
<polyline points="6 9 12 15 18 9" />
</FeatherSVG>
);
```
### `GitHubIssueButton`
Button used to create issues on GitHub. This component depends on the
`repository` and `siteUrl` fields configured in [site metadata](#site-metadata).
```js
import { GitHubIssueButton } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ------------ | -------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `labels` | string[] | no | | Labels that should be prepopulated for the issue. NOTE: This labels must be created in the repository where this button links to. |
| `issueTitle` | string | no | | The value that will pre-populate the issue title. |
| `issueBody` | string | no | | The value that will pre-populate the issue body. |
All other props are forwarded to [`Button`](#button)
#### Environment information
As a convenience, this component attaches environment information to the issue
body to allow for easier debugging. This eliminates the need for a section in
the issue body asking for environment information from the user filing the
issue.
The information gathered is:
- Page URL
- Browser name and version
- Operating system name and version
- Device type (mobile, tablet, etc.), vendor and model
If the browser environment is unable to be determined, these values are simply
set to "Unknown".
**Example**
```jsx
import { Button, GitHubIssueButton } from '@newrelic/gatsby-theme-newrelic';
const ISSUE_BODY = `
## Description
[NOTE]: # (Tell us some information!)
`
<GitHubIssueButton
labels={['bug']}
issueTitle="Bug found"
issueBody={ISSUE_BODY}
size={Button.SIZE.SMALL}
variant={Button.VARIANT.OUTLINE}
>
Found a bug!
</GitHubIssueButton>
```
### `GlobalFooter`
Renders the global footer used on all New Relic Gatsby sites. This component utilizes the [`layout` configuration](#layout) from the theme to size itself and the `siteMetadata` for the repository URL.
_NOTE_: The logo displayed in the footer is a generic to New Relic logo, but can be changed with [shadowing](https://www.gatsbyjs.com/docs/themes/shadowing).
```js
import { GlobalFooter } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ------------------ | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| `className` | string | no | | Additional `className` for the component. |
| `fileRelativePath` | string | no | | The relative path to the markdown file for the current page. If not supplied, the edit link will not be shown |
| `pageTitle` | string | no | | The title of the current page for use in a new GitHub issue. |
**Example**
```jsx
<GlobalFooter fileRelativePath={'/src/content/foobar.md'} />
```
### `GlobalHeader`
Renders the global header used on all New Relic Gatsby sites. This component
utilizes the [`layout` configuration](#layout) from the theme to size itself.
_Note_: The [`signup`](#signup) configuration options are needed for this component to function correctly.
```js
import { GlobalHeader } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| - | - | - | - | - |
| `activeSite` | enum | no | | The New Relic site that we should present as "active". This should come from `NR_SITES`, which is exported. |
**Examples**
```js
import { GlobalHeader } from '@newrelic/gatsby-theme-newrelic';
// Normal use
return <GlobalHeader />;
// With a custom-set active page
return <GlobalHeader activeSite={GlobalHeader.NR_SITES.IO} />;
```
### `HamburgerMenu`
Used as the toggle for mobile views to show and hide the mobile navigation.
```js
import { HamburgerMenu } from '@newrelic/gatsby-theme-newrelic';
```
**Props**
| Prop | Type | Required | Default | Description |
| ----------- | -------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `className` | string | no | | Additional `className` for the component. |
| `isOpen` | boolean | yes | `false` | Determines whether the `HamburgerMenu` is considered open or closed. |
| `onToggle` | function | yes | | Handler called when the user interacts with the hamburger menu. This handler should be responsible for toggling the `isOpen` state of the hamburger menu. |
**Examples**
```js
import React, { useState } from 'react';
const MobileMenu = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<HamburgerMenu
isOpen={isOpen}
onToggle={() => setIsOpen((isOpen) => !isOpen)}
/>
);
};
```
### `Icon`
Used to render icons on the website. This component utilizes a subset of the
[Feather icon set](https://feathericons.com/). To add additional icons for use
in your website, use [component
shadowing](https://www.gatsbyjs.org/docs/themes/shadowing/). See the "Shadowing"
section below for an explanation on how to use