Skip to content

Commit 9a6e7c8

Browse files
committed
feat(devtools-client): add zoom to devtools
1 parent ad880ff commit 9a6e7c8

File tree

12 files changed

+202
-8
lines changed

12 files changed

+202
-8
lines changed

packages/overmind-devtools-client/src/components/ActionSelector/styles.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ export const resultWrapper = css({
7979
overflowY: 'auto',
8080
left: 0,
8181
backgroundColor: colors.border,
82-
borderBottomLeftRadius: 3,
83-
borderBottomRightRadius: 3,
8482
zIndex: 2,
8583
})
8684

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as React from 'react'
2+
import { ZoomProvider, useZoom } from '../common/ZoomContext'
3+
import * as styles from './styles'
4+
import Workspace from '../Workspace'
5+
6+
// Wrapper component that applies the zoom level
7+
const ZoomableContainer: React.FC<{ children: React.ReactNode }> = ({
8+
children,
9+
}) => {
10+
const { zoomLevel } = useZoom()
11+
12+
return <div className={styles.container(zoomLevel)}>{children}</div>
13+
}
14+
15+
const App: React.FC = () => {
16+
return (
17+
<ZoomProvider>
18+
<ZoomableContainer>
19+
<Workspace />
20+
</ZoomableContainer>
21+
</ZoomProvider>
22+
)
23+
}
24+
25+
export default App
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { css } from 'emotion'
2+
import { colors } from '../../theme'
3+
4+
export const container = (zoomLevel: number) =>
5+
css({
6+
height: `calc(100vh / ${zoomLevel})`,
7+
width: `calc(100vw / ${zoomLevel})`,
8+
overflow: 'auto',
9+
transform: `scale(${zoomLevel})`,
10+
transformOrigin: 'top left',
11+
transition: 'transform 0.1s ease',
12+
scrollbarColor: `rgba(121, 121, 121, 0.4) ${colors.foreground}`,
13+
scrollbarWidth: 'thin',
14+
':hover': {
15+
scrollbarColor: `rgba(100, 100, 100, 0.7) ${colors.foreground}`,
16+
},
17+
})

packages/overmind-devtools-client/src/components/Devtools/index.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import * as React from 'react'
2-
import { useAppState } from '../../overmind'
2+
import { useAppState, useEffects } from '../../overmind'
33
import * as styles from './styles'
44
import * as text from '../../styles/text'
5-
import Workspace from '../Workspace'
5+
import App from '../App'
66
import { css } from 'emotion'
7+
import Workspace from '../Workspace'
78

