Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cf40e22

Browse files
committedFeb 4, 2024
feat: new navigation UX with sidebar
1 parent 1089964 commit cf40e22

File tree

12 files changed

+490
-378
lines changed

12 files changed

+490
-378
lines changed
 
Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
11
.v-popper__popper.v-popper--theme-tooltip code {
22
@apply bg-gray-500/50 rounded px-1 text-[11px] font-mono;
33
}
4-
5-
/* @TODO remove when vue-ui style is updated */
6-
7-
.vue-ui-group:not(.vertical) > .indicator > .content {
8-
margin: 0 12px;
9-
width: calc(100% - 24px);
10-
}

‎packages/app-frontend/src/assets/style/index.styl

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,6 @@ button:focus
6464
.vue-ui-icon svg
6565
fill currentColor
6666

67-
.preferences
68-
display flex
69-
flex-wrap wrap
70-
padding 12px 4px
71-
72-
> *
73-
margin 16px 24px
74-
75-
.vue-ui-form-field
76-
> .wrapper > .content
77-
min-height 32px
78-
justify-content center
79-
8067
// Popover
8168

8269
.v-popper--theme-dropdown

‎packages/app-frontend/src/features/App.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import { darkMode } from '@front/util/theme'
1919
import { useAppConnection } from './connection'
2020
import { showAppsSelector } from './header/header'
21+
import { useOrientation } from './layout/orientation'
2122
2223
const chromeTheme = isChrome ? chrome.devtools.panels.themeName : undefined
2324
@@ -72,20 +73,24 @@ export default defineComponent({
7273
}
7374
})
7475
76+
const { orientation } = useOrientation()
77+
7578
return {
7679
isConnected,
7780
isInitializing,
7881
showAppsSelector,
82+
orientation,
7983
}
8084
},
8185
})
8286
</script>
8387

8488
<template>
8589
<div
86-
class="app w-full h-full flex flex-col relative outline-none"
90+
class="app w-full h-full flex relative outline-none"
8791
:class="{
88-
'disconnected pointer-events-none': !isInitializing && !isConnected
92+
'disconnected pointer-events-none': !isInitializing && !isConnected,
93+
'flex-col': orientation === 'portrait',
8994
}"
9095
tabindex="0"
9196
>

