From 4a2eeb85b6d480da5f9b96305465e26d91c3a1aa Mon Sep 17 00:00:00 2001 From: Revanshu Paliwal Date: Tue, 6 Feb 2024 10:26:10 +0100 Subject: [PATCH] SONAR-21566 Migrate keyboard shortcut modal to new UI --- .../src/components/KeyboardHintKeys.tsx | 15 +- .../__snapshots__/KeyboardHint-test.tsx.snap | 36 ++- .../KeyboardHintKeys-test.tsx.snap | 38 +-- .../design-system/src/helpers/index.ts | 1 + .../app/components/KeyboardShortcutsModal.tsx | 281 ++++++++++-------- .../__tests__/KeyboardShortcutsModal-test.tsx | 2 +- .../resources/org/sonar/l10n/core.properties | 60 ++-- 7 files changed, 246 insertions(+), 187 deletions(-) diff --git a/server/sonar-web/design-system/src/components/KeyboardHintKeys.tsx b/server/sonar-web/design-system/src/components/KeyboardHintKeys.tsx index 84cf5e12a5e..44ac3e6c4ba 100644 --- a/server/sonar-web/design-system/src/components/KeyboardHintKeys.tsx +++ b/server/sonar-web/design-system/src/components/KeyboardHintKeys.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import styled from '@emotion/styled'; +import classNames from 'classnames'; import tw from 'twin.macro'; import { themeColor, themeContrast } from '../helpers'; import { Key } from '../helpers/keyboard'; @@ -35,6 +36,8 @@ export const mappedKeys = { [Key.Click]: 'click', }; +const NON_KEY_SYMBOLS = ['+', ' ']; + export function KeyboardHintKeys({ command }: { command: string }) { const keys = command .trim() @@ -42,11 +45,19 @@ export function KeyboardHintKeys({ command }: { command: string }) { .map((key, index) => { const uniqueKey = `${key}-${index}`; - if (!(Object.keys(mappedKeys).includes(key) || Object.values(mappedKeys).includes(key))) { + if (NON_KEY_SYMBOLS.includes(key)) { return {key}; } - return {mappedKeys[key as keyof typeof mappedKeys] || key}; + const isNonMappedKey = !( + Object.keys(mappedKeys).includes(key) || Object.values(mappedKeys).includes(key) + ); + + return ( + + {Object.keys(mappedKeys).includes(key) ? mappedKeys[key as keyof typeof mappedKeys] : key} + + ); }); return
{keys}
; diff --git a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHint-test.tsx.snap b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHint-test.tsx.snap index 798c34a273f..a45b1d68bd8 100644 --- a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHint-test.tsx.snap +++ b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHint-test.tsx.snap @@ -46,12 +46,12 @@ exports[`renders on mac 1`] = ` class="sw-flex sw-gap-1" > ⌘ ⌥ @@ -106,12 +106,12 @@ exports[`renders on windows 1`] = ` class="sw-flex sw-gap-1" > Ctrl Alt @@ -138,6 +138,26 @@ exports[`renders with command 1`] = ` color: rgb(106,117,144); } +.emotion-2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + padding-left: 0.125rem; + padding-right: 0.125rem; + border-radius: 0.125rem; + background-color: rgb(225,230,243); + color: rgb(62,67,87); +} +
- + command
@@ -204,7 +226,7 @@ exports[`renders with title 1`] = ` class="sw-flex sw-gap-1" > click @@ -259,7 +281,7 @@ exports[`renders without title 1`] = ` class="sw-flex sw-gap-1" > click diff --git a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHintKeys-test.tsx.snap b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHintKeys-test.tsx.snap index 337d1b9b385..d1ec21d7864 100644 --- a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHintKeys-test.tsx.snap +++ b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHintKeys-test.tsx.snap @@ -26,7 +26,7 @@ exports[`should render Alt 1`] = ` class="sw-flex sw-gap-1" > Alt @@ -60,7 +60,7 @@ exports[`should render ArrowDown 1`] = ` class="sw-flex sw-gap-1" > click @@ -286,7 +286,7 @@ exports[`should render Command 1`] = ` class="sw-flex sw-gap-1" > ⌘ @@ -320,7 +320,7 @@ exports[`should render Control 1`] = ` class="sw-flex sw-gap-1" > Ctrl @@ -354,7 +354,7 @@ exports[`should render Option 1`] = ` class="sw-flex sw-gap-1" > ⌥ @@ -388,7 +388,7 @@ exports[`should render a default text if no keys match 1`] = ` class="sw-flex sw-gap-1" > Ctrl @@ -396,7 +396,7 @@ exports[`should render a default text if no keys match 1`] = ` + click @@ -429,11 +429,13 @@ exports[`should render multiple keys 1`] = `
- + Use Ctrl @@ -441,7 +443,7 @@ exports[`should render multiple keys 1`] = ` + Ctrl @@ -516,7 +518,7 @@ exports[`should render multiple keys with non-key symbols 1`] = ` +
-

{translate('keyboard_shortcuts', category, 'title')}

- - - - - - - - - {shortcuts.map(({ action, keys }) => ( - - - - - ))} - -
{translate('keyboard_shortcuts.shortcut')}{translate('keyboard_shortcuts.action')}
- {keys.map((k) => - k === '+' ? ( - - {k} - - ) : ( - - {k} - - ), - )} - {translate('keyboard_shortcuts', category, action)}
-
- ))} - - ); +const FILE_ROWS = [ + { + command: `${Key.ArrowUp} ${Key.ArrowDown}`, + description: 'keyboard_shortcuts_modal.code_page.select_files', + }, + { + command: `${Key.ArrowRight}`, + description: 'keyboard_shortcuts_modal.code_page.open_file', + }, + { + command: `${Key.ArrowLeft}`, + description: 'keyboard_shortcuts_modal.return_back_to_the_list', + }, +]; + +export const SECTIONS: Array
= [ + { + rows: [ + { + command: 's', + description: 'keyboard_shortcuts_modal.global.open_search_bar', + }, + { + command: '?', + description: 'keyboard_shortcuts_modal.global.open_keyboard_shortcuts_modal', + }, + ], + subTitle: 'keyboard_shortcuts_modal.global', + }, + + { + rows: [ + { + command: `${Key.ArrowUp} ${Key.ArrowDown}`, + description: 'keyboard_shortcuts_modal.navigate_between_issues', + }, + { + command: `${Key.ArrowRight}`, + description: 'keyboard_shortcuts_modal.open_issue', + }, + { + command: `${Key.ArrowLeft}`, + description: 'keyboard_shortcuts_modal.return_back_to_the_list', + }, + { + command: `${Key.Alt} + ${Key.ArrowUp} ${Key.ArrowDown}`, + description: 'keyboard_shortcuts_modal.issue_details_page.navigate_issue_locations', + }, + { + command: `${Key.Alt} + ${Key.ArrowLeft} ${Key.ArrowRight}`, + description: 'keyboard_shortcuts_modal.issue_details_page.switch_flows', + }, + { + command: 'f', + description: 'keyboard_shortcuts_modal.do_issue_transition', + }, + { + command: 'a', + description: 'keyboard_shortcuts_modal.assign_issue', + }, + { + command: 'm', + description: 'keyboard_shortcuts_modal.assign_issue_to_me', + }, + { + command: 't', + description: 'keyboard_shortcuts_modal.change_tags_of_issue', + }, + { + command: `${Key.Control} + ${Key.Enter}`, + description: 'keyboard_shortcuts_modal.issue_details_page.submit_comment', + }, + ], + subTitle: 'keyboard_shortcuts_modal.issues_page', + }, + + { + rows: FILE_ROWS, + subTitle: 'keyboard_shortcuts_modal.code_page', + }, + + { + rows: FILE_ROWS, + subTitle: 'keyboard_shortcuts_modal.measures_page', + }, + + { + rows: [ + { + command: `${Key.ArrowUp} ${Key.ArrowDown}`, + description: 'keyboard_shortcuts_modal.rules_page.navigate_between_rule', + }, + { + command: `${Key.ArrowRight}`, + description: 'keyboard_shortcuts_modal.rules_page.open_rule', + }, + { + command: `${Key.ArrowLeft}`, + description: 'keyboard_shortcuts_modal.return_back_to_the_list', + }, + ], + subTitle: 'keyboard_shortcuts_modal.rules_page', + }, +]; + +function renderSection() { + return SECTIONS.map((section) => ( +
+ {translate(section.subTitle)} + + {section.rows.map((row) => ( + + + + + {translate(row.description)} + + ))} +
+
+ )); } export default function KeyboardShortcutsModal() { @@ -158,31 +191,29 @@ export default function KeyboardShortcutsModal() { return null; } - const title = translate('keyboard_shortcuts.title'); + const title = translate('keyboard_shortcuts_modal.title'); + + const body = ( + <> + { + setDisplay(false); + return true; + }} + > + {translate('keyboard_shortcuts_modal.disable_link')} + +
{renderSection()}
+ + ); return ( - setDisplay(false)} size="medium"> -
-

{title}

- { - setDisplay(false); - return true; - }} - > - {translate('keyboard_shortcuts.disable_link')} - -
- -
-
{renderShortcuts(CATEGORIES.left)}
-
{renderShortcuts(CATEGORIES.right)}
-
- -
- -
-
+ setDisplay(false)} + body={body} + secondaryButtonLabel={translate('close')} + /> ); } diff --git a/server/sonar-web/src/main/js/app/components/__tests__/KeyboardShortcutsModal-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/KeyboardShortcutsModal-test.tsx index 78cd1cc3c7f..e7830580862 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/KeyboardShortcutsModal-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/KeyboardShortcutsModal-test.tsx @@ -69,7 +69,7 @@ function renderKeyboardShortcutsModal() { } const ui = { - modalTitle: byRole('heading', { name: 'keyboard_shortcuts.title' }), + modalTitle: byRole('heading', { name: 'keyboard_shortcuts_modal.title' }), closeButton: byRole('button', { name: 'close' }), textInput: byRole('textbox'), diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 84fb6571a6b..3f1fccb3184 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3454,40 +3454,32 @@ formatting.example.link.example=[link label](https://www.domain.com) # KEYBOARD SHORTCUTS # #------------------------------------------------------------------------------ - -keyboard_shortcuts.title=Keyboard Shortcuts -keyboard_shortcuts.disable_link=Disable shortcuts -keyboard_shortcuts.shortcut=Shortcut -keyboard_shortcuts.action=Action -keyboard_shortcuts.global.title=Global -keyboard_shortcuts.global.search=Open the search bar -keyboard_shortcuts.global.open_shortcuts=Open this panel -keyboard_shortcuts.code_page.title=Code Page -keyboard_shortcuts.code_page.select_files=Select files -keyboard_shortcuts.code_page.open_file=Open the selected file -keyboard_shortcuts.code_page.back=Return back to the list -keyboard_shortcuts.issues_page.title=Issues Page -keyboard_shortcuts.issues_page.navigate=navigate between issues -keyboard_shortcuts.issues_page.source_code=go from the list of issues to the source code -keyboard_shortcuts.issues_page.back=return back to the list -keyboard_shortcuts.issues_page.navigate_locations=to navigate issue locations -keyboard_shortcuts.issues_page.switch_flows=to switch flows -keyboard_shortcuts.issues_page.transition=do an issue transition -keyboard_shortcuts.issues_page.assign=assign issue -keyboard_shortcuts.issues_page.assign_to_me=assign issue to the current user -keyboard_shortcuts.issues_page.severity=change severity of issue -keyboard_shortcuts.issues_page.comment=comment issue -keyboard_shortcuts.issues_page.submit_comment=submit comment -keyboard_shortcuts.issues_page.tags=change tags of issue -keyboard_shortcuts.measures_page.title=Measures Page -keyboard_shortcuts.measures_page.select_files=Select files -keyboard_shortcuts.measures_page.open_file=Open the selected file -keyboard_shortcuts.measures_page.back=Return back to the list -keyboard_shortcuts.rules_page.title=Rules Page -keyboard_shortcuts.rules_page.navigate=navigate between rules -keyboard_shortcuts.rules_page.rule_details=go from the list of rules to the rule details -keyboard_shortcuts.rules_page.back=Return back to the list - +keyboard_shortcuts_modal.title=Keyboard Shortcuts +keyboard_shortcuts_modal.disable_link=Disable shortcuts +keyboard_shortcuts_modal.description= You can use the following shortcuts when navigating within SonarCloud +keyboard_shortcuts_modal.global= Global +keyboard_shortcuts_modal.global.open_search_bar= Open search bar +keyboard_shortcuts_modal.global.open_keyboard_shortcuts_modal= Open keyboard shortcuts modal +keyboard_shortcuts_modal.navigate_between_issues= Navigate between issues +keyboard_shortcuts_modal.open_issue= Open issue +keyboard_shortcuts_modal.return_back_to_the_list= Return back to the list +keyboard_shortcuts_modal.do_issue_transition= Do an issue transition +keyboard_shortcuts_modal.assign_issue= Assign issue +keyboard_shortcuts_modal.assign_issue_to_me= Assign issue to me +keyboard_shortcuts_modal.change_tags_of_issue= Change tags of issue +keyboard_shortcuts_modal.select_an_issue= Select an issue +keyboard_shortcuts_modal.issues_page= Issues page +keyboard_shortcuts_modal.issue_details_page.navigate_issue_locations= To navigate issue locations +keyboard_shortcuts_modal.issue_details_page.switch_flows= To switch flows +keyboard_shortcuts_modal.issue_details_page.comment_an_issue= Comment an issue +keyboard_shortcuts_modal.issue_details_page.submit_comment= Submit comment +keyboard_shortcuts_modal.code_page= Code page +keyboard_shortcuts_modal.code_page.select_files= Select files +keyboard_shortcuts_modal.code_page.open_file= Open file +keyboard_shortcuts_modal.measures_page= Measures page +keyboard_shortcuts_modal.rules_page= Rules page +keyboard_shortcuts_modal.rules_page.navigate_between_rule= Navigate between rules +keyboard_shortcuts_modal.rules_page.open_rule= Open rule #------------------------------------------------------------------------------ # -- 2.39.5