
3D Extruded Buildings & Urban Footprints
Real-world 3D building extrusions with dynamic sunlight shadows, terrain DEM elevations, and pitch/bearing camera controls.
Docs-style sidebar with a version switcher at the top, a search input below, and collapsible navigation groups. All sample data inlined so consumers edit routes in place.
Also available for React ->$pnpm dlx shadcn-vue@latest add https://uipkge.dev/r/vue/sidebar-03.json$npx shadcn-vue@latest add https://uipkge.dev/r/vue/sidebar-03.json$yarn dlx shadcn-vue@latest add https://uipkge.dev/r/vue/sidebar-03.json$bunx shadcn-vue@latest add https://uipkge.dev/r/vue/sidebar-03.jsonnpx shadcn-vue@latest add @uipkge/sidebar-03Installs to:app/components/blocks/sidebar-03/<script setup lang="ts">
import { ChevronRight } from 'lucide-vue-next'
import SearchForm from './SearchForm.vue'
import VersionSwitcher from './VersionSwitcher.vue'
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarRail,
} from '@/components/ui/sidebar'
// This is sample data.
const data = {
versions: ['1.0.1', '1.1.0-alpha', '2.0.0-beta1'],
navMain: [
{
title: 'Getting Started',
url: '#',
items: [
{
title: 'Installation',
url: '#',
},
{
title: 'Project Structure',
url: '#',
},
],
},
{
title: 'Building Your Application',
url: '#',
items: [
{
title: 'Routing',
url: '#',
},
{
title: 'Data Fetching',
url: '#',
isActive: true,
},
{
title: 'Rendering',
url: '#',
},
{
title: 'Caching',
url: '#',
},
{
title: 'Styling',
url: '#',
},
{
title: 'Optimizing',
url: '#',
},
{
title: 'Configuring',
url: '#',
},
{
title: 'Testing',
url: '#',
},
{
title: 'Authentication',
url: '#',
},
{
title: 'Deploying',
url: '#',
},
{
title: 'Upgrading',
url: '#',
},
{
title: 'Examples',
url: '#',
},
],
},
{
title: 'API Reference',
url: '#',
items: [
{
title: 'Components',
url: '#',
},
{
title: 'File Conventions',
url: '#',
},
{
title: 'Functions',
url: '#',
},
{
title: 'next.config.js Options',
url: '#',
},
{
title: 'CLI',
url: '#',
},
{
title: 'Edge Runtime',
url: '#',
},
],
},
{
title: 'Architecture',
url: '#',
items: [
{
title: 'Accessibility',
url: '#',
},
{
title: 'Fast Refresh',
url: '#',
},
{
title: 'Next.js Compiler',
url: '#',
},
{
title: 'Supported Browsers',
url: '#',
},
{
title: 'Turbopack',
url: '#',
},
],
},
{
title: 'Community',
url: '#',
items: [
{
title: 'Contribution Guide',
url: '#',
},
],
},
],
}
</script>
<template>
<Sidebar data-slot="sidebar-03">
<SidebarHeader>
<VersionSwitcher :versions="data.versions" :default-version="data.versions[0]!" />
<SearchForm />
</SidebarHeader>
<SidebarContent class="gap-0">
<Collapsible
v-for="item in data.navMain"
:key="item.title"
:title="item.title"
default-open
class="group/collapsible"
>
<SidebarGroup>
<SidebarGroupLabel
as-child
class="group/label text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground text-sm"
>
<CollapsibleTrigger>
{{ item.title }}
<ChevronRight class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem v-for="childItem in item.items" :key="childItem.title">
<SidebarMenuButton as-child :is-active="childItem.isActive">
<a :href="item.url">{{ childItem.title }}</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
</SidebarContent>
<SidebarRail />
</Sidebar>
</template>
<script setup lang="ts">
import { Search } from 'lucide-vue-next'
import { Label } from '@/components/ui/label'
import { SidebarGroup, SidebarGroupContent, SidebarInput } from '@/components/ui/sidebar'
</script>
<template>
<form data-slot="sidebar-03">
<SidebarGroup class="py-0">
<SidebarGroupContent>
<Label for="search" class="sr-only">Search</Label>
<SidebarInput id="search" type="text" placeholder="Search the docs..." :allow-clear="true">
<template #prefix>
<Search class="text-muted-foreground size-3.5" />
</template>
</SidebarInput>
</SidebarGroupContent>
</SidebarGroup>
</form>
</template>
<script setup lang="ts">
import { Check, ChevronsUpDown } from 'lucide-vue-next'
import { ref } from 'vue'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
import { SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar'
const props = defineProps<{
versions: string[]
defaultVersion: string
}>()
const selectedVersion = ref(props.defaultVersion)
</script>
<template>
<SidebarMenu data-slot="sidebar-03">
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<SidebarMenuButton
size="lg"
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<div
class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg"
>
<svg viewBox="0 0 24 24" class="size-4" fill="currentColor" aria-hidden="true">
<rect x="2" y="2" width="9" height="9" rx="1.5" />
<rect x="13" y="2" width="9" height="9" rx="1.5" opacity="0.55" />
<rect x="2" y="13" width="9" height="9" rx="1.5" opacity="0.55" />
<rect x="13" y="13" width="9" height="9" rx="1.5" />
</svg>
</div>
<div class="flex flex-col gap-0.5 leading-none">
<span class="font-medium">uipkge</span>
<span class="">v{{ selectedVersion }}</span>
</div>
<ChevronsUpDown class="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent class="w-(--reka-dropdown-menu-trigger-width)" align="start">
<DropdownMenuItem v-for="version in versions" :key="version" @select="selectedVersion = version">
v{{ version }}
<Check v-if="selectedVersion === version" class="ml-auto" />
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</template>
Raw manifest:https://uipkge.dev/r/vue/sidebar-03.json