‎packages/app-frontend/src/features/apps/AppSelect.vue

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,30 +86,14 @@ export default defineComponent({
8686
>
8787
<template #trigger>
8888
<VueButton
89-
class="flat"
90-
icon-left="wysiwyg"
91-
:icon-right="orientation === 'landscape' ? 'arrow_drop_down' : null"
92-
:class="{
93-
'icon-button': orientation === 'portrait'
94-
}"
89+
class="flat icon-button"
9590
>
96-
<div class="flex items-center space-x-2">
97-
<template v-if="orientation === 'landscape'">
98-
<span v-if="currentApp">
99-
{{ currentApp.name }}
100-
</span>
101-
<span
102-
v-else
103-
class="opacity-50"
104-
>
105-
No app
106-
</span>
107-
</template>
108-
91+
<div class="flex items-center space-x-2 relative">
92+
<img src="~@front/assets/vue-logo.svg" class="w-8 h-8">
10993
<VueIcon
11094
v-if="hasNewVueVersion"
11195
icon="new_releases"
112-
class="text-green-500"
96+
class="text-green-400 absolute right-0 bottom-0 w-4 h-4"
11397
/>
11498
</div>
11599
</VueButton>

‎packages/app-frontend/src/features/components/ComponentsInspector.vue

Lines changed: 95 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -105,18 +105,101 @@ export default defineComponent({
105105
>
106106
<template #left>
107107
<div class="flex flex-col h-full">
108-
<VueInput
109-
ref="treeFilterInput"
110-
v-model="treeFilter"
111-
v-tooltip="{
112-
content: $t('ComponentTree.filter.tooltip'),
113-
html: true
114-
}"
115-
icon-left="search"
116-
placeholder="Find components..."
117-
select-all
118-
class="search flat border-b border-gray-200 dark:border-gray-800 !min-w-0"
119-
/>
108+
<div class="flex items-center border-b border-gray-200 dark:border-gray-800">
109+
<VueInput
110+
ref="treeFilterInput"
111+
v-model="treeFilter"
112+
v-tooltip="{
113+
content: $t('ComponentTree.filter.tooltip'),
114+
html: true
115+
}"
116+
icon-left="search"
117+
placeholder="Find components..."
118+
select-all
119+
class="search flat !min-w-0 flex-1"
120+
/>
121+
122+
<VueButton
123+
v-tooltip="{
124+
content: $t('ComponentTree.select.tooltip'),
125+
html: true
126+
}"
127+
class="icon-button flat"
128+
icon-left="gps_fixed"
129+
@click="startPickingComponent()"
130+
/>
131+
132+
<VueButton
133+
v-tooltip="{
134+
content: $t('ComponentTree.refresh.tooltip'),
135+
html: true
136+
}"
137+
class="icon-button flat"
138+
:class="{
139+
'animate-icon': animateRefresh,
140+
}"
141+
icon-left="refresh"
142+
@click="refresh()"
143+
/>
144+
145+
<VueDropdown
146+
placement="bottom-end"
147+
>
148+
<template #trigger>
149+
<VueButton
150+
icon-left="more_vert"
151+
class="icon-button flat"
152+
/>
153+
</template>
154+
155+
<div class="space-y-1 px-3 py-2 text-sm">
156+
<div>Component names:</div>
157+
158+
<VueGroup
159+
v-model="$shared.componentNameStyle"
160+
>
161+
<VueGroupButton
162+
value="original"
163+
label="Original"
164+
/>
165+
<VueGroupButton
166+
value="class"
167+
label="PascalCase"
168+
/>
169+
<VueGroupButton
170+
value="kebab"
171+
label="kebab-case"
172+
/>
173+
</VueGroup>
174+
</div>
175+
176+
<div class="space-y-1 px-3 py-2 text-sm">
177+
<VueSwitch v-model="$shared.editableProps">
178+
Editable props
179+
</VueSwitch>
180+
<div class="flex items-center space-x-1 text-xs opacity-50">
181+
<VueIcon
182+
icon="warning"
183+
class="w-4 h-4 flex-none"
184+
/>
185+
<span>May print warnings in the console</span>
186+
</div>
187+
</div>
188+
189+
<div class="space-y-1 px-3 py-2 text-sm">
190+
<VueSwitch v-model="$shared.flashUpdates">
191+
Highlight updates
192+
</VueSwitch>
193+
<div class="flex items-center space-x-1 text-xs opacity-50">
194+
<VueIcon
195+
icon="warning"
196+
class="w-4 h-4 flex-none"
197+
/>
198+
<span>Don't enable if you are sensitive to flashing</span>
199+
</div>
200+
</div>
201+
</VueDropdown>
202+
</div>
120203

121204
<div
122205
ref="treeScroller"
@@ -136,82 +219,6 @@ export default defineComponent({
136219
</template>
137220
</SplitPane>
138221

139-
<SafeTeleport to="#more-menu">
140-
<div class="space-y-1 px-3 py-2 text-sm">
141-
<div>Component names:</div>
142-
143-
<VueGroup
144-
v-model="$shared.componentNameStyle"
145-
>
146-
<VueGroupButton
147-
value="original"
148-
label="Original"
149-
/>
150-
<VueGroupButton
151-
value="class"
152-
label="PascalCase"
153-
/>
154-
<VueGroupButton
155-
value="kebab"
156-
label="kebab-case"
157-
/>
158-
</VueGroup>
159-
</div>
160-
161-
<div class="space-y-1 px-3 py-2 text-sm">
162-
<VueSwitch v-model="$shared.editableProps">
163-
Editable props
164-
</VueSwitch>
165-
<div class="flex items-center space-x-1 text-xs opacity-50">
166-
<VueIcon
167-
icon="warning"
168-
class="w-4 h-4 flex-none"
169-
/>
170-
<span>May print warnings in the console</span>
171-
</div>
172-
</div>
173-
174-
<div class="space-y-1 px-3 py-2 text-sm">
175-
<VueSwitch v-model="$shared.flashUpdates">
176-
Highlight updates
177-
</VueSwitch>
178-
<div class="flex items-center space-x-1 text-xs opacity-50">
179-
<VueIcon
180-
icon="warning"
181-
class="w-4 h-4 flex-none"
182-
/>
183-
<span>Don't enable if you are sensitive to flashing</span>
184-
</div>
185-
</div>
186-
187-
<div class="border-t border-gray-200 dark:border-gray-800 my-1" />
188-
</SafeTeleport>
189-
190-
<SafeTeleport to="#header-end">
191-
<VueButton
192-
v-tooltip="{
193-
content: $t('ComponentTree.select.tooltip'),
194-
html: true
195-
}"
196-
class="icon-button flat"
197-
icon-left="gps_fixed"
198-
@click="startPickingComponent()"
199-
/>
200-
201-
<VueButton
202-
v-tooltip="{
203-
content: $t('ComponentTree.refresh.tooltip'),
204-
html: true
205-
}"
206-
class="icon-button flat"
207-
:class="{
208-
'animate-icon': animateRefresh,
209-
}"
210-
icon-left="refresh"
211-
@click="refresh()"
212-
/>
213-
</SafeTeleport>
214-
215222
<SafeTeleport to="#root">
216223
<div
217224
v-if="pickingComponent"

