Skip to content

Commit 8110c18

Browse files
committed
fix(devtools): use iconify icon for sidebar
1 parent a37df2c commit 8110c18

File tree

25 files changed

+1294
-383
lines changed

25 files changed

+1294
-383
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<script setup lang="ts">
2+
defineProps<{
3+
title?: string
4+
description?: string
5+
headline?: string
6+
}>()
7+
</script>
8+
9+
<template>
10+
<div class="w-full h-full flex flex-col p-12 relative" style="background: #0a0505; color: white;">
11+
<!-- Main container with border -->
12+
<div class="flex flex-col flex-1 border-2 border-white/20 p-10 relative">
13+
<!-- Corner decorations -->
14+
<svg class="absolute -top-2 -left-2" width="17" height="17" fill="none">
15+
<path d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z" fill="#cacaca" />
16+
</svg>
17+
<svg class="absolute -top-2 -right-2" width="17" height="17" fill="none">
18+
<path d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z" fill="#cacaca" />
19+
</svg>
20+
<svg class="absolute -bottom-2 -left-2" width="17" height="17" fill="none">
21+
<path d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z" fill="#cacaca" />
22+
</svg>
23+
<svg class="absolute -bottom-2 -right-2" width="17" height="17" fill="none">
24+
<path d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z" fill="#cacaca" />
25+
</svg>
26+
27+
<!-- Content -->
28+
<div class="flex flex-col flex-1 py-6">
29+
<!-- Logo -->
30+
<svg width="100" height="75" viewBox="0 0 60 45" fill="none" xmlns="http://www.w3.org/2000/svg">
31+
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0H15V15H30V30H15V45H0V30V15V0ZM45 30V15H30V0H45H60V15V30V45H45H30V30H45Z" fill="white" />
32+
</svg>
33+
34+
<!-- Type indicator -->
35+
<div class="flex items-center gap-2 mt-8 text-xl uppercase font-semibold text-white/80">
36+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
37+
<path fill="currentColor" fill-rule="evenodd" d="M4.172 3.172C3 4.343 3 6.229 3 10v4c0 3.771 0 5.657 1.172 6.828S7.229 22 11 22h2c3.771 0 5.657 0 6.828-1.172S21 17.771 21 14v-4c0-3.771 0-5.657-1.172-6.828S16.771 2 13 2h-2C7.229 2 5.343 2 4.172 3.172M8 9.25a.75.75 0 0 0 0 1.5h8a.75.75 0 0 0 0-1.5zm0 4a.75.75 0 0 0 0 1.5h5a.75.75 0 0 0 0-1.5z" clip-rule="evenodd" />
38+
</svg>
39+
<span>{{ headline || 'Documentation' }}</span>
40+
</div>
41+
42+
<!-- Title -->
43+
<div class="mt-4 text-5xl font-bold leading-tight max-w-[70%]" :class="title && title.length > 50 ? 'text-4xl' : 'text-5xl'">
44+
{{ (title || 'Nuxt Better Auth').slice(0, 80) }}
45+
</div>
46+
47+
<!-- Description -->
48+
<div v-if="description" class="mt-4 text-2xl text-white/70 max-w-[70%] leading-snug">
49+
{{ description.slice(0, 120) }}
50+
</div>
51+
</div>
52+
53+
<!-- Footer -->
54+
<div class="flex items-center justify-between">
55+
<div class="text-xl font-semibold">
56+
Nuxt Better Auth
57+
</div>
58+
<div class="flex items-center gap-2 text-xl text-white/80">
59+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
60+
<path fill="currentColor" d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2" />
61+
</svg>
62+
<span>github.com/onmax/nuxt-better-auth</span>
63+
</div>
64+
</div>
65+
</div>
66+
</div>
67+
</template>

