Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import React from 'react';
import Shortcut from '@patternfly/react-component-groups/dist/dynamic/Shortcut';

export const BasicExample: React.FunctionComponent = () => <Shortcut description='Shortcut description' keys={[ 'cmd', 'shift' ]} click/>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
# Sidenav top-level section
# should be the same for all markdown files
section: extensions
subsection: Component groups
# Sidenav secondary level section
# should be the same for all markdown files
id: Shortcut grid
# Tab (react | react-demos | html | html-demos | design-guidelines | accessibility)
source: react
# If you use typescript, the name of the interface to display props for
# These are found through the sourceProps function provided in patternfly-docs.source.js
propComponents: [
'ShortcutGrid',
'Shortcut'
]
sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/ShortcutGrid/ShortcutGrid.md
---

import ShortcutGrid from '@patternfly/react-component-groups/dist/dynamic/ShortcutGrid';
import Shortcut from '@patternfly/react-component-groups/dist/dynamic/Shortcut';

A **shortcut grid** component displays keyboard shortcuts with their description in a grid.

## Examples

### Basic shortcut grid

A basic shortcut grid can be used to display shortcuts available to the user together with their description.

You can customize displayed shortcuts using `shortcuts` props. For mouse actions with given shortcuts, there are separate props to be enabled. You can customize showing symbols for control keys using `showSymbols`. The component also accepts all properties of the [grid layout](/layouts/grid).

```js file="./ShortcutGridExample.tsx"

```

### Single shortcut

Shortcut component can be also used outside of the grid.

Appearance of the component can be customized using the `className` property.

```js file="./ShortcutExample.tsx"

```


Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import ShortcutGrid from '@patternfly/react-component-groups/dist/dynamic/ShortcutGrid';

export const BasicExample: React.FunctionComponent = () => (
<ShortcutGrid
shortcuts={[
{ description: 'Open new tab', keys: [ 'cmd', 'shift', 't' ] },
{ description: 'Open new page', keys: [ 'opt', 'n' ] },
{ description: 'Move object', keys: [ 'ctrl' ], drag: true },
]}
/>
);
9 changes: 9 additions & 0 deletions packages/module/src/Shortcut/Shortcut.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import { render } from '@testing-library/react';
import Shortcut from './Shortcut';

describe('Shortcut component', () => {
it('should render correctly', () => {
expect(render(<Shortcut description='Shortcut description' keys={[ 'cmd', 'shift' ]} click/>)).toMatchSnapshot();
});
});
105 changes: 105 additions & 0 deletions packages/module/src/Shortcut/Shortcut.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import * as React from 'react';
import { MouseIcon } from '@patternfly/react-icons';
import { Chip } from '@patternfly/react-core';
import { createUseStyles } from 'react-jss';
import clsx from 'clsx';

export interface ShortcutProps {
/** Array of shortcut keys */
keys: string[];
/** Shortcut description */
description?: React.ReactNode;
/** Indicates whether symbols should be displayed for certain keys */
showSymbols?: boolean;
/** Show hover in the shortcut */
hover?: boolean;
/** Show click in the shortcut */
click?: boolean;
/** Show right click in the shortcut */
rightClick?: boolean;
/** Show drag in the shortcut */
drag?: boolean;
/** Show drag and drop in the shortcut */
dragAndDrop?: boolean;
/** Shortcut className */
className?: string;
}

const symbols = {
'shift': '⇧',
'opt': '⌥',
'cmd': '⌘',
'enter': '↵',
'ctrl': '^',
'caps lock': '⇪',
'tab': '↹',
'win': '⊞',
'backspace': '⌫'
}

const useStyles = createUseStyles({
shortcut: {
marginRight: 'var(--pf-v5-global--spacer--lg)'
}
})

const Shortcut: React.FunctionComponent<ShortcutProps> = ({
keys = [],
description = null,
showSymbols = true,
hover,
click,
drag,
rightClick,
dragAndDrop,
className
}: ShortcutProps) => {
const classes = useStyles();
const badges = [
...(hover ? [
<Chip key="hover" isReadOnly data-test-id="hover">
<MouseIcon /> Hover
</Chip>
] : []),
...keys.map((key) => {
const trimmedKey = key.trim().toLowerCase();
return(
<Chip key={key} isReadOnly data-test-id={`${key}-key`}>
{showSymbols && symbols[trimmedKey] ? `${symbols[trimmedKey]} ` : '' }
{key.length === 1 ? key.toUpperCase() : key[0].toUpperCase() + key.slice(1).toLowerCase()}
</Chip>
)}),
...(click ? [
<Chip key="click" isReadOnly data-test-id="click">
<MouseIcon /> Click
</Chip>
] : []),
...(rightClick ? [
<Chip key="right-click" isReadOnly data-test-id="right-click">
<MouseIcon /> Right click
</Chip>
] : []),
...(drag ? [
<Chip key="drag" isReadOnly data-test-id="drag">
<MouseIcon /> Drag
</Chip>
] : []),
...(dragAndDrop ? [
<Chip key="drag-and-drop" isReadOnly data-test-id="drag-and-drop">
<MouseIcon /> Drag + Drop
</Chip>
] : [])
]

return (
<>
<span className={clsx({ [classes.shortcut]: description, className })}>
{badges.length > 0 && badges.reduce((prev, curr) => (
<>{[ prev, ' + ', curr ]}</>
))}
</span>
{description}
</>
);}