‎packages/app-frontend/src/features/header/AppHeader.vue

Lines changed: 151 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ import { useInspectors } from '@front/features/inspector/custom/composable'
1414
import { useTabs } from './tabs'
1515
import { showAppsSelector } from './header'
1616
import { useOrientation } from '../layout/orientation'
17+
import { type Plugin, usePlugins } from '../plugin/index'
1718
1819
interface HeaderRoute {
1920
icon: string
2021
label: string
2122
targetRoute: RouteLocationRaw
2223
matchRoute: (route: RouteLocation) => boolean
2324
pluginId?: string
25+
plugin?: Plugin
2426
}
2527
2628
export default defineComponent({
@@ -35,6 +37,16 @@ export default defineComponent({
3537
setup () {
3638
const route = useRoute()
3739
40+
// Plugins
41+
42+
const {
43+
plugins,
44+
} = usePlugins()
45+
46+
function getPlugin (pluginId: string) {
47+
return plugins.value.find(p => p.id === pluginId)
48+
}
49+
3850
// Inspector routes
3951
4052
const { inspectors: customInspectors } = useInspectors()
@@ -56,10 +68,26 @@ export default defineComponent({
5668
icon: i.icon || 'tab',
5769
label: i.label,
5870
pluginId: i.pluginId,
71+
plugin: getPlugin(i.pluginId),
5972
targetRoute: { name: 'custom-inspector', params: { inspectorId: i.id } },
6073
matchRoute: route => route.params.inspectorId === i.id,
6174
}))))
6275
76+
const routesPerPlugin = computed(() => {
77+
const routes: Record<string, HeaderRoute[]> = {}
78+
for (const route of headerRoutes.value) {
79+
if (route.pluginId) {
80+
if (!routes[route.pluginId]) {
81+
routes[route.pluginId] = []
82+
}
83+
routes[route.pluginId].push(route)
84+
}
85+
}
86+
return routes
87+
})
88+
89+
const logoErrors = ref(new Set<string>())
90+
6391
const currentHeaderRoute = computed(() => headerRoutes.value.find(r => r.matchRoute(route)))
6492
6593
const lastHeaderRoute = ref(null)
@@ -69,6 +97,13 @@ export default defineComponent({
6997
}
7098
})
7199
100+
function shouldDisplayLogo (item: HeaderRoute) {
101+
if (item.pluginId?.startsWith('org.vuejs')) {
102+
return false
103+
}
104+
return item.plugin?.logo && routesPerPlugin.value[item.pluginId]?.length < 2 && !logoErrors.value.has(item.pluginId)
105+
}
106+
72107
// Current tab
73108
const { currentTab } = useTabs()
74109
const { bridge } = useBridge()
@@ -89,139 +124,140 @@ export default defineComponent({
89124
lastHeaderRoute,
90125
showAppsSelector,
91126
orientation,
127+
routesPerPlugin,
128+
logoErrors,
129+
shouldDisplayLogo,
92130
}
93131
},
94132
})
95133
</script>
96134

97135
<template>
98-
<div class="flex items-center space-x-2 px-2 h-8 box-content">
99-
<AppHistoryNav />
100-
101-
<template v-if="showAppsSelector">
102-
<AppSelect />
136+
<div class="flex items-center border-r border-gray-200 dark:border-gray-800 p-0.5"
137+
:class="{
138+
'flex-col': orientation === 'landscape',
139+
}"
140+
>
141+
<AppSelect v-if="showAppsSelector"/>
142+
<img
143+
v-else
144+
src="~@front/assets/vue-logo.svg"
145+
class="w-8 h-8"
146+
>
103147

