Skip to content

Commit fde948b

Browse files
committed
add ability to expand/collapse the toolbar
1 parent 6d0dd30 commit fde948b

7 files changed

Lines changed: 123 additions & 29 deletions

File tree

.changeset/curvy-cats-fetch.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@react-trace/ui-components": patch
3+
"@react-trace/core": patch
4+
---
5+
6+
Add ability to expand/collapse the toolbar
Lines changed: 97 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
import { ToolbarButton, Tooltip } from '@react-trace/ui-components'
1+
import {
2+
ChevronLeftIcon,
3+
ChevronRightIcon,
4+
ToolbarButton,
5+
Tooltip,
6+
} from '@react-trace/ui-components'
27
import { Logo } from '@react-trace/ui-components'
38
import { useAtom, useAtomValue } from 'jotai'
9+
import type { CSSProperties } from 'react'
410

511
import {
612
coreSettingsAtom,
@@ -20,42 +26,73 @@ const DEFAULT_SPACING = 32
2026

2127
const POSITION_STYLES: Record<
2228
NonNullable<TraceProps['position']>,
23-
React.CSSProperties
29+
CSSProperties
2430
> = {
2531
'bottom-right': { bottom: DEFAULT_SPACING, right: DEFAULT_SPACING },
2632
'bottom-left': { bottom: DEFAULT_SPACING, left: DEFAULT_SPACING },
2733
'top-right': { top: DEFAULT_SPACING, right: DEFAULT_SPACING },
2834
'top-left': { top: DEFAULT_SPACING, left: DEFAULT_SPACING },
2935
}
3036

37+
const MINIMIZED_POSITION_STYLES: Record<
38+
NonNullable<TraceProps['position']>,
39+
CSSProperties
40+
> = {
41+
'bottom-right': { bottom: DEFAULT_SPACING, right: 0 },
42+
'bottom-left': { bottom: DEFAULT_SPACING, left: 0 },
43+
'top-right': { top: DEFAULT_SPACING, right: 0 },
44+
'top-left': { top: DEFAULT_SPACING, left: 0 },
45+
}
46+
3147
const TOGGLE_SHORTCUT = IS_MAC ? 'Long-press ⌘X' : 'Long-press Ctrl+X'
3248

49+
const contentGridStyle: CSSProperties = {
50+
display: 'grid',
51+
transition: 'grid-template-columns 0.3s ease',
52+
}
53+
54+
const contentInnerStyle: CSSProperties = {
55+
overflow: 'hidden',
56+
minWidth: 0,
57+
display: 'flex',
58+
alignItems: 'center',
59+
}
60+
3361
export function Toolbar({ plugins }: ToolbarProps) {
3462
const [isInspectorActive, setInspectorActive] = useAtom(inspectorActiveAtom)
3563
const portalContainer = useAtomValue(portalContainerAtom)
36-
const coreSettings = useAtomValue(coreSettingsAtom)
64+
const [coreSettings, setCoreSettings] = useAtom(coreSettingsAtom)
3765

38-
return (
39-
<Tooltip.Provider delay={300}>
40-
<div
41-
style={{
42-
position: 'fixed',
43-
...POSITION_STYLES[coreSettings.position],
44-
display: 'flex',
45-
alignItems: 'center',
46-
background: '#18181b',
47-
borderRadius: 10,
48-
boxShadow: '0 4px 16px rgba(0,0,0,0.5)',
49-
outline: isInspectorActive
50-
? '2px solid #3b82f6'
51-
: '2px solid transparent',
52-
userSelect: 'none',
53-
height: 32,
54-
boxSizing: 'border-box',
55-
zIndex: 999999,
56-
}}
57-
>
58-
{/* Toggle button */}
66+
const minimized = coreSettings.minimized ?? false
67+
const isRightAligned = coreSettings.position.includes('right')
68+
69+
const toggleMinimized = () => {
70+
setCoreSettings({ ...coreSettings, minimized: !minimized })
71+
}
72+
73+
const CollapseArrow = isRightAligned ? ChevronRightIcon : ChevronLeftIcon
74+
const ExpandArrow = isRightAligned ? ChevronLeftIcon : ChevronRightIcon
75+
76+
const toggleButton = (
77+
<Tooltip
78+
label={minimized ? 'Expand toolbar' : 'Collapse toolbar'}
79+
container={portalContainer}
80+
render={<ToolbarButton style={{ width: 16, color: '#71717a' }} />}
81+
aria-label={minimized ? 'Expand toolbar' : 'Collapse toolbar'}
82+
onClick={toggleMinimized}
83+
>
84+
{minimized ? <ExpandArrow /> : <CollapseArrow />}
85+
</Tooltip>
86+
)
87+
88+
const toolbarContent = (
89+
<div
90+
style={{
91+
...contentGridStyle,
92+
gridTemplateColumns: minimized ? '0fr' : '1fr',
93+
}}
94+
>
95+
<div style={contentInnerStyle}>
5996
<Tooltip
6097
label="Inspector"
6198
shortcut={isInspectorActive ? 'Esc to exit' : TOGGLE_SHORTCUT}
@@ -66,7 +103,6 @@ export function Toolbar({ plugins }: ToolbarProps) {
66103
>
67104
<Logo />
68105
</Tooltip>
69-
{/* Plugin toolbar content */}
70106
{plugins
71107
.filter((plugin) => plugin.toolbar)
72108
.map((plugin) => {
@@ -79,6 +115,42 @@ export function Toolbar({ plugins }: ToolbarProps) {
79115
})}
80116
<SettingsMenu plugins={plugins} />
81117
</div>
118+
</div>
119+
)
120+
121+
return (
122+
<Tooltip.Provider delay={300}>
123+
<div
124+
style={{
125+
position: 'fixed',
126+
...(minimized
127+
? MINIMIZED_POSITION_STYLES[coreSettings.position]
128+
: POSITION_STYLES[coreSettings.position]),
129+
display: 'flex',
130+
alignItems: 'center',
131+
overflow: 'hidden',
132+
background: '#18181b',
133+
borderRadius: minimized
134+
? isRightAligned
135+
? '10px 0 0 10px'
136+
: '0 10px 10px 0'
137+
: 10,
138+
boxShadow: '0 4px 16px rgba(0,0,0,0.5)',
139+
outline: isInspectorActive
140+
? '2px solid #3b82f6'
141+
: '2px solid transparent',
142+
transition:
143+
'right 0.3s ease, left 0.3s ease, border-radius 0.3s ease',
144+
userSelect: 'none',
145+
height: 32,
146+
boxSizing: 'border-box',
147+
zIndex: 999999,
148+
}}
149+
>
150+
{!isRightAligned && toggleButton}
151+
{toolbarContent}
152+
{isRightAligned && toggleButton}
153+
</div>
82154
</Tooltip.Provider>
83155
)
84156
}

packages/core/src/hooks/useLongPressHotkey.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { useSetAtom } from 'jotai'
2-
import { useEffect } from 'react'
1+
import { useAtom, useSetAtom } from 'jotai'
2+
import { useEffect, useRef } from 'react'
33

4-
import { inspectorActiveAtom } from '../store'
4+
import { coreSettingsAtom, inspectorActiveAtom } from '../store'
55
import { IS_MAC } from '../utils/platform'
66

77
const LONGPRESS_MS = 600
@@ -13,6 +13,9 @@ const LONGPRESS_MS = 600
1313
*/
1414
export function useLongPressHotkey() {
1515
const setInspectorActive = useSetAtom(inspectorActiveAtom)
16+
const [coreSettings, setCoreSettings] = useAtom(coreSettingsAtom)
17+
const settingsRef = useRef(coreSettings)
18+
settingsRef.current = coreSettings
1619

1720
useEffect(() => {
1821
let timer: ReturnType<typeof setTimeout> | null = null
@@ -24,6 +27,9 @@ export function useLongPressHotkey() {
2427
timer = setTimeout(() => {
2528
timer = null
2629
setInspectorActive(true)
30+
if (settingsRef.current.minimized) {
31+
setCoreSettings({ ...settingsRef.current, minimized: false })
32+
}
2733
}, LONGPRESS_MS)
2834
}
2935
}

packages/core/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@ export interface TraceProps {
4545
export interface TraceSettings {
4646
core: {
4747
position: WidgetPosition
48+
minimized?: boolean
4849
}
4950
}

packages/ui-components/src/icons.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
2-
Clipboard,
2+
ChevronLeft,
33
ChevronRight,
4+
Clipboard,
45
ExternalLink,
56
Folder,
67
Maximize2,
@@ -29,6 +30,12 @@ export function XIcon({ size = DEFAULT_SIZE }: { size?: number }) {
2930
return <X size={size} strokeWidth={DEFAULT_STROKE_WIDTH} aria-hidden />
3031
}
3132

33+
export function ChevronLeftIcon({ size = DEFAULT_SIZE }: { size?: number }) {
34+
return (
35+
<ChevronLeft size={size} strokeWidth={DEFAULT_STROKE_WIDTH} aria-hidden />
36+
)
37+
}
38+
3239
export function ChevronRightIcon({ size = DEFAULT_SIZE }: { size?: number }) {
3340
return (
3441
<ChevronRight size={size} strokeWidth={DEFAULT_STROKE_WIDTH} aria-hidden />

packages/ui-components/src/index.prod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const PanelHeader = () => null
2020
export const Textarea = () => null
2121
export const Separator = () => null
2222

23+
export const ChevronLeftIcon = () => null
2324
export const ClipboardIcon = () => null
2425
export const XIcon = () => null
2526
export const ChevronRightIcon = () => null

packages/ui-components/src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export type { SeparatorProps } from './Separator'
2323

2424
export {
2525
ChatBubbleIcon,
26+
ChevronLeftIcon,
2627
ChevronRightIcon,
2728
ClipboardIcon,
2829
CollapseIcon,

0 commit comments

Comments
 (0)