export default Shortcut;
216 changes: 216 additions & 0 deletions packages/module/src/Shortcut/__snapshots__/Shortcut.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Shortcut component should render correctly 1`] = `
{
"asFragment": [Function],
"baseElement": <body>
<div>
<span
class="shortcut-0-2-1"
>
<div
class="pf-v5-c-chip"
data-ouia-component-id="OUIA-Generated-Chip-1"
data-ouia-component-type="PF5/Chip"
data-ouia-safe="true"
data-test-id="cmd-key"
>
<span
class="pf-v5-c-chip__content"
>
<span
class="pf-v5-c-chip__text"
id="pf-random-id-0"
>
Cmd
</span>
</span>
</div>
+
<div
class="pf-v5-c-chip"
data-ouia-component-id="OUIA-Generated-Chip-2"
data-ouia-component-type="PF5/Chip"
data-ouia-safe="true"
data-test-id="shift-key"
>
<span
class="pf-v5-c-chip__content"
>
<span
class="pf-v5-c-chip__text"
id="pf-random-id-1"
>
Shift
</span>
</span>
</div>
+
<div
class="pf-v5-c-chip"
data-ouia-component-id="OUIA-Generated-Chip-3"
data-ouia-component-type="PF5/Chip"
data-ouia-safe="true"
data-test-id="click"
>
<span
class="pf-v5-c-chip__content"
>
<span
class="pf-v5-c-chip__text"
id="pf-random-id-2"
>
<svg
aria-hidden="true"
class="pf-v5-svg"
fill="currentColor"
height="1em"
role="img"
viewBox="0 0 384 512"
width="1em"
>
<path
d="M0 352a160 160 0 0 0 160 160h64a160 160 0 0 0 160-160V224H0zM176 0h-16A160 160 0 0 0 0 160v32h176zm48 0h-16v192h176v-32A160 160 0 0 0 224 0z"
/>
</svg>
Click
</span>
</span>
</div>
</span>
Shortcut description
</div>
</body>,
"container": <div>
<span
class="shortcut-0-2-1"
>
<div
class="pf-v5-c-chip"
data-ouia-component-id="OUIA-Generated-Chip-1"
data-ouia-component-type="PF5/Chip"
data-ouia-safe="true"
data-test-id="cmd-key"
>
<span
class="pf-v5-c-chip__content"
>
<span
class="pf-v5-c-chip__text"
id="pf-random-id-0"
>
Cmd
</span>
</span>
</div>
+
<div
class="pf-v5-c-chip"
data-ouia-component-id="OUIA-Generated-Chip-2"
data-ouia-component-type="PF5/Chip"
data-ouia-safe="true"
data-test-id="shift-key"
>
<span
class="pf-v5-c-chip__content"
>
<span
class="pf-v5-c-chip__text"
id="pf-random-id-1"
>
Shift
</span>
</span>
</div>
+
<div
class="pf-v5-c-chip"
data-ouia-component-id="OUIA-Generated-Chip-3"
data-ouia-component-type="PF5/Chip"
data-ouia-safe="true"
data-test-id="click"
>
<span
class="pf-v5-c-chip__content"
>
<span
class="pf-v5-c-chip__text"
id="pf-random-id-2"
>
<svg
aria-hidden="true"
class="pf-v5-svg"
fill="currentColor"
height="1em"
role="img"
viewBox="0 0 384 512"
width="1em"
>
<path
d="M0 352a160 160 0 0 0 160 160h64a160 160 0 0 0 160-160V224H0zM176 0h-16A160 160 0 0 0 0 160v32h176zm48 0h-16v192h176v-32A160 160 0 0 0 224 0z"
/>
</svg>
Click
</span>
</span>
</div>
</span>
Shortcut description
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;
Loading