104-
<img src="~@front/assets/breadcrumb-separator.svg">
105-
</template>
106-
107-
<template v-if="orientation === 'portrait' || headerRoutes.length * 200 > $responsive.width.value - 250">
108-
<AppHeaderSelect
109-
:items="headerRoutes"
110-
:selected-item="currentHeaderRoute"
111-
@select="route => $router.push(route.targetRoute)"
148+
<VueGroup
149+
:model-value="currentHeaderRoute"
150+
class="primary"
151+
:class="{
152+
vertical: orientation === 'landscape',
153+
}"
154+
indicator
155+
@update:modelValue="(route: HeaderRoute) => route && $router.push(route.targetRoute)"
156+
>
157+
<VTooltip
158+
v-for="(item, index) of headerRoutes"
159+
:key="index"
160+
placement="right"
161+
class="leading-none"
112162
>
113-
<template #default="{ item }">
114-
<div class="flex items-center space-x-2">
115-
<span class="flex-1">{{ item.label }}</span>
116-
<PluginSourceIcon
117-
v-if="item.pluginId"
118-
:plugin-id="item.pluginId"
119-
class="flex-none"
120-
/>
121-
</div>
122-
</template>
123-
</AppHeaderSelect>
124-
</template>
125-
126-
<template v-else>
127-
<VueGroup
128-
:model-value="currentHeaderRoute"
129-
class="primary"
130-
indicator
131-
@update:modelValue="(route: HeaderRoute) => route && $router.push(route.targetRoute)"
132-
>
133-
<VTooltip
134-
v-for="(item, index) of headerRoutes"
135-
:key="index"
136-
:disabled="!item.pluginId"
137-
class="leading-none"
163+
<VueGroupButton
164+
:value="item"
165+
:icon-left="shouldDisplayLogo(item) ? null : item.icon"
166+
class="flat icon-button"
138167
>
139-
<VueGroupButton
140-
:value="item"
141-
:icon-left="item.icon"
142-
class="flat"
143-
>
144-
{{ item.label }}
145-
</VueGroupButton>
146-
147-
<template #popper>
148-
<PluginSourceDescription
149-
:plugin-id="item.pluginId"
150-
/>
151-
</template>
152-
</VTooltip>
153-
</VueGroup>
154-
</template>
168+
<img
169+
v-if="shouldDisplayLogo(item)"
170+
:src="item.plugin.logo"
171+
class="w-4 h-4"
172+
@error="logoErrors.add(item.pluginId)"
173+
/>
174+
</VueGroupButton>
175+
176+
<template #popper>
177+
<div class="font-bold">{{ item.label }}</div>
178+
<PluginSourceDescription
179+
v-if="item.pluginId"
180+
:plugin-id="item.pluginId"
181+
class="mt-2"
182+
/>
183+
</template>
184+
</VTooltip>
185+
</VueGroup>
155186

156187
<div class="flex-1" />
157188

158-
<div class="flex items-center">
159-
<TeleportTarget
160-
id="header-end"
161-
class="flex items-center"
189+
<VueDropdown
190+
:placement="orientation === 'landscape' ? 'right' : 'bottom-end'"
191+
>
192+
<template #trigger>
193+
<VueButton
194+
icon-left="settings"
195+
class="icon-button flat"
196+
/>
197+
</template>
198+
199+
<AppHistoryNav
200+
class="px-2 py-1"
162201
/>
163-
<VueDropdown
164-
:offset="[0, 0]"
202+
203+
<VueDropdownButton
204+
:to="{
205+
name: 'global-settings'
206+
}"
207+
icon-left="settings"
165208
>
166-
<template #trigger>
167-
<VueButton
168-
icon-left="more_vert"
169-
class="icon-button flat"
170-
/>
171-
</template>
209+
More settings
210+
</VueDropdownButton>
172211

173-
<TeleportTarget id="more-menu" />
212+
<VueDropdownButton
213+
:to="{
214+
name: 'plugins'
215+
}"
216+
icon-left="extension"
217+
>
218+
Devtools plugins
219+
</VueDropdownButton>
174220

175-
<VueDropdownButton
176-
:to="{
177-
name: 'plugins'
178-
}"
179-
icon-left="extension"
180-
>
181-
Devtools plugins
182-
</VueDropdownButton>
221+
<div class="border-t border-gray-200 dark:border-gray-800 my-1" />
183222