docs/app/components/docs/DocsSidebar.vue

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
const route = useRoute()
33
const { sections, standaloneLinks } = useSidebarConfig()
44
5-
const openSection = ref<string>('')
6-
75
function isActive(href: string) {
86
if (href.startsWith('http'))
97
return false
@@ -14,6 +12,16 @@ function isSectionActive(sectionIndex: number) {
1412
return sections[sectionIndex]?.items.some(item => isActive(item.href)) ?? false
1513
}
1614
15+
const openSection = ref<string>('')
16+
17+
// Update open section when route changes (immediate: fires on mount + navigation)
18+
watch(() => route.path, () => {
19+
const activeIndex = sections.findIndex((_, index) => isSectionActive(index))
20+
if (activeIndex !== -1) {
21+
openSection.value = String(activeIndex)
22+
}
23+
}, { immediate: true })
24+
1725
// Build accordion items from sections
1826
const accordionItems = computed(() =>
1927
sections.map((section, index) => ({
@@ -25,22 +33,6 @@ const accordionItems = computed(() =>
2533
slot: `item-${index}` as const,
2634
})),
2735
)
28-
29-
// Set initial open section based on current route
30-
onMounted(() => {
31-
const activeIndex = sections.findIndex((_, index) => isSectionActive(index))
32-
if (activeIndex !== -1) {
33-
openSection.value = String(activeIndex)
34-
}
35-
})
36-
37-
// Update open section when route changes
38-
watch(() => route.path, () => {
39-
const activeIndex = sections.findIndex((_, index) => isSectionActive(index))
40-
if (activeIndex !== -1) {
41-
openSection.value = String(activeIndex)
42-
}
43-
})
4436
</script>
4537

4638
<template>

docs/public/favicon.svg

Lines changed: 3 additions & 0 deletions
Loading

docs/public/og.png

-2.69 MB
Binary file not shown.

playground/app/auth.client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import { navigateTo } from '#imports'
12
import { passkeyClient } from '@better-auth/passkey/client'
23
import { adminClient, multiSessionClient, twoFactorClient } from 'better-auth/client/plugins'
34
import { createAuthClient } from 'better-auth/vue'
4-
import { navigateTo } from '#imports'
55

66
export function createAppAuthClient(baseURL: string) {
77
return createAuthClient({

playground/app/layouts/default.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const { user, loggedIn, ready, signOut } = useUserSession()
4343
<span class="text-sm text-muted-foreground">{{ user?.name || user?.email }}</span>
4444
<button
4545
class="inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-9 px-3"
46-
@click="signOut()"
46+
@click="signOut({ onSuccess: () => navigateTo('/login') })"
4747
>
4848
Sign Out
4949
</button>

playground/app/pages/admin/index.vue

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ const { client } = useUserSession()
33
const toast = useToast()
44
55
// Type assertion for admin plugin methods
6+
type AsyncFn = (...args: unknown[]) => Promise<unknown>
67
const adminClient = client as typeof client & {
7-
admin: {
8-
listUsers: Function, createUser: Function, banUser: Function
9-
unbanUser: Function, impersonateUser: Function, removeUser: Function
10-
}
8+
admin: { listUsers: AsyncFn, createUser: AsyncFn, banUser: AsyncFn, unbanUser: AsyncFn, impersonateUser: AsyncFn, removeUser: AsyncFn }
119
}
1210
1311
// Users
@@ -28,7 +26,8 @@ async function loadUsers() {
2826
}
2927
3028
const filteredUsers = computed(() => {
31-
if (!search.value) return users.value
29+
if (!search.value)
30+
return users.value
3231
const s = search.value.toLowerCase()
3332
return users.value.filter(u => u.email?.toLowerCase().includes(s) || u.name?.toLowerCase().includes(s))
3433
})
@@ -125,7 +124,9 @@ async function impersonate(userId: string) {
125124
126125
// Delete user
127126
async function deleteUser(userId: string) {
128-
if (!confirm('Are you sure you want to delete this user?')) return
127+
// eslint-disable-next-line no-alert
128+
if (!confirm('Are you sure you want to delete this user?'))
129+
return
129130
try {
130131
await adminClient?.admin.removeUser({ userId })
131132
toast.add({ title: 'User deleted', color: 'success' })
@@ -144,7 +145,9 @@ onMounted(loadUsers)
144145
<UCard>
145146
<template #header>
146147
<div class="flex justify-between items-center gap-4">
147-
<h1 class="text-xl font-semibold">Admin Dashboard</h1>
148+
<h1 class="text-xl font-semibold">
149+
Admin Dashboard
150+
</h1>
148151
<div class="flex gap-2">
149152
<UInput v-model="search" placeholder="Search users..." class="w-48" />
150153
<UButton @click="createOpen = true">
@@ -193,7 +196,9 @@ onMounted(loadUsers)
193196

194197
<!-- Create User Modal -->
195198
<UModal v-model:open="createOpen">
196-
<template #header>Create New User</template>
199+
<template #header>
200+
Create New User
201+
</template>
197202
<template #body>
198203
<div class="space-y-4 p-4">
199204
<UFormField label="Email">
@@ -208,14 +213,18 @@ onMounted(loadUsers)
208213
<UFormField label="Role">
209214
<USelect v-model="createForm.role" :options="['user', 'admin']" />
210215
</UFormField>
211-
<UButton block :loading="createLoading" @click="createUser">Create User</UButton>
216+
<UButton block :loading="createLoading" @click="createUser">
217+
Create User
218+
</UButton>
212219
</div>
213220
</template>
214221
</UModal>
215222

216223
<!-- Ban User Modal -->
217224
<UModal v-model:open="banOpen">
218-
<template #header>Ban User</template>
225+
<template #header>
226+
Ban User
227+
</template>
219228
<template #body>
220229
<div class="space-y-4 p-4">
221230
<UFormField label="Reason (optional)">
@@ -224,7 +233,9 @@ onMounted(loadUsers)
224233
<UFormField label="Duration (hours, leave empty for permanent)">
225234
<UInput v-model="banForm.expiresIn" type="number" placeholder="e.g. 24" />
226235
</UFormField>
227-
<UButton block color="error" :loading="banLoading" @click="banUser">Ban User</UButton>
236+
<UButton block color="error" :loading="banLoading" @click="banUser">
237+
Ban User
238+
</UButton>
228239
</div>
229240
</template>
230241
</UModal>

0 commit comments

Comments
 (0)