mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Navigation: Add keyboard shortcut to search input (#62116)
* Show shortcut * add icon to search bar, make same changes in search modal * rename to modKey Co-authored-by: joshhunt <josh@trtr.co>
This commit is contained in:
parent
8f06784449
commit
a77c342764
@ -1,12 +1,13 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { useKBar, VisualState } from 'kbar';
|
import { useKBar, VisualState } from 'kbar';
|
||||||
import React, { useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { getInputStyles, Icon, ToolbarButton, useStyles2, useTheme2 } from '@grafana/ui';
|
import { getInputStyles, Icon, ToolbarButton, useStyles2, useTheme2 } from '@grafana/ui';
|
||||||
import { focusCss } from '@grafana/ui/src/themes/mixins';
|
import { focusCss } from '@grafana/ui/src/themes/mixins';
|
||||||
import { useMediaQueryChange } from 'app/core/hooks/useMediaQueryChange';
|
import { useMediaQueryChange } from 'app/core/hooks/useMediaQueryChange';
|
||||||
import { t } from 'app/core/internationalization';
|
import { t } from 'app/core/internationalization';
|
||||||
|
import { getModKey } from 'app/core/utils/browser';
|
||||||
|
|
||||||
export function TopSearchBarCommandPaletteTrigger() {
|
export function TopSearchBarCommandPaletteTrigger() {
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
@ -44,8 +45,13 @@ export function TopSearchBarCommandPaletteTrigger() {
|
|||||||
return <PretendTextInput onClick={onOpenSearch} />;
|
return <PretendTextInput onClick={onOpenSearch} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function PretendTextInput({ onClick }: { onClick: () => void }) {
|
interface PretendTextInputProps {
|
||||||
|
onClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function PretendTextInput({ onClick }: PretendTextInputProps) {
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
const modKey = useMemo(() => getModKey(), []);
|
||||||
|
|
||||||
// We want the desktop command palette trigger to look like a search box,
|
// We want the desktop command palette trigger to look like a search box,
|
||||||
// but it actually behaves like a button - you active it and it performs an
|
// but it actually behaves like a button - you active it and it performs an
|
||||||
@ -61,6 +67,11 @@ function PretendTextInput({ onClick }: { onClick: () => void }) {
|
|||||||
<button className={styles.fakeInput} onClick={onClick}>
|
<button className={styles.fakeInput} onClick={onClick}>
|
||||||
{t('nav.search.placeholder', 'Search Grafana')}
|
{t('nav.search.placeholder', 'Search Grafana')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div className={styles.suffix}>
|
||||||
|
<Icon name="keyboard" />
|
||||||
|
<span className={styles.shortcut}>{modKey}+k</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -73,6 +84,16 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
wrapper: baseStyles.wrapper,
|
wrapper: baseStyles.wrapper,
|
||||||
inputWrapper: baseStyles.inputWrapper,
|
inputWrapper: baseStyles.inputWrapper,
|
||||||
prefix: baseStyles.prefix,
|
prefix: baseStyles.prefix,
|
||||||
|
suffix: css([
|
||||||
|
baseStyles.suffix,
|
||||||
|
{
|
||||||
|
display: 'flex',
|
||||||
|
gap: theme.spacing(0.5),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
shortcut: css({
|
||||||
|
fontSize: theme.typography.bodySmall.fontSize,
|
||||||
|
}),
|
||||||
fakeInput: css([
|
fakeInput: css([
|
||||||
baseStyles.input,
|
baseStyles.input,
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Modal, useStyles2 } from '@grafana/ui';
|
import { Modal, useStyles2 } from '@grafana/ui';
|
||||||
|
import { getModKey } from 'app/core/utils/browser';
|
||||||
|
|
||||||
const shortcuts = {
|
const getShortcuts = (modKey: string) => ({
|
||||||
Global: [
|
Global: [
|
||||||
{ keys: ['g', 'h'], description: 'Go to Home Dashboard' },
|
{ keys: ['g', 'h'], description: 'Go to Home Dashboard' },
|
||||||
{ keys: ['g', 'e'], description: 'Go to Explore' },
|
{ keys: ['g', 'e'], description: 'Go to Explore' },
|
||||||
@ -12,11 +13,11 @@ const shortcuts = {
|
|||||||
{ keys: ['s', 'o'], description: 'Open search' },
|
{ keys: ['s', 'o'], description: 'Open search' },
|
||||||
{ keys: ['esc'], description: 'Exit edit/setting views' },
|
{ keys: ['esc'], description: 'Exit edit/setting views' },
|
||||||
{ keys: ['h'], description: 'Show all keyboard shortcuts' },
|
{ keys: ['h'], description: 'Show all keyboard shortcuts' },
|
||||||
{ keys: ['mod+k'], description: 'Open command palette' },
|
{ keys: [`${modKey}+k`], description: 'Open command palette' },
|
||||||
{ keys: ['c', 't'], description: 'Change theme' },
|
{ keys: ['c', 't'], description: 'Change theme' },
|
||||||
],
|
],
|
||||||
Dashboard: [
|
Dashboard: [
|
||||||
{ keys: ['mod+s'], description: 'Save dashboard' },
|
{ keys: [`${modKey}+s`], description: 'Save dashboard' },
|
||||||
{ keys: ['d', 'r'], description: 'Refresh all panels' },
|
{ keys: ['d', 'r'], description: 'Refresh all panels' },
|
||||||
{ keys: ['d', 's'], description: 'Dashboard settings' },
|
{ keys: ['d', 's'], description: 'Dashboard settings' },
|
||||||
{ keys: ['d', 'v'], description: 'Toggle in-active / view mode' },
|
{ keys: ['d', 'v'], description: 'Toggle in-active / view mode' },
|
||||||
@ -24,7 +25,7 @@ const shortcuts = {
|
|||||||
{ keys: ['d', 'E'], description: 'Expand all rows' },
|
{ keys: ['d', 'E'], description: 'Expand all rows' },
|
||||||
{ keys: ['d', 'C'], description: 'Collapse all rows' },
|
{ keys: ['d', 'C'], description: 'Collapse all rows' },
|
||||||
{ keys: ['d', 'a'], description: 'Toggle auto fit panels (experimental feature)' },
|
{ keys: ['d', 'a'], description: 'Toggle auto fit panels (experimental feature)' },
|
||||||
{ keys: ['mod+o'], description: 'Toggle shared graph crosshair' },
|
{ keys: [`${modKey}+o`], description: 'Toggle shared graph crosshair' },
|
||||||
{ keys: ['d', 'l'], description: 'Toggle all panel legends' },
|
{ keys: ['d', 'l'], description: 'Toggle all panel legends' },
|
||||||
],
|
],
|
||||||
'Focused Panel': [
|
'Focused Panel': [
|
||||||
@ -50,7 +51,7 @@ const shortcuts = {
|
|||||||
description: 'Make time range absolute/permanent',
|
description: 'Make time range absolute/permanent',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
});
|
||||||
|
|
||||||
export interface HelpModalProps {
|
export interface HelpModalProps {
|
||||||
onDismiss: () => void;
|
onDismiss: () => void;
|
||||||
@ -58,11 +59,10 @@ export interface HelpModalProps {
|
|||||||
|
|
||||||
export const HelpModal = ({ onDismiss }: HelpModalProps): JSX.Element => {
|
export const HelpModal = ({ onDismiss }: HelpModalProps): JSX.Element => {
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
const modKey = useMemo(() => getModKey(), []);
|
||||||
|
const shortcuts = useMemo(() => getShortcuts(modKey), [modKey]);
|
||||||
return (
|
return (
|
||||||
<Modal title="Shortcuts" isOpen onDismiss={onDismiss} onClickBackdrop={onDismiss}>
|
<Modal title="Shortcuts" isOpen onDismiss={onDismiss} onClickBackdrop={onDismiss}>
|
||||||
<div className={styles.titleDescription}>
|
|
||||||
<span className={styles.shortcutTableKey}>mod</span> =<span> CTRL on windows or linux and CMD key on Mac</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.categories}>
|
<div className={styles.categories}>
|
||||||
{Object.entries(shortcuts).map(([category, shortcuts], i) => (
|
{Object.entries(shortcuts).map(([category, shortcuts], i) => (
|
||||||
<div className={styles.shortcutCategory} key={i}>
|
<div className={styles.shortcutCategory} key={i}>
|
||||||
|
@ -32,3 +32,12 @@ export function checkBrowserCompatibility() {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function userAgentIsApple() {
|
||||||
|
const appleRe = /(iPhone|iPad|Mac)/;
|
||||||
|
return appleRe.test(navigator.platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getModKey() {
|
||||||
|
return userAgentIsApple() ? 'cmd' : 'ctrl';
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user