184-
<VueDropdownButton
185-
:to="{
186-
name: 'global-settings'
187-
}"
188-
icon-left="settings"
189-
>
190-
Global settings
191-
</VueDropdownButton>
223+
<VueDropdownButton
224+
href="https://devtools.vuejs.org"
225+
target="_blank"
226+
icon-left="description"
227+
icon-right="open_in_new"
228+
class="right-icon-reveal"
229+
>
230+
Documentation
231+
</VueDropdownButton>
192232

193-
<div class="border-t border-gray-200 dark:border-gray-800 my-1" />
233+
<VueDropdownButton
234+
href="https://github.com/vuejs/devtools/issues/new/choose"
235+
target="_blank"
236+
icon-left="bug_report"
237+
icon-right="open_in_new"
238+
class="right-icon-reveal"
239+
>
240+
Report a bug
241+
</VueDropdownButton>
194242

195-
<VueDropdownButton
196-
href="https://devtools.vuejs.org"
197-
target="_blank"
198-
icon-left="description"
199-
icon-right="open_in_new"
200-
class="right-icon-reveal"
201-
>
202-
Documentation
203-
</VueDropdownButton>
204-
205-
<VueDropdownButton
206-
href="https://github.com/vuejs/devtools/issues/new/choose"
207-
target="_blank"
208-
icon-left="bug_report"
209-
icon-right="open_in_new"
210-
class="right-icon-reveal"
211-
>
212-
Report a bug
213-
</VueDropdownButton>
214-
215-
<VueDropdownButton
216-
href="https://github.com/vuejs/vue-devtools/releases"
217-
target="_blank"
218-
icon-left="campaign"
219-
icon-right="open_in_new"
220-
class="right-icon-reveal"
221-
>
222-
What's new
223-
</VueDropdownButton>
224-
</VueDropdown>
225-
</div>
243+
<VueDropdownButton
244+
href="https://github.com/vuejs/vue-devtools/releases"
245+
target="_blank"
246+
icon-left="campaign"
247+
icon-right="open_in_new"
248+
class="right-icon-reveal"
249+
>
250+
What's new
251+
</VueDropdownButton>
252+
</VueDropdown>
226253
</div>
227254
</template>
255+
256+
<style lang="postcss" scoped>
257+
.vue-ui-group :deep(.indicator) {
258+
@apply !p-0.5;
259+
.content {
260+
@apply !border !border-green-500/30 rounded-md bg-green-500/10;
261+
}
262+
}
263+
</style>

