Commit f00e94ca authored by Lukas 'Eipi' Eipert's avatar Lukas 'Eipi' Eipert Committed by Nathan Friend

Make keyboard shortcut help dynamic

parent 9b466bb0
......@@ -375,7 +375,7 @@ export const MR_PREVIOUS_FILE_IN_DIFF = {
export const MR_GO_TO_FILE = {
id: 'mergeRequests.goToFile',
description: __('Go to file'),
defaultKeys: ['t', 'mod+p'],
defaultKeys: ['mod+p', 't'],
customizable: false,
};
......
<script>
import { __, s__ } from '~/locale';
// Map some keys to their proper representation depending on the system
// See also: https://craig.is/killing/mice#keys
const getKeyMap = () => {
const keyMap = {
up: '',
down: '',
left: '',
right: '',
ctrl: s__('KeyboardKey|Ctrl'),
shift: s__('KeyboardKey|Shift'),
enter: s__('KeyboardKey|Enter'),
esc: s__('KeyboardKey|Esc'),
command: '',
option: window.gl?.client?.isMac ? '' : s__('KeyboardKey|Alt'),
};
// Meta and alt are aliases
keyMap.meta = keyMap.command;
keyMap.alt = keyMap.option;
// Mod is Command on Mac, and Ctrl on Windows/Linux
keyMap.mod = window.gl?.client?.isMac ? keyMap.command : keyMap.ctrl;
return keyMap;
};
export default {
functional: true,
props: {
shortcuts: {
type: Array,
required: true,
},
},
render(createElement, context) {
const keyMap = getKeyMap();
const { staticClass } = context.data;
const shortcuts = context.props.shortcuts.reduce((acc, shortcut, i) => {
if (
!window.gl?.client?.isMac &&
(shortcut.includes('command') || shortcut.includes('meta'))
) {
return acc;
}
const keys = shortcut.split(/([ +])/);
if (i !== 0 && acc.length) {
acc.push(` ${__('or')} `);
// If there are multiple alternative shortcuts,
// we keep them on the same line if they are single-key, e.g. `]` or `j`
// but if they consist of multiple keys, we insert a line break, e.g.:
// `shift` + `]` <br> or `shift` + `j`
if (keys.length > 1) {
acc.push(createElement('br'));
}
}
keys.forEach((key) => {
if (key === '+') {
acc.push(' + ');
} else if (key === ' ') {
acc.push(` ${__('then')} `);
} else {
acc.push(createElement('kbd', {}, [keyMap[key] ?? key]));
}
});
return acc;
}, []);
return createElement('div', { staticClass }, shortcuts);
},
};
</script>
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import { GlIcon, GlModal } from '@gitlab/ui';
import { GlModal, GlSearchBoxByType } from '@gitlab/ui';
import { s__, __ } from '~/locale';
import { keybindingGroups } from './keybindings';
import Shortcut from './shortcut.vue';
import ShortcutsToggle from './shortcuts_toggle.vue';
export default {
components: {
GlIcon,
GlModal,
GlSearchBoxByType,
ShortcutsToggle,
Shortcut,
},
data() {
return {
searchTerm: '',
};
},
computed: {
ctrlCharacter() {
return window.gl.client.isMac ? '' : 'ctrl';
filteredKeybindings() {
if (!this.searchTerm) {
return keybindingGroups;
}
const search = this.searchTerm.toLocaleLowerCase();
const mapped = keybindingGroups.map((group) => {
if (group.name.toLocaleLowerCase().includes(search)) {
return group;
}
return {
...group,
keybindings: group.keybindings.filter((binding) =>
binding.description.toLocaleLowerCase().includes(search),
),
};
});
return mapped.filter((group) => group.keybindings.length);
},
onDotCom() {
return window.gon.dot_com;
},
i18n: {
title: __(`Keyboard shortcuts`),
search: s__(`KeyboardShortcuts|Search keyboard shortcuts`),
noMatch: s__(`KeyboardShortcuts|No shortcuts matched your search`),
},
};
</script>
......@@ -23,503 +51,49 @@ export default {
<gl-modal
modal-id="keyboard-shortcut-modal"
size="lg"
:title="$options.i18n.title"
data-testid="modal-shortcuts"
body-class="shortcut-help-body gl-p-0!"
:visible="true"
:hide-footer="true"
@hidden="$emit('hidden')"
>
<template #modal-title>
<shortcuts-toggle />
</template>
<div class="row">
<div class="col-lg-4">
<table class="shortcut-mappings text-2">
<tbody>
<tr>
<th></th>
<th>{{ __('Global Shortcuts') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>?</kbd>
</td>
<td>{{ __('Toggle this dialog') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>shift p</kbd>
</td>
<td>{{ __('Go to your projects') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>shift g</kbd>
</td>
<td>{{ __('Go to your groups') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>shift a</kbd>
</td>
<td>{{ __('Go to the activity feed') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>shift l</kbd>
</td>
<td>{{ __('Go to the milestone list') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>shift s</kbd>
</td>
<td>{{ __('Go to your snippets') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>s</kbd>
/
<kbd>/</kbd>
</td>
<td>{{ __('Start search') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>shift i</kbd>
</td>
<td>{{ __('Go to your issues') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>shift m</kbd>
</td>
<td>{{ __('Go to your merge requests') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>shift t</kbd>
</td>
<td>{{ __('Go to your To-Do list') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>p</kbd>
<kbd>b</kbd>
</td>
<td>{{ __('Toggle the Performance Bar') }}</td>
</tr>
<tr v-if="onDotCom">
<td class="shortcut">
<kbd>g</kbd>
<kbd>x</kbd>
</td>
<td>{{ __('Toggle GitLab Next') }}</td>
</tr>
</tbody>
<tbody>
<tr>
<th></th>
<th>{{ __('Editing') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>{{ ctrlCharacter }} shift p</kbd>
</td>
<td>{{ __('Toggle Markdown preview') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>
<gl-icon name="arrow-up" />
</kbd>
</td>
<td>
{{ __('Edit your most recent comment in a thread (from an empty textarea)') }}
</td>
</tr>
</tbody>
<tbody>
<tr>
<th></th>
<th>{{ __('Wiki') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>e</kbd>
</td>
<td>{{ __('Edit wiki page') }}</td>
</tr>
</tbody>
<tbody>
<tr>
<th></th>
<th>{{ __('Repository Graph') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>
<gl-icon name="arrow-left" />
</kbd>
/
<kbd>h</kbd>
</td>
<td>{{ __('Scroll left') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>
<gl-icon name="arrow-right" />
</kbd>
/
<kbd>l</kbd>
</td>
<td>{{ __('Scroll right') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>
<gl-icon name="arrow-up" />
</kbd>
/
<kbd>k</kbd>
</td>
<td>{{ __('Scroll up') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>
<gl-icon name="arrow-down" />
</kbd>
/
<kbd>j</kbd>
</td>
<td>{{ __('Scroll down') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>
shift
<gl-icon name="arrow-up" />
/ k
</kbd>
</td>
<td>{{ __('Scroll to top') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>
shift
<gl-icon name="arrow-down" />
/ j
</kbd>
</td>
<td>{{ __('Scroll to bottom') }}</td>
</tr>
</tbody>
</table>
<div
class="gl-sticky gl-top-0 gl-py-5 gl-px-5 gl-display-flex gl-align-items-center gl-bg-white"
>
<gl-search-box-by-type
v-model.trim="searchTerm"
:aria-label="$options.i18n.search"
class="gl-w-half gl-mr-3"
/>
<shortcuts-toggle class="gl-w-half gl-ml-3" />
</div>
<div v-if="filteredKeybindings.length === 0" class="gl-px-5">
{{ $options.i18n.noMatch }}
</div>
<div class="col-lg-4">
<table class="shortcut-mappings text-2">
<tbody>
<tr>
<th></th>
<th>{{ __('Project') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>p</kbd>
</td>
<td>{{ __("Go to the project's overview page") }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>v</kbd>
</td>
<td>{{ __("Go to the project's activity feed") }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>r</kbd>
</td>
<td>{{ __('Go to releases') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>f</kbd>
</td>
<td>{{ __('Go to files') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>t</kbd>
</td>
<td>{{ __('Go to find file') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>c</kbd>
</td>
<td>{{ __('Go to commits') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>n</kbd>
</td>
<td>{{ __('Go to repository graph') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>d</kbd>
</td>
<td>{{ __('Go to repository charts') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>i</kbd>
</td>
<td>{{ __('Go to issues') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>i</kbd>
</td>
<td>{{ __('New issue') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>b</kbd>
</td>
<td>{{ __('Go to issue boards') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>m</kbd>
</td>
<td>{{ __('Go to merge requests') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>j</kbd>
</td>
<td>{{ __('Go to jobs') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>l</kbd>
</td>
<td>{{ __('Go to metrics') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>e</kbd>
</td>
<td>{{ __('Go to environments') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>k</kbd>
</td>
<td>{{ __('Go to kubernetes') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>s</kbd>
</td>
<td>{{ __('Go to snippets') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>g</kbd>
<kbd>w</kbd>
</td>
<td>{{ __('Go to wiki') }}</td>
</tr>
</tbody>
<tbody>
<tr>
<th></th>
<th>{{ __('Project Files') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>
<gl-icon name="arrow-up" />
</kbd>
</td>
<td>{{ __('Move selection up') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>
<gl-icon name="arrow-down" />
</kbd>
</td>
<td>{{ __('Move selection down') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>enter</kbd>
</td>
<td>{{ __('Open Selection') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>esc</kbd>
</td>
<td>{{ __('Go back (while searching for files)') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>y</kbd>
</td>
<td>{{ __('Go to file permalink (while viewing a file)') }}</td>
</tr>
</tbody>
</table>
<div v-else class="shortcut-help-container gl-mt-8 gl-px-5 gl-pb-5">
<section
v-for="group in filteredKeybindings"
:key="group.id"
class="shortcut-help-mapping gl-mb-4"
>
<strong class="shortcut-help-mapping-title gl-w-half gl-display-inline-block">
{{ group.name }}
</strong>
<div
v-for="keybinding in group.keybindings"
:key="keybinding.id"
class="gl-display-flex gl-align-items-center"
>
<shortcut
class="gl-w-40p gl-flex-shrink-0 gl-text-right gl-pr-4"
:shortcuts="keybinding.defaultKeys"
/>
<div class="gl-w-half gl-flex-shrink-0 gl-flex-grow-1">
{{ keybinding.description }}
</div>
<div class="col-lg-4">
<table class="shortcut-mappings text-2">
<tbody>
<tr>
<th></th>
<th>{{ __('Epics, issues, and merge requests') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>r</kbd>
</td>
<td>{{ __('Comment/Reply (quoting selected text)') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>e</kbd>
</td>
<td>{{ __('Edit description') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>l</kbd>
</td>
<td>{{ __('Change label') }}</td>
</tr>
</tbody>
<tbody>
<tr>
<th></th>
<th>{{ __('Issues and merge requests') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>a</kbd>
</td>
<td>{{ __('Change assignee') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>m</kbd>
</td>
<td>{{ __('Change milestone') }}</td>
</tr>
</tbody>
<tbody>
<tr>
<th></th>
<th>{{ __('Merge requests') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>]</kbd>
/
<kbd>j</kbd>
</td>
<td>{{ __('Next file in diff') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>[</kbd>
/
<kbd>k</kbd>
</td>
<td>{{ __('Previous file in diff') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>{{ ctrlCharacter }} p</kbd>
</td>
<td>{{ __('Go to file') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>n</kbd>
</td>
<td>{{ __('Next unresolved discussion') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>p</kbd>
</td>
<td>{{ __('Previous unresolved discussion') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>b</kbd>
</td>
<td>{{ __('Copy source branch name') }}</td>
</tr>
</tbody>
<tbody>
<tr>
<th></th>
<th>{{ __('Merge request commits') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>c</kbd>
</td>
<td>{{ __('Next commit') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>x</kbd>
</td>
<td>{{ __('Previous commit') }}</td>
</tr>
</tbody>
<tbody>
<tr>
<th></th>
<th>{{ __('Web IDE') }}</th>
</tr>
<tr>
<td class="shortcut">
<kbd>{{ ctrlCharacter }} p</kbd>
</td>
<td>{{ __('Go to file') }}</td>
</tr>
<tr>
<td class="shortcut">
<kbd>{{ ctrlCharacter }} enter</kbd>
</td>
<td>{{ __('Commit (when editing commit message)') }}</td>
</tr>
</tbody>
</table>
</div>
</section>
</div>
</gl-modal>
</template>
......@@ -6,7 +6,7 @@ import { disableShortcuts, enableShortcuts, shouldDisableShortcuts } from './sho
export default {
i18n: {
toggleLabel: __('Keyboard shortcuts'),
toggleLabel: __('Toggle shortcuts'),
},
components: {
GlToggle,
......@@ -31,14 +31,12 @@ export default {
</script>
<template>
<div v-if="localStorageUsable" class="d-inline-flex align-items-center js-toggle-shortcuts">
<div v-if="localStorageUsable" class="js-toggle-shortcuts">
<gl-toggle
v-model="shortcutsEnabled"
aria-describedby="shortcutsToggle"
:label="$options.i18n.toggleLabel"
label-position="left"
@change="onChange"
/>
<div id="shortcutsToggle" class="sr-only">{{ __('Enable or disable keyboard shortcuts') }}</div>
</div>
</template>
......@@ -105,10 +105,6 @@ hr {
}
}
kbd {
display: inline-block;
}
code {
padding: 2px 4px;
color: $code-color;
......
......@@ -22,6 +22,7 @@
@import 'framework/flash';
@import 'framework/forms';
@import 'framework/gfm';
@import 'framework/kbd';
@import 'framework/header';
@import 'framework/highlight';
@import 'framework/issue_box';
......
......@@ -266,15 +266,6 @@
}
}
.shortcut-mappings {
display: none;
}
&.shortcuts .shortcut-mappings {
display: inline-block;
margin-right: 5px;
}
ul {
margin: 0;
padding: 0;
......
kbd {
display: inline-block;
padding: 3px 5px;
font-size: $gl-font-size-monospace-sm;
line-height: 10px;
color: var(--gray-700, $gray-700);
vertical-align: middle;
background-color: var(--gray-10, $gray-10);
border-width: 1px;
border-style: solid;
border-color: var(--gray-100, $gray-100) var(--gray-100, $gray-100) var(--gray-200, $gray-200);
border-image: none;
border-radius: 3px;
box-shadow: 0 -1px 0 var(--gray-200, $gray-200) inset;
}
......@@ -81,22 +81,6 @@
word-break: keep-all;
}
kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: $gray-700;
vertical-align: middle;
background-color: $gray-10;
border-width: 1px;
border-style: solid;
border-color: $gray-100 $gray-100 $gray-200;
border-image: none;
border-radius: 3px;
box-shadow: 0 -1px 0 $gray-200 inset;
}
h1 {
font-size: 1.75em;
font-weight: $gl-font-weight-bold;
......
.shortcut-mappings {
font-size: 12px;
color: $gray-700;
tbody:first-child tr:first-child {
padding-top: 0;
.shortcut-help {
&-body {
height: 80vh;
overflow-y: scroll;
}
th {
padding-top: 15px;
line-height: 1.5;
color: $help-shortcut-header-color;
text-align: left;
&-container {
column-count: 1;
@include media-breakpoint-up(md) {
column-count: 2;
}
column-gap: 1rem;
}
td {
padding-top: 3px;
padding-bottom: 3px;
vertical-align: top;
line-height: 20px;
&-mapping {
overflow: hidden;
break-inside: avoid;
&-title {
margin-left: 40%;
}
.shortcut {
padding-right: 10px;
color: $gray-300;
text-align: right;
white-space: nowrap;
kbd {
margin: 0.1rem 0;
line-height: unset;
font-size: unset;
}
}
}
......
---
title: "Update Keyboard shortcut help: adding search, update styling"
merge_request: 56400
author:
type: changed
......@@ -12185,9 +12185,6 @@ msgstr ""
msgid "Enable or disable Seat Link."
msgstr ""
msgid "Enable or disable keyboard shortcuts"
msgstr ""
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
......@@ -18798,9 +18795,30 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
msgid "KeyboardKey|Alt"
msgstr ""
msgid "KeyboardKey|Ctrl"
msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
msgid "KeyboardKey|Enter"
msgstr ""
msgid "KeyboardKey|Esc"
msgstr ""
msgid "KeyboardKey|Shift"
msgstr ""
msgid "KeyboardShortcuts|No shortcuts matched your search"
msgstr ""
msgid "KeyboardShortcuts|Search keyboard shortcuts"
msgstr ""
msgid "Keys"
msgstr ""
......@@ -33762,13 +33780,13 @@ msgstr ""
msgid "Toggle project select"
msgstr ""
msgid "Toggle sidebar"
msgid "Toggle shortcuts"
msgstr ""
msgid "Toggle the Performance Bar"
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle this dialog"
msgid "Toggle the Performance Bar"
msgstr ""
msgid "Toggle thread"
......@@ -38934,6 +38952,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
msgid "then"
msgstr ""
msgid "this document"
msgstr ""
......
import { shallowMount } from '@vue/test-utils';
import Shortcut from '~/behaviors/shortcuts/shortcut.vue';
describe('Shortcut Vue Component', () => {
const render = (shortcuts) => shallowMount(Shortcut, { propsData: { shortcuts } }).html();
afterEach(() => {
delete window.gl.client;
});
describe.each([true, false])('With browser env isMac: %p', (isMac) => {
beforeEach(() => {
window.gl = { client: { isMac } };
});
it.each([
['up', '<kbd>↑</kbd>'],
['down', '<kbd>↓</kbd>'],
['left', '<kbd>←</kbd>'],
['right', '<kbd>→</kbd>'],
['ctrl', '<kbd>Ctrl</kbd>'],
['shift', '<kbd>Shift</kbd>'],
['enter', '<kbd>Enter</kbd>'],
['esc', '<kbd>Esc</kbd>'],
// Some normal ascii letter
['a', '<kbd>a</kbd>'],
// An umlaut letter
['ø', '<kbd>ø</kbd>'],
// A number
['5', '<kbd>5</kbd>'],
])('renders platform agnostic key %p as: %p', (key, rendered) => {
expect(render([key])).toEqual(`<div>${rendered}</div>`);
});
it('renders keys combined with plus ("+") correctly', () => {
expect(render(['shift+a+b+c'])).toEqual(
`<div><kbd>Shift</kbd> + <kbd>a</kbd> + <kbd>b</kbd> + <kbd>c</kbd></div>`,
);
});
it('renders keys combined with space (" ") correctly', () => {
expect(render(['shift a b c'])).toEqual(
`<div><kbd>Shift</kbd> then <kbd>a</kbd> then <kbd>b</kbd> then <kbd>c</kbd></div>`,
);
});
it('renders multiple shortcuts correctly', () => {
expect(render(['shift+[', 'shift+k'])).toEqual(
`<div><kbd>Shift</kbd> + <kbd>[</kbd> or <br><kbd>Shift</kbd> + <kbd>k</kbd></div>`,
);
expect(render(['[', 'k'])).toEqual(`<div><kbd>[</kbd> or <kbd>k</kbd></div>`);
});
});
describe('With browser env isMac: true', () => {
beforeEach(() => {
window.gl = { client: { isMac: true } };
});
it.each([
['mod', '<kbd>⌘</kbd>'],
['command', '<kbd>⌘</kbd>'],
['meta', '<kbd>⌘</kbd>'],
['option', '<kbd>⌥</kbd>'],
['alt', '<kbd>⌥</kbd>'],
])('renders platform specific key %p as: %p', (key, rendered) => {
expect(render([key])).toEqual(`<div>${rendered}</div>`);
});
it('does render Mac specific shortcuts', () => {
expect(render(['command+[', 'ctrl+k'])).toEqual(
`<div><kbd>⌘</kbd> + <kbd>[</kbd> or <br><kbd>Ctrl</kbd> + <kbd>k</kbd></div>`,
);
});
});
describe('With browser env isMac: false', () => {
beforeEach(() => {
window.gl = { client: { isMac: false } };
});
it.each([
['mod', '<kbd>Ctrl</kbd>'],
['command', ''],
['meta', ''],
['option', '<kbd>Alt</kbd>'],
['alt', '<kbd>Alt</kbd>'],
])('renders platform specific key %p as: %p', (key, rendered) => {
expect(render([key])).toEqual(`<div>${rendered}</div>`);
});
it('does not render Mac specific shortcuts', () => {
expect(render(['command+[', 'ctrl+k'])).toEqual(`<div><kbd>Ctrl</kbd> + <kbd>k</kbd></div>`);
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment