[{"data":1,"prerenderedAt":1136},["ShallowReactive",2],{"docs-pages":3,"doc-\u002F":85,"docs-search":249},[4,10,15,20,24,29,34,40,45,50,55,61,67,72,77,81],{"title":5,"navTitle":5,"path":6,"section":7,"order":8,"description":9},"Introduction","\u002F","Getting started",1,"AdminLTE 4 for Vue 3 & Nuxt — a framework-agnostic component library and a thin Nuxt module.",{"title":11,"navTitle":11,"path":12,"section":7,"order":13,"description":14},"Installation","\u002Fgetting-started\u002Finstallation",2,"Install the component library or the Nuxt module.",{"title":16,"navTitle":16,"path":17,"section":18,"order":8,"description":19},"Nuxt module","\u002Fguide\u002Fnuxt-module","Guide","Configure @adminlte\u002Fnuxt — auto-registration, auto-imports, CSS, the color-mode head script.",{"title":21,"navTitle":21,"path":22,"section":18,"order":13,"description":23},"Color mode","\u002Fguide\u002Fcolor-mode","Light\u002Fdark\u002Fauto color mode with an SSR-safe, flash-free theme.",{"title":25,"navTitle":25,"path":26,"section":18,"order":27,"description":28},"SSR safety","\u002Fguide\u002Fssr-safety",3,"How the library stays hydration-safe under SSR.",{"title":30,"navTitle":30,"path":31,"section":18,"order":32,"description":33},"Routing & links","\u002Fguide\u002Frouting",4,"How the framework-agnostic library integrates with your router.",{"title":35,"navTitle":36,"path":37,"section":38,"order":8,"description":39},"Components overview","Overview","\u002Fcomponents\u002Foverview","Components","The full set of Lte* components and how they are organized.",{"title":41,"navTitle":42,"path":43,"section":38,"order":13,"description":44},"Layout components","Layout","\u002Fcomponents\u002Flayout","LteDashboardLayout, LteSidebar, LteTopbar, LteAppContent, LteFooter, LteAuthLayout.",{"title":46,"navTitle":47,"path":48,"section":38,"order":27,"description":49},"Widget components","Widgets","\u002Fcomponents\u002Fwidgets","Cards, boxes, timeline, direct chat, progress, callouts and more.",{"title":51,"navTitle":52,"path":53,"section":38,"order":32,"description":54},"Form components","Forms","\u002Fcomponents\u002Fforms","Inputs, selects, switches and form helpers.",{"title":56,"navTitle":57,"path":58,"section":38,"order":59,"description":60},"Plugin components","Plugins","\u002Fcomponents\u002Fplugins",5,"[object Object]",{"title":62,"navTitle":63,"path":64,"section":65,"order":8,"description":66},"State composables","State","\u002Fcomposables\u002Fstate","Composables","useSidebar, useColorMode, useCommandPalette — the provided dashboard state.",{"title":68,"navTitle":69,"path":70,"section":65,"order":13,"description":71},"Component composables","Component","\u002Fcomposables\u002Fcomponent","useCardWidget, useFullscreen, useDirectChat, useSortable, useTreeview.",{"title":73,"navTitle":73,"path":74,"section":75,"order":8,"description":76},"Migration","\u002Fresources\u002Fmigration","Resources","Coming from raw AdminLTE 4, the React port, or the Laravel edition.",{"title":78,"navTitle":78,"path":79,"section":75,"order":13,"description":80},"Deployment","\u002Fresources\u002Fdeployment","Building the library and deploying a Nuxt app that uses it.",{"title":82,"navTitle":82,"path":83,"section":75,"order":27,"description":84},"FAQ","\u002Fresources\u002Ffaq","Common questions about adminlte-vue.",{"id":86,"title":5,"body":87,"description":9,"extension":242,"icon":243,"meta":244,"navTitle":5,"navigation":245,"order":8,"path":6,"section":7,"seo":246,"stem":247,"__hash__":248},"docs\u002Findex.md",{"type":88,"value":89,"toc":236},"minimark",[90,115,120,163,167,187,194,198,227],[91,92,93,97,98,102,103,110,111,114],"p",{},[94,95,96],"strong",{},"AdminLTE Vue"," (the ",[99,100,101],"code",{},"adminlte-vue"," package) is a faithful port of ",[104,105,109],"a",{"href":106,"rel":107},"https:\u002F\u002Fadminlte.io",[108],"nofollow","AdminLTE 4","\n(Bootstrap 5.3) for ",[94,112,113],{},"Vue 3 & Nuxt",". It comes in two pieces so you can adopt as much or as little as\nyou need:",[116,117,119],"h2",{"id":118},"the-packages","The packages",[121,122,123,136],"table",{},[124,125,126],"thead",{},[127,128,129,133],"tr",{},[130,131,132],"th",{},"Package",[130,134,135],{},"What it is",[137,138,139,151],"tbody",{},[127,140,141,148],{},[142,143,144],"td",{},[94,145,146],{},[99,147,101],{},[142,149,150],{},"The framework-agnostic Vue 3 component library — works in any Vite \u002F Vue 3 \u002F Nuxt app.",[127,152,153,160],{},[142,154,155],{},[94,156,157],{},[99,158,159],{},"@adminlte\u002Fnuxt",[142,161,162],{},"A thin Nuxt module: auto-registers the components, auto-imports the composables, injects the CSS + an SSR-safe color-mode script.",[116,164,166],{"id":165},"which-one","Which one?",[168,169,170,179],"ul",{},[171,172,173,174,178],"li",{},"Use ",[94,175,176],{},[99,177,101],{}," directly for full control in any Vue 3 \u002F Vite app — you wire the router and CSS yourself.",[171,180,181,182,186],{},"Add ",[94,183,184],{},[99,185,159],{}," in a Nuxt app to remove all the wiring boilerplate (auto-registration, auto-imports, CSS, the color-mode head script).",[91,188,189,190,193],{},"The ",[94,191,192],{},"demo app"," is a 1:1 AdminLTE 4 showcase of every component and page — the best way to see what's available.",[116,195,197],{"id":196},"highlights","Highlights",[168,199,200,210,215,221],{},[171,201,202,205,206,209],{},[94,203,204],{},"SSR-safe"," — every browser API is isolated to ",[99,207,208],{},"onMounted","\u002Feffects; no hydration mismatches.",[171,211,212,214],{},[94,213,21],{}," with a blocking head script (no flash of the wrong theme).",[171,216,217,220],{},[94,218,219],{},"Composables + provide\u002Finject"," for state (no Pinia required in the library).",[171,222,223,226],{},[94,224,225],{},"Heavy plugins are dynamic-imported"," (ApexCharts, FullCalendar, Tabulator, Quill, …) and stay out of the default bundle.",[228,229,230],"blockquote",{},[91,231,232,233,235],{},"Looking to get going fast? Jump to ",[104,234,11],{"href":12},".",{"title":237,"searchDepth":27,"depth":27,"links":238},"",[239,240,241],{"id":118,"depth":13,"text":119},{"id":165,"depth":13,"text":166},{"id":196,"depth":13,"text":197},"md","bi-rocket-takeoff",{},true,{"title":5,"description":9},"index","9gWsGf9EYYykbunHC5RjgM-q0fJEBd8ZUY32WOrPuZE",[250,253,258,263,268,271,275,280,285,290,294,299,304,309,314,319,324,329,332,336,340,345,350,355,360,365,368,373,378,383,388,393,398,403,406,411,416,421,426,431,436,441,446,449,454,459,463,468,473,478,483,486,491,496,501,506,511,515,519,524,528,532,536,541,545,549,554,558,562,567,571,575,578,583,587,591,596,600,604,609,613,618,622,627,632,636,640,645,650,655,659,664,668,672,677,681,684,689,693,697,701,706,710,714,718,723,727,730,735,739,743,748,752,756,759,764,769,774,779,783,788,792,796,801,806,810,814,818,823,827,831,836,841,845,849,854,857,862,866,871,876,881,885,890,895,900,904,909,912,917,921,926,931,936,940,944,949,953,957,962,966,971,975,979,984,989,994,997,1001,1006,1011,1016,1021,1026,1030,1035,1040,1045,1050,1053,1058,1063,1068,1073,1078,1081,1086,1091,1096,1101,1106,1111,1116,1121,1124,1128,1132],{"id":12,"title":11,"titles":251,"content":252,"level":8},[],"Install the component library or the Nuxt module. AdminLTE Vue is one library — the components, composables, and rendered markup are identical\nwhether you use plain Vue or Nuxt. The only thing that differs is setup: the Nuxt module wires\neverything for you, while plain Vue\u002FVite needs a few lines. Pick the entry point that matches your app.",{"id":254,"title":255,"titles":256,"content":257,"level":13},"\u002Fgetting-started\u002Finstallation#nuxt-recommended","Nuxt (recommended)",[11],"pnpm add adminlte-vue @adminlte\u002Fnuxt bootstrap @popperjs\u002Fcore export default defineNuxtConfig({\n  modules: ['@adminlte\u002Fnuxt'],\n  adminlte: {\n    defaults: { sidebarTheme: 'dark', initialColorMode: 'auto' },\n  },\n}) The module auto-registers every Lte* component and auto-imports the composables, so you can use\nthem in any page without imports: \u003Ctemplate>\n  \u003CLteDashboardLayout :menu-items=\"menu\" brand-text=\"Acme\">\n    \u003CLteAppContent title=\"Dashboard\">…\u003C\u002FLteAppContent>\n  \u003C\u002FLteDashboardLayout>\n\u003C\u002Ftemplate>",{"id":259,"title":260,"titles":261,"content":262,"level":13},"\u002Fgetting-started\u002Finstallation#plain-vue-3-vite","Plain Vue 3 \u002F Vite",[11],"pnpm add adminlte-vue bootstrap import { createApp } from 'vue'\nimport AdminLte from 'adminlte-vue'\nimport 'adminlte-vue\u002Fcss'\nimport App from '.\u002FApp.vue'\n\ncreateApp(App).use(AdminLte).mount('#app') You own the wiring: pass currentPath for active-link detection and linkComponent for your router.\nSee Routing & links.",{"id":264,"title":265,"titles":266,"content":267,"level":13},"\u002Fgetting-started\u002Finstallation#peer-dependencies","Peer dependencies",[11],"bootstrap is a peer dependency (the components are class-only and rely on AdminLTE's prebuilt CSS).\nThe heavy plugin wrappers (LteApexChart, LteCalendar, LteDatatable, …) declare their underlying\nlibraries as optional peer dependencies — install only the ones you use. See\nPlugin components. html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"id":17,"title":16,"titles":269,"content":270,"level":8},[],"Configure @adminlte\u002Fnuxt — auto-registration, auto-imports, CSS, the color-mode head script. @adminlte\u002Fnuxt is a thin Nuxt module that wires the adminlte-vue component library into your app: it auto-registers every Lte* component, auto-imports the composables, injects the AdminLTE CSS, loads Bootstrap's client-side JS, and adds an SSR-safe color-mode head script. After adding it you can use the components and composables in any page or component with no manual imports.",{"id":272,"title":11,"titles":273,"content":274,"level":13},"\u002Fguide\u002Fnuxt-module#installation",[16],"Install the module and the underlying library, then add the module to nuxt.config.ts. pnpm add @adminlte\u002Fnuxt adminlte-vue export default defineNuxtConfig({\n  modules: ['@adminlte\u002Fnuxt'],\n}) That's it — with zero configuration the module registers all components, auto-imports the composables, injects the CSS, loads Bootstrap, and adds the theme head script.",{"id":276,"title":277,"titles":278,"content":279,"level":13},"\u002Fguide\u002Fnuxt-module#configuration","Configuration",[16],"Options live under the adminlte key in nuxt.config.ts. export default defineNuxtConfig({\n  modules: ['@adminlte\u002Fnuxt'],\n  adminlte: {\n    prefix: 'Lte',\n    components: true,\n    composables: true,\n    css: true,\n    bootstrap: true,\n    themeScript: true,\n    defaults: {\n      layoutFixed: true,\n      sidebarTheme: 'dark',\n      sidebarBreakpoint: 'lg',\n      initialColorMode: 'auto',\n      enableSidebarPersistence: false,\n    },\n  },\n})",{"id":281,"title":282,"titles":283,"content":284,"level":27},"\u002Fguide\u002Fnuxt-module#module-options","Module options",[16,277],"These are the fields of AdminlteModuleOptions. NameTypeDefaultDescriptionprefixstring'Lte'Component name prefix used when auto-registering. With the default 'Lte', names are used as-is (LteCard); any other value replaces the leading Lte (e.g. 'App' → AppCard).componentsbooleantrueAuto-register all Lte* components globally. Set false to opt out.composablesbooleantrueAuto-import the composables (useSidebar, useColorMode, …).cssbooleantrueInject adminlte-vue\u002Fcss automatically into nuxt.options.css.bootstrapbooleantrueLoad Bootstrap's JS bundle client-side (powers dropdowns, modals, offcanvas, tooltips).themeScriptbooleantrueInject the blocking head script that sets data-bs-theme before first paint.defaultsAdminlteLayoutDefaultssee belowDefault layout + theme flags, surfaced via useAdminlteConfig().",{"id":286,"title":287,"titles":288,"content":289,"level":27},"\u002Fguide\u002Fnuxt-module#layout-defaults","Layout defaults",[16,277],"defaults accepts the fields of AdminlteLayoutDefaults. These values are written to runtimeConfig.public.adminlte and read back at runtime through useAdminlteConfig(). NameTypeDefaultDescriptionsidebarTheme'light' | 'dark''dark'Sidebar color theme.sidebarMiniboolean—Enable the collapsed mini-sidebar variant.sidebarBreakpoint'lg' | 'md''lg'Breakpoint at which the sidebar expands.fixedHeaderboolean—Fix the topbar to the top of the viewport.fixedSidebarboolean—Fix the sidebar so it does not scroll with the page.fixedFooterboolean—Fix the footer to the bottom of the viewport.layoutFixedbooleantrueApply the layout-fixed body class.initialColorMode'light' | 'dark' | 'auto''auto'Initial color mode; also the fallback used by the theme head script.enableSidebarPersistencebooleanfalsePersist the sidebar collapse state in localStorage.dir'ltr' | 'rtl'—Text direction.",{"id":291,"title":292,"titles":293,"content":237,"level":13},"\u002Fguide\u002Fnuxt-module#what-the-module-registers","What the module registers",[16],{"id":295,"title":296,"titles":297,"content":298,"level":27},"\u002Fguide\u002Fnuxt-module#auto-registered-components","Auto-registered components",[16,292],"When components is enabled, the module registers every component globally so you can use them in templates without importing. Core components resolve from the adminlte-vue entry; plugin wrappers resolve from adminlte-vue\u002Fplugins. Core components: LteDashboardLayout, LteAuthLayout, LteAppContent, LteSidebar, LteSidebarBrand, LteSidebarNav, LteSidebarNavItem, LteSidebarOverlay, LteTopbar, LteFooter, LteColorModeToggle, LteFullscreenToggle, LteCard, LteSmallBox, LteInfoBox, LteAlert, LteCallout, LteProgress, LteProgressGroup, LteTimeline, LteRatings, LteProfileCard, LteDescriptionBlock, LteDirectChat, LteNavMessages, LteNavNotifications, LteNavTasks, LteToast, LteTabs, LteTab, LteAccordion, LteAccordionItem, LteBreadcrumb, LteCommandPalette, LteButton, LteInput, LteTextarea, LteSelect, LteInputSwitch, LteInputColor, LteInputFile, LteInputFlatpickr, LteInputTomSelect, LteModal, LteWizard, LteWizardStep. Plugin-wrapper components (heavy third-party libs, dynamically imported client-side): LteApexChart, LteSparklineChart, LteDatatable, LteEditor, LteFlatpickr, LteTomSelect, LteCalendar, LteVectorMap, LteSortable, LteKanban.",{"id":300,"title":301,"titles":302,"content":303,"level":27},"\u002Fguide\u002Fnuxt-module#auto-imported-composables","Auto-imported composables",[16,292],"When composables is enabled, these are auto-imported from adminlte-vue: useSidebar, useColorMode, useCardWidget, useTreeviewRegistry, useFullscreen, useDirectChat, useSortable, useCommandPalette. The module also always auto-imports useAdminlteConfig (see below), independent of the composables option.",{"id":305,"title":306,"titles":307,"content":308,"level":27},"\u002Fguide\u002Fnuxt-module#css","CSS",[16,292],"When css is enabled, the module pushes adminlte-vue\u002Fcss onto nuxt.options.css, so the prebuilt AdminLTE stylesheet loads automatically.",{"id":310,"title":311,"titles":312,"content":313,"level":27},"\u002Fguide\u002Fnuxt-module#bootstrap-js","Bootstrap JS",[16,292],"When bootstrap is enabled, the module registers a client-only plugin that imports Bootstrap's JS bundle. Its data-API delegation is what powers dropdowns, modals, offcanvas, and tooltips. The module also adds bootstrap and @popperjs\u002Fcore to vite.optimizeDeps.include.",{"id":315,"title":316,"titles":317,"content":318,"level":27},"\u002Fguide\u002Fnuxt-module#build-transpilation","Build transpilation",[16,292],"The module always pushes adminlte-vue into build.transpile. The library ships compiled SFC ESM that uses Vue runtime helpers, so it must be transpiled by your build rather than externalized by Nitro. This is not configurable.",{"id":320,"title":321,"titles":322,"content":323,"level":13},"\u002Fguide\u002Fnuxt-module#theme-head-script","Theme head script",[16],"When themeScript is enabled (the default), the module injects a small blocking inline script into \u003Chead> that runs before first paint. It reads the persisted preference from the lte-theme localStorage key (falling back to defaults.initialColorMode, or 'auto'), resolves 'auto' against prefers-color-scheme, and sets data-bs-theme on \u003Chtml>. This eliminates the flash of incorrect theme on load. After hydration, useColorMode owns reactive theme updates. The script is tagged lte-theme-init and its innerHTML is exempted from Nuxt's head sanitizer so it is not minified or reordered away.",{"id":325,"title":326,"titles":327,"content":328,"level":13},"\u002Fguide\u002Fnuxt-module#useadminlteconfig","useAdminlteConfig()",[16],"useAdminlteConfig() reads the layout defaults you configured under adminlte.defaults back at runtime. It returns the AdminlteLayoutDefaults object (or an empty object if none were set). \u003Cscript setup lang=\"ts\">\nconst config = useAdminlteConfig()\n\u002F\u002F config.sidebarTheme, config.sidebarBreakpoint, config.initialColorMode, …\n\u003C\u002Fscript> The composable is auto-imported by the module, so no manual import is needed. Under the hood it reads runtimeConfig.public.adminlte, which the module populates by merging your defaults with the module's built-in defaults. html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"id":22,"title":21,"titles":330,"content":331,"level":8},[],"Light\u002Fdark\u002Fauto color mode with an SSR-safe, flash-free theme. adminlte-vue supports light, dark, and auto color modes built on Bootstrap's data-bs-theme\nattribute. The preference is persisted to localStorage and applied before first paint in Nuxt, so\nthere is no flash of the wrong theme on reload.",{"id":333,"title":36,"titles":334,"content":335,"level":13},"\u002Fguide\u002Fcolor-mode#overview",[21],"Color mode is provided by LteDashboardLayout, which calls provideColorMode() in its setup().\nDescendant components read and update the mode through the useColorMode() composable. The state is: colorMode — the user's preference: 'light' | 'dark' | 'auto'.resolvedMode — the concrete mode applied to the page: 'light' | 'dark'. When colorMode\nis 'auto', it follows the system prefers-color-scheme setting. The resolved mode is written to data-bs-theme on the \u003Chtml> element, and the preference is saved\nunder the lte-theme localStorage key.",{"id":337,"title":338,"titles":339,"content":237,"level":13},"\u002Fguide\u002Fcolor-mode#usage","Usage",[21],{"id":341,"title":342,"titles":343,"content":344,"level":27},"\u002Fguide\u002Fcolor-mode#the-toggle-component","The toggle component",[21,338],"LteColorModeToggle is a ready-made dropdown (rendered as a navbar \u003Cli>) that lets the user pick\nLight, Dark, or Auto. It takes no props and must live inside LteDashboardLayout — typically in the\ntopbar's navbar list. In Nuxt it is auto-registered, so no import is needed. \u003Ctemplate>\n  \u003Cul class=\"navbar-nav ms-auto\">\n    \u003CClientOnly>\n      \u003CLteColorModeToggle \u002F>\n    \u003C\u002FClientOnly>\n  \u003C\u002Ful>\n\u003C\u002Ftemplate> Wrapping the toggle in \u003CClientOnly> avoids a hydration mismatch on the trigger glyph, which\ndepends on the persisted preference resolved on the client.",{"id":346,"title":347,"titles":348,"content":349,"level":27},"\u002Fguide\u002Fcolor-mode#reading-and-setting-the-mode","Reading and setting the mode",[21,338],"Use useColorMode() anywhere inside the layout to read or change the mode programmatically. \u003Cscript setup lang=\"ts\">\nconst { colorMode, resolvedMode, setColorMode } = useColorMode()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cp>Preference: {{ colorMode }} (resolved: {{ resolvedMode }})\u003C\u002Fp>\n    \u003Cbutton @click=\"setColorMode('light')\">Light\u003C\u002Fbutton>\n    \u003Cbutton @click=\"setColorMode('dark')\">Dark\u003C\u002Fbutton>\n    \u003Cbutton @click=\"setColorMode('auto')\">Auto\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate> colorMode is a writable Ref, so colorMode.value = 'dark' works too — setColorMode() is just a\nconvenience wrapper.",{"id":351,"title":352,"titles":353,"content":354,"level":13},"\u002Fguide\u002Fcolor-mode#usecolormode-api","useColorMode() API",[21],"useColorMode() injects the color-mode state provided by LteDashboardLayout. Calling it outside\nthe layout throws an error. NameTypeDescriptioncolorModeRef\u003C'light' | 'dark' | 'auto'>The user's color-mode preference. Writable.resolvedModeComputedRef\u003C'light' | 'dark'>The concrete mode applied to the page; resolves 'auto' against the system setting.setColorMode(mode: 'light' | 'dark' | 'auto') => voidSet the preference. Persists to localStorage and updates data-bs-theme. import { useColorMode } from 'adminlte-vue'\n\nconst { colorMode, resolvedMode, setColorMode } = useColorMode()",{"id":356,"title":357,"titles":358,"content":359,"level":13},"\u002Fguide\u002Fcolor-mode#setting-the-initial-mode","Setting the initial mode",[21],"The initial preference defaults to 'auto'. In Nuxt, set it through the module's defaults: export default defineNuxtConfig({\n  modules: ['@adminlte\u002Fnuxt'],\n  adminlte: {\n    defaults: {\n      initialColorMode: 'auto', \u002F\u002F 'light' | 'dark' | 'auto'\n    },\n  },\n}) This value is used as the fallback by the blocking head script and seeds the layout's initial state.\nA persisted lte-theme value always takes precedence once the page loads.",{"id":361,"title":362,"titles":363,"content":364,"level":13},"\u002Fguide\u002Fcolor-mode#how-the-flash-is-avoided-in-nuxt","How the flash is avoided in Nuxt",[21],"A flash of the wrong theme happens when the saved preference is only applied after Vue hydrates. To\nprevent it, @adminlte\u002Fnuxt injects a small blocking inline \u003Chead> script (keyed\nlte-theme-init) that runs before first paint. It reads lte-theme from localStorage (falling\nback to initialColorMode), resolves auto against prefers-color-scheme, and sets data-bs-theme\non \u003Chtml> immediately: (function () {\n  try {\n    var k = localStorage.getItem('lte-theme') || 'auto'\n    var d = k === 'auto'\n      ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')\n      : k\n    document.documentElement.setAttribute('data-bs-theme', d)\n  } catch (e) {}\n})() After hydration, useColorMode() owns all reactive updates — it reconciles with the persisted\npreference, listens for system prefers-color-scheme changes (while in auto), and re-applies\ndata-bs-theme whenever the mode changes. The script is on by default. You can disable it with the themeScript module option (for example if\nyou inject your own): export default defineNuxtConfig({\n  modules: ['@adminlte\u002Fnuxt'],\n  adminlte: {\n    themeScript: false,\n  },\n}) html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"id":26,"title":25,"titles":366,"content":367,"level":8},[],"How the library stays hydration-safe under SSR. The library is built to render the same markup on the server and the client, so it hydrates cleanly under Nuxt SSR with no class-mismatch warnings. This page documents the rules it follows and what they mean if you extend it.",{"id":369,"title":370,"titles":371,"content":372,"level":13},"\u002Fguide\u002Fssr-safety#the-core-rule-no-browser-apis-at-render-time","The core rule: no browser APIs at render time",[25],"Every browser-API access — window, document, localStorage, matchMedia — is isolated inside onMounted, watchEffect, or an event handler. None of it runs at module top level or synchronously in setup, because that code also runs on the server where those globals do not exist. The patterns below show how this rule plays out in each composable.",{"id":374,"title":375,"titles":376,"content":377,"level":13},"\u002Fguide\u002Fssr-safety#window-width-starts-as-null","Window width starts as null",[25],"useWindowWidth() returns a Ref\u003Cnumber | null> that begins as null — meaning \"unknown\" — and is only populated once the component mounts on the client. Callers treat the unknown value as desktop so the server always renders the expanded layout deterministically. import { useWindowWidth } from 'adminlte-vue'\n\nconst width = useWindowWidth() \u002F\u002F Ref\u003Cnumber | null>, null until mounted AspectBehaviourReturn type`Ref\u003CnumberInitial valuenull (unknown — treated as desktop by callers)On mountSet to window.innerWidth; a resize listener is attached (passive, rAF-throttled)On unmountThe listener is removed provideSidebar consumes this and computes the mobile breakpoint defensively: \u002F\u002F Treat unknown width (SSR \u002F pre-mount) as desktop.\nconst isMobile = computed(() => (windowWidth.value ?? 9999) \u003C= sidebarBreakpoint) Because isMobile is false on the server, the push-menu logic renders the desktop layout on both sides of hydration.",{"id":379,"title":380,"titles":381,"content":382,"level":13},"\u002Fguide\u002Fssr-safety#body-classes-are-toggled-from-a-watcheffect","Body classes are toggled from a watchEffect",[25],"provideSidebar reflects its reactive state onto document.body — not onto an element inside the component tree. The \u003Cbody> element lives outside the Vue app, so mutating its classList imperatively is hydration-safe: Vue never diffs \u003Cbody>, so there is no class-mismatch warning. \u002F\u002F Reflect state onto \u003Cbody>. The body element lives outside the Vue app tree,\n\u002F\u002F so imperative classList mutation is hydration-safe. No-ops on the server.\nwatchEffect(() => {\n  if (typeof document === 'undefined') return\n  const body = document.body\n  const dynamic = {\n    'sidebar-collapse': isCollapsed.value,\n    'sidebar-open': isMobileOpen.value,\n    'sidebar-mini': isMiniMode.value,\n  }\n  for (const [cls, on] of Object.entries(dynamic)) body.classList.toggle(cls, on)\n  \u002F\u002F staticBodyClasses are added here too.\n}) The typeof document === 'undefined' guard makes the effect a no-op on the server, and watchEffect only runs its first pass on the client during hydration.",{"id":384,"title":385,"titles":386,"content":387,"level":27},"\u002Fguide\u002Fssr-safety#providesidebar-options","provideSidebar options",[25,380],"NameTypeDefaultDescriptionsidebarMinibooleanfalseStart in mini (icon-only) mode → body.sidebar-mini.enablePersistencebooleanfalsePersist the collapse state under lte.sidebar.state. Reads\u002Fwrites happen in onMounted\u002Fwatch, never on the server.sidebarBreakpointnumber992Viewport width (px) below which the sidebar behaves as a mobile overlay.staticBodyClassesMaybeRefOrGetter\u003Cstring>—Static layout classes (e.g. layout-fixed sidebar-expand-lg) added to \u003Cbody> alongside the dynamic state classes. Persistence is opt-in for a reason: the saved collapse state can differ from the server-rendered default, so it is read in onMounted (after first paint) to avoid driving a hydration mismatch.",{"id":389,"title":390,"titles":391,"content":392,"level":13},"\u002Fguide\u002Fssr-safety#color-mode-avoids-the-flash-with-a-head-script","Color mode avoids the flash with a head script",[25],"Color mode writes data-bs-theme on \u003Chtml> and persists the preference under the lte-theme localStorage key. The persisted value cannot influence the server render, so @adminlte\u002Fnuxt injects a blocking inline head script (the themeScript option) that sets the attribute before first paint. useColorMode only owns reactive updates after hydration. In the demo, the toggle glyph is rendered under \u003CClientOnly>.",{"id":394,"title":395,"titles":396,"content":397,"level":13},"\u002Fguide\u002Fssr-safety#the-dynamic-import-plugin-pattern","The dynamic-import plugin pattern",[25],"Heavy third-party libs (ApexCharts, Tabulator, Quill, FullCalendar, …) are never statically imported — a static import would pull browser-only code into the server bundle. Each wrapper in src\u002Fplugins\u002F*.vue follows the same shape (LteApexChart.vue is the reference implementation): await import(...) the lib inside onMounted only;guard if (!el.value) return after the await, since the component may unmount before the import resolves;destroy the instance in onBeforeUnmount. Wrap these components in \u003CClientOnly> so they never render during SSR, and provide a #fallback for the server pass: \u003Ctemplate>\n  \u003CClientOnly>\n    \u003CLteApexChart :options=\"options\" :series=\"series\" \u002F>\n    \u003Ctemplate #fallback>\n      \u003Cdiv class=\"placeholder-glow\">\u003Cspan class=\"placeholder col-12\" \u002F>\u003C\u002Fdiv>\n    \u003C\u002Ftemplate>\n  \u003C\u002FClientOnly>\n\u003C\u002Ftemplate> Consumers install the matching lib as their own dependency and load its CSS.",{"id":399,"title":400,"titles":401,"content":402,"level":13},"\u002Fguide\u002Fssr-safety#checklist-for-new-code","Checklist for new code",[25],"Touch window \u002F document \u002F localStorage \u002F matchMedia only inside onMounted, watchEffect (with a typeof … === 'undefined' guard), or an event handler.Default any value derived from a browser API to a server-safe constant (the way window width defaults to desktop).Mutate only elements outside the app tree (like \u003Cbody>) imperatively; never imperatively change rendered DOM that Vue will diff.Wrap any component that loads a browser-only lib in \u003CClientOnly> with a #fallback.Verify with pnpm build:demo (and node apps\u002Fdemo\u002F.output\u002Fserver\u002Findex.mjs) — a clean production demo build with no hydration warnings is the real gate. html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}",{"id":31,"title":30,"titles":404,"content":405,"level":8},[],"How the framework-agnostic library integrates with your router. The core adminlte-vue library never imports a router. Instead, LteDashboardLayout takes a small set of props that let you wire it to whatever routing solution your app uses — Nuxt, Vue Router, or plain anchors. This keeps the library framework-agnostic while still giving you active-link highlighting and working navigation in the command palette.",{"id":407,"title":408,"titles":409,"content":410,"level":13},"\u002Fguide\u002Frouting#the-three-integration-points","The three integration points",[30],"PropTypeDefaultWhat it doescurrentPathstring'\u002F'The current route path. Used for active-link detection in the sidebar — the nav item whose href matches gets the active state.linkComponentstring | Component'a'The component used to render sidebar and palette links. Pass your router's link component (e.g. NuxtLink) for client-side navigation.navigate(href: string) => void—Callback invoked when a command-palette result is chosen. Wire it to your router's programmatic navigation. By default the layout renders plain \u003Ca> tags and reads currentPath as '\u002F', so it works with zero configuration — links just do full-page navigation.",{"id":412,"title":413,"titles":414,"content":415,"level":13},"\u002Fguide\u002Frouting#nuxt-example","Nuxt example",[30],"In Nuxt, pull the current path from useRoute(), resolve NuxtLink for client-side navigation, and pass navigateTo as the palette's navigate callback. \u003Cscript setup lang=\"ts\">\nimport { resolveComponent } from 'vue'\nimport type { MenuNode } from 'adminlte-vue'\n\nconst route = useRoute()\nconst NuxtLink = resolveComponent('NuxtLink')\n\nconst menuItems: MenuNode[] = [\n  { type: 'header', text: 'MAIN' },\n  { type: 'item', text: 'Dashboard', href: '\u002F', icon: 'bi-speedometer' },\n  {\n    type: 'group',\n    text: 'Pages',\n    icon: 'bi-files',\n    children: [\n      { type: 'item', text: 'Profile', href: '\u002Fpages\u002Fprofile' },\n      { type: 'item', text: 'Settings', href: '\u002Fpages\u002Fsettings' },\n    ],\n  },\n]\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteDashboardLayout\n    :menu-items=\"menuItems\"\n    :current-path=\"route.path\"\n    :link-component=\"NuxtLink\"\n    :navigate=\"navigateTo\"\n  >\n    \u003Cslot \u002F>\n  \u003C\u002FLteDashboardLayout>\n\u003C\u002Ftemplate> The @adminlte\u002Fnuxt module auto-registers LteDashboardLayout and auto-imports the MenuNode type, so no manual component import is needed in a Nuxt app.",{"id":417,"title":418,"titles":419,"content":420,"level":13},"\u002Fguide\u002Frouting#vue-router-example","Vue Router example",[30],"The same props work with plain Vue Router — resolve RouterLink, read the path from the current route, and use router.push for the palette. \u003Cscript setup lang=\"ts\">\nimport { resolveComponent } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { LteDashboardLayout, type MenuNode } from 'adminlte-vue'\n\nconst route = useRoute()\nconst router = useRouter()\nconst RouterLink = resolveComponent('RouterLink')\n\nconst menuItems: MenuNode[] = [\n  { type: 'item', text: 'Dashboard', href: '\u002F', icon: 'bi-speedometer' },\n]\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteDashboardLayout\n    :menu-items=\"menuItems\"\n    :current-path=\"route.path\"\n    :link-component=\"RouterLink\"\n    :navigate=\"(href) => router.push(href)\"\n  >\n    \u003CRouterView \u002F>\n  \u003C\u002FLteDashboardLayout>\n\u003C\u002Ftemplate> Most router link components (NuxtLink, RouterLink) accept an href\u002Fto prop and render an anchor, so the sidebar's link rendering stays compatible. With the default 'a', links navigate with a full page load.",{"id":422,"title":423,"titles":424,"content":425,"level":13},"\u002Fguide\u002Frouting#the-menu-structure","The menu structure",[30],"A single MenuNode[] array drives both the sidebar navigation tree and the ⌘K command palette. MenuNode is a discriminated union of three node types, distinguished by the type field.",{"id":427,"title":428,"titles":429,"content":430,"level":27},"\u002Fguide\u002Frouting#menuheader","MenuHeader",[30,423],"A non-interactive section label. FieldTypeDescriptiontype'header'Discriminant.textstringThe label text.",{"id":432,"title":433,"titles":434,"content":435,"level":27},"\u002Fguide\u002Frouting#menuitem","MenuItem",[30,423],"A clickable leaf link. FieldTypeDescriptiontype'item'Discriminant.textstringLink label.hrefstringLink target. Matched against currentPath for the active state.iconstringBootstrap Icons class, e.g. 'bi-speedometer' (with or without the leading bi).iconColorBootstrapThemeIcon color variant.badgestring | numberOptional badge content.badgeColorBootstrapThemeBadge color variant.target'_blank' | '_self'Anchor target.",{"id":437,"title":438,"titles":439,"content":440,"level":27},"\u002Fguide\u002Frouting#menugroup","MenuGroup",[30,423],"A collapsible submenu (treeview) that nests further MenuNodes. FieldTypeDescriptiontype'group'Discriminant.textstringGroup label.iconstringBootstrap Icons class.iconColorBootstrapThemeIcon color variant.badgestring | numberOptional badge content.badgeColorBootstrapThemeBadge color variant.childrenMenuNode[]Nested nodes — groups can nest other groups for multi-level menus. import type { MenuNode } from 'adminlte-vue'\n\nconst menuItems: MenuNode[] = [\n  { type: 'header', text: 'NAVIGATION' },\n  { type: 'item', text: 'Dashboard', href: '\u002F', icon: 'bi-speedometer' },\n  {\n    type: 'group',\n    text: 'Pages',\n    icon: 'bi-files',\n    badge: 4,\n    badgeColor: 'secondary',\n    children: [\n      { type: 'item', text: 'Profile', href: '\u002Fpages\u002Fprofile' },\n      {\n        type: 'group',\n        text: 'Auth',\n        children: [\n          { type: 'item', text: 'Login', href: '\u002Flogin' },\n          { type: 'item', text: 'Register', href: '\u002Fregister' },\n        ],\n      },\n    ],\n  },\n]",{"id":442,"title":443,"titles":444,"content":445,"level":13},"\u002Fguide\u002Frouting#active-link-detection-the-treeview","Active-link detection & the treeview",[30],"The sidebar compares each MenuItem's href against currentPath to apply the active class. Because currentPath is reactive, the highlighted item updates automatically on navigation when you wire it to route.path. For nested menus, set accordion on the layout to keep only one group open at a time: \u003CLteDashboardLayout :menu-items=\"menuItems\" :current-path=\"route.path\" :accordion=\"true\">\n  \u003Cslot \u002F>\n\u003C\u002FLteDashboardLayout> html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":37,"title":35,"titles":447,"content":448,"level":8},[],"The full set of Lte* components and how they are organized. adminlte-vue ships a complete set of Vue 3 components for building AdminLTE 4 dashboards. Every\ncomponent is prefixed Lte and is grouped into five categories: layout, widget, form, tool, and\nplugin wrappers.",{"id":450,"title":451,"titles":452,"content":453,"level":13},"\u002Fcomponents\u002Foverview#two-entry-points","Two entry points",[35],"Core components (layout, widget, form, tool) come from the package root. Plugin wrappers — thin\ncomponents around heavy third-party libraries — live in a separate \u002Fplugins entry so those\ndependencies stay out of your default import. import { LteDashboardLayout, LteCard, LteButton } from 'adminlte-vue'\nimport { LteApexChart, LteDatatable } from 'adminlte-vue\u002Fplugins' In Nuxt with @adminlte\u002Fnuxt, all of these are auto-registered, so you can use the tags in any\npage without importing them.",{"id":455,"title":456,"titles":457,"content":458,"level":13},"\u002Fcomponents\u002Foverview#registering-everything-plain-vue-3","Registering everything (plain Vue 3)",[35],"The default export is a Vue plugin that globally registers all core components. Plugin wrappers\nare not registered by the plugin — import them explicitly. import { createApp } from 'vue'\nimport AdminLte from 'adminlte-vue'\nimport 'adminlte-vue\u002Fcss'\nimport App from '.\u002FApp.vue'\n\ncreateApp(App).use(AdminLte).mount('#app')",{"id":460,"title":42,"titles":461,"content":462,"level":13},"\u002Fcomponents\u002Foverview#layout",[35],"The structural shell of a dashboard. LteDashboardLayout is the single provider host — wrap your\napp in it. Import from adminlte-vue. ComponentPurposeLteDashboardLayoutTop-level dashboard shell and state providerLteAuthLayoutCentered shell for login \u002F register pagesLteAppContentPage content wrapper with headerLteSidebarMain sidebar containerLteSidebarBrandSidebar brand \u002F logo areaLteSidebarNavSidebar navigation listLteSidebarNavItemRecursive nav item (renders the menu tree)LteSidebarOverlayMobile backdrop for the open sidebarLteTopbarTop navigation barLteFooterPage footerLteColorModeToggleLight \u002F dark \u002F auto theme toggleLteFullscreenToggleEnter \u002F exit browser fullscreen",{"id":464,"title":465,"titles":466,"content":467,"level":13},"\u002Fcomponents\u002Foverview#widget","Widget",[35],"Cards, boxes, stats and nav-dropdown widgets. Import from adminlte-vue. ComponentPurposeLteCardStandard AdminLTE cardLteSmallBoxStat box with icon and linkLteInfoBoxCompact info \u002F metric boxLteAlertDismissible alertLteCalloutBordered callout noteLteProgressSingle progress barLteProgressGroupLabeled progress groupLteTimelineVertical timelineLteRatingsStar rating displayLteProfileCardUser profile cardLteDescriptionBlockDescription \u002F stat blockLteDirectChatDirect-chat message panelLteNavMessagesTopbar messages dropdownLteNavNotificationsTopbar notifications dropdownLteNavTasksTopbar tasks dropdownLteToastBootstrap toastLteTabs \u002F LteTabTab container and panelLteAccordion \u002F LteAccordionItemAccordion container and itemLteBreadcrumbBreadcrumb trailLteCommandPalette⌘K command palette LteCommandPalette is accompanied by a flattenMenuToCommands helper (also exported from\nadminlte-vue) that turns a menu array into palette commands. import { LteCommandPalette, flattenMenuToCommands } from 'adminlte-vue'",{"id":469,"title":470,"titles":471,"content":472,"level":13},"\u002Fcomponents\u002Foverview#form","Form",[35],"Form controls, plain and enhanced. Import from adminlte-vue. ComponentPurposeLteButtonButtonLteInputText inputLteTextareaTextareaLteSelectNative selectLteInputSwitchToggle switchLteInputColorColor picker inputLteInputFileFile inputLteInputFlatpickrDate input (Flatpickr-backed)LteInputTomSelectEnhanced select (Tom Select-backed)",{"id":474,"title":475,"titles":476,"content":477,"level":13},"\u002Fcomponents\u002Foverview#tool","Tool",[35],"Interactive utilities, imported from adminlte-vue (listed here — no separate detail page). ComponentPurposeLteModalBootstrap modalLteWizard \u002F LteWizardStepMulti-step wizard and step",{"id":479,"title":480,"titles":481,"content":482,"level":13},"\u002Fcomponents\u002Foverview#plugin","Plugin",[35],"Wrappers around heavy third-party libraries. Each one dynamically imports its dependency on the\nclient, so you must install the matching peer library yourself and load its CSS. In SSR apps (Nuxt),\nwrap them in \u003CClientOnly>. Import from adminlte-vue\u002Fplugins. ComponentPeer libraryLteApexChartapexchartsLteSparklineChartapexchartsLteDatatabletabulator-tablesLteEditorquillLteFlatpickrflatpickrLteTomSelecttom-selectLteCalendar@fullcalendar\u002F*LteVectorMapjsvectormapLteSortablesortablejsLteKanbansortablejs LteKanban also exports its KanbanCard and KanbanColumn types. \u003Ctemplate>\n  \u003CClientOnly>\n    \u003CLteApexChart :options=\"options\" :series=\"series\" \u002F>\n  \u003C\u002FClientOnly>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nimport { LteApexChart } from 'adminlte-vue\u002Fplugins'\n\u003C\u002Fscript> pnpm add apexcharts html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"id":43,"title":41,"titles":484,"content":485,"level":8},[],"LteDashboardLayout, LteSidebar, LteTopbar, LteAppContent, LteFooter, LteAuthLayout. The layout components assemble the AdminLTE shell. LteDashboardLayout is the single host that wires\nthe topbar, sidebar, footer and command palette together and provides the shared sidebar \u002F color-mode\n\u002F command-palette state to every descendant. The remaining components either render inside it or, like\nLteAuthLayout, stand alone for sign-in pages.",{"id":487,"title":488,"titles":489,"content":490,"level":13},"\u002Fcomponents\u002Flayout#ltedashboardlayout","LteDashboardLayout",[41],"The top-level wrapper for an admin page. It renders LteTopbar, LteSidebar, your page content (via\nthe default slot), LteFooter, and the ⌘K command palette — and installs all shared state. \u003Ctemplate>\n  \u003CLteDashboardLayout\n    :menu-items=\"menu\"\n    brand-text=\"Acme\"\n    :current-path=\"$route.path\"\n    @logout=\"signOut\"\n    @profile=\"goToProfile\"\n  >\n    \u003CLteAppContent title=\"Dashboard\">\n      \u003C!-- page content -->\n    \u003C\u002FLteAppContent>\n  \u003C\u002FLteDashboardLayout>\n\u003C\u002Ftemplate>",{"id":492,"title":493,"titles":494,"content":495,"level":27},"\u002Fcomponents\u002Flayout#props","Props",[41,488],"NameTypeDefaultDescriptionmenuItemsMenuNode[]—Navigation tree feeding the sidebar and the command palette.logostring—Logo image src. When omitted the logo slot (or default AdminLTE text) is used.logoHrefstring'\u002F'Link target for the sidebar brand.userTopbarUser—Signed-in user shown in the topbar menu.sidebarTheme'light' | 'dark''dark'Sidebar color theme (independent of the global color mode).sidebarClassstring—Extra classes on the \u003Caside class=\"app-sidebar\">.sidebarBreakpoint'sm' | 'md' | 'lg' | 'xl' | 'xxl''lg'Breakpoint where the sidebar expands \u002F push-menu activates.sidebarMinibooleanfalseEnable the collapsed mini-sidebar behavior.fixedHeaderbooleanfalseAdd the fixed-header body class.fixedSidebarbooleanfalseAdd the fixed-sidebar body class.fixedFooterbooleanfalseAdd the fixed-footer body class.layoutFixedbooleantrueAdd the layout-fixed body class.colorModeTogglebooleantrueShow the light\u002Fdark toggle in the topbar.initialColorMode'light' | 'dark' | 'auto''auto'Starting color mode before persisted preference loads.dir'ltr' | 'rtl'—Text direction.enableSidebarPersistencebooleanfalsePersist the sidebar collapse state to localStorage.navbarClassstring—Extra classes on the topbar \u003Cnav>.bodyClassstring—Extra classes appended to the body layout classes.currentPathstring'\u002F'Current route path for active-link detection.brandTextstring—Brand text shown next to the logo in the sidebar.linkComponentstring | Component'a'Link component for sidebar\u002Fpalette nav (e.g. NuxtLink).accordionbooleanfalseAccordion treeview — one open group per parent.navigate(href: string) => void—Navigation callback for the command palette (e.g. router.push).",{"id":497,"title":498,"titles":499,"content":500,"level":27},"\u002Fcomponents\u002Flayout#emits","Emits",[41,488],"NamePayloadDescriptionlogout—The user clicked \"Sign out\" in the topbar menu.profile—The user clicked \"Profile\" in the topbar menu.",{"id":502,"title":503,"titles":504,"content":505,"level":27},"\u002Fcomponents\u002Flayout#slots","Slots",[41,488],"NameDescriptiondefaultPage content (rendered inside \u003Cmain class=\"app-main\">).topbar-startExtra nav items at the start of the topbar.topbar-endExtra nav items at the end of the topbar.sidebar-brandReplace the entire sidebar brand area.logoCustom logo markup inside the brand.footerFooter content (forwarded to LteFooter).",{"id":507,"title":508,"titles":509,"content":510,"level":13},"\u002Fcomponents\u002Flayout#ltesidebar","LteSidebar",[41],"The off-canvas navigation aside. Renders the brand, a scroll wrapper (auto-hiding OverlayScrollbars on\ndesktop when installed), and the recursive nav tree. Normally rendered for you by LteDashboardLayout. \u003CLteSidebar :items=\"menu\" brand-text=\"Acme\" :current-path=\"$route.path\" theme=\"dark\" \u002F>",{"id":512,"title":493,"titles":513,"content":514,"level":27},"\u002Fcomponents\u002Flayout#props-1",[41,508],"NameTypeDefaultDescriptionitemsMenuNode[]—Navigation tree.logostring—Logo image src.logoHrefstring'\u002F'Brand link target.brandTextstring—Brand text next to the logo.theme'light' | 'dark''dark'Sidebar color theme.sidebarClassstring'bg-body-secondary shadow'Extra classes on the \u003Caside>.currentPathstring'\u002F'Active-link detection path.accordionbooleanfalseOne open group per parent.linkComponentstring | Component'a'Link component for nav items.animationSpeednumber300Treeview expand\u002Fcollapse duration in ms.",{"id":516,"title":503,"titles":517,"content":518,"level":27},"\u002Fcomponents\u002Flayout#slots-1",[41,508],"NameDescriptionbrandReplace the brand area entirely.logoCustom logo markup (inside the default brand).defaultReplace the nav tree with custom markup.",{"id":520,"title":521,"titles":522,"content":523,"level":13},"\u002Fcomponents\u002Flayout#ltetopbar","LteTopbar",[41],"The fixed application navbar: sidebar toggle, optional search\u002Fcommand-palette trigger, fullscreen and\ncolor-mode toggles, and the user dropdown menu. Rendered for you by LteDashboardLayout.",{"id":525,"title":493,"titles":526,"content":527,"level":27},"\u002Fcomponents\u002Flayout#props-2",[41,521],"NameTypeDefaultDescriptionuserTopbarUser—User shown in the menu (falls back to a demo user).colorModeTogglebooleantrueShow the light\u002Fdark toggle.searchbooleantrueShow the search button (opens the command palette).fullscreenbooleantrueShow the fullscreen toggle.navbarClassstring—Extra classes on the \u003Cnav>.",{"id":529,"title":498,"titles":530,"content":531,"level":27},"\u002Fcomponents\u002Flayout#emits-1",[41,521],"NamePayloadDescriptionlogout—\"Sign out\" clicked.profile—\"Profile\" clicked.",{"id":533,"title":503,"titles":534,"content":535,"level":27},"\u002Fcomponents\u002Flayout#slots-2",[41,521],"NameDescriptionstartExtra nav items after the sidebar toggle.endExtra nav items before the built-in toggles. The TopbarUser interface: interface TopbarUser {\n  name: string\n  image: string\n  role?: string\n  memberSince?: string\n}",{"id":537,"title":538,"titles":539,"content":540,"level":13},"\u002Fcomponents\u002Flayout#lteappcontent","LteAppContent",[41],"The content region for a page: an optional header (title + breadcrumbs) and a Bootstrap container\nwrapping your content. \u003CLteAppContent\n  title=\"Dashboard\"\n  :breadcrumbs=\"[{ label: 'Home', href: '\u002F' }, { label: 'Dashboard' }]\"\n>\n  \u003C!-- page content -->\n\u003C\u002FLteAppContent>",{"id":542,"title":493,"titles":543,"content":544,"level":27},"\u002Fcomponents\u002Flayout#props-3",[41,538],"NameTypeDefaultDescriptiontitlestring—Page title rendered as an \u003Ch3> in the header.breadcrumbsBreadcrumb[]—Breadcrumb trail; the last entry is marked active.fluidbooleantruetrue → container-fluid, false → container-lg.",{"id":546,"title":503,"titles":547,"content":548,"level":27},"\u002Fcomponents\u002Flayout#slots-3",[41,538],"NameDescriptionheaderReplace the header left column (overrides title).defaultPage content (inside the container). The Breadcrumb interface: interface Breadcrumb {\n  label: string\n  href?: string\n}",{"id":550,"title":551,"titles":552,"content":553,"level":13},"\u002Fcomponents\u002Flayout#ltefooter","LteFooter",[41],"The application footer. Defaults to the AdminLTE copyright line; override via slots. Rendered for you\nby LteDashboardLayout (its footer slot is forwarded here).",{"id":555,"title":493,"titles":556,"content":557,"level":27},"\u002Fcomponents\u002Flayout#props-4",[41,551],"NameTypeDefaultDescriptionrightTextstring'Anything you want'Right-aligned text (hidden on extra-small screens).yearnumber | stringcurrent yearYear used in the default copyright line.",{"id":559,"title":503,"titles":560,"content":561,"level":27},"\u002Fcomponents\u002Flayout#slots-4",[41,551],"NameDescriptiondefaultMain footer content (replaces the default copyright).rightRight-aligned content (replaces rightText).",{"id":563,"title":564,"titles":565,"content":566,"level":13},"\u002Fcomponents\u002Flayout#lteauthlayout","LteAuthLayout",[41],"A standalone wrapper for sign-in \u002F register pages. It applies the page-level body classes\n(login-page \u002F register-page plus bg-body-secondary) on mount and renders a centered card. \u003Ctemplate>\n  \u003CLteAuthLayout auth-type=\"login\" variant=\"v2\" logo=\"\u002Flogo.svg\">\n    \u003C!-- login form -->\n  \u003C\u002FLteAuthLayout>\n\u003C\u002Ftemplate>",{"id":568,"title":493,"titles":569,"content":570,"level":27},"\u002Fcomponents\u002Flayout#props-5",[41,564],"NameTypeDefaultDescriptionauthType'login' | 'register''login'Drives the body class and box\u002Fcard-body class prefixes.variant'default' | 'v2''default''default' → logo above a plain card; 'v2' → card-outline card-primary with the logo in the card header.logostring—Logo image src (used by the default logo slot).logoHrefstring'\u002F'Logo link target.",{"id":572,"title":503,"titles":573,"content":574,"level":27},"\u002Fcomponents\u002Flayout#slots-5",[41,564],"NameDescriptionlogoCustom logo markup (overrides the default image \u002F AdminLTE text).defaultThe form \u002F card body content. html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"id":48,"title":46,"titles":576,"content":577,"level":8},[],"Cards, boxes, timeline, direct chat, progress, callouts and more. Widgets are the building blocks of an AdminLTE dashboard body — cards, stat boxes, timelines and\nchat panels. They are auto-registered by the Nuxt module (and by app.use(AdminLte) in plain Vue),\nso you can use them without imports. Every widget styles itself from the prebuilt AdminLTE CSS; you\nonly pass props and slots. Colors use the shared BootstrapTheme union: primary, secondary,\nsuccess, info, warning, danger, light, dark. This page covers the main widgets. Other widgets also ship in the library (see the components\noverview) — the API tables below reflect the real component source.",{"id":579,"title":580,"titles":581,"content":582,"level":13},"\u002Fcomponents\u002Fwidgets#ltecard","LteCard",[46],"The general-purpose container. Renders a .card with an optional header (driven by title\u002Ficon\nor the #header slot), an optional footer slot, and built-in collapse \u002F maximize \u002F remove tools.\nThe theme + variant combination controls the color treatment; gradient adds bg-gradient. \u003Ctemplate>\n  \u003CLteCard title=\"Monthly recap\" icon=\"bi-graph-up\" theme=\"primary\" variant=\"outline\" collapsible>\n    \u003Cp>Card body content.\u003C\u002Fp>\n    \u003Ctemplate #footer>Updated just now\u003C\u002Ftemplate>\n  \u003C\u002FLteCard>\n\u003C\u002Ftemplate> Use the #header slot to fully replace the default header (title + tools): \u003CLteCard>\n  \u003Ctemplate #header>\n    \u003Ch3 class=\"card-title\">Custom header\u003C\u002Fh3>\n  \u003C\u002Ftemplate>\n  Body\n\u003C\u002FLteCard>",{"id":584,"title":493,"titles":585,"content":586,"level":27},"\u002Fcomponents\u002Fwidgets#props",[46,580],"NameTypeDefaultDescriptiontitlestring—Header title text (rendered inside .card-title).iconstring—Bootstrap Icons class shown before the title.themeBootstrapTheme—Color theme; enables the colored treatments.variant'default' | 'outline' | 'solid''default'default colored header, outline colored top border, solid fully colored card.gradientbooleanfalseAdds bg-gradient (most visible with variant: 'solid').collapsiblebooleanfalseShow the collapse\u002Fexpand tool button.defaultCollapsedbooleanfalseStart collapsed.removablebooleanfalseShow the remove tool button.maximizablebooleanfalseShow the maximize tool button.bodyClassstring—Extra classes on .card-body.headerClassstring—Extra classes on .card-header.footerClassstring—Extra classes on .card-footer.",{"id":588,"title":503,"titles":589,"content":590,"level":27},"\u002Fcomponents\u002Fwidgets#slots",[46,580],"NameDescriptiondefaultCard body content.headerReplaces the entire header (title + tools).titleReplaces only the title content.toolsExtra tool buttons, rendered before the built-in tools.footerFooter content; the footer only renders when this slot is used.",{"id":592,"title":593,"titles":594,"content":595,"level":13},"\u002Fcomponents\u002Fwidgets#ltesmallbox","LteSmallBox",[46],"A colored stat box with a big number, label, icon and an optional footer link. The whole box is\ntinted with text-bg-{theme}. \u003CLteSmallBox\n  :title=\"150\"\n  text=\"New orders\"\n  icon=\"bi-bag\"\n  theme=\"success\"\n  url=\"\u002Forders\"\n  url-text=\"View orders\"\n\u002F>",{"id":597,"title":493,"titles":598,"content":599,"level":27},"\u002Fcomponents\u002Fwidgets#props-1",[46,593],"NameTypeDefaultDescriptiontitlestring | number—The large headline value.textstring—The label under the value.iconstring—Bootstrap Icons class for the corner icon.themeBootstrapTheme'primary'Background color of the box.urlstring—Footer link href; the footer only renders when set.urlTextstring'More info'Footer link label.loadingbooleanfalseShows a spinner overlay.",{"id":601,"title":503,"titles":602,"content":603,"level":27},"\u002Fcomponents\u002Fwidgets#slots-1",[46,593],"NameDescriptiontitleReplaces the headline value.defaultReplaces the label text.iconReplaces the corner icon.",{"id":605,"title":606,"titles":607,"content":608,"level":13},"\u002Fcomponents\u002Fwidgets#lteinfobox","LteInfoBox",[46],"A horizontal stat box: a colored icon chip plus a text label, number and optional progress bar. \u003CLteInfoBox\n  text=\"Bookmarks\"\n  :title=\"41410\"\n  icon=\"bi-bookmark\"\n  theme=\"info\"\n  :progress=\"70\"\n  progress-text=\"70% increase in 30 days\"\n\u002F>",{"id":610,"title":493,"titles":611,"content":612,"level":27},"\u002Fcomponents\u002Fwidgets#props-2",[46,606],"NameTypeDefaultDescriptiontitlestring | number—The number value (rendered when not null).textstring—The label above the number.iconstring—Bootstrap Icons class for the icon chip.themeBootstrapTheme'info'Box \u002F icon \u002F progress color.iconThemeBootstrapTheme—Override the icon chip color (default variant only).variant'default' | 'solid''default'default white box with a colored chip; solid colors the whole box.gradientbooleanfalseAdds bg-gradient (only meaningful with variant=\"solid\").boxClassstring—Extra classes on the .info-box root.unitstring—Small unit rendered after the number, e.g. %.progressnumber—Progress percentage (0–100); renders a bar when set.progressTextstring—Caption under the progress bar. The default slot renders inside .info-box-content (after the number) for custom content.",{"id":614,"title":615,"titles":616,"content":617,"level":13},"\u002Fcomponents\u002Fwidgets#ltetimeline","LteTimeline",[46],"Renders a vertical timeline from an array of items. Each item's body and footer are inserted as\nHTML (v-html). \u003Cscript setup lang=\"ts\">\nimport type { TimelineItem } from 'adminlte-vue'\n\nconst items: TimelineItem[] = [\n  { time: '12:05', icon: 'bi-envelope', iconTheme: 'primary', title: 'New message', body: 'You have a new message.' },\n  { time: '5 mins ago', icon: 'bi-person', iconTheme: 'success', title: 'New user registered' },\n]\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteTimeline :items=\"items\" \u002F>\n\u003C\u002Ftemplate>",{"id":619,"title":493,"titles":620,"content":621,"level":27},"\u002Fcomponents\u002Fwidgets#props-3",[46,615],"NameTypeDefaultDescriptionitemsTimelineItem[]—The timeline entries (required).",{"id":623,"title":624,"titles":625,"content":626,"level":27},"\u002Fcomponents\u002Fwidgets#timelineitem","TimelineItem",[46,615],"FieldTypeDescriptiontimestringTimestamp label shown in the header.titlestringEntry heading.iconstringBootstrap Icons class (defaults to bi-circle-fill).iconThemeBootstrapThemeIcon background color (defaults to primary).bodystringBody markup, inserted as HTML.footerstringFooter markup, inserted as HTML.urlstringWraps the title in a link.",{"id":628,"title":629,"titles":630,"content":631,"level":13},"\u002Fcomponents\u002Fwidgets#ltedirectchat","LteDirectChat",[46],"A chat card with a messages pane and a sliding contacts panel toggled by the header button. \u003Cscript setup lang=\"ts\">\nimport type { DirectChatMessage, DirectChatContact } from 'adminlte-vue'\n\nconst messages: DirectChatMessage[] = [\n  { from: 'Alex', image: '\u002Favatar.png', timestamp: '23 Jan 2:00 pm', text: 'Hey!' },\n  { from: 'You', image: '\u002Fme.png', timestamp: '23 Jan 2:05 pm', text: 'Hi there', isOwn: true },\n]\nconst contacts: DirectChatContact[] = [\n  { name: 'Count Dracula', image: '\u002Fd.png', date: '1\u002F28\u002F2022', preview: 'How have you been?' },\n]\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteDirectChat title=\"Direct chat\" theme=\"primary\" :messages=\"messages\" :contacts=\"contacts\" \u002F>\n\u003C\u002Ftemplate>",{"id":633,"title":493,"titles":634,"content":635,"level":27},"\u002Fcomponents\u002Fwidgets#props-4",[46,629],"NameTypeDefaultDescriptiontitlestring—Card header title.themeBootstrapTheme'primary'Chat accent color (direct-chat-{theme}).messagesDirectChatMessage[][]Messages to render in the default messages markup.contactsDirectChatContact[][]Contacts to render in the contacts panel.",{"id":637,"title":503,"titles":638,"content":639,"level":27},"\u002Fcomponents\u002Fwidgets#slots-2",[46,629],"NameDescriptionmessagesReplaces the default messages list.contactsReplaces the default contacts list.footerFooter content; renders only when used (e.g. a message input).",{"id":641,"title":642,"titles":643,"content":644,"level":27},"\u002Fcomponents\u002Fwidgets#directchatmessage","DirectChatMessage",[46,629],"FieldTypeDescriptionfromstringSender name.imagestringAvatar URL.timestampstringDisplayed time.textstringMessage body.isOwnbooleanAligns the message to the end (the current user).",{"id":646,"title":647,"titles":648,"content":649,"level":27},"\u002Fcomponents\u002Fwidgets#directchatcontact","DirectChatContact",[46,629],"FieldTypeDescriptionnamestringContact name.imagestringAvatar URL.datestringLast-activity date.previewstringLast-message preview text.",{"id":651,"title":652,"titles":653,"content":654,"level":13},"\u002Fcomponents\u002Fwidgets#ltecallout","LteCallout",[46],"A bordered, themed note block. Pass body content via the default slot. \u003CLteCallout theme=\"warning\" title=\"Follow the steps\">\n  Make sure you complete the setup before continuing.\n\u003C\u002FLteCallout>",{"id":656,"title":493,"titles":657,"content":658,"level":27},"\u002Fcomponents\u002Fwidgets#props-5",[46,652],"NameTypeDefaultDescriptionthemeBootstrapTheme'info'Callout color (callout-{theme}).titlestring—Optional heading (h5).",{"id":660,"title":661,"titles":662,"content":663,"level":13},"\u002Fcomponents\u002Fwidgets#ltealert","LteAlert",[46],"A Bootstrap alert with an optional icon, title and dismiss button. Supports both controlled\n(v-model:show) and uncontrolled usage. \u003Ctemplate>\n  \u003CLteAlert theme=\"success\" icon=\"bi-check-circle\" title=\"Saved!\" dismissible>\n    Your changes were stored.\n  \u003C\u002FLteAlert>\n\n  \u003C!-- Controlled -->\n  \u003CLteAlert v-model:show=\"visible\" theme=\"danger\" dismissible @dismissed=\"onDismiss\">\n    Something went wrong.\n  \u003C\u002FLteAlert>\n\u003C\u002Ftemplate>",{"id":665,"title":493,"titles":666,"content":667,"level":27},"\u002Fcomponents\u002Fwidgets#props-6",[46,661],"NameTypeDefaultDescriptionthemeBootstrapTheme'info'Alert color (alert-{theme}).iconstring—Bootstrap Icons class shown in the heading.titlestring—Heading text.dismissiblebooleanfalseAdds a close button.showbooleantrueVisibility (use with v-model:show).",{"id":669,"title":498,"titles":670,"content":671,"level":27},"\u002Fcomponents\u002Fwidgets#emits",[46,661],"NamePayloadDescriptionupdate:showbooleanFired on dismiss (enables v-model:show).dismissed—Fired when the alert is dismissed.",{"id":673,"title":674,"titles":675,"content":676,"level":13},"\u002Fcomponents\u002Fwidgets#lteprogress","LteProgress",[46],"A progress bar with theming, sizing, striped\u002Fanimated options and an optional percentage label. \u003CLteProgress :value=\"60\" theme=\"success\" striped animated show-label \u002F>",{"id":678,"title":493,"titles":679,"content":680,"level":27},"\u002Fcomponents\u002Fwidgets#props-7",[46,674],"NameTypeDefaultDescriptionvaluenumber—Current value (required).maxnumber100Maximum value; the bar width is value \u002F max.themeBootstrapTheme'primary'Bar color (bg-{theme}).sizeComponentSize—'sm' or 'lg' track height.stripedbooleanfalseAdds the striped style.animatedbooleanfalseAnimates the stripes.showLabelbooleanfalseRenders the rounded percentage inside the bar.heightstring—Custom track height (CSS value). html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"id":53,"title":51,"titles":682,"content":683,"level":8},[],"Inputs, selects, switches and form helpers. AdminLTE Vue ships a small set of form controls that wrap Bootstrap 5.3 markup with v-model support, optional labels, validation feedback and consistent sizing. The components are LteInput, LteSelect, LteTextarea, LteInputSwitch and LteButton. Every control forwards unknown attributes to the underlying element, so native attributes like name, autocomplete or maxlength work as expected.",{"id":685,"title":686,"titles":687,"content":688,"level":13},"\u002Fcomponents\u002Fforms#lteinput","LteInput",[51],"A labelled text input that supports input-group prepend\u002Fappend addons and inline validation. \u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst email = ref('')\nconst amount = ref('')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteInput v-model=\"email\" label=\"Email\" type=\"email\" placeholder=\"you@example.com\" required \u002F>\n\n  \u003CLteInput\n    v-model=\"amount\"\n    label=\"Amount\"\n    prepend=\"$\"\n    append=\".00\"\n    group-size=\"lg\"\n  \u002F>\n\n  \u003CLteInput v-model=\"email\" label=\"Email\" error=\"This field is required.\" \u002F>\n\u003C\u002Ftemplate> When prepend, append or error is set, the input is wrapped in a Bootstrap input-group. The error string renders as .invalid-feedback and applies is-invalid to the field. The default slot renders below the field (useful for help text).",{"id":690,"title":493,"titles":691,"content":692,"level":27},"\u002Fcomponents\u002Fforms#props",[51,686],"NameTypeDefaultDescriptionmodelValuestring | number—Bound value (v-model).labelstring—Label text rendered above the input.typestring'text'Native input type.idstringautoInput id; auto-generated via useId() when omitted.placeholderstring—Placeholder text.errorstring—Validation message; adds is-invalid and renders feedback.fgroupClassstring—Extra classes on the wrapping .mb-3 div.groupSize'sm' | 'lg'—Sizing for the input-group (only when an addon\u002Ferror is present).prependstring—Text addon before the input.appendstring—Text addon after the input.disabledbooleanfalseDisables the input.requiredbooleanfalseMarks the input as required.",{"id":694,"title":498,"titles":695,"content":696,"level":27},"\u002Fcomponents\u002Fforms#emits",[51,686],"NamePayloadDescriptionupdate:modelValuestringFired on input for v-model.",{"id":698,"title":503,"titles":699,"content":700,"level":27},"\u002Fcomponents\u002Fforms#slots",[51,686],"NameDescriptiondefaultRendered below the field, inside the wrapper.",{"id":702,"title":703,"titles":704,"content":705,"level":13},"\u002Fcomponents\u002Fforms#lteselect","LteSelect",[51],"A labelled form-select supporting single or multiple selection. Options can come from the options prop or the default slot. \u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst country = ref('us')\nconst tags = ref\u003Cstring[]>([])\n\nconst countries = [\n  { value: 'us', label: 'United States' },\n  { value: 'lv', label: 'Latvia' },\n]\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteSelect v-model=\"country\" label=\"Country\" :options=\"countries\" \u002F>\n\n  \u003CLteSelect v-model=\"tags\" label=\"Tags\" multiple :options=\"countries\" \u002F>\n\n  \u003C!-- Custom options via the default slot -->\n  \u003CLteSelect v-model=\"country\" label=\"Country\">\n    \u003Coption value=\"us\">United States\u003C\u002Foption>\n    \u003Coption value=\"lv\">Latvia\u003C\u002Foption>\n  \u003C\u002FLteSelect>\n\u003C\u002Ftemplate> With multiple, modelValue is an array of the selected option values.",{"id":707,"title":493,"titles":708,"content":709,"level":27},"\u002Fcomponents\u002Fforms#props-1",[51,703],"NameTypeDefaultDescriptionmodelValuestring | number | Array\u003Cstring | number>—Bound value (v-model). Array when multiple.labelstring—Label text rendered above the select.idstringautoSelect id; auto-generated when omitted.options{ value: string | number; label: string }[][]Options to render when the slot is empty.errorstring—Validation message; adds is-invalid and renders feedback.fgroupClassstring—Extra classes on the wrapping .mb-3 div.multiplebooleanfalseEnables multi-select; emits an array value.disabledbooleanfalseDisables the select.",{"id":711,"title":498,"titles":712,"content":713,"level":27},"\u002Fcomponents\u002Fforms#emits-1",[51,703],"NamePayloadDescriptionupdate:modelValuestring | number | Array\u003Cstring | number>Fired on change; array when multiple.",{"id":715,"title":503,"titles":716,"content":717,"level":27},"\u002Fcomponents\u002Fforms#slots-1",[51,703],"NameDescriptiondefaultReplaces the auto-rendered \u003Coption> list.",{"id":719,"title":720,"titles":721,"content":722,"level":13},"\u002Fcomponents\u002Fforms#ltetextarea","LteTextarea",[51],"A labelled multi-line text control. \u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst bio = ref('')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteTextarea v-model=\"bio\" label=\"Bio\" :rows=\"6\" placeholder=\"Tell us about yourself\" \u002F>\n\u003C\u002Ftemplate>",{"id":724,"title":493,"titles":725,"content":726,"level":27},"\u002Fcomponents\u002Fforms#props-2",[51,720],"NameTypeDefaultDescriptionmodelValuestring—Bound value (v-model).labelstring—Label text rendered above the textarea.idstringautoTextarea id; auto-generated when omitted.rowsnumber4Number of visible text rows.placeholderstring—Placeholder text.errorstring—Validation message; adds is-invalid and renders feedback.fgroupClassstring—Extra classes on the wrapping .mb-3 div.disabledbooleanfalseDisables the textarea.",{"id":728,"title":498,"titles":729,"content":696,"level":27},"\u002Fcomponents\u002Fforms#emits-2",[51,720],{"id":731,"title":732,"titles":733,"content":734,"level":13},"\u002Fcomponents\u002Fforms#lteinputswitch","LteInputSwitch",[51],"A Bootstrap switch (form-switch) bound to a boolean. \u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst notifications = ref(true)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteInputSwitch v-model=\"notifications\" label=\"Email notifications\" \u002F>\n\u003C\u002Ftemplate>",{"id":736,"title":493,"titles":737,"content":738,"level":27},"\u002Fcomponents\u002Fforms#props-3",[51,732],"NameTypeDefaultDescriptionmodelValueboolean—Checked state (v-model).labelstring—Label text rendered beside the switch.idstringautoInput id; auto-generated when omitted.themeBootstrapTheme—Bootstrap color variant.disabledbooleanfalseDisables the switch.",{"id":740,"title":498,"titles":741,"content":742,"level":27},"\u002Fcomponents\u002Fforms#emits-3",[51,732],"NamePayloadDescriptionupdate:modelValuebooleanFired on change with the new checked state.",{"id":744,"title":745,"titles":746,"content":747,"level":13},"\u002Fcomponents\u002Fforms#ltebutton","LteButton",[51],"A themed Bootstrap button with optional icon and block layout. \u003Ctemplate>\n  \u003CLteButton theme=\"primary\" label=\"Save\" \u002F>\n  \u003CLteButton theme=\"danger\" outline icon=\"trash\" label=\"Delete\" \u002F>\n  \u003CLteButton type=\"submit\" theme=\"success\" size=\"lg\" block>\n    Submit\n  \u003C\u002FLteButton>\n\u003C\u002Ftemplate> The icon value is passed through the biClass() helper (Bootstrap Icons). When a label or default slot is present, the icon gets a trailing me-1 margin. The default slot overrides the label prop.",{"id":749,"title":493,"titles":750,"content":751,"level":27},"\u002Fcomponents\u002Fforms#props-4",[51,745],"NameTypeDefaultDescriptiontype'button' | 'submit' | 'reset''button'Native button type.themeBootstrapTheme'primary'Bootstrap color variant.outlinebooleanfalseRenders the outline (btn-outline-*) style.size'sm' | 'lg'—Button size.iconstring—Bootstrap Icon name, resolved via biClass().labelstring—Button text (overridden by the default slot).blockbooleanfalseFull-width button (w-100).",{"id":753,"title":503,"titles":754,"content":755,"level":27},"\u002Fcomponents\u002Fforms#slots-2",[51,745],"NameDescriptiondefaultButton content; overrides label. html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"id":58,"title":56,"titles":757,"content":758,"level":8},[],"[object Object] Plugin components wrap heavy third-party libraries (charts, calendars, data grids, editors, drag-and-drop). They are exported from the adminlte-vue\u002Fplugins entry — separate from the core components — so the plugin libs stay out of the default import. Each wrapper renders a host element, then await import(...)s its library inside onMounted and destroys the instance in onBeforeUnmount.",{"id":760,"title":761,"titles":762,"content":763,"level":13},"\u002Fcomponents\u002Fplugins#installation-and-usage","Installation and usage",[56],"Because these wrappers load their library only in the browser, the consuming app must install the matching peer dependency and its CSS, and the component must run client-side only.",{"id":765,"title":766,"titles":767,"content":768,"level":27},"\u002Fcomponents\u002Fplugins#install-the-peer-lib-css","Install the peer lib + CSS",[56,761],"Each wrapper depends on its own (optional) peer library. Install only the ones you use, and import the library's stylesheet yourself. # install the peer lib for the wrapper(s) you use\npnpm add apexcharts          # LteApexChart, LteSparklineChart\npnpm add @fullcalendar\u002Fcore @fullcalendar\u002Fdaygrid @fullcalendar\u002Finteraction  # LteCalendar\npnpm add tabulator-tables    # LteDatatable\npnpm add quill               # LteEditor\npnpm add tom-select          # LteTomSelect\npnpm add flatpickr           # LteFlatpickr\npnpm add jsvectormap         # LteVectorMap\npnpm add sortablejs          # LteSortable, LteKanban",{"id":770,"title":771,"titles":772,"content":773,"level":27},"\u002Fcomponents\u002Fplugins#wrap-in-clientonly","Wrap in \u003CClientOnly>",[56,761],"In a Nuxt (SSR) app, wrap every plugin component in \u003CClientOnly> so it only mounts in the browser. A #fallback keeps the layout stable during hydration. \u003Ctemplate>\n  \u003CClientOnly>\n    \u003CLteApexChart type=\"line\" :series=\"series\" \u002F>\n    \u003Ctemplate #fallback>\n      \u003Cdiv style=\"height: 350px\" \u002F>\n    \u003C\u002Ftemplate>\n  \u003C\u002FClientOnly>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nconst series = [{ name: 'Sales', data: [30, 40, 35, 50, 49, 60, 70] }]\n\u003C\u002Fscript>",{"id":775,"title":776,"titles":777,"content":778,"level":13},"\u002Fcomponents\u002Fplugins#lteapexchart","LteApexChart",[56],"Wraps ApexCharts. The host options are built as { chart: { type, height, width }, series }, with options merged over the top. The chart updates reactively when series, options, type, or height change.",{"id":780,"title":493,"titles":781,"content":782,"level":27},"\u002Fcomponents\u002Fplugins#props",[56,776],"NameTypeDefaultDescriptionseriesunknown[]— (required)The chart series data.typestring'line'ApexCharts chart type (e.g. bar, area, donut).optionsApexOptionsundefinedExtra ApexCharts options merged over { chart: { type, height }, series }.heightnumber | string350Chart height.widthnumber | stringundefinedChart width. \u003CLteApexChart\n  type=\"bar\"\n  :series=\"[{ name: 'Net Profit', data: [44, 55, 57, 56] }]\"\n  :options=\"{ xaxis: { categories: ['Q1', 'Q2', 'Q3', 'Q4'] } }\"\n\u002F>",{"id":784,"title":785,"titles":786,"content":787,"level":13},"\u002Fcomponents\u002Fplugins#ltecalendar","LteCalendar",[56],"Wraps FullCalendar with the daygrid and interaction plugins. The header toolbar and editable: true are preset; pass options to override or extend the FullCalendar config. Updating events reloads the event sources.",{"id":789,"title":493,"titles":790,"content":791,"level":27},"\u002Fcomponents\u002Fplugins#props-1",[56,785],"NameTypeDefaultDescriptioneventsEventInput[][]FullCalendar event inputs.initialViewstring'dayGridMonth'The initial calendar view.optionsPartial\u003CCalendarOptions>undefinedExtra FullCalendar options spread over the defaults.",{"id":793,"title":498,"titles":794,"content":795,"level":27},"\u002Fcomponents\u002Fplugins#emits",[56,785],"NamePayloadDescriptiondateClickDateClickArgA calendar date was clicked.eventClickEventClickArgAn event was clicked.eventDropEventDropArgAn event was dragged to a new date.",{"id":797,"title":798,"titles":799,"content":800,"level":27},"\u002Fcomponents\u002Fplugins#exposed","Exposed",[56,785],"NameReturnsDescriptiongetApi()Calendar | nullThe underlying FullCalendar instance (null until mounted). \u003Ctemplate>\n  \u003CClientOnly>\n    \u003CLteCalendar ref=\"cal\" :events=\"events\" @event-click=\"onEventClick\" \u002F>\n  \u003C\u002FClientOnly>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nconst cal = ref()\nconst events = [{ title: 'Meeting', date: '2026-06-01' }]\nfunction onEventClick(arg) {\n  console.log(arg.event.title)\n}\n\u003C\u002Fscript>",{"id":802,"title":803,"titles":804,"content":805,"level":13},"\u002Fcomponents\u002Fplugins#ltedatatable","LteDatatable",[56],"Wraps Tabulator. The host options default to { layout: 'fitColumns', height, columns, data }, with options merged over the top. Updating data calls Tabulator's replaceData.",{"id":807,"title":493,"titles":808,"content":809,"level":27},"\u002Fcomponents\u002Fplugins#props-2",[56,803],"NameTypeDefaultDescriptioncolumnsArray\u003CRecord\u003Cstring, unknown>>[]Tabulator column definitions.dataunknown[][]Row data.optionsRecord\u003Cstring, unknown>undefinedExtra Tabulator options merged over { columns, data }.heightstringundefinedTable height.",{"id":811,"title":498,"titles":812,"content":813,"level":27},"\u002Fcomponents\u002Fplugins#emits-1",[56,803],"NamePayloadDescriptionreadytableFired on Tabulator's tableBuilt; receives the Tabulator instance.",{"id":815,"title":798,"titles":816,"content":817,"level":27},"\u002Fcomponents\u002Fplugins#exposed-1",[56,803],"NameReturnsDescriptiongetTable()Tabulator | nullThe underlying Tabulator instance (null until mounted). \u003CLteDatatable\n  :columns=\"[{ title: 'Name', field: 'name' }, { title: 'Age', field: 'age' }]\"\n  :data=\"[{ name: 'Ada', age: 36 }, { name: 'Linus', age: 54 }]\"\n  @ready=\"(table) => console.log(table)\"\n\u002F>",{"id":819,"title":820,"titles":821,"content":822,"level":13},"\u002Fcomponents\u002Fplugins#ltesortable","LteSortable",[56],"A generic drag-to-reorder list backed by SortableJS. It renders a configurable host tag containing your default slot and emits update:modelValue with the reordered array. Use v-model to bind the list.",{"id":824,"title":493,"titles":825,"content":826,"level":27},"\u002Fcomponents\u002Fplugins#props-3",[56,820],"NameTypeDefaultDescriptionmodelValueT[][]v-model — the ordered list.tagstring'div'The host element tag to render.optionsOptions (sortablejs)undefinedExtra SortableJS options (merged over { animation: 150 }).",{"id":828,"title":498,"titles":829,"content":830,"level":27},"\u002Fcomponents\u002Fplugins#emits-2",[56,820],"NamePayloadDescriptionupdate:modelValueT[]The reordered list.endSortableEventThe underlying SortableJS onEnd event. \u003Ctemplate>\n  \u003CLteSortable v-model=\"items\" tag=\"ul\" class=\"list-group\">\n    \u003Cli v-for=\"item in items\" :key=\"item\" class=\"list-group-item\">{{ item }}\u003C\u002Fli>\n  \u003C\u002FLteSortable>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nconst items = ref(['Alpha', 'Bravo', 'Charlie'])\n\u003C\u002Fscript>",{"id":832,"title":833,"titles":834,"content":835,"level":13},"\u002Fcomponents\u002Fplugins#ltekanban","LteKanban",[56],"A multi-column drag-and-drop board built on SortableJS (shared group: 'kanban', so cards move between columns). It renders Bootstrap cards per column and emits move when a card is dropped. The KanbanCard and KanbanColumn types are exported from adminlte-vue\u002Fplugins.",{"id":837,"title":838,"titles":839,"content":840,"level":27},"\u002Fcomponents\u002Fplugins#types","Types",[56,833],"interface KanbanCard {\n  id: string\n  title: string\n  text?: string\n}\ninterface KanbanColumn {\n  id: string\n  title: string\n  theme?: BootstrapTheme\n  cards: KanbanCard[]\n}",{"id":842,"title":493,"titles":843,"content":844,"level":27},"\u002Fcomponents\u002Fplugins#props-4",[56,833],"NameTypeDefaultDescriptioncolumnsKanbanColumn[]— (required)The board columns and their cards.",{"id":846,"title":498,"titles":847,"content":848,"level":27},"\u002Fcomponents\u002Fplugins#emits-3",[56,833],"NamePayloadDescriptionmove{ card: string; from: string; to: string; newIndex: number }A card was moved; identifies the card and source\u002Ftarget column ids and its new index. \u003Ctemplate>\n  \u003CLteKanban :columns=\"columns\" @move=\"onMove\" \u002F>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup lang=\"ts\">\nimport type { KanbanColumn } from 'adminlte-vue\u002Fplugins'\n\nconst columns = ref\u003CKanbanColumn[]>([\n  { id: 'todo', title: 'To Do', theme: 'primary', cards: [{ id: '1', title: 'Draft spec' }] },\n  { id: 'done', title: 'Done', theme: 'success', cards: [] },\n])\n\nfunction onMove(payload) {\n  console.log(payload.card, payload.from, '->', payload.to, payload.newIndex)\n}\n\u003C\u002Fscript>",{"id":850,"title":851,"titles":852,"content":853,"level":13},"\u002Fcomponents\u002Fplugins#other-wrappers","Other wrappers",[56],"The plugins entry also exports these wrappers, which follow the same dynamic-import \u002F \u003CClientOnly> pattern: ComponentPeer libraryLteSparklineChartapexchartsLteEditorquillLteTomSelecttom-selectLteFlatpickrflatpickrLteVectorMapjsvectormap html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"id":64,"title":62,"titles":855,"content":856,"level":8},[],"useSidebar, useColorMode, useCommandPalette — the provided dashboard state. LteDashboardLayout is the single provider host for the dashboard's shared state. In its setup() it calls provideSidebar(), provideColorMode(), and provideCommandPalette(), and descendant components consume that state via the useSidebar, useColorMode, and useCommandPalette composables. Because they rely on inject, the use* composables only work inside the layout's component tree. useSidebar() and useColorMode() throw if used outside \u003CLteDashboardLayout>; useCommandPalette() returns undefined instead so a topbar button can degrade gracefully.",{"id":858,"title":859,"titles":860,"content":861,"level":13},"\u002Fcomposables\u002Fstate#usesidebar","useSidebar",[62],"Reactive sidebar state and the responsive collapse logic ported from AdminLTE's push-menu.ts. function useSidebar(): SidebarApi",{"id":863,"title":338,"titles":864,"content":865,"level":27},"\u002Fcomposables\u002Fstate#usage",[62,859],"\u003Cscript setup lang=\"ts\">\nimport { useSidebar } from 'adminlte-vue'\n\nconst { isCollapsed, isMobile, toggle } = useSidebar()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton type=\"button\" class=\"btn\" @click=\"toggle\">\n    \u003Ci class=\"bi\" :class=\"isCollapsed ? 'bi-list' : 'bi-x-lg'\" \u002F>\n    \u003Cspan v-if=\"isMobile\">Menu\u003C\u002Fspan>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>",{"id":867,"title":868,"titles":869,"content":870,"level":27},"\u002Fcomposables\u002Fstate#returned-api-sidebarapi","Returned API (SidebarApi)",[62,859],"NameTypeDescriptionisCollapsedRef\u003Cboolean>Desktop collapse state → body.sidebar-collapse.isMobileOpenRef\u003Cboolean>Mobile off-canvas open state → body.sidebar-open.isMiniModeRef\u003Cboolean>Whether the sidebar is in mini (icon-only) mode → body.sidebar-mini.isMobileComputedRef\u003Cboolean>Reactive: is the viewport at\u002Fbelow the sidebar breakpoint?sidebarBreakpointnumberThe breakpoint, in pixels.toggle() => voidOn mobile toggles the overlay; on desktop toggles the collapse state.collapse() => voidCollapse the sidebar (and close the mobile overlay).expand() => voidExpand the sidebar (and close the mobile overlay). The provider (provideSidebar, called by the layout) reflects this state onto \u003Cbody> and accepts the following options.",{"id":872,"title":873,"titles":874,"content":875,"level":27},"\u002Fcomposables\u002Fstate#provider-options-providesidebaroptions","Provider options (ProvideSidebarOptions)",[62,859],"NameTypeDefaultDescriptionsidebarMinibooleanfalseStart in mini (icon-only) mode.enablePersistencebooleanfalsePersist the collapse state under the lte.sidebar.state localStorage key.sidebarBreakpointnumber992Breakpoint in pixels below which the sidebar behaves as a mobile overlay.staticBodyClassesMaybeRefOrGetter\u003Cstring>—Static body classes (e.g. layout-fixed sidebar-expand-lg) reflected onto \u003Cbody> alongside the dynamic state classes.",{"id":877,"title":878,"titles":879,"content":880,"level":13},"\u002Fcomposables\u002Fstate#usecolormode","useColorMode",[62],"Light\u002Fdark\u002Fauto theme state. Writes Bootstrap's data-bs-theme attribute on \u003Chtml> and persists the preference under the lte-theme localStorage key. In Nuxt, a blocking inline head script (added by @adminlte\u002Fnuxt) sets data-bs-theme before first paint to avoid a flash; this composable owns the reactive updates thereafter. function useColorMode(): ColorModeApi",{"id":882,"title":338,"titles":883,"content":884,"level":27},"\u002Fcomposables\u002Fstate#usage-1",[62,878],"\u003Cscript setup lang=\"ts\">\nimport { useColorMode } from 'adminlte-vue'\n\nconst { colorMode, resolvedMode, setColorMode } = useColorMode()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"btn-group\">\n    \u003Cbutton type=\"button\" @click=\"setColorMode('light')\">Light\u003C\u002Fbutton>\n    \u003Cbutton type=\"button\" @click=\"setColorMode('dark')\">Dark\u003C\u002Fbutton>\n    \u003Cbutton type=\"button\" @click=\"setColorMode('auto')\">Auto\u003C\u002Fbutton>\n    \u003Cspan>Active: {{ resolvedMode }} (preference: {{ colorMode }})\u003C\u002Fspan>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>",{"id":886,"title":887,"titles":888,"content":889,"level":27},"\u002Fcomposables\u002Fstate#returned-api-colormodeapi","Returned API (ColorModeApi)",[62,878],"NameTypeDescriptioncolorModeRef\u003CColorMode>The current preference: 'light' | 'dark' | 'auto'.resolvedModeComputedRef\u003CResolvedColorMode>The concrete mode after auto is evaluated against the system setting: 'light' | 'dark'.setColorMode(mode: ColorMode) => voidSet the preference.",{"id":891,"title":892,"titles":893,"content":894,"level":27},"\u002Fcomposables\u002Fstate#provider-options-providecolormodeoptions","Provider options (ProvideColorModeOptions)",[62,878],"NameTypeDefaultDescriptioninitialModeColorMode'auto'The initial preference before the persisted value is read on mount.",{"id":896,"title":897,"titles":898,"content":899,"level":13},"\u002Fcomposables\u002Fstate#usecommandpalette","useCommandPalette",[62],"State for the ⌘K command palette. The provider registers a global ⌘K \u002F Ctrl+K shortcut to toggle it and Escape to close it. function useCommandPalette(): CommandPaletteApi | undefined Unlike the others, this composable returns undefined when called outside \u003CLteDashboardLayout>, so always guard the result.",{"id":901,"title":338,"titles":902,"content":903,"level":27},"\u002Fcomposables\u002Fstate#usage-2",[62,897],"\u003Cscript setup lang=\"ts\">\nimport { useCommandPalette } from 'adminlte-vue'\n\nconst palette = useCommandPalette()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton v-if=\"palette\" type=\"button\" class=\"btn\" @click=\"palette.open()\">\n    Search \u003Ckbd>⌘K\u003C\u002Fkbd>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>",{"id":905,"title":906,"titles":907,"content":908,"level":27},"\u002Fcomposables\u002Fstate#returned-api-commandpaletteapi","Returned API (CommandPaletteApi)",[62,897],"NameTypeDescriptionisOpenRef\u003Cboolean>Whether the palette is currently open.open() => voidOpen the palette.close() => voidClose the palette.toggle() => voidToggle the open state. html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}",{"id":70,"title":68,"titles":910,"content":911,"level":8},[],"useCardWidget, useFullscreen, useDirectChat, useSortable, useTreeview. These composables hold local, per-component state — unlike the provided composables (useSidebar, useColorMode, …) they do not rely on the layout's provide\u002Finject context and can be called from any component. Import them from adminlte-vue (or rely on auto-import in Nuxt).",{"id":913,"title":914,"titles":915,"content":916,"level":13},"\u002Fcomposables\u002Fcomponent#usecardwidget","useCardWidget",[68],"Per-card widget state porting AdminLTE's card-widget.ts: collapse, maximize, and remove. Maximizing also toggles the maximized-card class on \u003Chtml>. function useCardWidget(options?: UseCardWidgetOptions): CardWidgetApi",{"id":918,"title":338,"titles":919,"content":920,"level":27},"\u002Fcomposables\u002Fcomponent#usage",[68,914],"\u003Cscript setup lang=\"ts\">\nimport { useCardWidget } from 'adminlte-vue'\n\nconst { isCollapsed, isMaximized, isRemoved, toggleCollapse, toggleMaximize, remove } =\n  useCardWidget()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv v-if=\"!isRemoved\" class=\"card\" :class=\"{ 'collapsed-card': isCollapsed, maximized: isMaximized }\">\n    \u003Cdiv class=\"card-header\">\n      \u003Ch3 class=\"card-title\">Widget\u003C\u002Fh3>\n      \u003Cdiv class=\"card-tools\">\n        \u003Cbutton type=\"button\" class=\"btn btn-tool\" @click=\"toggleCollapse\">\n          \u003Ci class=\"bi\" :class=\"isCollapsed ? 'bi-plus-lg' : 'bi-dash-lg'\" \u002F>\n        \u003C\u002Fbutton>\n        \u003Cbutton type=\"button\" class=\"btn btn-tool\" @click=\"toggleMaximize\">\n          \u003Ci class=\"bi bi-fullscreen\" \u002F>\n        \u003C\u002Fbutton>\n        \u003Cbutton type=\"button\" class=\"btn btn-tool\" @click=\"remove\">\n          \u003Ci class=\"bi bi-x-lg\" \u002F>\n        \u003C\u002Fbutton>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv v-show=\"!isCollapsed\" class=\"card-body\">Content\u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>",{"id":922,"title":923,"titles":924,"content":925,"level":27},"\u002Fcomposables\u002Fcomponent#options","Options",[68,914],"NameTypeDefaultDescriptiondefaultCollapsedbooleanfalseInitial collapsed state.",{"id":927,"title":928,"titles":929,"content":930,"level":27},"\u002Fcomposables\u002Fcomponent#returns","Returns",[68,914],"NameTypeDescriptionisCollapsedRef\u003Cboolean>Whether the card is collapsed.isMaximizedRef\u003Cboolean>Whether the card is maximized.isRemovedRef\u003Cboolean>Whether the card has been removed.collapse() => voidSet collapsed to true.expand() => voidSet collapsed to false.toggleCollapse() => voidToggle the collapsed state.maximize() => voidMaximize; adds maximized-card to \u003Chtml>.minimize() => voidUn-maximize; removes maximized-card from \u003Chtml>.toggleMaximize() => voidToggle the maximized state.remove() => voidSet removed to true.",{"id":932,"title":933,"titles":934,"content":935,"level":13},"\u002Fcomposables\u002Fcomponent#usefullscreen","useFullscreen",[68],"A wrapper around the browser Fullscreen API (ports AdminLTE's fullscreen.ts). It listens to fullscreenchange while mounted and reflects the current state in isFullscreen. The async methods request fullscreen on document.documentElement and log errors to the console rather than throwing. function useFullscreen(): FullscreenApi",{"id":937,"title":338,"titles":938,"content":939,"level":27},"\u002Fcomposables\u002Fcomponent#usage-1",[68,933],"\u003Cscript setup lang=\"ts\">\nimport { useFullscreen } from 'adminlte-vue'\n\nconst { isFullscreen, toggleFullscreen } = useFullscreen()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton type=\"button\" class=\"btn btn-tool\" @click=\"toggleFullscreen\">\n    \u003Ci class=\"bi\" :class=\"isFullscreen ? 'bi-fullscreen-exit' : 'bi-fullscreen'\" \u002F>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>",{"id":941,"title":928,"titles":942,"content":943,"level":27},"\u002Fcomposables\u002Fcomponent#returns-1",[68,933],"NameTypeDescriptionisFullscreenRef\u003Cboolean>Whether the document is currently in fullscreen.toggleFullscreen() => Promise\u003Cvoid>Enter if not fullscreen, exit otherwise.enterFullscreen() => Promise\u003Cvoid>Request fullscreen on the document element.exitFullscreen() => Promise\u003Cvoid>Exit fullscreen if currently active.",{"id":945,"title":946,"titles":947,"content":948,"level":13},"\u002Fcomposables\u002Fcomponent#usedirectchat","useDirectChat",[68],"Local state for a direct-chat contacts pane (ports AdminLTE's direct-chat.ts). Bind isContactsOpen to the direct-chat-contacts-open class. function useDirectChat(): DirectChatApi",{"id":950,"title":338,"titles":951,"content":952,"level":27},"\u002Fcomposables\u002Fcomponent#usage-2",[68,946],"\u003Cscript setup lang=\"ts\">\nimport { useDirectChat } from 'adminlte-vue'\n\nconst { isContactsOpen, toggleContacts } = useDirectChat()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"card direct-chat\" :class=\"{ 'direct-chat-contacts-open': isContactsOpen }\">\n    \u003Cdiv class=\"card-header\">\n      \u003Cbutton type=\"button\" class=\"btn btn-tool\" @click=\"toggleContacts\">\n        \u003Ci class=\"bi bi-people\" \u002F>\n      \u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n    \u003Cdiv class=\"direct-chat-contacts\">\u003C!-- contacts -->\u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>",{"id":954,"title":928,"titles":955,"content":956,"level":27},"\u002Fcomposables\u002Fcomponent#returns-2",[68,946],"NameTypeDescriptionisContactsOpenRef\u003Cboolean>Whether the contacts pane is open.toggleContacts() => voidToggle the contacts pane.openContacts() => voidOpen the contacts pane.closeContacts() => voidClose the contacts pane.",{"id":958,"title":959,"titles":960,"content":961,"level":13},"\u002Fcomposables\u002Fcomponent#usesortable","useSortable",[68],"Initializes SortableJS on a target element. The library is imported lazily and client-only, so it is SSR-safe. Install sortablejs as your own dependency. Cleanup runs automatically on unmount; a destroy handle is also returned. function useSortable(target: Ref\u003CHTMLElement | null>, options?: UseSortableOptions): SortableApi",{"id":963,"title":338,"titles":964,"content":965,"level":27},"\u002Fcomposables\u002Fcomponent#usage-3",[68,959],"\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { useSortable } from 'adminlte-vue'\n\nconst list = ref\u003CHTMLElement | null>(null)\nuseSortable(list, { options: { animation: 150 } })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cul ref=\"list\" class=\"list-group\">\n    \u003Cli class=\"list-group-item\">Item 1\u003C\u002Fli>\n    \u003Cli class=\"list-group-item\">Item 2\u003C\u002Fli>\n    \u003Cli class=\"list-group-item\">Item 3\u003C\u002Fli>\n  \u003C\u002Ful>\n\u003C\u002Ftemplate> Pass a reactive enabled ref to initialize and destroy the instance on demand: const enabled = ref(true)\nuseSortable(list, { enabled, options: { animation: 150 } })",{"id":967,"title":968,"titles":969,"content":970,"level":27},"\u002Fcomposables\u002Fcomponent#parameters","Parameters",[68,959],"NameTypeDescriptiontargetRef\u003CHTMLElement | null>Element to make sortable.optionsUseSortableOptionsSee below. Optional.",{"id":972,"title":923,"titles":973,"content":974,"level":27},"\u002Fcomposables\u002Fcomponent#options-1",[68,959],"NameTypeDefaultDescriptionenabledRef\u003Cboolean> | booleantrueWhen a boolean, initializes only if true. When a ref, watched to init\u002Fdestroy reactively.optionsSortable.Options—Options forwarded directly to SortableJS.",{"id":976,"title":928,"titles":977,"content":978,"level":27},"\u002Fcomposables\u002Fcomponent#returns-3",[68,959],"NameTypeDescriptiondestroy() => voidDestroy the SortableJS instance manually.",{"id":980,"title":981,"titles":982,"content":983,"level":13},"\u002Fcomposables\u002Fcomponent#usetreeview","useTreeview",[68],"Powers the sidebar nav's accordion behavior and submenu animation. It is used internally by LteSidebarNav \u002F LteSidebarNavItem, but the exported helpers are available for custom nav-like UIs.",{"id":985,"title":986,"titles":987,"content":988,"level":27},"\u002Fcomposables\u002Fcomponent#providetreeviewregistry-usetreeviewregistry","provideTreeviewRegistry \u002F useTreeviewRegistry",[68,981],"A registry for accordion mode (one open group per parent at a time). provideTreeviewRegistry is called by the nav container; descendants read it with useTreeviewRegistry, which returns undefined if no registry was provided. function provideTreeviewRegistry(accordion: boolean): TreeviewRegistry\nfunction useTreeviewRegistry(): TreeviewRegistry | undefined The TreeviewRegistry shape: NameTypeDescriptionaccordionbooleanWhether accordion mode is active.openByParentRef\u003CRecord\u003Cstring, string | null>>Map of parent key → currently open child id.setOpen(parentKey: string, id: string, open: boolean) => voidOpen\u002Fclose a child within its parent.isOpen(parentKey: string, id: string) => booleanWhether the given child is open.",{"id":990,"title":991,"titles":992,"content":993,"level":27},"\u002Fcomposables\u002Fcomponent#treeviewtransition","treeviewTransition",[68,981],"Returns height-based enter\u002Fleave hooks for a \u003CTransition>, animating a submenu from 0 to its scroll height and back. The Vue port of the React useTreeviewAnimation technique. function treeviewTransition(speed?: number) NameTypeDefaultDescriptionspeednumber300Transition duration in milliseconds. \u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { treeviewTransition } from 'adminlte-vue'\n\nconst isOpen = ref(false)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CTransition v-bind=\"treeviewTransition(300)\">\n    \u003Cul v-if=\"isOpen\" class=\"nav nav-treeview\">\n      \u003Cli class=\"nav-item\">\u003Ca href=\"#\" class=\"nav-link\">Child\u003C\u002Fa>\u003C\u002Fli>\n    \u003C\u002Ful>\n  \u003C\u002FTransition>\n\u003C\u002Ftemplate> html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"id":74,"title":73,"titles":995,"content":996,"level":8},[],"Coming from raw AdminLTE 4, the React port, or the Laravel edition. adminlte-vue ships the same prebuilt AdminLTE 4 CSS, so your visual result is unchanged — what\nchanges is that imperative markup and data-lte-* attributes become declarative Lte* components\nplus composables. This guide maps the most common patterns.",{"id":998,"title":999,"titles":1000,"content":237,"level":13},"\u002Fresources\u002Fmigration#from-raw-adminlte-4","From raw AdminLTE 4",[73],{"id":1002,"title":1003,"titles":1004,"content":1005,"level":27},"\u002Fresources\u002Fmigration#the-page-shell","The page shell",[73,999],"Raw AdminLTE wires the topbar, sidebar, content and footer by hand and toggles \u003Cbody> classes\n(layout-fixed, sidebar-expand-lg, sidebar-collapse, sidebar-mini, …) with adminlte.js.\nLteDashboardLayout is the single host that replaces all of that: it renders the topbar\u002Fsidebar\u002F\nfooter, provides the sidebar\u002Fcolor-mode\u002Fcommand-palette state, and reflects the body classes from a\nwatchEffect (SSR\u002Fhydration-safe). You pass the layout flags as props and the menu as data. \u003Cscript setup lang=\"ts\">\nimport { LteDashboardLayout, LteAppContent } from 'adminlte-vue'\nimport type { MenuNode } from 'adminlte-vue'\n\nconst menu: MenuNode[] = [\n  { type: 'header', text: 'MAIN' },\n  { type: 'item', text: 'Dashboard', href: '\u002F', icon: 'bi-speedometer' },\n  {\n    type: 'group',\n    text: 'Layout',\n    icon: 'bi-layout-wtf',\n    children: [{ type: 'item', text: 'Fixed', href: '\u002Flayout\u002Ffixed' }],\n  },\n]\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteDashboardLayout\n    :menu-items=\"menu\"\n    brand-text=\"Acme\"\n    sidebar-theme=\"dark\"\n    :fixed-header=\"true\"\n    :layout-fixed=\"true\"\n    current-path=\"\u002F\"\n  >\n    \u003CLteAppContent title=\"Dashboard\">…\u003C\u002FLteAppContent>\n  \u003C\u002FLteDashboardLayout>\n\u003C\u002Ftemplate>",{"id":1007,"title":1008,"titles":1009,"content":1010,"level":32},"\u002Fresources\u002Fmigration#body-class-flags","Body-class flags",[73,999,1003],"The raw \u003Cbody class=\"…\"> toggles become LteDashboardLayout props: Raw body classPropDefaultlayout-fixedlayoutFixedtruefixed-headerfixedHeaderfalsefixed-sidebarfixedSidebarfalsefixed-footerfixedFooterfalsesidebar-minisidebarMinifalsesidebar-expand-*sidebarBreakpoint'lg' Extra static classes you can't express as props go through bodyClass \u002F navbarClass \u002F\nsidebarClass. sidebarTheme is 'dark' by default; currentPath drives active-link detection\n(replaces hand-maintained .active classes); initialColorMode is 'auto'.",{"id":1012,"title":1013,"titles":1014,"content":1015,"level":27},"\u002Fresources\u002Fmigration#sidebar-treeview-push-menu","Sidebar treeview + push-menu",[73,999],"Don't hand-write the \u003Cnav class=\"sidebar-menu\"> tree or the nav-treeview open\u002Fclose markup —\ndescribe it as a MenuNode[] array and the layout renders the recursive sidebar for you. A\nMenuNode is a discriminated union: typeFields'header'text'item'text, href, icon?, iconColor?, badge?, badgeColor?, target?'group'text, icon?, iconColor?, badge?, badgeColor?, children The push-menu \u002F collapse logic from push-menu.ts lives in the provided sidebar state. Anywhere\ninside the layout you can drive it instead of dispatching data-lte-toggle=\"sidebar\" clicks: \u003Cscript setup lang=\"ts\">\nimport { useSidebar } from 'adminlte-vue'\nconst { isCollapsed, isMobile, toggle, collapse, expand } = useSidebar()\n\u003C\u002Fscript> useSidebar() exposes isCollapsed, isMobileOpen, isMiniMode, isMobile (reactive breakpoint),\nsidebarBreakpoint, and toggle \u002F collapse \u002F expand. toggle() opens the overlay on mobile and\ncollapses on desktop, matching AdminLTE. Set enableSidebarPersistence to persist the collapse state\nunder the lte.sidebar.state key.",{"id":1017,"title":1018,"titles":1019,"content":1020,"level":27},"\u002Fresources\u002Fmigration#cards-collapse-maximize-remove","Cards (collapse \u002F maximize \u002F remove)",[73,999],"The LteCard component ports card-widget.ts. Drop the data-lte-toggle=\"card-collapse\"\nbuttons — toggle the tool buttons with boolean props instead: \u003CLteCard title=\"Sales\" collapsible maximizable removable>…\u003C\u002FLteCard> PropTypeDefaulttitle \u002F iconstring—themeBootstrapTheme—variant'default' | 'outline' | 'solid''default'gradientbooleanfalsecollapsiblebooleanfalsedefaultCollapsedbooleanfalsemaximizablebooleanfalseremovablebooleanfalse For your own bespoke card markup, useCardWidget() returns the same state imperatively:\nisCollapsed, isMaximized, isRemoved, collapse, expand, toggleCollapse, maximize,\nminimize, toggleMaximize, remove.",{"id":1022,"title":1023,"titles":1024,"content":1025,"level":27},"\u002Fresources\u002Fmigration#keeping-raw-markup-working-useltebehaviors","Keeping raw markup working — useLteBehaviors",[73,999],"You don't have to convert everything at once. LteDashboardLayout installs useLteBehaviors(),\nwhich delegates clicks for hand-written controls so they keep working without adminlte.js: data-lte-toggle=\"card-collapse\" \u002F \"card-maximize\" \u002F \"card-remove\" — finds the enclosing\n.card and collapses \u002F maximizes \u002F removes it.data-lte-toggle=\"chat-pane\" — toggles .direct-chat-contacts-open on the enclosing\n.direct-chat.Bootstrap .needs-validation forms get the was-validated \u002F checkValidity() submit handler. So you can paste an existing AdminLTE card with its collapse button into a slot and it still works —\nthen migrate it to \u003CLteCard collapsible> at your leisure.",{"id":1027,"title":21,"titles":1028,"content":1029,"level":27},"\u002Fresources\u002Fmigration#color-mode",[73,999],"The dark\u002Flight switch persists under the lte-theme localStorage key and writes data-bs-theme on\n\u003Chtml>. Use \u003CLteColorModeToggle> for the topbar glyph, or useColorMode() which returns\ncolorMode ('light' | 'dark' | 'auto'), resolvedMode (computed 'light' | 'dark') and\nsetColorMode(mode). In Nuxt the module injects a blocking head script that sets the attribute\nbefore first paint to avoid a flash.",{"id":1031,"title":1032,"titles":1033,"content":1034,"level":27},"\u002Fresources\u002Fmigration#bootstrap-driven-js","Bootstrap-driven JS",[73,999],"Dropdowns, modals, offcanvas and tooltips are still powered by Bootstrap's data-API. In plain Vue,\nimport bootstrap once in your entry; the Nuxt module does this in a .client plugin for you.",{"id":1036,"title":1037,"titles":1038,"content":1039,"level":13},"\u002Fresources\u002Fmigration#from-the-react-port-adminlte-react","From the React port (adminlte-react)",[73],"The component surface mirrors adminlte-react one-to-one (same Lte* names, same AdminLTE CSS), so\nmigration is mostly idiomatic translation: React Context + hooks → Vue provide\u002Finject + composables. LteDashboardLayout is the single\nprovider; useSidebar() \u002F useColorMode() \u002F useCommandPalette() inject and throw if used\noutside it (the analog of calling a hook outside its provider).children → default \u003Cslot \u002F>. Named render props become named slots (e.g. #header,\n#title, #tools, #footer on LteCard; #topbar-start \u002F #topbar-end \u002F #sidebar-brand \u002F\n#logo \u002F #footer on the layout).usePathname() is replaced by the explicit currentPath prop.Routing is decoupled: pass a linkComponent prop (default 'a') instead of importing a\n\u003CLink>, and a navigate callback for the command palette.",{"id":1041,"title":1042,"titles":1043,"content":1044,"level":13},"\u002Fresources\u002Fmigration#from-the-laravel-edition-adminlte-laravel","From the Laravel edition (adminlte-laravel)",[73],"The Laravel edition renders Blade partials server-side. Here the same structure is component-driven: Blade layout includes \u002F @yield → LteDashboardLayout + slots.The PHP menu config array → a MenuNode[] passed to :menu-items. The same array also feeds\nthe ⌘K command palette via flattenMenuToCommands() — no second menu definition.Active-link detection done in Blade (Request::is(...)) → the currentPath prop.route() \u002F \u003Ca href> links → set linkComponent to your router's link component (e.g.\nNuxtLink \u002F RouterLink) so menu entries become SPA navigations.",{"id":1046,"title":1047,"titles":1048,"content":1049,"level":13},"\u002Fresources\u002Fmigration#verifying-the-port","Verifying the port",[73],"After migrating, the project's correctness gates are pnpm --filter adminlte-vue type-check and a\nsuccessful demo build: pnpm --filter adminlte-vue type-check\npnpm build:demo html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"id":79,"title":78,"titles":1051,"content":1052,"level":8},[],"Building the library and deploying a Nuxt app that uses it. This page covers building adminlte-vue and shipping a Nuxt app to production — Nitro presets (Node, Vercel, Netlify, Cloudflare), Docker, and the .env \u002F runtimeConfig basics.",{"id":1054,"title":1055,"titles":1056,"content":1057,"level":13},"\u002Fresources\u002Fdeployment#building-the-library","Building the library",[78],"packages\u002Fadminlte-vue is built with Vite library mode. The output is ESM-only with two entries — index (.) and plugins (.\u002Fplugins) — so the heavy plugin libs stay out of the default import. build.minify is intentionally off: the library ships readable ESM and lets the consuming app minify (it also sidesteps an esbuild lib-mode identifier collision). pnpm install                            # install all workspace deps\npnpm build                              # build packages\u002F* in order (lib → nuxt module)\npnpm --filter adminlte-vue build        # just the library (vite build + dts + copy-css) The build does three things: @vitejs\u002Fplugin-vue compiles the \u003Cscript setup lang=\"ts\"> SFCs.vite-plugin-dts (via vue-tsc) emits the .d.ts tree from src\u002F**.A closeBundle hook copies admin-lte\u002Fdist\u002Fcss\u002Fadminlte.css and adminlte.rtl.css into dist\u002Fcss\u002F, exposed as the .\u002Fcss and .\u002Fcss\u002Frtl package exports. Peer libraries (vue, bootstrap, apexcharts, tabulator-tables, quill, flatpickr, tom-select, sortablejs, jsvectormap, overlayscrollbars, @fullcalendar\u002F*) are external — never bundled. The consuming app installs the ones it uses.",{"id":1059,"title":1060,"titles":1061,"content":1062,"level":13},"\u002Fresources\u002Fdeployment#building-a-nuxt-app","Building a Nuxt app",[78],"A Nuxt app using @adminlte\u002Fnuxt compiles to a standard Nitro server. After editing the library, rebuild it (or keep pnpm --filter adminlte-vue dev running) so the app picks up the change. pnpm build:demo                         # production build of apps\u002Fdemo\nnode apps\u002Fdemo\u002F.output\u002Fserver\u002Findex.mjs # run the SSR server (honors HOST \u002F PORT) The Nitro output under .output\u002F is self-contained — only that directory is needed at runtime.",{"id":1064,"title":1065,"titles":1066,"content":1067,"level":13},"\u002Fresources\u002Fdeployment#nitro-presets","Nitro presets",[78],"By default Nuxt builds with the node-server preset, which produces the .output\u002Fserver\u002Findex.mjs entry above (honors HOST and PORT). Vercel, Netlify and Cloudflare are auto-detected in their CI environments; otherwise set the preset explicitly in nuxt.config.ts: export default defineNuxtConfig({\n  modules: ['@adminlte\u002Fnuxt'],\n\n  \u002F\u002F Pick the preset for your host:\n  nitro: { preset: 'node-server' }, \u002F\u002F or 'vercel', 'netlify', 'cloudflare-pages'\n}) PresetTargetNotesnode-serverAny Node host \u002F DockerDefault. Runs node .output\u002Fserver\u002Findex.mjs.vercelVercelAuto-detected in Vercel CI.netlifyNetlifyAuto-detected in Netlify CI.cloudflare-pagesCloudflare PagesSet explicitly or via Cloudflare's Nuxt support. You can also set the preset without editing config via the NITRO_PRESET environment variable at build time.",{"id":1069,"title":1070,"titles":1071,"content":1072,"level":13},"\u002Fresources\u002Fdeployment#docker","Docker",[78],"A standalone Nuxt app that depends on adminlte-vue + @adminlte\u002Fnuxt deploys with a standard\nmulti-stage Dockerfile — build, then ship only the self-contained .output: FROM node:22-alpine AS build\nWORKDIR \u002Fapp\nRUN corepack enable\nCOPY . .\nRUN pnpm install --frozen-lockfile\nRUN pnpm build\n\nFROM node:22-alpine AS runtime\nWORKDIR \u002Fapp\nENV NODE_ENV=production HOST=0.0.0.0 PORT=3000\nCOPY --from=build \u002Fapp\u002F.output .\u002F.output\nEXPOSE 3000\nCMD [\"node\", \".output\u002Fserver\u002Findex.mjs\"] docker build -t my-admin .\ndocker run -p 3000:3000 my-admin",{"id":1074,"title":1075,"titles":1076,"content":1077,"level":13},"\u002Fresources\u002Fdeployment#environment-runtimeconfig","Environment & runtimeConfig",[78],"Configuration follows Nuxt's runtimeConfig convention. Keys declared under runtimeConfig.public are sent to the browser; top-level keys are server-only. Override either at runtime with prefixed environment variables (NUXT_PUBLIC_* for public, NUXT_* for private). export default defineNuxtConfig({\n  runtimeConfig: {\n    public: {\n      appName: 'My Admin',\n    },\n    \u002F\u002F private (server-only) keys go here, e.g.\n    \u002F\u002F authSecret: '',\n  },\n}) Override either at runtime with prefixed environment variables: # Public (sent to the browser) — overrides runtimeConfig.public.appName\nNUXT_PUBLIC_APP_NAME=\"My Admin\"\n\n# Private (server only)\n# NUXT_AUTH_SECRET=\"change-me\"\n# NUXT_DATABASE_URL=\"postgres:\u002F\u002Fuser:pass@localhost:5432\u002Fapp\" html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"id":83,"title":82,"titles":1079,"content":1080,"level":8},[],"Common questions about adminlte-vue. Answers to the questions that come up most often when adopting adminlte-vue — the framework-agnostic AdminLTE 4 \u002F Bootstrap 5.3 component library for Vue 3 and Nuxt.",{"id":1082,"title":1083,"titles":1084,"content":1085,"level":13},"\u002Fresources\u002Ffaq#why-is-the-package-esm-only","Why is the package ESM-only?",[82],"The library ships as ESM only — there is no CommonJS build. State is shared through provide\u002Finject using injection keys that are module-singleton Symbols (in src\u002Fcomposables\u002Fkeys.ts). A dual ESM\u002FCJS build could load those modules twice, duplicate the Symbols, and silently break injection between LteDashboardLayout and its descendants. The package.json reflects this: \"type\": \"module\" with only an import condition per export. \"exports\": {\n  \".\":         { \"types\": \".\u002Fdist\u002Findex.d.ts\",   \"import\": \".\u002Fdist\u002Findex.js\" },\n  \".\u002Fplugins\": { \"types\": \".\u002Fdist\u002Fplugins.d.ts\", \"import\": \".\u002Fdist\u002Fplugins.js\" },\n  \".\u002Fcss\":     \".\u002Fdist\u002Fcss\u002Fadminlte.css\",\n  \".\u002Fcss\u002Frtl\": \".\u002Fdist\u002Fcss\u002Fadminlte.rtl.css\"\n} There are two JS entry points: . for the core components\u002Fcomposables and .\u002Fplugins for the heavy third-party wrappers. The split keeps the plugin libs out of the default import.",{"id":1087,"title":1088,"titles":1089,"content":1090,"level":13},"\u002Fresources\u002Ffaq#why-no-pinia-in-the-library","Why no Pinia in the library?",[82],"The core library uses composables + provide\u002Finject rather than a store. LteDashboardLayout is the single provider host: in setup() it calls provideSidebar(), provideColorMode(), and provideCommandPalette(), and installs useLteBehaviors() + useAccessibility(). Descendants consume that state with useSidebar(), useColorMode(), and useCommandPalette(), which throw a clear error if used outside the layout. This keeps the library dependency-free and is the Vue analog of the React port's Context + hooks pattern. Bring your own store (e.g. Pinia) at the app level for domain state — the library doesn't impose one.",{"id":1092,"title":1093,"titles":1094,"content":1095,"level":13},"\u002Fresources\u002Ffaq#do-i-need-nuxt-to-use-it","Do I need Nuxt to use it?",[82],"No. adminlte-vue is framework-agnostic and works in any Vue 3 \u002F Vite app. Register it as a plugin and import the CSS: import { createApp } from 'vue'\nimport AdminLte from 'adminlte-vue'\nimport 'adminlte-vue\u002Fcss'\nimport App from '.\u002FApp.vue'\n\ncreateApp(App).use(AdminLte).mount('#app') If you do use Nuxt, the @adminlte\u002Fnuxt module handles the wiring for you: it auto-registers the components, auto-imports the composables, pushes adminlte-vue\u002Fcss into nuxt.options.css, initializes Bootstrap's JS client-side, and injects an SSR-safe color-mode head script.",{"id":1097,"title":1098,"titles":1099,"content":1100,"level":13},"\u002Fresources\u002Ffaq#how-are-the-heavy-plugins-handled","How are the heavy plugins handled?",[82],"Heavy third-party libraries are never statically imported. Each wrapper under src\u002Fplugins\u002F*.vue does an await import(...) inside onMounted, guards against the element being gone, and destroys the instance in onBeforeUnmount. They are also a separate entry point (adminlte-vue\u002Fplugins) so they stay out of the default bundle. Because they load dynamically and touch the DOM, wrap them in \u003CClientOnly> under Nuxt: \u003Ctemplate>\n  \u003CClientOnly>\n    \u003CLteApexChart :options=\"options\" :series=\"series\" \u002F>\n    \u003Ctemplate #fallback>Loading chart…\u003C\u002Ftemplate>\n  \u003C\u002FClientOnly>\n\u003C\u002Ftemplate> You install only the libs you actually use (and load their CSS yourself) — see the peer dependencies below.",{"id":1102,"title":1103,"titles":1104,"content":1105,"level":13},"\u002Fresources\u002Ffaq#how-do-i-use-my-own-router-link-component","How do I use my own router \u002F link component?",[82],"The core is decoupled from any router. The layout takes a currentPath prop for active-link detection and a linkComponent prop (default 'a') for the element to render links with. In Nuxt you'd pass the current route path and NuxtLink: \u003Cscript setup lang=\"ts\">\nconst route = useRoute()\nconst NuxtLink = resolveComponent('NuxtLink')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CLteDashboardLayout :current-path=\"route.path\" :link-component=\"NuxtLink\" :menu=\"menu\">\n    \u003C!-- page content -->\n  \u003C\u002FLteDashboardLayout>\n\u003C\u002Ftemplate> The command palette accepts a navigate callback (e.g. navigateTo) for the same reason.",{"id":1107,"title":1108,"titles":1109,"content":1110,"level":13},"\u002Fresources\u002Ffaq#what-are-the-peerdependencies","What are the peerDependencies?",[82],"vue (^3.5.0) is the only one you'll always need. Everything else is an optional peer dependency — install a lib only if you use the wrapper that depends on it. Peer dependencyVersion rangeRequiredUsed byvue^3.5.0Yesthe whole librarybootstrap^5.3.0Optional*dropdowns, modals, offcanvasapexcharts^4.0.0 || ^5.0.0OptionalLteApexCharttabulator-tables^6.0.0Optionaldata tablesquill^2.0.0Optionalrich-text editorflatpickr^4.6.0Optionaldate pickertom-select^2.0.0Optionalselect inputssortablejs^1.15.0Optionaldrag-and-dropjsvectormap^1.5.0Optionalvector mapsoverlayscrollbars^2.0.0Optionalcustom scrollbars@fullcalendar\u002Fcore^6.0.0Optionalcalendar@fullcalendar\u002Fdaygrid^6.0.0Optionalcalendar@fullcalendar\u002Finteraction^6.0.0Optionalcalendar * bootstrap is declared optional in peerDependenciesMeta, but in practice you need it for the interactive widgets (dropdowns, modals, offcanvas) to work. The @adminlte\u002Fnuxt module imports it for you on the client.",{"id":1112,"title":1113,"titles":1114,"content":1115,"level":13},"\u002Fresources\u002Ffaq#do-i-need-bootstrap","Do I need Bootstrap?",[82],"Yes — the design system is Bootstrap 5.3, and AdminLTE 4's CSS builds on top of it. Bootstrap's JavaScript data-API powers the interactive widgets (dropdowns, modals, offcanvas). Under Nuxt, the module loads bootstrap client-side automatically; in a plain Vue app you import it yourself.",{"id":1117,"title":1118,"titles":1119,"content":1120,"level":13},"\u002Fresources\u002Ffaq#is-rtl-i18n-supported","Is RTL \u002F i18n supported?",[82],"RTL is supported via a prebuilt stylesheet. Import the RTL CSS export instead of (or alongside) the default one: import 'adminlte-vue\u002Fcss\u002Frtl' i18n is not built into the core component library — its strings come from the props and menu data you pass in, so you localize at the app level with your own solution (for example @nuxtjs\u002Fi18n): translate your menu\u002Flabels and pass them in. html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"id":6,"title":5,"titles":1122,"content":1123,"level":8},[],"AdminLTE 4 for Vue 3 & Nuxt — a framework-agnostic component library and a thin Nuxt module. AdminLTE Vue (the adminlte-vue package) is a faithful port of AdminLTE 4\n(Bootstrap 5.3) for Vue 3 & Nuxt. It comes in two pieces so you can adopt as much or as little as\nyou need:",{"id":1125,"title":119,"titles":1126,"content":1127,"level":13},"\u002F#the-packages",[5],"PackageWhat it isadminlte-vueThe framework-agnostic Vue 3 component library — works in any Vite \u002F Vue 3 \u002F Nuxt app.@adminlte\u002FnuxtA thin Nuxt module: auto-registers the components, auto-imports the composables, injects the CSS + an SSR-safe color-mode script.",{"id":1129,"title":166,"titles":1130,"content":1131,"level":13},"\u002F#which-one",[5],"Use adminlte-vue directly for full control in any Vue 3 \u002F Vite app — you wire the router and CSS yourself.Add @adminlte\u002Fnuxt in a Nuxt app to remove all the wiring boilerplate (auto-registration, auto-imports, CSS, the color-mode head script). The demo app is a 1:1 AdminLTE 4 showcase of every component and page — the best way to see what's available.",{"id":1133,"title":197,"titles":1134,"content":1135,"level":13},"\u002F#highlights",[5],"SSR-safe — every browser API is isolated to onMounted\u002Feffects; no hydration mismatches.Color mode with a blocking head script (no flash of the wrong theme).Composables + provide\u002Finject for state (no Pinia required in the library).Heavy plugins are dynamic-imported (ApexCharts, FullCalendar, Tabulator, Quill, …) and stay out of the default bundle. Looking to get going fast? Jump to Installation.",1780323128803]