Skip to content

Commit

Permalink
Simplify keyboard shortcuts (#1599)
Browse files Browse the repository at this point in the history
* Add keyboard shortcut for reloading renderer

* Mock core plugin in renderer core tests

* Right-align shortcut column

* Fix duplicate key listeners

* Simplify keyboard shortcuts

* Update testBlocks.ts
  • Loading branch information
ovidiuch committed Jan 18, 2024
1 parent 561b52a commit f128af2
Show file tree
Hide file tree
Showing 25 changed files with 81 additions and 29 deletions.
2 changes: 1 addition & 1 deletion cypress/support/testBlocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export function selectFixtureTests() {
});

it('renders searched fixture', () => {
getRendererBody().type(`{meta}{shift}p`);
getRendererBody().type(`{meta}k`);
cy.get('[placeholder="Fixture search"]').type(`Hello`).type('{enter}');
getRendererBody().find('#root').should('have.text', 'Hello World!');
});
Expand Down
17 changes: 9 additions & 8 deletions docs/pages/docs/user-interface.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ and their state persists between sessions.

## Fixture Search

A snappy fixture search feature with fuzzy matching. Use `⌘ + P` from anywhere to launch the search modal.
A snappy fixture search feature with fuzzy matching. Use `⌘ + K` from anywhere to launch the search modal.

<br />
<Image
Expand Down Expand Up @@ -124,13 +124,14 @@ A beautiful notifications interface used to communicate renderer and server conn

The Cosmos UI supports a set of useful keyboard shortcuts for the most commonly used actions:

| Shortcut | Action |
| ----------- | -------------------- |
| `⌘ + P` | Search fixtures |
| `⌘ + ⇧ + P` | Toggle fixture list |
| `⌘ + ⇧ + K` | Toggle control panel |
| `⌘ + ⇧ + E` | Edit fixture |
| `⌘ + ⇧ + F` | Go full screen |
| Shortcut | Action |
| -------: | -------------------- |
| `⌘ + K` | Search fixtures |
| `L` | Toggle fixture list |
| `P` | Toggle control panel |
| `E` | Edit fixture |
| `F` | Go full screen |
| `R` | Reload renderer |

## UI Plugins

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,26 @@ export function registerPlaygroundShortcuts(
}

