Skip to content

Commit

Permalink
feat: help page for each tab (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Apr 23, 2023
1 parent 3075fc1 commit 5ce8df3
Show file tree
Hide file tree
Showing 34 changed files with 258 additions and 40 deletions.
1 change: 1 addition & 0 deletions packages/devtools-kit/src/_types/integrations.ts
Expand Up @@ -37,6 +37,7 @@ export interface NpmCommandOptions {
export interface AutoImportsWithMetadata {
imports: Import[]
metadata?: UnimportMeta
dirs: string[]
}

export interface RouteInfo extends Pick<RouteRecordNormalized, 'name' | 'path' | 'meta' | 'props' | 'children'> {
Expand Down
7 changes: 6 additions & 1 deletion packages/devtools/client/components/ComposableTree.vue
Expand Up @@ -13,7 +13,12 @@ defineProps<{
<div v-for="[key, value] of map.entries()" :key="key">
<FilepathItem :filepath="key" op50 hover:underline />
<div flex="~ wrap gap2" p2 pl4>
<ComposableItem v-for="i of value" :key="i.as" :item="i" :metadata="metadata" :filepath="key.match(/^[\w@]/) ? undefined : key" />
<ComposableItem
v-for="i of value" :key="i.as"
:item="i"
:metadata="metadata"
:filepath="key.match(/^[\w@]/) ? undefined : key"
/>
</div>
</div>
</div>
Expand Down
69 changes: 69 additions & 0 deletions packages/devtools/client/components/HelpFab.vue
@@ -0,0 +1,69 @@
<script setup lang="ts">
const props = defineProps<{
path: string
}>()
const { data } = useAsyncData(props.path, () => queryContent(props.path).findOne())
const open = ref(false)
const {
showHelpButtons,
} = useDevToolsSettings()
</script>

<template>
<template v-if="showHelpButtons">
<button
pos="absolute bottom-5 right-5"
border="~ base rounded-full "
flex="~ items-center justify-center"
z-110 h-11 w-11 backdrop-blur-8
bg="bg-base op50!" light:shadow
hover="bg-active"
title="Help"
@click="open = !open"
>
<div i-ri:question-mark />
</button>
<Transition name="fade-in">
<div
v-if="open"
class="fixed bottom-0 left-0 right-0 top-0 z-100"
bg-black:20 backdrop-blur-2 @click="open = false"
/>
</Transition>
<Transition name="slide-in">
<div
v-if="open" border="l base"
class="prose" pos="fixed bottom-0 right-0 top-0" z-200 w-150 px8 py4 bg-base
>
<ContentRenderer v-if="data" :value="data" />
<NIconButton
icon="carbon-close"
pos="absolute top-3 right-3"
rounded-full text-xl
@click="open = false"
/>
</div>
</Transition>
</template>
</template>

<style>
.slide-in-enter-active,
.slide-in-leave-active {
transition: transform 0.3s;
}
.slide-in-enter-from,
.slide-in-leave-to {
transform: translateX(100%);
}
.fade-in-enter-active,
.fade-in-leave-active {
transition: opacity 0.3s;
}
.fade-in-enter-from,
.fade-in-leave-to {
opacity: 0;
}
</style>
11 changes: 11 additions & 0 deletions packages/devtools/client/components/content/HelpImportsDirs.vue
@@ -0,0 +1,11 @@
<script setup lang="ts">
const imports = useAutoImports()
</script>

<template>
<div v-if="imports?.dirs" flex="~ col gap-2 items-start">
<template v-for="dir of imports.dirs" :key="dir">
<FilepathItem :filepath="dir" text-primary />
</template>
</div>
</template>
15 changes: 15 additions & 0 deletions packages/devtools/client/components/content/HelpImportsModules.vue
@@ -0,0 +1,15 @@
<script setup lang="ts">
const config = useAutoImports()
const modules = computed(() => {
return [...new Set(config.value?.imports.map(i => getModuleNameFromPath(i.from)).filter(x => Boolean(x) && !isBuiltInModule(x)))]
})
</script>

<template>
<div flex="~ gap-2 wrap" mb6>
<code v-for="name of modules" :key="name" rounded bg-primary:5 p="x2 y0.5" text-primary>
{{ name }}
</code>
</div>
</template>
22 changes: 22 additions & 0 deletions packages/devtools/client/components/content/HelpTip.vue
@@ -0,0 +1,22 @@
<script setup lang="ts">
defineProps<{
title: string
icon?: string
}>()
</script>

<template>
<div class="n-tip n-tip-base" flex="~ col items-start" mx--4 px4 py4>
<div flex="~ items-center gap-1" font-bold>
<NIcon v-if="icon" :icon="icon" class="n-tip-icon" />
<div>
{{ title }}
</div>
</div>
<div>
<slot>
<ContentSlot :use="$slots.default" unwrap="p" />
</slot>
</div>
</div>
</template>
@@ -0,0 +1,9 @@
<template>
<HelpTip
title="Performance Tip"
icon="carbon-meter"
n="lime6 dark:lime5"
>
<ContentSlot :use="$slots.default" unwrap="p" />
</HelpTip>
</template>
1 change: 1 addition & 0 deletions packages/devtools/client/composables/storage.ts
Expand Up @@ -11,6 +11,7 @@ const devToolsSettings = useLocalStorage<DevToolsUISettings>('nuxt-devtools-sett
componentsGraphShowWorkspace: true,
interactionCloseOnOutsideClick: false,
showExperimentalFeatures: false,
showHelpButtons: true,
scale: 1,
hiddenTabs: [],
hiddenTabCategories: [],
Expand Down
5 changes: 5 additions & 0 deletions packages/devtools/client/content/components.md
@@ -0,0 +1,5 @@
# Components

Vue components under the `components/` directory are automatically registered and can be used in your templates without importing them.

[Learn more on the documentation](https://nuxt.com/docs/guide/directory-structure/components)
5 changes: 5 additions & 0 deletions packages/devtools/client/content/hooks.md
@@ -0,0 +1,5 @@
# Hooks

Hooks are an advanced API mainly for module authors or advanced use cases. The hooking system to expand almost every aspect of Nuxt. It's powered by [unjs/hookable](https://github.com/unjs/hookable).

[Learn more about hooks](https://nuxt.com/docs/guide/going-further/hooks).
17 changes: 17 additions & 0 deletions packages/devtools/client/content/imports.md
@@ -0,0 +1,17 @@
# Auto imports

Nuxt auto-imports helper functions, composables and Vue APIs to use across your application without explicitly importing them. Based on the directory structure, every Nuxt application can also use auto-imports for its own components, composables and plugins. Components, composables or plugins can use these functions.

<hr>

According to your config, exports of files under the following folders will be registed as auto-imports entry:

:help-imports-dirs

Meanwhile, modules could also provide auto-imports for their own components. You have auto-imports from the following modules as well:

:help-imports-modules

<hr>

[Learn more on the documentation](https://nuxt.com/docs/guide/concepts/auto-imports)
5 changes: 5 additions & 0 deletions packages/devtools/client/content/modules.md
@@ -0,0 +1,5 @@
# Modules

Nuxt provides a module system to extend the framework core and simplify integrations. You don't need to develop everything from scratch or maintain boilerplate if there is already a Nuxt module for it. Adding Nuxt modules is possible using `nuxt.config`.

[Learn more on the documentation](https://nuxt.com/docs/guide/concepts/modules)
5 changes: 5 additions & 0 deletions packages/devtools/client/content/pages.md
@@ -0,0 +1,5 @@
# Pages

One core feature of Nuxt is the file system router. Every Vue file inside the `pages/` directory creates a corresponding URL (or route) that displays the contents of the file. By using dynamic imports for each page, Nuxt leverages code-splitting to ship the minimum amount of JavaScript for the requested route.

[Learn more on the documentation](https://nuxt.com/docs/getting-started/routing)
3 changes: 3 additions & 0 deletions packages/devtools/client/content/payload.md
@@ -0,0 +1,3 @@
# State & Async Data

// TODO
9 changes: 9 additions & 0 deletions packages/devtools/client/content/plugins.md
@@ -0,0 +1,9 @@
# Plugins

Nuxt plugins allows you to extend the functionality of Nuxt runtime and the Vue instance. You can add plugins to the `plugins/` directory and they will be automatically imported and registered.

::help-tip-performance
Plugins runs before your application at runtime, the time each plugin cost will directly affect your application's initial loading time.
::

[Learn more on the documentation](https://nuxt.com/docs/guide/directory-structure/plugins)
3 changes: 3 additions & 0 deletions packages/devtools/client/content/runtime-configs.md
@@ -0,0 +1,3 @@
# Runtime Configs

// TODO:
3 changes: 3 additions & 0 deletions packages/devtools/client/content/virtual-files.md
@@ -0,0 +1,3 @@
# Virtual Files

Virtual files are generated on the fly to support the conventions of the framework, and to provide a better developer experience.
1 change: 1 addition & 0 deletions packages/devtools/client/nuxt.config.ts
Expand Up @@ -10,6 +10,7 @@ function r(p: string) {
export default defineNuxtConfig({
modules: [
'nuxt-vitest',
'@nuxt/content',
'~/modules/custom-tabs',
DevToolsUiKit,
DevTools,
Expand Down
2 changes: 2 additions & 0 deletions packages/devtools/client/pages/modules/components.vue
Expand Up @@ -53,4 +53,6 @@ function toggleView() {
</div>
</component>
</div>
<HelpFab path="/components" />
</template>
2 changes: 2 additions & 0 deletions packages/devtools/client/pages/modules/hooks.vue
Expand Up @@ -30,4 +30,6 @@ const clientHooks = computed(() => client.value?.getClientHooksMetrics())
<HooksTable :hooks="serverHooks" />
</NSectionBlock>
</div>
<HelpFab path="/hooks" />
</template>
4 changes: 3 additions & 1 deletion packages/devtools/client/pages/modules/imports.vue
Expand Up @@ -71,7 +71,7 @@ const filtered = computed(() => {
</script>

<template>
<div v-if="config" h-full of-auto>
<div v-if="config" relative h-full of-auto>
<Navbar v-model:search="search" pb2>
<div v-if="importsMetadata">
<NSwitch v-model="onlyUsed" n="primary sm">
Expand Down Expand Up @@ -107,4 +107,6 @@ const filtered = computed(() => {
<ComposableTree :map="filtered.lib" :root="config.rootDir" :metadata="importsMetadata" />
</NSectionBlock>
</div>

<HelpFab path="/imports" />
</template>
2 changes: 2 additions & 0 deletions packages/devtools/client/pages/modules/modules.vue
Expand Up @@ -70,4 +70,6 @@ watchEffect(() => {
</template>
</NSectionBlock>
</div>
<HelpFab path="/modules" />
</template>
2 changes: 2 additions & 0 deletions packages/devtools/client/pages/modules/pages.vue
Expand Up @@ -138,4 +138,6 @@ function navigateToRoute(path: string) {
},
]"
/>
<HelpFab path="/pages" />
</template>
2 changes: 2 additions & 0 deletions packages/devtools/client/pages/modules/payload.vue
Expand Up @@ -65,4 +65,6 @@ async function refreshData(keys?: string[]) {
/>
</NSectionBlock>
</div>

<HelpFab path="/payload" />
</template>
5 changes: 2 additions & 3 deletions packages/devtools/client/pages/modules/plugins.vue
Expand Up @@ -31,9 +31,6 @@ const plugins = computed((): PluginInfoWithMetic[] => {
text="Plugins"
:description="`Total plugins: ${config.plugins.length}`"
>
<NTip n="green6" icon="carbon-meter">
Plugins runs before your application at runtime, the time plugins cost will directly affect your application's initial loading time.
</NTip>
<div pt4>
<PluginItem
v-for="plugin, idx of plugins"
Expand All @@ -44,4 +41,6 @@ const plugins = computed((): PluginInfoWithMetic[] => {
/>
</div>
</NSectionBlock>

<HelpFab path="/plugins" />
</template>
2 changes: 2 additions & 0 deletions packages/devtools/client/pages/modules/runtime-configs.vue
Expand Up @@ -49,4 +49,6 @@ const privateConfig = computed(() => {
<StateEditor :state="privateConfig" readonly />
</NSectionBlock>
</div>
<HelpFab path="/runtime-configs" />
</template>
2 changes: 2 additions & 0 deletions packages/devtools/client/pages/modules/virtual-files.vue
Expand Up @@ -108,6 +108,8 @@ const filteredFiles = computed(() => {
</NPanelGrids>
</template>
</PanelLeftRight>
<HelpFab path="/virtual-files" />
</template>
<style>
Expand Down
4 changes: 4 additions & 0 deletions packages/devtools/client/pages/settings.vue
Expand Up @@ -2,6 +2,7 @@
const {
interactionCloseOnOutsideClick,
showExperimentalFeatures,
showHelpButtons,
scale,
hiddenTabs,
hiddenTabCategories,
Expand Down Expand Up @@ -60,6 +61,9 @@ function toggleTabCategory(name: string, v: boolean) {
<NCheckbox v-model="showExperimentalFeatures" n-primary>
<span>Show experimental features</span>
</NCheckbox>
<NCheckbox v-model="showHelpButtons" n-primary>
<span>Show help buttons</span>
</NCheckbox>
</div>
<div py3 flex="~ col gap-1">
<h3 mb1 text-lg>
Expand Down
12 changes: 12 additions & 0 deletions packages/devtools/client/styles/global.css
Expand Up @@ -45,6 +45,18 @@ html.dark {
.n-markdown a {
--at-apply: text-primary hover:underline;
}
.prose a {
--uno: hover:text-primary;
}
.prose code::before {
content: ""
}
.prose code::after {
content: ""
}
.prose hr {
--uno: border-solid border-1 border-b border-base h-1px w-full block my-2 op50;
}

/* Splitpanes */
.splitpanes__splitter {
Expand Down
8 changes: 7 additions & 1 deletion packages/devtools/client/unocss.config.ts
@@ -1,4 +1,4 @@
import { defineConfig, presetAttributify, presetIcons, presetUno, presetWebFonts, transformerDirectives } from 'unocss'
import { defineConfig, presetAttributify, presetIcons, presetTypography, presetUno, presetWebFonts, transformerDirectives } from 'unocss'
import { unocssPreset as devtoolsUIKitUnoPreset } from '../../devtools-ui-kit/src/unocss'

export default defineConfig({
Expand Down Expand Up @@ -40,9 +40,15 @@ export default defineConfig({
mono: 'Fira Code',
},
}),
presetTypography(),
devtoolsUIKitUnoPreset(),
],
transformers: [
transformerDirectives(),
],
extraContent: {
filesystem: [
'content/*.md',
],
},
})
1 change: 1 addition & 0 deletions packages/devtools/package.json
Expand Up @@ -77,6 +77,7 @@
"@iconify-json/mdi": "^1.1.50",
"@iconify-json/ri": "^1.1.8",
"@iconify-json/tabler": "^1.1.74",
"@nuxt/content": "^2.6.0",
"@nuxt/devtools": "workspace:*",
"@nuxtjs/color-mode": "^3.2.0",
"@unocss/nuxt": "^0.51.6",
Expand Down

0 comments on commit 5ce8df3

Please sign in to comment.