Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
f00e94ca
Commit
f00e94ca
authored
May 07, 2021
by
Lukas 'Eipi' Eipert
Committed by
Nathan Friend
May 07, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make keyboard shortcut help dynamic
parent
9b466bb0
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
323 additions
and
562 deletions
+323
-562
app/assets/javascripts/behaviors/shortcuts/keybindings.js
app/assets/javascripts/behaviors/shortcuts/keybindings.js
+1
-1
app/assets/javascripts/behaviors/shortcuts/shortcut.vue
app/assets/javascripts/behaviors/shortcuts/shortcut.vue
+80
-0
app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue
...assets/javascripts/behaviors/shortcuts/shortcuts_help.vue
+74
-500
app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue
...sets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue
+2
-4
app/assets/stylesheets/bootstrap_migration.scss
app/assets/stylesheets/bootstrap_migration.scss
+0
-4
app/assets/stylesheets/framework.scss
app/assets/stylesheets/framework.scss
+1
-0
app/assets/stylesheets/framework/dropdowns.scss
app/assets/stylesheets/framework/dropdowns.scss
+0
-9
app/assets/stylesheets/framework/kbd.scss
app/assets/stylesheets/framework/kbd.scss
+15
-0
app/assets/stylesheets/framework/typography.scss
app/assets/stylesheets/framework/typography.scss
+0
-16
app/assets/stylesheets/pages/help.scss
app/assets/stylesheets/pages/help.scss
+22
-22
changelogs/unreleased/leipert-dynamic-kbd-help.yml
changelogs/unreleased/leipert-dynamic-kbd-help.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+27
-6
spec/frontend/behaviors/shortcuts/shortcut_spec.js
spec/frontend/behaviors/shortcuts/shortcut_spec.js
+96
-0
No files found.
app/assets/javascripts/behaviors/shortcuts/keybindings.js
View file @
f00e94ca
...
...
@@ -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
,
};
...
...
app/assets/javascripts/behaviors/shortcuts/shortcut.vue
0 → 100644
View file @
f00e94ca
<
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
>
app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue
View file @
f00e94ca
<
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
'
;
},
onDotCom
()
{
return
window
.
gon
.
dot_com
;
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
);
},
},
i18n
:
{
title
:
__
(
`Keyboard shortcuts`
),
search
:
s__
(
`KeyboardShortcuts|Search keyboard shortcuts`
),
noMatch
:
s__
(
`KeyboardShortcuts|No shortcuts matched your search`
),
},
};
</
script
>
<
template
>
<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>
<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>
<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>
<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
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>
</section>
</div>
</gl-modal>
</
template
>
app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue
View file @
f00e94ca
...
...
@@ -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
>
app/assets/stylesheets/bootstrap_migration.scss
View file @
f00e94ca
...
...
@@ -105,10 +105,6 @@ hr {
}
}
kbd
{
display
:
inline-block
;
}
code
{
padding
:
2px
4px
;
color
:
$code-color
;
...
...
app/assets/stylesheets/framework.scss
View file @
f00e94ca
...
...
@@ -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'
;
...
...
app/assets/stylesheets/framework/dropdowns.scss
View file @
f00e94ca
...
...
@@ -266,15 +266,6 @@
}
}
.shortcut-mappings
{
display
:
none
;
}
&
.shortcuts
.shortcut-mappings
{
display
:
inline-block
;
margin-right
:
5px
;
}
ul
{
margin
:
0
;
padding
:
0
;
...
...
app/assets/stylesheets/framework/kbd.scss
0 → 100644
View file @
f00e94ca
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
;
}
app/assets/stylesheets/framework/typography.scss
View file @
f00e94ca
...
...
@@ -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
;
...
...
app/assets/stylesheets/pages/help.scss
View file @
f00e94ca
.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
:
righ
t
;
white-space
:
nowrap
;
kbd
{
margin
:
0
.1rem
0
;
line-height
:
unset
;
font-size
:
unse
t
;
}
}
}
...
...
changelogs/unreleased/leipert-dynamic-kbd-help.yml
0 → 100644
View file @
f00e94ca
---
title
:
"
Update
Keyboard
shortcut
help:
adding
search,
update
styling"
merge_request
:
56400
author
:
type
:
changed
locale/gitlab.pot
View file @
f00e94ca
...
...
@@ -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 s
idebar
"
msgid "Toggle s
hortcuts
"
msgstr ""
msgid "Toggle
the Performance B
ar"
msgid "Toggle
sideb
ar"
msgstr ""
msgid "Toggle th
is dialog
"
msgid "Toggle th
e Performance Bar
"
msgstr ""
msgid "Toggle thread"
...
...
@@ -38934,6 +38952,9 @@ msgstr ""
msgid "the wiki"
msgstr ""
msgid "then"
msgstr ""
msgid "this document"
msgstr ""
...
...
spec/frontend/behaviors/shortcuts/shortcut_spec.js
0 → 100644
View file @
f00e94ca
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>`
);
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment