leafyGreen UI Kit Code Blocks
npm install @leafygreen-ui/code``shell`
pnpm add @leafygreen-ui/code
`shell`
yarn add @leafygreen-ui/code
`shell`
npm install @leafygreen-ui/code
In addition to using a limited amount of our standard brand font, this component uses the open-source monospace font "Source Code Pro". For this component to display correctly, loading the following weights / styles of "Source Code Pro" is necessary:
- 400 / normal400 / italic
- 600 / normal
-
You can find instructions for using Google's CDN for font delivery, and download "Source Code Pro" on Google Fonts.
We recommend using Google's CDN for loading this font to optimize for caching the assets, speeding up loading times for webpages as a result. We use the following HTML in our
tags to load the necessary variants of "Source Code Pro":`HTML
`Example
`js
import Code from '@leafygreen-ui/code';const codeSnippet =
Hello, \${entity}!\;console.log(greeting('World'));;
const SomeComponentWithPanel = () => (
language="javascript"
showLineNumbers={true}
darkMode={true}
panel={
languageOptions={[]}
showCustomActionButtons
customActionButtons={[]}
onCopy={() => {}}
title="Title"
/>
}
>
{codeSnippet}
);
const SomeComponentWithoutPanel = () => (
language="javascript"
showLineNumbers={true}
onCopy={() => {}}
darkMode={true}
copyButtonAppearance="persist"
>
{codeSnippet}
);
`
| Prop | Type | Description | Default |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| children (Required) | string | This is the code snippet that will be rendered in the code block. | '' |language
| (Required) | 'javascript', 'typescript', 'cs', 'csharp', 'cpp', 'go', 'http','java', 'perl', 'php', 'python', 'ruby', 'scala', 'swift', 'kotlin','objectivec', 'dart', 'bash', 'shell', 'sql', 'yaml', 'json', 'diff', 'xml', 'none' | The language to highlight the code block as. When set to 'none', no syntax highlighting will be applied. | |darkMode
| | boolean | Determines whether or not the component will appear in dark mode. | false |className
| | string | Applies a className to the root element's classList. | |showLineNumbers
| | boolean | Shows line numbers next to each line of code in the passed code snippet. NOTE: While you can set this to true regardless of the code component being multiline, the line numbers will not be displayed if the multiline prop is true. | false |lineNumberStart
| | number | Specifies the number by which to start line numbering. | 1 |onCopy
| | () => void | Callback fired when the copy button is clicked. panel
_Note_: When using the prop, the copy button is rendered within the panel itself, so this callback should be passed as a prop to the component instead of the [number, number]> component. | |expandable
| | boolean | When true, allows the code block to be expanded and collapsed when there are more lines than specified by collapsedLines. | false |collapsedLines
| | number | The number of lines to display when the code block is collapsed (only applies when expandable is true). | 5 |highlightLines
| | Array | An optional array of lines to highlight. The array can only contain numbers corresponding to the line numbers to highlight, and / or tuples representing a range (e.g. [6, 10]); | |copyButtonAppearance
| | 'none', 'hover', 'persist' | Determines the appearance of the copy button without a panel. The copy button allows the code block to be copied to the user's clipboard by clicking the button. 'hover'
Appearance:
\ : the copy button will only appear when the user hovers over the code block. On mobile devices, the copy button will always be visible. 'persist'
\ : the copy button will always be visible. 'none'
\* : the copy button will not be rendered panel
_Note_: cannot be used with copyButtonAppearance. Either use copyButtonAppearance or panel, not both. The component will automatically render the copy button to the right of panel and will ignore the copyButtonAppearance prop. | hover |panel
| | React.ReactNode | Slot to pass the sub-component which will render the top panel with a language switcher, custom action buttons, and copy button. If no props are passed to the panel sub-component, the panel will render with only the copy button. panel
_Note_: cannot be used with copyButtonAppearance. Either use copyButtonAppearance or panel, not both. The component will automatically render the copy button to the right of panel and will ignore the copyButtonAppearance prop. | |isLoading
| | boolean | Determines whether or not the loading skeleton will be rendered in place of the code block. Iftrue, the language switcher and copy button will be disabled in the top panel. | false |baseFontSize
| | '13' \| '16' | Determines the base font-size of the component | 13 |customKeywords
| | { [key: string]: string } | Custom keywords to be highlighted in the code block. The key is the keyword to be highlighted, and the value is the classname to be applied to the keyword. E.g. customKeywords: {{ 'keyword': 'className' }} | {} |
| Prop | Type | Description | Default |
| ------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| showCustomActionButtons | boolean | Shows custom action buttons in the panel if set to true and there is at least one item in customActionButtons. | false |customActionButtons
| | Array | An array of custom action buttons using the IconButton component. For example: [ | [] |title
| | string | Shows a filename-like title in the window chrome frame. | '' |languageOptions
| | Array | An array of language options. When provided, a LanguageSwitcher dropdown is rendered. | |onChange
| | (language: LanguageOption) => void | A change handler triggered when the language is changed. Invalid when no languageOptions are provided. |onCopy
| | () => void | Callback fired when Code is copied. | |
``
interface LanguageOption {
displayName: string;
language: Language;
image?: React.ReactElement;
}
getTestUtils() is a util that allows consumers to reliably interact with LG Code in a product test suite. If the Code component cannot be found, an error will be thrown.
`tsx
import { getTestUtils } from '@leafygreen-ui/code';
const utils = getTestUtils(lgId?: lg-${string}); // lgId refers to the custom data-lgid attribute passed to Code. It defaults to 'lg-code' if left empty.`
#### Single Code component
`tsx
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Code, { getTestUtils } from '@leafygreen-ui/code';
...
test('code', () => {
render(
language="javascript"
panel={
languageOptions={languageOptions}
title="Title"
/>
}
>
{codeSnippet}
);
const { getLanguage, getLanguageSwitcherUtils, getIsLoading, getCopyButtonUtils, getExpandButtonUtils } = getTestUtils();
const { getInput, getOptions, getOptionByValue, getInputValue, isDisabled: isLanguageSwitcherDisabled } = getLanguageSwitcherUtils();
const { getButton, queryButton, findButton, isDisabled } = getCopyButtonUtils();
const { getButton, queryButton, findButton } = getExpandButtonUtils();
expect(getLanguage()).toBe('javascript');
expect(getTitle()).toBe('Title');
expect(getInput()).toBeInTheDocument();
expect(getOptions()).toHaveLength(2);
expect(getOptionByValue('js')).toBeInTheDocument();
expect(getInputValue()).toBe('javascript');
expect(isLanguageSwitcherDisabled()).toBe(false);
expect(getIsLoading()).toBe(false);
expect(getCopyButtonUtils().getButton()).toBeInTheDocument();
expect(getCopyButtonUtils().findButton()).toBeInTheDocument();
expect(getCopyButtonUtils().queryButton()).toBeInTheDocument();
expect(getCopyButtonUtils().isDisabled()).toBe(false);
expect(getExpandButtonUtils().getButton()).toBeInTheDocument();
expect(getExpandButtonUtils().findButton()).toBeInTheDocument();
expect(getExpandButtonUtils().queryButton()).toBeInTheDocument();
expect(isExpanded()).toBe(false);
});
`
#### Multiple Code components
When testing multiple Code components, it is recommended to add the custom data-lgid attribute to each Code.
`tsx
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Code, getTestUtils } from '@leafygreen-ui/code';
...
test('code', () => {
render(
<>
language="javascript"
panel={
data-lgid="lg-code-1"
>
{codeSnippet}
language="python"
panel={
data-lgid="lg-code-2"
>
{codeSnippet}
>
);
const testUtils1 = getTestUtils('lg-code-1');
const testUtils2 = getTestUtils('lg-code-2');
// First Code
expect(testUtils1.getLanguage()).toBe('javascript');
// Second Code
expect(testUtils2.getLanguage()).toBe('python');
});
`
`tsx`
const {
getLanguage,
getIsLoading,
getTitle,
queryPanel,
getLanguageSwitcherUtils: {
getInput,
getOptions,
getOptionByValue,
isDisabled,
},
getCopyButtonUtils: { getButton, queryButton, findButton, isDisabled },
getExpandButtonUtils: { getButton, queryButton, findButton },
} = getTestUtils();
| Util | Description | Returns |
| ---------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| getLanguage() | Returns the current language of the code block | string |getLanguageSwitcherUtils()
| | Returns utils for interacting with the language switcher | LanguageSwitcherUtils |getIsLoading()
| | Returns whether the code block is in loading state | boolean |getCopyButtonUtils()
| | Returns utils for interacting with the copy button | Button test utils return type |getExpandButtonUtils()
| | Returns utils for interacting with the expand button | Button test utils return type |getIsExpanded()
| | Returns whether the code block is expanded | boolean |getTitle()
| | Returns the title of the code block | string \| null |queryPanel()
| | Returns the panel element | HTMLElement \| null |
| Util | Description | Returns |
| --------------------------------- | ------------------------------------------------- | ----------------------- |
| getInput() | Returns the language switcher trigger | HTMLButtonElement |getInputValue()
| | Returns the language switcher input value | string |getOptions()
| | Returns all options in the language switcher | Array |getOptionByValue(value: string)
| | Returns the option element by its value | HTMLElement \| null |isDisabled()
| | Returns whether the language switcher is disabled | boolean` |