AdminKitDocs
Frameworks

Angular

Add AdminKit to an Angular app through the styles and scripts arrays in angular.json and a standalone layout component with the AdminKit sidebar.

Angular CLI projects load global CSS and classic scripts through the styles and scripts arrays in angular.json. AdminKit's compiled files go there, and the layout is a standalone component.

Install

npx @angular/cli@latest new my-app --defaults --style=css --ssr=false
cd my-app
npm install @adminkit/core

Angular CLI 22 requires Node.js ^22.22.3, ^24.15.0 or >=26.0.0.

AdminKit PRO is not published to npm. Copy dist/ from the download into src/adminkit/ and use src/adminkit/css/app.css and src/adminkit/js/app.js in the arrays below.

Import the CSS and JavaScript

Add the files to the build options of the project in angular.json. Keep src/styles.css after the AdminKit stylesheet so your own styles override it. Angular loads the scripts entry as a plain script before the app starts.

angular.json
"options": {
  "styles": [
    "@adminkit/core/dist/css/app.css",
    "src/styles.css"
  ],
  "scripts": [
    "@adminkit/core/dist/js/app.js"
  ]
}

Optional: avoid a color mode flash

Without head.js, app.js applies the stored color mode once it runs, so a visitor who picked the mode opposite to their operating system briefly sees the other one. head.js applies it before the first paint. It has to be a plain, blocking script in <head>, so copy it into the build with an assets entry:

angular.json
"assets": [
  { "glob": "**/*", "input": "public" },
  { "glob": "head.js", "input": "node_modules/@adminkit/core/dist/js" }
]
src/index.html
<script src="head.js"></script>

Minimal layout

app.js sets up icons, the sidebar toggle and the SimpleBar scrollbar in markup that Angular renders later, also after each route change, so the layout is plain markup with the js-sidebar, js-simplebar and js-sidebar-toggle classes. From the lg breakpoint the toggle collapses the sidebar; below it, the sidebar is a Bootstrap offcanvas sheet (offcanvas-lg on #sidebar).

src/app/layout/layout.ts
import { Component } from '@angular/core';
import { RouterLink, RouterLinkActive } from '@angular/router';

@Component({
  selector: 'app-layout',
  imports: [RouterLink, RouterLinkActive],
  templateUrl: './layout.html',
})
export class Layout {}
src/app/layout/layout.html
<div class="wrapper">
  <nav id="sidebar" class="sidebar js-sidebar offcanvas-lg offcanvas-start" tabindex="-1" aria-label="Sidebar">
    <div class="sidebar-content js-simplebar">
      <a class="sidebar-brand" routerLink="/">
        <span class="align-middle">AdminKit</span>
      </a>
      <ul class="sidebar-nav">
        <li class="sidebar-header">Pages</li>
        <li class="sidebar-item" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">
          <a class="sidebar-link" routerLink="/">
            <i class="align-middle" data-lucide="sliders-vertical"></i> <span class="align-middle">Dashboard</span>
          </a>
        </li>
        <li class="sidebar-item" routerLinkActive="active">
          <a class="sidebar-link" routerLink="/profile">
            <i class="align-middle" data-lucide="user"></i> <span class="align-middle">Profile</span>
          </a>
        </li>
      </ul>
    </div>
  </nav>

  <div class="main">
    <nav class="navbar navbar-expand navbar-light navbar-bg" aria-label="Top bar">
      <button type="button" class="sidebar-toggle js-sidebar-toggle" aria-controls="sidebar" aria-expanded="true" aria-label="Collapse sidebar">
        <i class="hamburger align-self-center"></i>
      </button>
    </nav>
    <main class="content">
      <div class="container-fluid p-0">
        <ng-content />
      </div>
    </main>
  </div>
</div>

Replace the generated root component and its template, and delete src/app/app.css. The dashboard is a route:

src/app/app.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { Layout } from './layout/layout';

@Component({
  imports: [RouterOutlet, Layout],
  selector: 'app-root',
  templateUrl: './app.html',
})
export class App {}
src/app/app.html
<app-layout>
  <router-outlet />
</app-layout>
src/app/dashboard.ts
import { Component } from '@angular/core';

@Component({
  template: `
    <h1 class="h3 mb-3">Dashboard</h1>
    <div class="card">
      <div class="card-body">Hello from AdminKit.</div>
    </div>
  `,
})
export class Dashboard {}
src/app/app.routes.ts
import { Routes } from '@angular/router';
import { Dashboard } from './dashboard';

export const routes: Routes = [{ path: '', component: Dashboard }];

Add a profile route and component the same way for the second link.

Run

npx ng serve

Open http://localhost:4200. You should see the dark sidebar with its two icons, the navbar with the hamburger toggle and the card. Clicking Profile navigates client-side; the icons stay rendered and the active item moves. In a window narrower than 992px the sidebar is hidden, and the toggle opens it as a sheet over the page; Escape, the backdrop or a link closes it.

Notes

  • ng build stops at Angular's default initial budget of 1 MB, because app.css and app.js add about 830 kB. Raise maximumError of the initial budget in angular.json, for example to 2MB.
  • With server-side rendering (--ssr), the server renders the pages without app.js, and the browser runs it from scripts before the app hydrates. Hydration works as is.

Last updated on

On this page