Skip to content

Commit b20787d

Browse files
committed
feat: add tabs segment to switch between them
1 parent 7ee7d76 commit b20787d

File tree

10 files changed

+221
-5
lines changed

10 files changed

+221
-5
lines changed

examples/react/basic/vite.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ export default defineConfig({
1010
// },
1111
}),
1212
],
13+
ssr: {
14+
external: ['@tanstack/react-devtools'],
15+
},
1316
})
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { createEffect, createSignal } from 'solid-js'
2+
import { useDevtoolsState } from '../context/use-devtools-context'
3+
import { tabs } from '../tabs'
4+
import type { JSX } from 'solid-js';
5+
6+
export const TabContent = () => {
7+
const { state } = useDevtoolsState()
8+
const [component, setComponent] = createSignal<JSX.Element | null>(
9+
tabs.find((t) => t.id === state().activeTab)?.component || null,
10+
)
11+
createEffect(() => {
12+
setComponent(
13+
tabs.find((t) => t.id === state().activeTab)?.component || null,
14+
)
15+
})
16+
17+
return <div>{component()}</div>
18+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import clsx from 'clsx'
2+
import { For } from 'solid-js'
3+
import { useStyles } from '../styles/use-styles'
4+
import { useDevtoolsState } from '../context/use-devtools-context'
5+
import { tabs } from '../tabs'
6+
7+
interface TabsProps {
8+
toggleOpen: () => void
9+
}
10+
11+
export const Tabs = (props: TabsProps) => {
12+
const styles = useStyles()
13+
const { state, setState } = useDevtoolsState()
14+
15+
return (
16+
<div class={styles().tabContainer}>
17+
<For each={tabs}>
18+
{(tab) => (
19+
<button
20+
type="button"
21+
onClick={() => setState({ activeTab: tab.id })}
22+
class={clsx(styles().tab, { active: state().activeTab === tab.id })}
23+
>
24+
{tab.icon}
25+
</button>
26+
)}
27+
</For>
28+
<button
29+
type="button"
30+
class={clsx(styles().tab, 'close')}
31+
onClick={() => props.toggleOpen()}
32+
>
33+
<svg
34+
xmlns="http://www.w3.org/2000/svg"
35+
width="24"
36+
height="24"
37+
viewBox="0 0 24 24"
38+
fill="none"
39+
stroke="currentColor"
40+
stroke-width="2"
41+
stroke-linecap="round"
42+
stroke-linejoin="round"
43+
>
44+
<path d="M18 6 6 18" />
45+
<path d="m6 6 12 12" />
46+
</svg>
47+
</button>
48+
</div>
49+
)
50+
}

packages/devtools/src/context/devtools-store.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { TabName } from '../tabs'
12
import type { DevtoolsPlugin } from './devtools-context'
23

34
type ModifierKey = 'Alt' | 'Control' | 'Meta' | 'Shift'
@@ -51,7 +52,7 @@ export type DevtoolsStore = {
5152
urlFlag: string
5253
}
5354
state: {
54-
activeTab: string
55+
activeTab: TabName
5556
height: number
5657
activePlugin?: DevtoolsPlugin | undefined
5758
persistOpen: boolean
@@ -70,7 +71,7 @@ export const initialState: DevtoolsStore = {
7071
urlFlag: 'tanstack-devtools',
7172
},
7273
state: {
73-
activeTab: 'pages',
74+
activeTab: 'plugins',
7475
height: 400,
7576
activePlugin: undefined,
7677
persistOpen: false,

packages/devtools/src/context/use-devtools-context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const usePlugins = () => {
3636
return { plugins, setActivePlugin, activePlugin }
3737
} */
3838

39-
const useDevtoolsState = () => {
39+
export const useDevtoolsState = () => {
4040
const { store, setStore } = useDevtoolsContext()
4141
const state = createMemo(() => store.state)
4242
const setState = (newState: Partial<DevtoolsStore['state']>) => {

packages/devtools/src/devtools.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { TANSTACK_DEVTOOLS } from './utils/storage'
1010
import { Trigger } from './components/trigger'
1111
import { MainPanel } from './components/main-panel'
1212
import { ContentPanel } from './components/content-panel'
13+
import { Tabs } from './components/tabs'
14+
import { TabContent } from './components/tab-content'
1315

1416
export default function DevTools() {
1517
const { settings } = useDevtoolsSettings()
@@ -135,7 +137,8 @@ export default function DevTools() {
135137
ref={(ref) => (panelRef = ref)}
136138
handleDragStart={(e) => handleDragStart(panelRef, e)}
137139
>
138-
hello
140+
<Tabs toggleOpen={toggleOpen} />
141+
<TabContent />
139142
</ContentPanel>
140143
</MainPanel>
141144
</div>

packages/devtools/src/styles/use-styles.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const stylesFactory = () => {
7474
background-color: ${colors.darkGray[700]};
7575
color: ${colors.gray[300]};
7676
width: w-screen;
77-
flex-direction: column;
77+
flex-direction: row;
7878
overflow: auto;
7979
height: 100%;
8080
`,
@@ -144,6 +144,63 @@ const stylesFactory = () => {
144144
visibility: hidden;
145145
`
146146
},
147+
tabContainer: css`
148+
display: flex;
149+
flex-direction: column;
150+
align-items: center;
151+
justify-content: flex-start;
152+
height: 100%;
153+
background-color: ${colors.darkGray[800]};
154+
border-right: 1px solid ${colors.gray[700]};
155+
box-shadow: 0 1px 0 ${colors.gray[700]};
156+
position: relative;
157+
width: ${size[10]};
158+
`,
159+
160+
tab: css`
161+
display: flex;
162+
align-items: center;
163+
justify-content: center;
164+
width: 100%;
165+
height: ${size[10]};
166+
cursor: pointer;
167+
font-size: ${fontSize.sm};
168+
font-family: ${fontFamily.sans};
169+
color: ${colors.gray[300]};
170+
background-color: transparent;
171+
border: none;
172+
transition: all 0.2s ease-in-out;
173+
border-left: 2px solid transparent;
174+
&:hover:not(.close):not(.active) {
175+
background-color: ${colors.gray[700]};
176+
color: ${colors.gray[100]};
177+
border-left: 2px solid ${colors.purple[500]};
178+
}
179+
&.active {
180+
background-color: ${colors.purple[500]};
181+
color: ${colors.gray[100]};
182+
border-left: 2px solid ${colors.purple[500]};
183+
}
184+
&.close {
185+
margin-top: auto;
186+
&:hover {
187+
background-color: ${colors.gray[700]};
188+
}
189+
&:hover {
190+
color: ${colors.red[500]};
191+
}
192+
}
193+
194+
&.disabled {
195+
cursor: not-allowed;
196+
opacity: 0.2;
197+
pointer-events: none;
198+
}
199+
&.disabled:hover {
200+
background-color: transparent;
201+
color: ${colors.gray[300]};
202+
}
203+
`,
147204
}
148205
}
149206

packages/devtools/src/tabs/index.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { SettingsTab } from './settings-tab'
2+
import { PluginsTab } from './plugins-tab'
3+
import type { JSX } from 'solid-js/jsx-runtime'
4+
5+
export const tabs = [
6+
{
7+
name: 'Plugins',
8+
id: 'plugins',
9+
component: <PluginsTab />,
10+
icon: (
11+
<svg
12+
xmlns="http://www.w3.org/2000/svg"
13+
width="24"
14+
height="24"
15+
viewBox="0 0 24 24"
16+
fill="none"
17+
stroke="currentColor"
18+
stroke-width="2"
19+
stroke-linecap="round"
20+
stroke-linejoin="round"
21+
>
22+
<path d="M8 6h10" />
23+
<path d="M6 12h9" />
24+
<path d="M11 18h7" />
25+
</svg>
26+
),
27+
},
28+
{
29+
name: 'Settings',
30+
id: 'settings',
31+
component: <SettingsTab />,
32+
icon: (
33+
<svg
34+
xmlns="http://www.w3.org/2000/svg"
35+
width="24"
36+
height="24"
37+
viewBox="0 0 24 24"
38+
fill="none"
39+
stroke="currentColor"
40+
stroke-width="2"
41+
stroke-linecap="round"
42+
stroke-linejoin="round"
43+
>
44+
<path d="M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z" />
45+
<path d="M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z" />
46+
<path d="M12 2v2" />
47+
<path d="M12 22v-2" />
48+
<path d="m17 20.66-1-1.73" />
49+
<path d="M11 10.27 7 3.34" />
50+
<path d="m20.66 17-1.73-1" />
51+
<path d="m3.34 7 1.73 1" />
52+
<path d="M14 12h8" />
53+
<path d="M2 12h2" />
54+
<path d="m20.66 7-1.73 1" />
55+
<path d="m3.34 17 1.73-1" />
56+
<path d="m17 3.34-1 1.73" />
57+
<path d="m11 13.73-4 6.93" />
58+
</svg>
59+
),
60+
},
61+
] as const
62+
63+
export interface Tab {
64+
name: string
65+
icon: JSX.Element
66+
id: string
67+
component: JSX.Element
68+
}
69+
70+
export type TabName = (typeof tabs)[number]['id']
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const PluginsTab = () => {
2+
return (
3+
<div>
4+
Plugins
5+
</div>
6+
)
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const SettingsTab = () => {
2+
return (
3+
<div>
4+
Settings
5+
</div>
6+
)
7+
}

0 commit comments

Comments
 (0)