function handleWindowKeyDown(e: KeyboardEvent) {
if (isEditing()) {
// Allow meta key shortcuts to work when focused on input fields
if (isEditing() && !e.metaKey) {
return;
}

const keyChar = String.fromCharCode(e.keyCode);
const metaKey = e.metaKey || e.ctrlKey;

if (keyChar === 'P' && metaKey) {
if (keyChar === 'K' && metaKey) {
run(e, 'searchFixtures');
} else if (keyChar === 'L' && metaKey && e.shiftKey) {
} else if (keyChar === 'L') {
run(e, 'toggleFixtureList');
} else if (keyChar === 'K' && metaKey && e.shiftKey) {
} else if (keyChar === 'P') {
run(e, 'toggleControlPanel');
} else if (keyChar === 'F' && metaKey && e.shiftKey) {
} else if (keyChar === 'F') {
run(e, 'goFullScreen');
} else if (keyChar === 'E' && metaKey && e.shiftKey) {
} else if (keyChar === 'E') {
run(e, 'editFixture');
} else if (keyChar === 'R') {
run(e, 'reloadRenderer');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export function createPostMessageConnect(): RendererConnect {
parent.postMessage(msg, '*');
}

registerPlaygroundShortcuts(command => {
postMessage({ type: 'playgroundCommand', payload: { command } });
});

return {
postMessage,

Expand All @@ -18,14 +22,8 @@ export function createPostMessageConnect(): RendererConnect {
onMessage(msg.data);
}
window.addEventListener('message', handleMessage, false);

const removeShortcuts = registerPlaygroundShortcuts(command => {
postMessage({ type: 'playgroundCommand', payload: { command } });
});

return () => {
window.removeEventListener('message', handleMessage);
removeShortcuts();
};
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function FixtureSearchHeader({
</SearchIconContainer>
<SearchLabel>Search fixtures</SearchLabel>
<KeyBox value={'⌘'} bgColor={white10} textColor={grey160} size={20} />
<KeyBox value={'P'} bgColor={white10} textColor={grey160} size={20} />
<KeyBox value={'K'} bgColor={white10} textColor={grey160} size={20} />
</SearchButton>
<NavButtonContainer>
<IconButton32
Expand Down
3 changes: 2 additions & 1 deletion packages/react-cosmos-ui/src/plugins/FixtureSearch/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ onLoad(pluginContext => {
const { getMethodsOf, setState } = pluginContext;
const core = getMethodsOf<CoreSpec>('core');
return core.registerCommands({
searchFixtures: () => setState(prevState => ({ ...prevState, open: true })),
searchFixtures: () =>
setState(prevState => ({ ...prevState, open: !prevState.open })),
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { loadPlugins, resetPlugins } from 'react-plugin';
import { getRendererCoreMethods } from '../../../testHelpers/pluginMocks.js';
import {
getRendererCoreMethods,
mockCore,
} from '../../../testHelpers/pluginMocks.js';
import { register } from '../index.js';
import { RendererCoreSpec } from '../spec.js';

Expand All @@ -13,6 +16,7 @@ const rendererCoreConfig: RendererCoreSpec['config'] = {
};

it('returns web renderer URL', () => {
mockCore();
loadPlugins({
config: {
rendererCore: rendererCoreConfig,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
mockCore,
mockNotifications,
mockRouter,
} from '../../../testHelpers/pluginMocks.js';
Expand All @@ -12,6 +13,7 @@ beforeEach(register);
afterEach(resetPlugins);

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => null,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FixtureList } from 'react-cosmos-core';
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
mockCore,
mockNotifications,
mockRouter,
} from '../../../testHelpers/pluginMocks.js';
Expand All @@ -25,6 +26,7 @@ const fixtureId = { path: 'foo.js' };
const fixtureState = { props: [] };

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => fixtureId,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
getRouterContext,
mockCore,
mockNotifications,
mockRouter,
} from '../../../testHelpers/pluginMocks.js';
Expand All @@ -19,6 +20,7 @@ afterEach(resetPlugins);
const fixtureId = { path: 'zwei.js' };

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => fixtureId,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
getRouterContext,
mockCore,
mockNotifications,
mockRouter,
onRendererCore,
Expand All @@ -15,6 +16,7 @@ beforeEach(register);
afterEach(resetPlugins);

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => null,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
getRouterContext,
mockCore,
mockNotifications,
mockRouter,
onRendererCore,
Expand All @@ -15,6 +16,7 @@ beforeEach(register);
afterEach(resetPlugins);

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => null,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { waitFor } from '@testing-library/dom';
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
mockCore,
mockNotifications,
mockRouter,
onRendererCore,
Expand All @@ -17,6 +18,7 @@ const rendererId = 'mockRendererId1';
const rendererReadyMsg = createRendererReadyResponse(rendererId);

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => null,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { waitFor } from '@testing-library/dom';
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
mockCore,
mockNotifications,
mockRouter,
} from '../../../testHelpers/pluginMocks.js';
Expand All @@ -13,6 +14,7 @@ beforeEach(register);
afterEach(resetPlugins);

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => null,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { waitFor } from '@testing-library/dom';
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
mockCore,
mockNotifications,
mockRouter,
onRendererCore,
Expand All @@ -24,6 +25,7 @@ const expectedFixtureState = {
};

function registerTestPlugins() {
mockCore();
mockSelectedFixture();
mockNotifications();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
getRouterContext,
mockCore,
mockNotifications,
mockRouter,
onRendererCore,
Expand All @@ -15,6 +16,7 @@ beforeEach(register);
afterEach(resetPlugins);

it('sets fixture state when setting global fixture state', async () => {
mockCore();
mockRouter({
getSelectedFixtureId: () => ({ path: 'zwei.js' }),
});
Expand Down Expand Up @@ -70,6 +72,7 @@ it('sets fixture state when setting global fixture state', async () => {
});

it('uses global fixture state when renderer connects', async () => {
mockCore();
mockRouter({
getSelectedFixtureId: () => ({ path: 'zwei.js' }),
});
Expand Down Expand Up @@ -98,6 +101,7 @@ it('uses global fixture state when renderer connects', async () => {
});

it('uses global fixture state when renderer connects with fixture selected', async () => {
mockCore();
mockRouter({
getSelectedFixtureId: () => ({ path: 'zwei.js' }),
});
Expand Down Expand Up @@ -126,6 +130,7 @@ it('uses global fixture state when renderer connects with fixture selected', asy
});

it('uses global fixture state on fixture select', async () => {
mockCore();
mockRouter({
getSelectedFixtureId: () => null,
});
Expand Down Expand Up @@ -155,6 +160,7 @@ it('uses global fixture state on fixture select', async () => {
});

it('uses global fixture state on fixture reselect', async () => {
mockCore();
mockRouter({
getSelectedFixtureId: () => ({ path: 'zwei.js' }),
});
Expand Down
8 changes: 8 additions & 0 deletions packages/react-cosmos-ui/src/plugins/RendererCore/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { RendererId, fixtureStateByName } from 'react-cosmos-core';
import { createPlugin } from 'react-plugin';
import { CoreSpec } from '../Core/spec.js';
import { RouterSpec } from '../Router/spec.js';
import { onRouterFixtureReselect } from './onRouterFixtureReselect.js';
import { onRouterFixtureSelect } from './onRouterFixtureSelect.js';
Expand Down Expand Up @@ -45,6 +46,13 @@ onLoad(({ getConfig, setState }) => {
setState(prevState => ({ ...prevState, fixtures }));
});

onLoad(context => {
const core = context.getMethodsOf<CoreSpec>('core');
return core.registerCommands({
reloadRenderer: () => reloadRenderer(context),
});
});

on<RouterSpec>('router', {
fixtureSelect: onRouterFixtureSelect,
fixtureReselect: onRouterFixtureReselect,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FixtureList } from 'react-cosmos-core';
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
mockCore,
mockNotifications,
mockRouter,
} from '../../../../testHelpers/pluginMocks.js';
Expand All @@ -23,6 +24,7 @@ const fixtures: FixtureList = {
};

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => null,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { RendererId } from 'react-cosmos-core';
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
mockCore,
mockNotifications,
mockRouter,
onRendererCore,
Expand All @@ -21,6 +22,7 @@ const fixtureId = { path: 'zwei.js' };
const fixtureState = { props: [] };

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => fixtureId,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { waitFor } from '@testing-library/dom';
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
getRendererCoreMethods,
mockCore,
mockNotifications,
mockRouter,
} from '../../../../testHelpers/pluginMocks.js';
Expand All @@ -19,6 +20,7 @@ const fixtureId = { path: 'zwei.js' };
const fixtureState = { props: [] };

function registerTestPlugins() {
mockCore();
mockRouter({
getSelectedFixtureId: () => fixtureId,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { waitFor } from '@testing-library/dom';
import { FixtureId } from 'react-cosmos-core';
import { loadPlugins, resetPlugins } from 'react-plugin';
import {
mockCore,
mockNotifications,
mockRouter,
onRendererCore,
Expand All @@ -14,6 +15,7 @@ beforeEach(register);
afterEach(resetPlugins);

function registerTestPlugins(selectedFixtureId: FixtureId) {
mockCore();
mockRouter({
getSelectedFixtureId: () => selectedFixtureId,
});
Expand Down

0 comments on commit f128af2

Please sign in to comment.