89
const Devtools: React.FunctionComponent = () => {
910
const state = useAppState()
11+
const effects = useEffects()
1012

1113
if (state.error) {
1214
return (
@@ -21,7 +23,11 @@ const Devtools: React.FunctionComponent = () => {
2123
)
2224
}
2325

24-
return <Workspace />
26+
if (effects.platform.isVSCodeExtension()) {
27+
return <Workspace />
28+
}
29+
30+
return <App />
2531
}
2632

2733
export default Devtools

packages/overmind-devtools-client/src/components/StateMachineSelector/styles.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,6 @@ export const resultWrapper = css({
8585
overflowY: 'auto',
8686
left: 0,
8787
backgroundColor: colors.border,
88-
borderBottomLeftRadius: 3,
89-
borderBottomRightRadius: 3,
9088
zIndex: 2,
9189
})
9290

packages/overmind-devtools-client/src/components/Workspace/styles.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ export const wrapper = css({
55
display: 'flex',
66
flexDirection: 'column',
77
justifyContent: 'stretch',
8-
height: '100vh',
8+
height: '100%',
9+
'*': {
10+
scrollbarColor: `rgba(121, 121, 121, 0.4) ${colors.foreground}`,
11+
':hover': {
12+
scrollbarColor: `rgba(100, 100, 100, 0.7) ${colors.foreground}`,
13+
},
14+
},
915
})
1016

1117
export const content = css({
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import * as React from 'react'
2+
import { useAppState, useActions, useEffects } from '../../../overmind'
3+
4+
type ZoomContextType = {
5+
zoomLevel: number
6+
zoomIn: () => void
7+
zoomOut: () => void
8+
resetZoom: () => void
9+
}
10+
11+
export const ZoomContext = React.createContext<ZoomContextType>({
12+
zoomLevel: 1,
13+
zoomIn: () => {},
14+
zoomOut: () => {},
15+
resetZoom: () => {},
16+
})
17+
18+
export const ZoomProvider: React.FC<{ children: React.ReactNode }> = ({
19+
children,
20+
}) => {
21+
const state = useAppState()
22+
const actions = useActions()
23+
const effects = useEffects()
24+
25+
const zoomIn = React.useCallback(() => {
26+
actions.zoomIn()
27+
}, [actions])
28+
29+
const zoomOut = React.useCallback(() => {
30+
actions.zoomOut()
31+
}, [actions])
32+
33+
const resetZoom = React.useCallback(() => {
34+
actions.resetZoom()
35+
}, [actions])
36+
37+
React.useEffect(() => {
38+
const handleKeyDown = (e: KeyboardEvent) => {
39+
if (e.ctrlKey) {
40+
if (e.key === '=' || e.key === '+') {
41+
e.preventDefault()
42+
zoomIn()
43+
} else if (e.key === '-') {
44+
e.preventDefault()
45+
zoomOut()
46+
} else if (e.key === '0') {
47+
e.preventDefault()
48+
resetZoom()
49+
}
50+
}
51+
}
52+
53+
window.addEventListener('keydown', handleKeyDown)
54+
55+
// Set up Electron IPC listeners
56+
if (effects.platform.isElectron()) {
57+
window.electronAPI.onZoomIn(zoomIn)
58+
window.electronAPI.onZoomOut(zoomOut)
59+
window.electronAPI.onZoomReset(resetZoom)
60+
}
61+
62+
return () => {
63+
window.removeEventListener('keydown', handleKeyDown)
64+
}
65+
}, [zoomIn, zoomOut, resetZoom])
66+
67+
const value = React.useMemo(
68+
() => ({
69+
zoomLevel: state.zoom.level,
70+
zoomIn,
71+
zoomOut,
72+
resetZoom,
73+
}),
74+
[state.zoom.level, zoomIn, zoomOut, resetZoom]
75+
)
76+
77+
return <ZoomContext.Provider value={value}>{children}</ZoomContext.Provider>
78+
}
79+
80+
export const useZoom = () => React.useContext(ZoomContext)

packages/overmind-devtools-client/src/overmind/actions.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,21 @@ export const handleSplitPaneMove = (
434434
export const stopSplitPaneDrag = ({ state }: Context) => {
435435
state.splitPane.isDragging = false
436436
}
437+
438+
export const zoomIn = ({ state }: Context) => {
439+
state.zoom.level = Math.min(
440+
state.zoom.max,
441+
state.zoom.level + state.zoom.step
442+
)
443+
}
444+
445+
export const zoomOut = ({ state }: Context) => {
446+
state.zoom.level = Math.max(
447+
state.zoom.min,
448+
state.zoom.level - state.zoom.step
449+
)
450+
}
451+
452+
export const resetZoom = ({ state }: Context) => {
453+
state.zoom.level = 1
454+
}

packages/overmind-devtools-client/src/overmind/state.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ type State = {
5959
splitType: string
6060
containerSize: number
6161
}
62+
zoom: {
63+
level: number
64+
min: number
65+
max: number
66+
step: number
67+
}
6268
}
6369

6470
const state: State = {
@@ -270,6 +276,12 @@ const state: State = {
270276
splitType: 'vertical',
271277
containerSize: 0,
272278
},
279+
zoom: {
280+
level: 1,
281+
min: 0.5,
282+
max: 2,
283+
step: 0.1,
284+
},
273285
}
274286

275287
export default state

packages/overmind-devtools-client/src/types.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ declare global {
1010
electronAPI?: {
1111
setNewPort: (port: number) => void
1212
restart: () => void
13+
onZoomIn: (callback: () => void) => void
14+
onZoomOut: (callback: () => void) => void
15+
onZoomReset: (callback: () => void) => void
1316
}
1417

1518
// VSCode environment

0 commit comments

Comments
 (0)