‎packages/app-frontend/src/features/header/AppHeaderSelect.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export default defineComponent({
157157
<template>
158158
<VueDropdown
159159
v-model="isShown"
160-
placement="bottom-start"
160+
:placement="orientation === 'landscape' ? 'right-start' : 'bottom-start'"
161161
:triggers="[]"
162162
:offset="[0, 0]"
163163
:delay="0"

‎packages/app-frontend/src/features/inspector/custom/CustomInspector.vue

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,26 @@ export default defineComponent({
9696
class="search flat !min-w-0 flex-1 mr-2"
9797
/>
9898

99+
<template v-if="inspector?.actions">
100+
<VueButton
101+
v-for="(action, index) of inspector.actions"
102+
:key="index"
103+
v-tooltip="action.tooltip"
104+
class="icon-button flat"
105+
:icon-left="action.icon"
106+
@click="executeCustomAction(index)"
107+
/>
108+
</template>
109+
<VueButton
110+
v-tooltip="'Refresh'"
111+
class="icon-button flat"
112+
icon-left="refresh"
113+
@click="refreshInspector()"
114+
/>
115+
99116
<PluginSourceIcon
100117
:plugin-id="inspector.pluginId"
118+
class="ml-2"
101119
/>
102120
</div>
103121

@@ -120,25 +138,6 @@ export default defineComponent({
120138
<CustomInspectorSelectedNodePane />
121139
</template>
122140
</SplitPane>
123-
124-
<SafeTeleport to="#header-end">
125-
<template v-if="inspector?.actions">
126-
<VueButton
127-
v-for="(action, index) of inspector.actions"
128-
:key="index"
129-
v-tooltip="action.tooltip"
130-
class="icon-button flat"
131-
:icon-left="action.icon"
132-
@click="executeCustomAction(index)"
133-
/>
134-
</template>
135-
<VueButton
136-
v-tooltip="'Refresh'"
137-
class="icon-button flat"
138-
icon-left="refresh"
139-
@click="refreshInspector()"
140-
/>
141-
</SafeTeleport>
142141
</div>
143142
<EmptyPane
144143
v-else

‎packages/app-frontend/src/features/plugin/Plugins.vue

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,25 @@ export default defineComponent({
4747
>
4848
<template #left>
4949
<div class="h-full flex flex-col">
50-
<div class="flex-none">
50+
<div class="flex-none flex items-center border-b border-gray-200 dark:border-gray-800">
5151
<VueInput
5252
v-model="search"
5353
icon-left="search"
5454
placeholder="Filter devtools plugins..."
5555
select-all
56-
class="w-full flat border-b border-gray-200 dark:border-gray-800"
56+
class="flex-1 w-0 flat"
5757
/>
58+
59+
<VueButton
60+
:to="{
61+
name: 'global-settings'
62+
}"
63+
icon-left="settings"
64+
icon-right="arrow_forward"
65+
class="flat"
66+
>
67+
Global settings
68+
</VueButton>
5869
</div>
5970
<div class="overflow-y-auto">
6071
<PluginListItem
@@ -72,18 +83,6 @@ export default defineComponent({
7283
</div>
7384
</template>
7485
</SplitPane>
75-
76-
<SafeTeleport to="#header-end">
77-
<VueButton
78-
:to="{
79-
name: 'global-settings'
80-
}"
81-
icon-left="settings"
82-
class="flat"
83-
>
84-
Global settings
85-
</VueButton>
86-
</SafeTeleport>
8786
</div>
8887
</template>
8988

‎packages/app-frontend/src/features/settings/GlobalSettings.vue

Lines changed: 115 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,49 @@
1-
<script lang="ts">
2-
import { defineComponent } from 'vue'
1+
<script lang="ts" setup>
2+
import { ref } from 'vue'
3+
import { supportsScreenshot } from '../timeline/composable/screenshot'
34
4-
// import NewTag from './NewTag.vue'
5+
type Tab = 'global' | 'components' | 'timeline'
56
6-
// export default {
7-
// components: {
8-
// NewTag
9-
// }
10-
// }
11-
12-
export default defineComponent({})
7+
const tab = ref<Tab>('global')
138
</script>
149

1510
<template>
16-
<div class="global-preferences">
17-
<div class="preferences">
11+
<div class="global-preferences p-6">
12+
<nav class="flex items-center gap-2 pb-4">
13+
<VueGroup
14+
v-model="tab"
15+
indicator
16+
>
17+
<VueGroupButton
18+
value="global"
19+
label="Global"
20+
class="flat"
21+
/>
22+
<VueGroupButton
23+
value="components"
24+
label="Components"
25+
class="flat"
26+
/>
27+
<VueGroupButton
28+
value="timeline"
29+
label="Timeline"
30+
class="flat"
31+
/>
32+
</VueGroup>
33+
34+
<VueButton
35+
:to="{
36+
name: 'plugins'
37+
}"
38+
icon-left="extension"
39+
icon-right="arrow_forward"
40+
class="flat"
41+
>
42+
Plugin settings
43+
</VueButton>
44+
</nav>
45+
46+
<div v-if="tab === 'global'" class="preferences flex flex-wrap gap-8">
1847
<VueFormField title="Theme">
1948
<VueGroup
2049
v-model="$shared.theme"
@@ -81,16 +110,80 @@ export default defineComponent({})
81110
</VueFormField>
82111
</div>
83112

84-
<SafeTeleport to="#header-end">
85-
<VueButton
86-
:to="{
87-
name: 'plugins'
88-
}"
89-
icon-left="extension"
90-
class="flat"
113+
<div v-if="tab === 'components'" class="preferences flex flex-wrap gap-8">
114+
<VueFormField
115+
title="Component names"
91116
>
92-
Plugin settings
93-
</VueButton>
94-
</SafeTeleport>
117+
<VueGroup
118+
v-model="$shared.componentNameStyle"
119+
>
120+
<VueGroupButton
121+
value="original"
122+
label="Original"
123+
/>
124+
<VueGroupButton
125+
value="class"
126+
label="PascalCase"
127+
/>
128+
<VueGroupButton
129+
value="kebab"
130+
label="kebab-case"
131+
/>
132+
</VueGroup>
133+
</VueFormField>
134+
135+
<VueFormField
136+
title="Editable props"
137+
>
138+
<VueSwitch v-model="$shared.editableProps">
139+
Enable
140+
</VueSwitch>
141+
<template #subtitle>
142+
May print warnings in the console
143+
</template>
144+
</VueFormField>
145+
146+
<VueFormField
147+
title="Highlight updates"
148+
>
149+
<VueSwitch v-model="$shared.flashUpdates">
150+
Enable
151+
</VueSwitch>
152+
<template #subtitle>
153+
Don't enable if you are sensitive to flashing
154+
</template>
155+
</VueFormField>
156+
</div>
157+
158+
<div v-if="tab === 'timeline'" class="preferences flex flex-wrap gap-8">
159+
<VueFormField
160+
title="Time grid"
161+
>
162+
<VueSwitch v-model="$shared.timelineTimeGrid">
163+
Enable
164+
</VueSwitch>
165+
</VueFormField>
166+
167+
<VueFormField
168+
v-if="supportsScreenshot"
169+
title="Screenshots"
170+
>
171+
<VueSwitch v-model="$shared.timelineScreenshots">
172+
Enable
173+
</VueSwitch>
174+
</VueFormField>
175+
</div>
95176
</div>
96177
</template>
178+
179+
<style lang="postcss" scoped>
180+
.preferences {
181+
182+
.vue-ui-form-field {
183+
> .wrapper > .content {
184+
min-height: 32px;
185+
justify-content: center;
186+
}
187+
}
188+
}
189+
</style>

‎packages/app-frontend/src/features/timeline/Timeline.vue

Lines changed: 83 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,88 @@ export default defineComponent({
337337
>
338338
<template #left>
339339
<div class="flex flex-col h-full">
340-
<div class="h-4 flex-none border-b border-gray-200 dark:border-gray-800 box-content" />
340+
<div class="h-8 flex-none border-b border-gray-200 dark:border-gray-800 box-content flex items-center">
341+
<VueDropdown>
342+
<template #trigger>
343+
<VueButton
344+
v-tooltip="'Select layers'"
345+
class="flat"
346+
icon-left="layers"
347+
>
348+
{{ layers.length }} layer{{ layers.length === 1 ? '' : 's' }}
349+
</VueButton>
350+
</template>
351+
352+
<div
353+
style="max-height: 250px;"
354+
class="overflow-x-hidden overflow-y-auto"
355+
>
356+
<div class="flex flex-col">
357+
<VueSwitch
358+
v-for="layer of allLayers"
359+
:key="layer.id"
360+
:model-value="!isLayerHidden(layer)"
361+
class="extend-left px-2 py-1 hover:bg-green-100 dark:hover:bg-green-900"
362+
@update:modelValue="value => setLayerHidden(layer, !value)"
363+
>
364+
<div class="flex items-center space-x-2 max-w-xs">
365+
<div
366+
class="flex-none w-3 h-3 rounded-full"
367+
:style="{
368+
backgroundColor: `#${layer.color.toString(16).padStart(6, '0')}`
369+
}"
370+
/>
371+
372+
<div class="flex-1 truncate">
373+
{{ layer.label }}
374+
</div>
375+
376+
<PluginSourceIcon
377+
v-if="layer.pluginId"
378+
:plugin-id="layer.pluginId"
379+
class="flex-none"
380+
/>
381+
</div>
382+
</VueSwitch>
383+
</div>
384+
</div>
385+
</VueDropdown>
386+
387+
<VueButton
388+
v-tooltip="'Clear all timelines'"
389+
class="icon-button flat"
390+
icon-left="delete_sweep"
391+
@click="resetTimeline()"
392+
/>
393+
394+
<div class="flex-1" />
395+
396+
<VueDropdown
397+
placement="bottom-end"
398+
>
399+
<template #trigger>
400+
<VueButton
401+
icon-left="more_vert"
402+
class="icon-button flat"
403+
/>
404+
</template>
405+
406+
<VueSwitch
407+
v-model="$shared.timelineTimeGrid"
408+
class="w-full px-3 py-1 extend-left"
409+
>
410+
Time grid
411+
</VueSwitch>
412+
413+
<VueSwitch
414+
v-if="supportsScreenshot"
415+
v-model="$shared.timelineScreenshots"
416+
class="w-full px-3 py-1 extend-left"
417+
>
418+
Screenshots
419+
</VueSwitch>
420+
</VueDropdown>
421+
</div>
341422

342423
<div
343424
ref="layersEl"
@@ -371,7 +452,7 @@ export default defineComponent({
371452
>
372453
<template #left>
373454
<div class="h-full flex flex-col select-none">
374-
<div class="flex items-center flex-none border-b border-gray-200 dark:border-gray-800">
455+
<div class="h-8 flex items-center flex-none border-b border-gray-200 dark:border-gray-800">
375456
<VueButton
376457
icon-left="arrow_left"
377458
class="flex-none w-4 h-4 p-0 flat zoom-btn"
@@ -450,78 +531,6 @@ export default defineComponent({
450531
</template>
451532
</SplitPane>
452533

453-
<SafeTeleport to="#header-end">
454-
<VueDropdown>
455-
<template #trigger>
456-
<VueButton
457-
v-tooltip="'Select layers'"
458-
class="icon-button flat"
459-
icon-left="layers"
460-
/>
461-
</template>
462-
463-
<div
464-
style="max-height: 250px;"
465-
class="overflow-x-hidden overflow-y-auto"
466-
>
467-
<div class="flex flex-col">
468-
<VueSwitch
469-
v-for="layer of allLayers"
470-
:key="layer.id"
471-
:model-value="!isLayerHidden(layer)"
472-
class="extend-left px-2 py-1 hover:bg-green-100 dark:hover:bg-green-900"
473-
@update:modelValue="value => setLayerHidden(layer, !value)"
474-
>
475-
<div class="flex items-center space-x-2 max-w-xs">
476-
<div
477-
class="flex-none w-3 h-3 rounded-full"
478-
:style="{
479-
backgroundColor: `#${layer.color.toString(16).padStart(6, '0')}`
480-
}"
481-
/>
482-
483-
<div class="flex-1 truncate">
484-
{{ layer.label }}
485-
</div>
486-
487-
<PluginSourceIcon
488-
v-if="layer.pluginId"
489-
:plugin-id="layer.pluginId"
490-
class="flex-none"
491-
/>
492-
</div>
493-
</VueSwitch>
494-
</div>
495-
</div>
496-
</VueDropdown>
497-
498-
<VueButton
499-
v-tooltip="'Clear all timelines'"
500-
class="icon-button flat"
501-
icon-left="delete_sweep"
502-
@click="resetTimeline()"
503-
/>
504-
</SafeTeleport>
505-
506-
<SafeTeleport to="#more-menu">
507-
<VueSwitch
508-
v-model="$shared.timelineTimeGrid"
509-
class="w-full px-3 py-1 extend-left"
510-
>
511-
Time grid
512-
</VueSwitch>
513-
514-
<VueSwitch
515-
v-if="supportsScreenshot"
516-
v-model="$shared.timelineScreenshots"
517-
class="w-full px-3 py-1 extend-left"
518-
>
519-
Screenshots
520-
</VueSwitch>
521-
522-
<div class="border-t border-gray-200 dark:border-gray-800 my-1" />
523-
</SafeTeleport>
524-
525534
<AskScreenshotPermission
526535
v-if="askScreenshotPermission"
527536
class="ask-permission"

‎packages/app-frontend/src/features/timeline/TimelineScrollbar.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,13 @@ export default defineComponent({
153153
<template>
154154
<div
155155
ref="el"
156-
class="h-4 bg-gray-200 dark:bg-black relative select-none"
156+
class="h-6 bg-gray-200 dark:bg-gray-900 relative select-none"
157157
>
158158
<!-- Main Bar -->
159159
<div
160-
class="absolute h-full top-0 bg-white dark:bg-gray-800 hover:bg-green-200 dark:hover:bg-green-800 cursor-move"
160+
class="absolute h-full top-0 bg-green-200 dark:bg-green-900 hover:bg-green-100 dark:hover:bg-green-800 cursor-move"
161161
:class="{
162-
'bg-green-200 dark:bg-green-800': moving
162+
'bg-green-100 dark:bg-green-800': moving
163163
}"
164164
:style="{
165165
left: `${(start - min) / (max - min) * 100}%`,

0 commit comments

Comments
 (0)
Please sign in to comment.