1import React from 'react';
2import { css } from '@emotion/css';
3import { GrafanaTheme2 } from '@grafana/data';
4import { Modal, useStyles2 } from '@grafana/ui';
5
6const shortcuts = {
7  Global: [
8    { keys: ['g', 'h'], description: 'Go to Home Dashboard' },
9    { keys: ['g', 'p'], description: 'Go to Profile' },
10    { keys: ['s', 'o'], description: 'Open search' },
11    { keys: ['esc'], description: 'Exit edit/setting views' },
12  ],
13  Dashboard: [
14    { keys: ['mod+s'], description: 'Save dashboard' },
15    { keys: ['d', 'r'], description: 'Refresh all panels' },
16    { keys: ['d', 's'], description: 'Dashboard settings' },
17    { keys: ['d', 'v'], description: 'Toggle in-active / view mode' },
18    { keys: ['d', 'k'], description: 'Toggle kiosk mode (hides top nav)' },
19    { keys: ['d', 'E'], description: 'Expand all rows' },
20    { keys: ['d', 'C'], description: 'Collapse all rows' },
21    { keys: ['d', 'a'], description: 'Toggle auto fit panels (experimental feature)' },
22    { keys: ['mod+o'], description: 'Toggle shared graph crosshair' },
23    { keys: ['d', 'l'], description: 'Toggle all panel legends' },
24  ],
25  'Focused Panel': [
26    { keys: ['e'], description: 'Toggle panel edit view' },
27    { keys: ['v'], description: 'Toggle panel fullscreen view' },
28    { keys: ['p', 's'], description: 'Open Panel Share Modal' },
29    { keys: ['p', 'd'], description: 'Duplicate Panel' },
30    { keys: ['p', 'r'], description: 'Remove Panel' },
31    { keys: ['p', 'l'], description: 'Toggle panel legend' },
32  ],
33  'Time Range': [
34    { keys: ['t', 'z'], description: 'Zoom out time range' },
35    {
36      keys: ['t', '←'],
37      description: 'Move time range back',
38    },
39    {
40      keys: ['t', '→'],
41      description: 'Move time range forward',
42    },
43  ],
44};
45
46export interface HelpModalProps {
47  onDismiss: () => void;
48}
49
50export const HelpModal = ({ onDismiss }: HelpModalProps): JSX.Element => {
51  const styles = useStyles2(getStyles);
52  return (
53    <Modal title="Shortcuts" isOpen onDismiss={onDismiss} onClickBackdrop={onDismiss}>
54      <div className={styles.titleDescription}>
55        <span className={styles.shortcutTableKey}>mod</span> =<span> CTRL on windows or linux and CMD key on Mac</span>
56      </div>
57      <div className={styles.categories}>
58        {Object.entries(shortcuts).map(([category, shortcuts], i) => (
59          <div className={styles.shortcutCategory} key={i}>
60            <table className={styles.shortcutTable}>
61              <tbody>
62                <tr>
63                  <th className={styles.shortcutTableCategoryHeader} colSpan={2}>
64                    {category}
65                  </th>
66                </tr>
67                {shortcuts.map((shortcut, j) => (
68                  <tr key={`${i}-${j}`}>
69                    <td className={styles.shortcutTableKeys}>
70                      {shortcut.keys.map((key, k) => (
71                        <span className={styles.shortcutTableKey} key={`${i}-${j}-${k}`}>
72                          {key}
73                        </span>
74                      ))}
75                    </td>
76                    <td className={styles.shortcutTableDescription}>{shortcut.description}</td>
77                  </tr>
78                ))}
79              </tbody>
80            </table>
81          </div>
82        ))}
83      </div>
84    </Modal>
85  );
86};
87
88function getStyles(theme: GrafanaTheme2) {
89  return {
90    titleDescription: css`
91      font-size: ${theme.typography.bodySmall.fontSize};
92      font-weight: ${theme.typography.bodySmall.fontWeight};
93      color: ${theme.colors.text.disabled};
94      padding-bottom: ${theme.spacing(2)};
95    `,
96    categories: css`
97      font-size: ${theme.typography.bodySmall.fontSize};
98      display: flex;
99      flex-flow: row wrap;
100      justify-content: space-between;
101      align-items: flex-start;
102    `,
103    shortcutCategory: css`
104      width: 50%;
105      font-size: ${theme.typography.bodySmall.fontSize};
106    `,
107    shortcutTable: css`
108      margin-bottom: ${theme.spacing(2)};
109    `,
110    shortcutTableCategoryHeader: css`
111      font-weight: normal;
112      font-size: ${theme.typography.h6.fontSize};
113      text-align: left;
114    `,
115    shortcutTableDescription: css`
116      text-align: left;
117      color: ${theme.colors.text.disabled};
118      width: 99%;
119      padding: ${theme.spacing(1, 2)};
120    `,
121    shortcutTableKeys: css`
122      white-space: nowrap;
123      width: 1%;
124      text-align: right;
125      color: ${theme.colors.text.primary};
126    `,
127    shortcutTableKey: css`
128      display: inline-block;
129      text-align: center;
130      margin-right: ${theme.spacing(0.5)};
131      padding: 3px 5px;
132      font: 11px Consolas, 'Liberation Mono', Menlo, Courier, monospace;
133      line-height: 10px;
134      vertical-align: middle;
135      border: solid 1px ${theme.colors.border.medium};
136      border-radius: ${theme.shape.borderRadius(3)};
137      color: ${theme.colors.text.primary};
138      background-color: ${theme.colors.background.secondary};
139    `,
140  };
141}
142