mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 01:23:52 +00:00
editor: improve a18y and visual appearance
This commit is contained in:
@@ -13,7 +13,7 @@ import { editorActivateFile, editorCloseFile } from './actions';
|
||||
|
||||
describe('Editor', () => {
|
||||
describe('tabs', () => {
|
||||
it('should dispatch action when tab is clicked', async () => {
|
||||
it('should dispatch activate action when tab is clicked', async () => {
|
||||
const [editor, dispatch] = testRender(<Editor />, {
|
||||
editor: { openFiles: ['test.file'] },
|
||||
});
|
||||
@@ -23,7 +23,23 @@ describe('Editor', () => {
|
||||
expect(dispatch).toHaveBeenCalledWith(editorActivateFile('test.file'));
|
||||
});
|
||||
|
||||
it('should dispatch action when close button is clicked', async () => {
|
||||
it.each(['enter', 'space'])(
|
||||
'should dispatch activate action when % button is pressed',
|
||||
async (button) => {
|
||||
const [editor, dispatch] = testRender(<Editor />, {
|
||||
editor: { openFiles: ['test.file'] },
|
||||
});
|
||||
|
||||
userEvent.type(
|
||||
editor.getByRole('tab', { name: 'test.file' }),
|
||||
`{${button}}`,
|
||||
);
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith(editorActivateFile('test.file'));
|
||||
},
|
||||
);
|
||||
|
||||
it('should dispatch close action when close button is clicked', async () => {
|
||||
const [editor, dispatch] = testRender(<Editor />, {
|
||||
editor: { openFiles: ['test.file'] },
|
||||
});
|
||||
@@ -32,6 +48,16 @@ describe('Editor', () => {
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith(editorCloseFile('test.file'));
|
||||
});
|
||||
|
||||
it('should dispatch close action when delete button is pressed', async () => {
|
||||
const [editor, dispatch] = testRender(<Editor />, {
|
||||
editor: { openFiles: ['test.file'] },
|
||||
});
|
||||
|
||||
userEvent.type(editor.getByRole('tab', { name: 'test.file' }), '{delete}');
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith(editorCloseFile('test.file'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('context menu', () => {
|
||||
|
||||
+25
-4
@@ -13,6 +13,7 @@ import {
|
||||
Tab,
|
||||
TabId,
|
||||
Tabs,
|
||||
Text,
|
||||
} from '@blueprintjs/core';
|
||||
import { ContextMenu2, ResizeSensor2 } from '@blueprintjs/popover2';
|
||||
import { I18n, useI18n } from '@shopify/react-i18n';
|
||||
@@ -202,25 +203,44 @@ const EditorTabs: React.VoidFunctionComponent<EditorTabsProps> = ({
|
||||
|
||||
const labelId = useUniqueId('pb-editor');
|
||||
|
||||
// close tab when delete key is pressed
|
||||
const handleKeyDown = useCallback(
|
||||
(e: React.KeyboardEvent, fileName: string) => {
|
||||
if (e.key === 'Delete') {
|
||||
dispatch(editorCloseFile(fileName));
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
},
|
||||
[dispatch],
|
||||
);
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
className="pb-editor-tabs"
|
||||
className="pb-editor-tablist"
|
||||
selectedTabId={activeFile}
|
||||
onChange={handleChange}
|
||||
>
|
||||
{openFiles.map((fileName, i) => (
|
||||
<Tab
|
||||
className="pb-editor-tab"
|
||||
className="pb-editor-tablist-tab"
|
||||
aria-labelledby={`${labelId}.${i}`}
|
||||
key={i}
|
||||
id={fileName}
|
||||
onKeyDown={(e) => handleKeyDown(e, fileName)}
|
||||
>
|
||||
<span id={`${labelId}.${i}`}>{fileName}</span>
|
||||
<Text tagName="span" id={`${labelId}.${i}`} ellipsize={true}>
|
||||
{fileName}
|
||||
</Text>
|
||||
<Button
|
||||
title={i18n.translate(I18nId.CloseFileTooltip, { fileName })}
|
||||
minimal={true}
|
||||
small={true}
|
||||
icon={'cross'}
|
||||
// tabs are closed with delete button by keyboard, so
|
||||
// don't focus the close button
|
||||
tabIndex={-1}
|
||||
onFocus={(e) => e.preventDefault()}
|
||||
onClick={(e) => {
|
||||
dispatch(editorCloseFile(fileName));
|
||||
// prevent triggering Tabs onChange
|
||||
@@ -414,7 +434,8 @@ const Editor: React.VFC = () => {
|
||||
<EditorTabs onChange={() => editor?.focus()} i18n={i18n} />
|
||||
<ResizeSensor2 onResize={() => editor?.layout()}>
|
||||
<ContextMenu2
|
||||
className="h-100"
|
||||
className="pb-editor-tabpanel"
|
||||
role="tabpanel"
|
||||
// NB: we have to create a new context menu each time it is
|
||||
// shown in order to get some state, like canUndo and canRedo
|
||||
// that don't have events to monitor changes.
|
||||
|
||||
+52
-15
@@ -4,6 +4,7 @@
|
||||
// Custom styling for the Editor control.
|
||||
|
||||
@use '@blueprintjs/core/lib/scss/variables' as bp;
|
||||
@use '../variables.scss' as pb;
|
||||
|
||||
// add "BETA" watermark
|
||||
|
||||
@@ -19,22 +20,58 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.#{bp.$ns}-dark .pb-editor-placeholder {
|
||||
color: bp.$pt-dark-text-color-muted;
|
||||
}
|
||||
.pb-editor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
.pb-editor-tab {
|
||||
padding: 3px;
|
||||
}
|
||||
&-tablist {
|
||||
padding: bp.$pt-grid-size * 0.3;
|
||||
overflow-x: auto;
|
||||
@include pb.background-contrast(6%);
|
||||
|
||||
.pb-editor-tabs {
|
||||
padding: 3px 6px;
|
||||
}
|
||||
.bp4-tab-list > * {
|
||||
padding-left: bp.$pt-grid-size * 1.5;
|
||||
|
||||
.pb-editor-placeholder {
|
||||
pointer-events: none;
|
||||
width: max-content;
|
||||
color: bp.$pt-text-color-muted;
|
||||
font-style: italic;
|
||||
padding-left: 4px;
|
||||
&:not(:last-child) {
|
||||
margin: unset;
|
||||
}
|
||||
}
|
||||
|
||||
&-tab {
|
||||
padding-right: bp.$pt-grid-size * 0.5;
|
||||
border-right: 1px solid bp.$pt-divider-black;
|
||||
max-width: bp.$pt-grid-size * 15;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.#{bp.$ns}-dark & {
|
||||
border-right-color: bp.$pt-dark-divider-white;
|
||||
}
|
||||
|
||||
& .#{bp.$ns}-text-overflow-ellipsis {
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-tabpanel {
|
||||
min-height: 0;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
&-placeholder {
|
||||
pointer-events: none;
|
||||
width: max-content;
|
||||
color: bp.$pt-text-color-muted;
|
||||
font-style: italic;
|
||||
padding-left: 4px;
|
||||
|
||||
.#{bp.$ns}-dark & {
|
||||
color: bp.$pt-dark-text-color-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user