From b2092aec00e2f66dba5d25a56aab38a4406a3bf1 Mon Sep 17 00:00:00 2001 From: Katie George Date: Wed, 20 Nov 2024 12:51:56 -0800 Subject: [PATCH 1/6] feat: Adds basic page and 3 shortcuts --- .../keyboard-shortcut-hackathon/demo.page.tsx | 227 ++++++++++++++++++ .../keyboard-shortcut-hackathon/kvp-table.tsx | 32 +++ pages/keyboard-shortcut-hackathon/styles.scss | 23 ++ 3 files changed, 282 insertions(+) create mode 100644 pages/keyboard-shortcut-hackathon/demo.page.tsx create mode 100644 pages/keyboard-shortcut-hackathon/kvp-table.tsx create mode 100644 pages/keyboard-shortcut-hackathon/styles.scss diff --git a/pages/keyboard-shortcut-hackathon/demo.page.tsx b/pages/keyboard-shortcut-hackathon/demo.page.tsx new file mode 100644 index 0000000000..c688a97fff --- /dev/null +++ b/pages/keyboard-shortcut-hackathon/demo.page.tsx @@ -0,0 +1,227 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React, { useContext, useEffect, useRef, useState } from 'react'; + +import { AppLayout, ContentLayout, Drawer, Header, SpaceBetween, SplitPanel } from '~components'; +import { AppLayoutProps } from '~components/app-layout'; + +import AppContext, { AppContextType } from '../app/app-context'; +import { Breadcrumbs, Containers } from '../app-layout/utils/content-blocks'; +import { drawerLabels } from '../app-layout/utils/drawers'; +import appLayoutLabels from '../app-layout/utils/labels'; +import ScreenshotArea from '../utils/screenshot-area'; +import KeyValuePairTable from './kvp-table'; + +import styles from '../app-layout/styles.scss'; + +type DemoContext = React.Context< + AppContextType<{ + hasDrawers: boolean | undefined; + splitPanelPosition: AppLayoutProps.SplitPanelPreferences['position']; + disableContentPaddings: boolean | undefined; + }> +>; + +export default function WithDrawers() { + const { urlParams, setUrlParams } = useContext(AppContext as DemoContext); + const [activeDrawerId, setActiveDrawerId] = useState('keyboard-shortcuts'); + + const [splitPanelOpen, setSplitPanelOpen] = useState(true); + const [navigationOpen, setNavigationOpen] = useState(true); + + const disableContentPaddings = urlParams.disableContentPaddings ?? false; + const appLayoutRef = useRef(null); + + useEffect(() => { + const handleKeyDown = (event: any) => { + if (event.key === ' ') { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + if (activeDrawerId !== null) { + setActiveDrawerId(null); + } else if (activeDrawerId === null) { + setActiveDrawerId('keyboard-shortcuts'); + } + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [activeDrawerId]); + + useEffect(() => { + const handleKeyDown = (event: any) => { + if (event.key === 'h') { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + if (activeDrawerId !== null) { + setActiveDrawerId(null); + } else if (activeDrawerId === null) { + setActiveDrawerId('keyboard-shortcuts'); + } + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [activeDrawerId]); + + useEffect(() => { + const handleKeyDown = (event: any) => { + if (event.key === 's') { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + setSplitPanelOpen(!splitPanelOpen); + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [splitPanelOpen]); + + useEffect(() => { + const handleKeyDown = (event: any) => { + if (event.key === 'n') { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + setNavigationOpen(!navigationOpen); + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [navigationOpen]); + + return ( + + } + content={ + +
+ Testing Keyboard shortcuts +
+ + } + > + +
+ } + splitPanelPreferences={{ + position: urlParams.splitPanelPosition, + }} + onSplitPanelPreferencesChange={event => { + const { position } = event.detail; + setUrlParams({ splitPanelPosition: position === 'side' ? position : undefined }); + }} + disableContentPaddings={disableContentPaddings} + splitPanelOpen={splitPanelOpen} + navigationOpen={navigationOpen} + splitPanel={ + + +
+
+
+ + + } + drawers={[ + { + ariaLabels: { + closeButton: `Close button`, + drawerName: `Keyboard shortcuts`, + triggerButton: `Trigger button`, + resizeHandle: `$Resize handle`, + }, + resizable: true, + defaultSize: 500, + content: ( + Keyboard shortcuts}> + + + ), + id: 'keyboard-shortcuts', + trigger: { + iconName: 'settings', + }, + }, + ]} + onDrawerChange={event => setActiveDrawerId(event.detail.activeDrawerId)} + activeDrawerId={activeDrawerId} + /> + + ); +} + +function DrawerContent() { + return ( + + + + + ); +} diff --git a/pages/keyboard-shortcut-hackathon/kvp-table.tsx b/pages/keyboard-shortcut-hackathon/kvp-table.tsx new file mode 100644 index 0000000000..7e6d56ef57 --- /dev/null +++ b/pages/keyboard-shortcut-hackathon/kvp-table.tsx @@ -0,0 +1,32 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React from 'react'; + +import { Box, ExpandableSection } from '~components'; + +import styles from './styles.scss'; + +interface KeyValuePairProps { + items: Array<{ + key: string; + value: string; + }>; + header?: string; +} + +function KeyValuePairTable(props: KeyValuePairProps) { + return ( + + {props.items.map((item, index) => ( +
+ {item.key} + +
{item.value}
+
+
+ ))} +
+ ); +} + +export default KeyValuePairTable; diff --git a/pages/keyboard-shortcut-hackathon/styles.scss b/pages/keyboard-shortcut-hackathon/styles.scss new file mode 100644 index 0000000000..32f89c2519 --- /dev/null +++ b/pages/keyboard-shortcut-hackathon/styles.scss @@ -0,0 +1,23 @@ +/* + Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: Apache-2.0 +*/ + +@use '~design-tokens' as awsui; + +.kvp { + display: flex; + justify-content: space-between; + padding-block: awsui.$space-scaled-s; + + &:not(:last-child) { + border-block-end: 1px solid awsui.$color-border-control-default; + } +} + +.shortcut { + background: awsui.$color-background-input-disabled; + padding-block: 2px; + padding-inline: 4px; + font-family: monospace; +} From 61c9826bb5ee646d4dc4e794336e4a493f182577 Mon Sep 17 00:00:00 2001 From: Katie George Date: Wed, 20 Nov 2024 15:22:52 -0800 Subject: [PATCH 2/6] feat: Adds more shortcuts --- pages/app/components/theme-switcher.tsx | 74 ++++++++++++++++++- .../keyboard-shortcut-hackathon/demo.page.tsx | 20 ++++- pages/keyboard-shortcut-hackathon/styles.scss | 2 +- 3 files changed, 91 insertions(+), 5 deletions(-) diff --git a/pages/app/components/theme-switcher.tsx b/pages/app/components/theme-switcher.tsx index 14e4322d23..fd3f22c9ab 100644 --- a/pages/app/components/theme-switcher.tsx +++ b/pages/app/components/theme-switcher.tsx @@ -1,6 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import React, { useContext } from 'react'; +import React, { useContext, useEffect } from 'react'; import { Density, Mode } from '@cloudscape-design/global-styles'; @@ -28,6 +28,78 @@ export default function ThemeSwitcher() { }; } + useEffect(() => { + let keyPressed: any = {}; + + const handleKeyDown = (e: any) => { + keyPressed[e.key + e.location] = true; + + if (keyPressed.Control1 === true && keyPressed.d0 === true) { + // Left shift+CONTROL pressed! + if (mode === 'dark') { + setMode(Mode.Light); + keyPressed = {}; // reset key map + } else if (mode === 'light') { + setMode(Mode.Dark); + keyPressed = {}; // reset key map + } + } + + if (keyPressed.Control1 === true && keyPressed.c0 === true) { + e.preventDefault(); + if (urlParams.density === 'comfortable') { + setUrlParams({ density: Density.Compact }); + } else if (urlParams.density === 'compact') { + setUrlParams({ density: Density.Comfortable }); + } + keyPressed = {}; // reset key map + } + + if (keyPressed.Control1 === true && keyPressed.m0 === true) { + e.preventDefault(); + setUrlParams({ motionDisabled: !urlParams.motionDisabled }); + keyPressed = {}; // reset key map + } + + if (keyPressed.Control1 === true && keyPressed.r0 === true) { + e.preventDefault(); + document.documentElement.setAttribute('dir', 'rtl'); + keyPressed = {}; // reset key map + } + + if (keyPressed.Control1 === true && keyPressed.l0 === true) { + e.preventDefault(); + document.documentElement.setAttribute('dir', 'ltr'); + keyPressed = {}; // reset key map + } + + if (keyPressed.Control1 === true && keyPressed.v0 === true) { + e.preventDefault(); + if (ALWAYS_VISUAL_REFRESH) { + setUrlParams({ visualRefresh: true }); + } else { + setUrlParams({ visualRefresh: !urlParams.visualRefresh }); + window.location.reload(); + } + keyPressed = {}; // reset key map + } + }; + + const handleKeyUp = (e: any) => { + keyPressed[e.key + e.location] = false; + + keyPressed = {}; + }; + + document.addEventListener('keydown', handleKeyDown); + document.addEventListener('keyup', handleKeyUp); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + document.removeEventListener('keyup', handleKeyUp); + }; + }, [mode, urlParams.density, urlParams.motionDisabled, urlParams.visualRefresh, setMode, setUrlParams]); + return ( } > @@ -223,8 +307,8 @@ function DrawerContent() { header="Panels" items={[ { - key: 'Toggle help panel', - value: 'h', + key: 'Toggle keyboard shortcuts', + value: '^ + /', }, { key: 'Toggle split panel', From 552160dadb0c7039db8bd85ab642bd44a4a4eae0 Mon Sep 17 00:00:00 2001 From: Katie George Date: Thu, 21 Nov 2024 11:43:27 -0800 Subject: [PATCH 4/6] feat: Adds keyboard shortcut page and inline table edit --- .../app-layout.tsx | 290 +++++++++++++++ .../keyboard-shortcut-hackathon/aws-logo.svg | 5 + .../keyboard-shortcut-hackathon/demo.page.tsx | 339 ++---------------- .../shortcut-page.page.tsx | 139 +++++++ .../unified-settings.tsx | 91 +++++ 5 files changed, 551 insertions(+), 313 deletions(-) create mode 100644 pages/keyboard-shortcut-hackathon/app-layout.tsx create mode 100644 pages/keyboard-shortcut-hackathon/aws-logo.svg create mode 100644 pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx create mode 100644 pages/keyboard-shortcut-hackathon/unified-settings.tsx diff --git a/pages/keyboard-shortcut-hackathon/app-layout.tsx b/pages/keyboard-shortcut-hackathon/app-layout.tsx new file mode 100644 index 0000000000..28a4d5b03c --- /dev/null +++ b/pages/keyboard-shortcut-hackathon/app-layout.tsx @@ -0,0 +1,290 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React, { useContext, useEffect, useRef, useState } from 'react'; + +import { AppLayout, ContentLayout, Drawer, Input, SpaceBetween, SplitPanel, TopNavigation } from '~components'; +import { AppLayoutProps } from '~components/app-layout'; + +import AppContext, { AppContextType } from '../app/app-context'; +import { drawerLabels } from '../app-layout/utils/drawers'; +import appLayoutLabels from '../app-layout/utils/labels'; +import ScreenshotArea from '../utils/screenshot-area'; +import AWSLogo from './aws-logo.svg'; +import KeyValuePairTable from './kvp-table'; + +import styles from '../app-layout/styles.scss'; + +type DemoContext = React.Context< + AppContextType<{ + hasDrawers: boolean | undefined; + splitPanelPosition: AppLayoutProps.SplitPanelPreferences['position']; + disableContentPaddings: boolean | undefined; + }> +>; + +export default function CustomAppLayout({ header, children }: any) { + const { urlParams, setUrlParams } = useContext(AppContext as DemoContext); + const [activeDrawerId, setActiveDrawerId] = useState(null); + + const [splitPanelOpen, setSplitPanelOpen] = useState(false); + const [navigationOpen, setNavigationOpen] = useState(false); + + const disableContentPaddings = urlParams.disableContentPaddings ?? false; + const appLayoutRef = useRef(null); + + useEffect(() => { + let keyPressed: any = {}; + + const handleKeyDown = (event: any) => { + keyPressed[event.key + event.location] = true; + + if (keyPressed.Control1 === true && keyPressed['/0'] === true) { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + if (activeDrawerId !== null) { + setActiveDrawerId(null); + } else if (activeDrawerId === null) { + setActiveDrawerId('keyboard-shortcuts'); + } + + keyPressed = {}; + } + console.log(keyPressed); + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [activeDrawerId]); + + useEffect(() => { + const handleKeyDown = (event: any) => { + if (event.key === 's') { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + setSplitPanelOpen(!splitPanelOpen); + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [splitPanelOpen]); + + useEffect(() => { + const handleKeyDown = (event: any) => { + if (event.key === 'n') { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + setNavigationOpen(!navigationOpen); + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [navigationOpen]); + + return ( + + + +
+ + } + utilities={[ + { + type: 'button', + iconName: 'notification', + title: 'Notifications', + ariaLabel: 'Notifications (unread)', + badge: true, + disableUtilityCollapse: false, + }, + { + type: 'menu-dropdown', + iconName: 'settings', + ariaLabel: 'Settings', + title: 'Settings', + onItemClick: event => { + if (event.detail.id === 'keyboard-shortcuts') { + setActiveDrawerId('keyboard-shortcuts'); + } + }, + items: [ + { + id: 'keyboard-shortcuts', + text: 'Keyboard shortcuts', + }, + ], + }, + { + type: 'menu-dropdown', + text: 'Customer Name', + description: 'email@example.com', + iconName: 'user-profile', + items: [ + { id: 'profile', text: 'Profile' }, + { id: 'preferences', text: 'Preferences' }, + { id: 'security', text: 'Security' }, + { + id: 'support-group', + text: 'Support', + items: [ + { + id: 'documentation', + text: 'Documentation', + href: '#', + external: true, + externalIconAriaLabel: ' (opens in new tab)', + }, + { id: 'support', text: 'Support' }, + { + id: 'feedback', + text: 'Feedback', + href: '#', + external: true, + externalIconAriaLabel: ' (opens in new tab)', + }, + ], + }, + { id: 'signout', text: 'Sign out' }, + ], + }, + ]} + /> + + {children} + + } + splitPanelPreferences={{ + position: urlParams.splitPanelPosition, + }} + onSplitPanelPreferencesChange={event => { + const { position } = event.detail; + setUrlParams({ splitPanelPosition: position === 'side' ? position : undefined }); + }} + disableContentPaddings={disableContentPaddings} + splitPanelOpen={splitPanelOpen} + onSplitPanelToggle={event => setSplitPanelOpen(event.detail.open)} + navigationOpen={navigationOpen} + onNavigationChange={event => setNavigationOpen(event.detail.open)} + splitPanel={ + + +
+
+
+ + + } + drawers={[ + { + ariaLabels: { + closeButton: `Close button`, + drawerName: `Keyboard shortcuts`, + triggerButton: `Trigger button`, + resizeHandle: `$Resize handle`, + }, + resizable: true, + defaultSize: 500, + content: ( + Keyboard shortcuts}> + + + ), + id: 'keyboard-shortcuts', + trigger: { + iconName: 'settings', + }, + }, + ]} + onDrawerChange={event => setActiveDrawerId(event.detail.activeDrawerId)} + activeDrawerId={activeDrawerId} + /> + + ); +} + +function DrawerContent() { + return ( + + + + + ); +} diff --git a/pages/keyboard-shortcut-hackathon/aws-logo.svg b/pages/keyboard-shortcut-hackathon/aws-logo.svg new file mode 100644 index 0000000000..9ed25f9dce --- /dev/null +++ b/pages/keyboard-shortcut-hackathon/aws-logo.svg @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/pages/keyboard-shortcut-hackathon/demo.page.tsx b/pages/keyboard-shortcut-hackathon/demo.page.tsx index 4414547865..d2f56e9017 100644 --- a/pages/keyboard-shortcut-hackathon/demo.page.tsx +++ b/pages/keyboard-shortcut-hackathon/demo.page.tsx @@ -1,325 +1,38 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import React, { useContext, useEffect, useRef, useState } from 'react'; +import React, { useState } from 'react'; -import { AppLayout, ContentLayout, Drawer, Header, SpaceBetween, SplitPanel, Toggle, TopNavigation } from '~components'; -import { AppLayoutProps } from '~components/app-layout'; +import { Header, SpaceBetween, Toggle } from '~components'; -import AppContext, { AppContextType } from '../app/app-context'; -import { Breadcrumbs, Containers } from '../app-layout/utils/content-blocks'; -import { drawerLabels } from '../app-layout/utils/drawers'; -import appLayoutLabels from '../app-layout/utils/labels'; -import ScreenshotArea from '../utils/screenshot-area'; -import KeyValuePairTable from './kvp-table'; +import CustomAppLayout from './app-layout'; +import UnifiedSettings from './unified-settings'; -import styles from '../app-layout/styles.scss'; - -type DemoContext = React.Context< - AppContextType<{ - hasDrawers: boolean | undefined; - splitPanelPosition: AppLayoutProps.SplitPanelPreferences['position']; - disableContentPaddings: boolean | undefined; - }> ->; - -export default function WithDrawers() { - const { urlParams, setUrlParams } = useContext(AppContext as DemoContext); - const [activeDrawerId, setActiveDrawerId] = useState('keyboard-shortcuts'); - - const [splitPanelOpen, setSplitPanelOpen] = useState(true); - const [navigationOpen, setNavigationOpen] = useState(true); +export default function Demo() { const [hideHeader, setHideHeader] = useState(false); - - const disableContentPaddings = urlParams.disableContentPaddings ?? false; - const appLayoutRef = useRef(null); - - useEffect(() => { - const handleKeyDown = (event: any) => { - if (event.key === ' ') { - // Check for spacebar press - event.preventDefault(); // Prevent default spacebar behavior - if (activeDrawerId !== null) { - setActiveDrawerId(null); - } else if (activeDrawerId === null) { - setActiveDrawerId('keyboard-shortcuts'); - } - } - }; - - document.addEventListener('keydown', handleKeyDown); - - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [activeDrawerId]); - - useEffect(() => { - let keyPressed: any = {}; - - const handleKeyDown = (event: any) => { - keyPressed[event.key + event.location] = true; - - if (keyPressed.Control1 === true && keyPressed['/0'] === true) { - // Check for spacebar press - event.preventDefault(); // Prevent default spacebar behavior - if (activeDrawerId !== null) { - setActiveDrawerId(null); - } else if (activeDrawerId === null) { - setActiveDrawerId('keyboard-shortcuts'); - } - - keyPressed = {}; - } - console.log(keyPressed); - }; - - document.addEventListener('keydown', handleKeyDown); - - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [activeDrawerId]); - - useEffect(() => { - const handleKeyDown = (event: any) => { - if (event.key === 's') { - // Check for spacebar press - event.preventDefault(); // Prevent default spacebar behavior - setSplitPanelOpen(!splitPanelOpen); - } - }; - - document.addEventListener('keydown', handleKeyDown); - - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [splitPanelOpen]); - - useEffect(() => { - const handleKeyDown = (event: any) => { - if (event.key === 'n') { - // Check for spacebar press - event.preventDefault(); // Prevent default spacebar behavior - setNavigationOpen(!navigationOpen); - } - }; - - document.addEventListener('keydown', handleKeyDown); - - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [navigationOpen]); - return ( - - { - if (event.detail.id === 'keyboard-shortcuts') { - setActiveDrawerId('keyboard-shortcuts'); - } - }, - items: [ - { - id: 'keyboard-shortcuts', - text: 'Keyboard shortcuts', - }, - ], - }, - { - type: 'menu-dropdown', - text: 'Customer Name', - description: 'email@example.com', - iconName: 'user-profile', - items: [ - { id: 'profile', text: 'Profile' }, - { id: 'preferences', text: 'Preferences' }, - { id: 'security', text: 'Security' }, - { - id: 'support-group', - text: 'Support', - items: [ - { - id: 'documentation', - text: 'Documentation', - href: '#', - external: true, - externalIconAriaLabel: ' (opens in new tab)', - }, - { id: 'support', text: 'Support' }, - { - id: 'feedback', - text: 'Feedback', - href: '#', - external: true, - externalIconAriaLabel: ' (opens in new tab)', - }, - ], - }, - { id: 'signout', text: 'Sign out' }, - ], - }, - ]} - /> - } - content={ - -
- Testing Keyboard shortcuts -
- - { - document.body.setAttribute('data-hide-header', `${!hideHeader}`); - setHideHeader(!hideHeader); - }} - checked={hideHeader} - > - Hide header - - - } + +
- - - } - splitPanelPreferences={{ - position: urlParams.splitPanelPosition, - }} - onSplitPanelPreferencesChange={event => { - const { position } = event.detail; - setUrlParams({ splitPanelPosition: position === 'side' ? position : undefined }); - }} - disableContentPaddings={disableContentPaddings} - splitPanelOpen={splitPanelOpen} - onSplitPanelToggle={event => setSplitPanelOpen(event.detail.open)} - navigationOpen={navigationOpen} - onNavigationChange={event => setNavigationOpen(event.detail.open)} - splitPanel={ - + + { + document.body.setAttribute('data-hide-header', `${!hideHeader}`); + setHideHeader(!hideHeader); }} + checked={hideHeader} > - -
-
-
- - - } - drawers={[ - { - ariaLabels: { - closeButton: `Close button`, - drawerName: `Keyboard shortcuts`, - triggerButton: `Trigger button`, - resizeHandle: `$Resize handle`, - }, - resizable: true, - defaultSize: 500, - content: ( - Keyboard shortcuts}> - - - ), - id: 'keyboard-shortcuts', - trigger: { - iconName: 'settings', - }, - }, - ]} - onDrawerChange={event => setActiveDrawerId(event.detail.activeDrawerId)} - activeDrawerId={activeDrawerId} - /> - - ); -} - -function DrawerContent() { - return ( - - - - + Hide header + + + } + > + + ); } diff --git a/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx b/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx new file mode 100644 index 0000000000..1dcf53127b --- /dev/null +++ b/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx @@ -0,0 +1,139 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React, { useState } from 'react'; + +import { Button, Container, Header, Select, SpaceBetween, StatusIndicator, Table } from '~components'; + +import CustomAppLayout from './app-layout'; + +export default function ShortcutPage() { + const [selectedItems, setSelectedItems] = useState([]); + const [submitting, setSubmitting] = useState(false); + + const removeFiles = () => { + // const newValue = files.filter(file => !selectedItems.includes(file)); + // setFiles(newValue); + + setSelectedItems([]); + }; + + const shortcuts = [ + { + name: 'Toggle navigation', + shortcut: 'n', + status: 'Enabled', + }, + ]; + + const [tableItems, setTableItems] = useState(shortcuts); + + const handleSubmit = async (currentItem: any, column: any, value: any) => { + setSubmitting(true); + await new Promise(resolve => setTimeout(resolve, 1000)); + const fullCollection = tableItems; + + const newItem = { ...currentItem, [column.id]: value }; + + setTableItems(fullCollection.map(item => (item === currentItem ? newItem : item))); + setSubmitting(false); + }; + + return ( + Save}>Keyboard shortcuts
}> + + + + + + + } + > + Keyboard shortcuts + + } + > + setSelectedItems(detail.selectedItems)} + selectedItems={selectedItems} + trackBy="name" + columnDefinitions={[ + { + id: 'name', + header: 'Action name', + cell: item => item.name || '-', + sortingField: 'name', + isRowHeader: true, + }, + { + id: 'type', + header: 'Shortcut', + cell: item => item.shortcut || '-', + sortingField: 'alt', + }, + { + id: 'status', + header: 'Status', + cell: item => + ( + + {item.status} + + ) || '-', + editConfig: { + ariaLabel: 'Type', + editIconAriaLabel: 'editable', + editingCell: (item, { currentValue, setValue }) => { + const value = currentValue ?? item.status; + return ( + setKeyCombo({ key1: detail.selectedOption, key2: keyCombo.key2 })} + options={[ + { label: 'Command', value: '1' }, + { label: 'Control', value: '2' }, + { label: 'Option', value: '3' }, + { label: 'Shift', value: '4' }, + ]} + /> + setShortcutName(detail.value)} + /> + + + + + + + + + ); +} + +export default AddNewShortcut; diff --git a/pages/keyboard-shortcut-hackathon/app-layout.tsx b/pages/keyboard-shortcut-hackathon/app-layout.tsx index 28a4d5b03c..8eb639f93b 100644 --- a/pages/keyboard-shortcut-hackathon/app-layout.tsx +++ b/pages/keyboard-shortcut-hackathon/app-layout.tsx @@ -2,17 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 import React, { useContext, useEffect, useRef, useState } from 'react'; -import { AppLayout, ContentLayout, Drawer, Input, SpaceBetween, SplitPanel, TopNavigation } from '~components'; +import { AppLayout, ContentLayout, Drawer, Input, SplitPanel, TopNavigation } from '~components'; import { AppLayoutProps } from '~components/app-layout'; import AppContext, { AppContextType } from '../app/app-context'; import { drawerLabels } from '../app-layout/utils/drawers'; import appLayoutLabels from '../app-layout/utils/labels'; import ScreenshotArea from '../utils/screenshot-area'; +import AddNewShortcut from './add-new-shortcut'; import AWSLogo from './aws-logo.svg'; -import KeyValuePairTable from './kvp-table'; - -import styles from '../app-layout/styles.scss'; type DemoContext = React.Context< AppContextType<{ @@ -22,11 +20,18 @@ type DemoContext = React.Context< }> >; -export default function CustomAppLayout({ header, children }: any) { +export default function CustomAppLayout({ + header, + children, + splitPanelOpen, + setSplitPanelOpen, + customItems, + setCustomItems, +}: any) { const { urlParams, setUrlParams } = useContext(AppContext as DemoContext); const [activeDrawerId, setActiveDrawerId] = useState(null); - const [splitPanelOpen, setSplitPanelOpen] = useState(false); + //const [splitPanelOpen, setSplitPanelOpen] = useState(false); const [navigationOpen, setNavigationOpen] = useState(false); const disableContentPaddings = urlParams.disableContentPaddings ?? false; @@ -38,49 +43,58 @@ export default function CustomAppLayout({ header, children }: any) { const handleKeyDown = (event: any) => { keyPressed[event.key + event.location] = true; - if (keyPressed.Control1 === true && keyPressed['/0'] === true) { + if (keyPressed.Control1 === true && keyPressed.h0 === true) { // Check for spacebar press event.preventDefault(); // Prevent default spacebar behavior if (activeDrawerId !== null) { setActiveDrawerId(null); } else if (activeDrawerId === null) { - setActiveDrawerId('keyboard-shortcuts'); + setActiveDrawerId('help-panel'); } keyPressed = {}; } - console.log(keyPressed); - }; - document.addEventListener('keydown', handleKeyDown); + if (keyPressed.Control1 === true && keyPressed.s0 === true) { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + setSplitPanelOpen(!splitPanelOpen); - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [activeDrawerId]); + keyPressed = {}; + } - useEffect(() => { - const handleKeyDown = (event: any) => { - if (event.key === 's') { + if (keyPressed.Control1 === true && (keyPressed.q0 || keyPressed.x0f) === true) { // Check for spacebar press event.preventDefault(); // Prevent default spacebar behavior - setSplitPanelOpen(!splitPanelOpen); + if (activeDrawerId !== null) { + setActiveDrawerId(null); + } else if (activeDrawerId === null) { + setActiveDrawerId('amazon-q'); + } + + keyPressed = {}; } - }; - document.addEventListener('keydown', handleKeyDown); + if (keyPressed.Control1 === true && keyPressed.n0 === true) { + // Check for spacebar press + event.preventDefault(); // Prevent default spacebar behavior + setNavigationOpen(!navigationOpen); - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [splitPanelOpen]); + keyPressed = {}; + } - useEffect(() => { - const handleKeyDown = (event: any) => { - if (event.key === 'n') { + if (keyPressed.Control1 === true && keyPressed.e0 === true) { // Check for spacebar press event.preventDefault(); // Prevent default spacebar behavior setNavigationOpen(!navigationOpen); + if (activeDrawerId !== null) { + setActiveDrawerId(null); + } else if (activeDrawerId === null) { + setActiveDrawerId('help-panel'); + } + setSplitPanelOpen(!splitPanelOpen); + + keyPressed = {}; } }; @@ -89,7 +103,7 @@ export default function CustomAppLayout({ header, children }: any) { return () => { document.removeEventListener('keydown', handleKeyDown); }; - }, [navigationOpen]); + }, [activeDrawerId, splitPanelOpen, navigationOpen, setSplitPanelOpen]); return ( @@ -174,7 +188,7 @@ export default function CustomAppLayout({ header, children }: any) { } splitPanelPreferences={{ - position: urlParams.splitPanelPosition, + position: 'side', }} onSplitPanelPreferencesChange={event => { const { position } = event.detail; @@ -187,7 +201,9 @@ export default function CustomAppLayout({ header, children }: any) { onNavigationChange={event => setNavigationOpen(event.detail.open)} splitPanel={ - -
-
-
- + } drawers={[ @@ -214,16 +226,27 @@ export default function CustomAppLayout({ header, children }: any) { closeButton: `Close button`, drawerName: `Keyboard shortcuts`, triggerButton: `Trigger button`, - resizeHandle: `$Resize handle`, + resizeHandle: `Resize handle`, }, resizable: true, - defaultSize: 500, - content: ( - Keyboard shortcuts}> - - - ), - id: 'keyboard-shortcuts', + + content: Help panel}>Keyboard shortcuts help you become superpowered., + id: 'help-panel', + trigger: { + iconName: 'status-info', + }, + }, + { + ariaLabels: { + closeButton: `Close button`, + drawerName: `Keyboard shortcuts`, + triggerButton: `Trigger button`, + resizeHandle: `Resize handle`, + }, + resizable: true, + + content: Amazon Q}>This is Amazon Q, + id: 'amazon-q', trigger: { iconName: 'settings', }, @@ -235,56 +258,3 @@ export default function CustomAppLayout({ header, children }: any) { ); } - -function DrawerContent() { - return ( - - - - - ); -} diff --git a/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx b/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx index 1dcf53127b..7f603dbbe8 100644 --- a/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx +++ b/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx @@ -5,28 +5,25 @@ import React, { useState } from 'react'; import { Button, Container, Header, Select, SpaceBetween, StatusIndicator, Table } from '~components'; import CustomAppLayout from './app-layout'; +import { shortcuts } from './shortcuts'; + +import styles from './styles.scss'; export default function ShortcutPage() { const [selectedItems, setSelectedItems] = useState([]); const [submitting, setSubmitting] = useState(false); + const [splitPanelOpen, setSplitPanelOpen] = useState(false); + + const [tableItems, setTableItems] = useState(shortcuts); + const [customItems, setCustomItems] = useState([]); const removeFiles = () => { - // const newValue = files.filter(file => !selectedItems.includes(file)); - // setFiles(newValue); + const newValue = customItems.filter(file => !selectedItems.includes(file)); + setCustomItems(newValue); setSelectedItems([]); }; - const shortcuts = [ - { - name: 'Toggle navigation', - shortcut: 'n', - status: 'Enabled', - }, - ]; - - const [tableItems, setTableItems] = useState(shortcuts); - const handleSubmit = async (currentItem: any, column: any, value: any) => { setSubmitting(true); await new Promise(resolve => setTimeout(resolve, 1000)); @@ -38,9 +35,93 @@ export default function ShortcutPage() { setSubmitting(false); }; + console.log(customItems); + return ( - Save}>Keyboard shortcuts}> + Save}>Keyboard shortcuts} + customItems={customItems} + setCustomItems={setCustomItems} + > + Default shortcuts}> +
setSelectedItems(detail.selectedItems)} + //selectedItems={selectedItems} + trackBy="name" + columnDefinitions={[ + { + id: 'name', + header: 'Action name', + cell: item => item.name || '-', + sortingField: 'name', + isRowHeader: true, + }, + { + id: 'type', + header: 'Shortcut', + cell: item => {item.shortcut} || '-', + sortingField: 'alt', + }, + { + id: 'status', + header: 'Status', + cell: item => + ( + + {item.status} + + ) || '-', + editConfig: { + ariaLabel: 'Type', + editIconAriaLabel: 'editable', + editingCell: (item, { currentValue, setValue }) => { + const value = currentValue ?? item.status; + return ( +
setSelectedItems(detail.selectedItems)} selectedItems={selectedItems} @@ -76,7 +157,12 @@ export default function ShortcutPage() { { id: 'type', header: 'Shortcut', - cell: item => item.shortcut || '-', + cell: item => + ( + <> + {item.shortcut} + + ) || '-', sortingField: 'alt', }, { @@ -128,7 +214,7 @@ export default function ShortcutPage() { itemSelectionLabel: ({ selectedItems }, item) => `${item.name} is ${selectedItems.indexOf(item) < 0 ? 'not ' : ''}selected`, }} - items={tableItems} + items={customItems} loadingText="Loading resources" sortingDisabled={true} /> diff --git a/pages/keyboard-shortcut-hackathon/shortcuts.ts b/pages/keyboard-shortcut-hackathon/shortcuts.ts new file mode 100644 index 0000000000..a922fd17ff --- /dev/null +++ b/pages/keyboard-shortcut-hackathon/shortcuts.ts @@ -0,0 +1,54 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +export const shortcuts = [ + { + name: 'Toggle navigation', + shortcut: 'N', + status: 'Enabled', + }, + { + name: 'Toggle split panel', + shortcut: 'S', + status: 'Enabled', + }, + { + name: 'Toggle help panel', + shortcut: 'H', + status: 'Enabled', + }, + { + name: 'Toggle Amazon Q', + shortcut: 'Q', + status: 'Enabled', + }, + { + name: 'Toggle dark mode', + shortcut: '^ + D', + status: 'Enabled', + }, + { + name: 'Toggle compact mode', + shortcut: '^ + C', + status: 'Enabled', + }, + { + name: 'Toggle visual refresh', + shortcut: '^ + V', + status: 'Enabled', + }, + { + name: 'Toggle motion disabled', + shortcut: '^ + M', + status: 'Enabled', + }, + { + name: 'RTL direction', + shortcut: '^ + R', + status: 'Enabled', + }, + { + name: 'LTR direction', + shortcut: '^ + L', + status: 'Enabled', + }, +]; diff --git a/pages/keyboard-shortcut-hackathon/styles.scss b/pages/keyboard-shortcut-hackathon/styles.scss index 985c5012e3..ffb994a733 100644 --- a/pages/keyboard-shortcut-hackathon/styles.scss +++ b/pages/keyboard-shortcut-hackathon/styles.scss @@ -16,7 +16,14 @@ } .shortcut { - background: awsui.$color-background-input-disabled; + //background: awsui.$color-background-input-disabled; + color: awsui.$color-text-body-secondary; + border-block: 1px solid awsui.$color-border-divider-default; + border-inline: 1px solid awsui.$color-border-divider-default; + border-start-start-radius: awsui.$border-radius-badge; + border-start-end-radius: awsui.$border-radius-badge; + border-end-start-radius: awsui.$border-radius-badge; + border-end-end-radius: awsui.$border-radius-badge; padding-block: 2px; padding-inline: 4px; font-family: monospace; From 77cfd0116a229ebcf7fe33eee52ada640fd51bc3 Mon Sep 17 00:00:00 2001 From: Katie George Date: Thu, 21 Nov 2024 16:27:52 -0800 Subject: [PATCH 6/6] final bugs --- .../add-new-shortcut.tsx | 3 ++- .../app-layout.tsx | 24 +++++++++++++++---- .../shortcut-page.page.tsx | 12 +++++++++- .../keyboard-shortcut-hackathon/shortcuts.ts | 20 ++++++++-------- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/pages/keyboard-shortcut-hackathon/add-new-shortcut.tsx b/pages/keyboard-shortcut-hackathon/add-new-shortcut.tsx index 89b6830deb..d2c39e8b2e 100644 --- a/pages/keyboard-shortcut-hackathon/add-new-shortcut.tsx +++ b/pages/keyboard-shortcut-hackathon/add-new-shortcut.tsx @@ -52,6 +52,7 @@ function AddNewShortcut({ customItems, setCustomItems }: any) { { label: 'D', value: '4' }, { label: 'E', value: '5' }, { label: 'F', value: '6' }, + { label: 'X', value: '7' }, ]} /> @@ -73,7 +74,7 @@ function AddNewShortcut({ customItems, setCustomItems }: any) { ...customItems, { name: shortcutName || `${actions[0].label} + ${actions[1]?.label} + ${actions[2]?.label}`, - shortcut: `${keyCombo.key1.label} ${keyCombo.key2.label}`, + shortcut: `${keyCombo.key1.label} + ${keyCombo.key2.label}`, actions: actions, status: 'Enabled', }, diff --git a/pages/keyboard-shortcut-hackathon/app-layout.tsx b/pages/keyboard-shortcut-hackathon/app-layout.tsx index 8eb639f93b..5d8205ebaa 100644 --- a/pages/keyboard-shortcut-hackathon/app-layout.tsx +++ b/pages/keyboard-shortcut-hackathon/app-layout.tsx @@ -63,7 +63,7 @@ export default function CustomAppLayout({ keyPressed = {}; } - if (keyPressed.Control1 === true && (keyPressed.q0 || keyPressed.x0f) === true) { + if (keyPressed.Control1 === true && (keyPressed.q0 || keyPressed.x0) === true) { // Check for spacebar press event.preventDefault(); // Prevent default spacebar behavior if (activeDrawerId !== null) { @@ -83,16 +83,16 @@ export default function CustomAppLayout({ keyPressed = {}; } - if (keyPressed.Control1 === true && keyPressed.e0 === true) { + if (keyPressed.Control1 === true && keyPressed.f0 === true) { // Check for spacebar press event.preventDefault(); // Prevent default spacebar behavior - setNavigationOpen(!navigationOpen); + setNavigationOpen(false); if (activeDrawerId !== null) { setActiveDrawerId(null); } else if (activeDrawerId === null) { setActiveDrawerId('help-panel'); } - setSplitPanelOpen(!splitPanelOpen); + setSplitPanelOpen(false); keyPressed = {}; } @@ -248,7 +248,21 @@ export default function CustomAppLayout({ content: Amazon Q}>This is Amazon Q, id: 'amazon-q', trigger: { - iconName: 'settings', + iconSvg: ( + + + + ), }, }, ]} diff --git a/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx b/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx index 7f603dbbe8..5bc33a904c 100644 --- a/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx +++ b/pages/keyboard-shortcut-hackathon/shortcut-page.page.tsx @@ -41,7 +41,17 @@ export default function ShortcutPage() { Save}>Keyboard shortcuts} + header={ +
+ Save + + } + > + Keyboard shortcuts +
+ } customItems={customItems} setCustomItems={setCustomItems} > diff --git a/pages/keyboard-shortcut-hackathon/shortcuts.ts b/pages/keyboard-shortcut-hackathon/shortcuts.ts index a922fd17ff..bb7f245be2 100644 --- a/pages/keyboard-shortcut-hackathon/shortcuts.ts +++ b/pages/keyboard-shortcut-hackathon/shortcuts.ts @@ -3,52 +3,52 @@ export const shortcuts = [ { name: 'Toggle navigation', - shortcut: 'N', + shortcut: 'Control + N', status: 'Enabled', }, { name: 'Toggle split panel', - shortcut: 'S', + shortcut: 'Control + S', status: 'Enabled', }, { name: 'Toggle help panel', - shortcut: 'H', + shortcut: 'Control + H', status: 'Enabled', }, { name: 'Toggle Amazon Q', - shortcut: 'Q', + shortcut: 'Control + Q', status: 'Enabled', }, { name: 'Toggle dark mode', - shortcut: '^ + D', + shortcut: 'Control + D', status: 'Enabled', }, { name: 'Toggle compact mode', - shortcut: '^ + C', + shortcut: 'Control + C', status: 'Enabled', }, { name: 'Toggle visual refresh', - shortcut: '^ + V', + shortcut: 'Control + V', status: 'Enabled', }, { name: 'Toggle motion disabled', - shortcut: '^ + M', + shortcut: 'Control + M', status: 'Enabled', }, { name: 'RTL direction', - shortcut: '^ + R', + shortcut: 'Control + R', status: 'Enabled', }, { name: 'LTR direction', - shortcut: '^ + L', + shortcut: 'Control + L', status: 'Enabled', }, ];