diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index 986267fe3..a993dea00 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -15,6 +15,7 @@ "/packages/docs/sandboxes/fullwidthtab-dockview", "/packages/docs/sandboxes/groupcontol-dockview", "/packages/docs/sandboxes/iframe-dockview", + "/packages/docs/sandboxes/keyboard-dockview", "/packages/docs/sandboxes/layout-dockview", "/packages/docs/sandboxes/lockedgroup-dockview", "/packages/docs/sandboxes/nativeapp-dockview", @@ -32,4 +33,4 @@ "/packages/docs/sandboxes/javascript/vanilla-dockview" ], "node": "16" -} +} \ No newline at end of file diff --git a/packages/docs/docs/components/dockview.mdx b/packages/docs/docs/components/dockview.mdx index 25f67edc5..f55a5023e 100644 --- a/packages/docs/docs/components/dockview.mdx +++ b/packages/docs/docs/components/dockview.mdx @@ -27,6 +27,7 @@ import DockviewTabheight from '@site/sandboxes/tabheight-dockview/src/app'; import DockviewWithIFrames from '@site/sandboxes/iframe-dockview/src/app'; import DockviewFloating from '@site/sandboxes/floatinggroup-dockview/src/app'; import DockviewLockedGroup from '@site/sandboxes/lockedgroup-dockview/src/app'; +import DockviewKeyboard from '@site/sandboxes/keyboard-dockview/src/app'; import { attach as attachDockviewVanilla } from '@site/sandboxes/javascript/vanilla-dockview/src/app'; import { attach as attachSimpleDockview } from '@site/sandboxes/javascript/simple-dockview/src/app'; @@ -899,7 +900,15 @@ A simple example showing events fired by `dockviewz that can be interacted with. react={EventsDockview} /> -## Advanced Examples +## Keyboard Navigation + +Keyboard shortcuts + + ### Nested Dockviews diff --git a/packages/docs/sandboxes/keyboard-dockview/package.json b/packages/docs/sandboxes/keyboard-dockview/package.json new file mode 100644 index 000000000..a5766dcba --- /dev/null +++ b/packages/docs/sandboxes/keyboard-dockview/package.json @@ -0,0 +1,34 @@ +{ + "name": "keyboard-dockview", + "description": "", + "keywords": [ + "dockview" + ], + "version": "1.0.0", + "main": "src/index.tsx", + "dependencies": { + "dockview": "*", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/uuid": "^9.0.0", + "typescript": "^4.9.5", + "react-scripts": "*" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/packages/docs/sandboxes/keyboard-dockview/public/index.html b/packages/docs/sandboxes/keyboard-dockview/public/index.html new file mode 100644 index 000000000..5a4850c1d --- /dev/null +++ b/packages/docs/sandboxes/keyboard-dockview/public/index.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + React App + + + + +
+ + + + diff --git a/packages/docs/sandboxes/keyboard-dockview/src/app.scss b/packages/docs/sandboxes/keyboard-dockview/src/app.scss new file mode 100644 index 000000000..53fd8f0be --- /dev/null +++ b/packages/docs/sandboxes/keyboard-dockview/src/app.scss @@ -0,0 +1,21 @@ +.keyboard-example-panel { + padding: 20px; + color: white; + font-size: 13px; + + input { + &:focus { + outline: 1px solid dodgerblue; + } + } + + .keyboard-example-description { + padding: 10px 0px; + .keyboard-example-shortcut { + background-color: lightblue; + color: black; + padding: 2px 4px; + border-radius: 4px; + } + } +} diff --git a/packages/docs/sandboxes/keyboard-dockview/src/app.tsx b/packages/docs/sandboxes/keyboard-dockview/src/app.tsx new file mode 100644 index 000000000..021491507 --- /dev/null +++ b/packages/docs/sandboxes/keyboard-dockview/src/app.tsx @@ -0,0 +1,137 @@ +import { + DockviewApi, + DockviewReact, + DockviewReadyEvent, + IDockviewPanelProps, +} from 'dockview'; +import './app.scss'; +import * as React from 'react'; + +const components = { + default: (props: IDockviewPanelProps<{ title: string }>) => { + const [active, setActive] = React.useState(props.api.isActive); + const ref = React.useRef(null); + + React.useEffect(() => { + const disposable = props.api.onDidActiveChange((event) => { + setActive(props.api.isActive); + }); + + return () => { + disposable.dispose(); + }; + }, [props.api]); + + React.useEffect(() => { + if (!active) { + return; + } + + requestAnimationFrame(() => { + ref.current?.focus(); + }); + }, [active]); + + return ( +
+
+ {props.api.title} +
+
+ {'Use '} + + {'Ctrl+ArrowLeft'} + + {' and '} + + {'Ctrl+ArrowRight'} + + {' to nativgate between tabs.'} +
+ +
+
+ { + 'This input box should take focus when the panel is active to demonsrate managed focus' + } + +
+
+ +
+ {'isPanelActive: '} + {active ? 'true' : 'false'} +
+
+ ); + }, +}; + +const DockviewDemo = (props: { theme?: string }) => { + const [api, setApi] = React.useState(); + + const onReady = (event: DockviewReadyEvent) => { + event.api.addPanel({ + id: 'panel_1', + component: 'default', + title: 'Panel 1', + }); + event.api.addPanel({ + id: 'panel_2', + component: 'default', + title: 'Panel 2', + }); + event.api.addPanel({ + id: 'panel_3', + component: 'default', + title: 'Panel 3', + }); + event.api.addPanel({ + id: 'panel_4', + component: 'default', + title: 'Panel 4', + position: { referencePanel: 'panel_3', direction: 'right' }, + }); + event.api.addPanel({ + id: 'panel_5', + component: 'default', + title: 'Panel 5', + position: { referencePanel: 'panel_4', direction: 'within' }, + }); + + event.api.getPanel('panel_1')!.api.setActive(); + + setApi(event.api); + }; + + const onKeyDown = (event: React.KeyboardEvent) => { + if (!api) { + return; + } + + if (event.ctrlKey && event.code === 'ArrowLeft') { + // move backwards + api.moveToPrevious({ includePanel: true }); + } + + if (event.ctrlKey && event.code === 'ArrowRight') { + // move backwards + api.moveToNext({ includePanel: true }); + } + }; + + return ( +
+ +
+ ); +}; + +export default DockviewDemo; diff --git a/packages/docs/sandboxes/keyboard-dockview/src/index.tsx b/packages/docs/sandboxes/keyboard-dockview/src/index.tsx new file mode 100644 index 000000000..2fe1be232 --- /dev/null +++ b/packages/docs/sandboxes/keyboard-dockview/src/index.tsx @@ -0,0 +1,20 @@ +import { StrictMode } from 'react'; +import * as ReactDOMClient from 'react-dom/client'; +import './styles.css'; +import 'dockview/dist/styles/dockview.css'; + +import App from './app'; + +const rootElement = document.getElementById('root'); + +if (rootElement) { + const root = ReactDOMClient.createRoot(rootElement); + + root.render( + +
+ +
+
+ ); +} diff --git a/packages/docs/sandboxes/keyboard-dockview/src/styles.css b/packages/docs/sandboxes/keyboard-dockview/src/styles.css new file mode 100644 index 000000000..92b6a1b36 --- /dev/null +++ b/packages/docs/sandboxes/keyboard-dockview/src/styles.css @@ -0,0 +1,16 @@ +body { + margin: 0px; + color: white; + font-family: sans-serif; + text-align: center; +} + +#root { + height: 100vh; + width: 100vw; +} + +.app { + height: 100%; + +} diff --git a/packages/docs/sandboxes/keyboard-dockview/tsconfig.json b/packages/docs/sandboxes/keyboard-dockview/tsconfig.json new file mode 100644 index 000000000..cdc4fb5f5 --- /dev/null +++ b/packages/docs/sandboxes/keyboard-dockview/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "outDir": "build/dist", + "module": "esnext", + "target": "es5", + "lib": ["es6", "dom"], + "sourceMap": true, + "allowJs": true, + "jsx": "react-jsx", + "moduleResolution": "node", + "rootDir": "src", + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "strictNullChecks": true + } +}