diff --git a/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app-routes.tsx b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app-routes.tsx
new file mode 100644
index 000000000..e65531d40
--- /dev/null
+++ b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app-routes.tsx
@@ -0,0 +1,5 @@
+import Home from './home/home';
+
+export const routes = [
+ { path: '/', element: , text: 'Home', icon: 'home' }
+];
diff --git a/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.css b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.css
new file mode 100644
index 000000000..039fafee2
--- /dev/null
+++ b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.css
@@ -0,0 +1,97 @@
+.app {
+ display: flex;
+ flex-flow: column nowrap;
+ height: 100%;
+ overflow: hidden;
+}
+
+.app__navbar {
+ display: flex;
+ align-items: center;
+ flex: 0 0 auto;
+ height: 56px;
+ padding: 0 16px;
+ background: #239ef0;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, .24);
+ box-sizing: border-box;
+}
+
+.app__menu-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ color: #000;
+ border: 0;
+ background: transparent;
+ cursor: pointer;
+ font-size: 24px;
+}
+
+.app__title {
+ margin: 0 0 0 16px;
+ color: #000;
+ font-size: 1.25rem;
+ font-weight: 600;
+ line-height: 1;
+}
+
+.app__body {
+ display: flex;
+ flex: 1 1 auto;
+ min-height: 0;
+}
+
+.app__drawer {
+ flex: 0 0 auto;
+ height: 100%;
+ --menu-full-width: 280px;
+}
+
+igc-nav-drawer-item[active]::part(base) {
+ background: #e0f2ff;
+ color: #0075d2;
+}
+
+igc-nav-drawer-item[active] igc-icon {
+ color: #0075d2;
+}
+
+.app--mini .app__drawer {
+ --menu-full-width: 68px;
+}
+
+igc-nav-drawer.app__drawer::part(base) {
+ transition: width 0.3s ease-out;
+ overflow: hidden;
+}
+
+.app--mini igc-nav-drawer-item::part(base) {
+ justify-content: center;
+ width: 40px;
+ min-height: 40px;
+ padding: 0;
+ margin: 4px auto;
+ border-radius: 8px;
+}
+
+.app--mini igc-nav-drawer-item::part(content) {
+ display: none;
+}
+
+.app__content {
+ flex: 1 1 auto;
+ min-width: 0;
+ overflow: auto;
+ display: flex;
+ justify-content: center;
+ align-items: flex-start;
+}
+
+@media (max-width: 1024px) {
+ .app__menu-button {
+ display: none;
+ }
+}
diff --git a/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.test.tsx b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.test.tsx
new file mode 100644
index 000000000..5ff3083c9
--- /dev/null
+++ b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.test.tsx
@@ -0,0 +1,20 @@
+import { beforeAll, expect, test } from 'vitest';
+import { render } from '@testing-library/react';
+import { MemoryRouter } from 'react-router-dom';
+import App from './app';
+import 'element-internals-polyfill';
+import { setupTestMocks } from '../setupTests';
+
+beforeAll(() => {
+ setupTestMocks();
+});
+
+test('renders without crashing', () => {
+ const wrapper = render(
+
+
+
+ );
+
+ expect(wrapper).toBeTruthy();
+});
diff --git a/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.tsx b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.tsx
new file mode 100644
index 000000000..f92274eb2
--- /dev/null
+++ b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/app.tsx
@@ -0,0 +1,78 @@
+import { useState, useEffect } from 'react';
+import { Outlet, useNavigate, useLocation } from 'react-router-dom';
+import {
+ IgrNavDrawer,
+ IgrNavDrawerItem,
+ IgrIcon,
+ registerIcon,
+} from 'igniteui-react';
+import { routes } from './app-routes';
+import 'igniteui-webcomponents/themes/light/bootstrap.css';
+import './app.css';
+
+const materialIcons = [
+ ['home', 'action/svg/production/ic_home_24px.svg'],
+ ['menu', 'navigation/svg/production/ic_menu_24px.svg'],
+ ['apps', 'navigation/svg/production/ic_apps_24px.svg'],
+ ['code', 'action/svg/production/ic_code_24px.svg'],
+ ['build', 'action/svg/production/ic_build_24px.svg'],
+ ['palette', 'image/svg/production/ic_palette_24px.svg'],
+] as const;
+
+materialIcons.forEach(([name, path]) =>
+ registerIcon(name, `https://unpkg.com/material-design-icons@3.0.1/${path}`, 'material')
+);
+
+const navRoutes = routes.filter((r) => r.text);
+
+export default function App() {
+ const [drawerOpen, setDrawerOpen] = useState(true);
+ const navigate = useNavigate();
+ const location = useLocation();
+
+ useEffect(() => {
+ const mq = window.matchMedia('(min-width: 1025px)');
+ const update = () => setDrawerOpen(mq.matches);
+ update();
+ mq.addEventListener('change', update);
+ return () => mq.removeEventListener('change', update);
+ }, []);
+
+ return (
+
+
+
+ $(name)
+
+
+
+ {navRoutes.map((route) => (
+ navigate(route.path)}
+ >
+
+ {route.text}
+
+ ))}
+
+
+
+
+
+
+ );
+}
diff --git a/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/home/home.tsx b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/home/home.tsx
new file mode 100644
index 000000000..cc9946e08
--- /dev/null
+++ b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/home/home.tsx
@@ -0,0 +1,69 @@
+import logo from "/logo.svg";
+import { IgrIcon } from "igniteui-react";
+import styles from "./style.module.css";
+
+export default function App() {
+ return (
+
+
+
Welcome to Ignite UI for React!
+
+ A routed application shell with a responsive side navigation drawer and curated Ignite UI resources.
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/home/style.module.css b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/home/style.module.css
new file mode 100644
index 000000000..ca8b97595
--- /dev/null
+++ b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/files/src/app/home/style.module.css
@@ -0,0 +1,105 @@
+:local(.home) {
+ width: 100%;
+ max-width: 920px;
+ margin: auto;
+ padding: 48px 24px;
+ box-sizing: border-box;
+ font-family: "Titillium Web", "Segoe UI", Arial, sans-serif;
+}
+
+:local(.intro) {
+ max-width: 720px;
+ margin: 0 auto 24px;
+ text-align: center;
+}
+
+:local(.header) {
+ margin: 0 0 12px;
+ color: #09f;
+ font-size: 3rem;
+ font-weight: 600;
+ line-height: 1.2;
+}
+
+:local(.description) {
+ margin: 0;
+ color: #000;
+ font-size: 1.125rem;
+ line-height: 1.5;
+}
+
+:local(.logo) {
+ display: block;
+ width: 500px;
+ height: 350px;
+ margin: 0 auto 28px;
+ max-width: 100%;
+ object-fit: contain;
+}
+
+:local(.resources) {
+ display: grid;
+ grid-template-columns: repeat(2, 300px);
+ justify-content: center;
+ margin: 0 auto;
+ gap: 4px 64px;
+}
+
+:local(.resource) {
+ display: flex;
+ align-items: center;
+ min-height: 64px;
+ padding: 6px 0;
+ color: rgba(0, 0, 0, .74);
+ text-align: left;
+ text-decoration: none;
+}
+
+:local(.resource):hover strong {
+ text-decoration: underline;
+}
+
+:local(.resourceIcon) {
+ flex: 0 0 28px;
+ margin-right: 16px;
+ color: #09f;
+ font-size: 28px;
+}
+
+:local(.resource) strong,
+:local(.resource) small {
+ display: block;
+}
+
+:local(.resource) strong {
+ margin-bottom: 2px;
+ color: #731963;
+ font-size: 1rem;
+}
+
+:local(.resource) small {
+ color: #000;
+ font-size: 0.875rem;
+ line-height: 1.4;
+}
+
+@media (max-width: 768px) {
+ :local(.home) {
+ padding: 32px 16px;
+ }
+
+ :local(.header) {
+ font-size: 2.25rem;
+ }
+
+ :local(.logo) {
+ width: 100%;
+ height: 240px;
+ }
+
+ :local(.resources) {
+ grid-template-columns: minmax(0, 300px);
+ justify-content: center;
+ gap: 4px;
+ }
+}
diff --git a/packages/cli/templates/react/igr-ts/projects/side-nav-mini/index.ts b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/index.ts
new file mode 100644
index 000000000..8e7b62f4e
--- /dev/null
+++ b/packages/cli/templates/react/igr-ts/projects/side-nav-mini/index.ts
@@ -0,0 +1,19 @@
+import { ProjectTemplate } from "@igniteui/cli-core";
+import * as path from "path";
+import { BaseWithHomeIgrTsProject } from "../_base_with_home";
+
+export class SideNavMiniIgrTsProject extends BaseWithHomeIgrTsProject implements ProjectTemplate {
+ public id: string = "side-nav-mini";
+ public name = "Side navigation + collapsible mini nav";
+ public description = "Side navigation with a collapsible mini (icons-only) variant and responsive breakpoints";
+ public dependencies: string[] = [];
+ public framework: string = "react";
+ public projectType: string = "igr-ts";
+ public hasExtraConfiguration: boolean = false;
+ public isHidden: boolean = false;
+
+ public get templatePaths(): string[] {
+ return [...super.templatePaths, path.join(__dirname, "files")];
+ }
+}
+export default new SideNavMiniIgrTsProject();
diff --git a/packages/cli/templates/react/igr-ts/projects/top-nav/files/src/app/app.css b/packages/cli/templates/react/igr-ts/projects/top-nav/files/src/app/app.css
index 9ebd834c8..458fca9a9 100644
--- a/packages/cli/templates/react/igr-ts/projects/top-nav/files/src/app/app.css
+++ b/packages/cli/templates/react/igr-ts/projects/top-nav/files/src/app/app.css
@@ -51,9 +51,6 @@
flex: 0 0 auto;
height: 100%;
--ig-nav-drawer-size: 280px;
- --ig-navdrawer-item-active-background: #e0f2ff;
- --ig-navdrawer-item-active-text-color: #0075d2;
- --ig-navdrawer-item-active-icon-color: #0075d2;
}
igc-nav-drawer-item[active]::part(base) {
diff --git a/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/files/src/app/app-routing.ts b/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/files/src/app/app-routing.ts
new file mode 100644
index 000000000..bd84d8975
--- /dev/null
+++ b/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/files/src/app/app-routing.ts
@@ -0,0 +1,13 @@
+import { type Route } from '@vaadin/router';
+import './home/home.js';
+import './not-found/not-found.js';
+
+export interface AppRoute extends Route {
+ icon?: string;
+}
+
+export const routes: AppRoute[] = [
+ { path: '/', component: 'app-home', name: 'Home', icon: 'home' },
+ // The fallback route should always be after other alternatives.
+ { path: '(.*)', component: 'app-not-found' },
+];
diff --git a/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/files/src/app/app.ts b/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/files/src/app/app.ts
new file mode 100644
index 000000000..a97318025
--- /dev/null
+++ b/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/files/src/app/app.ts
@@ -0,0 +1,230 @@
+import { html, css, LitElement } from 'lit';
+import { customElement, state } from 'lit/decorators.js';
+import {
+ defineComponents,
+ IgcIconComponent,
+ IgcNavDrawerComponent,
+ IgcNavDrawerItemComponent,
+ registerIcon,
+} from 'igniteui-webcomponents';
+import { Router } from '@vaadin/router';
+import { routes, type AppRoute } from './app-routing.js';
+
+defineComponents(
+ IgcIconComponent,
+ IgcNavDrawerComponent,
+ IgcNavDrawerItemComponent,
+);
+
+const materialIcons = [
+ ['home', 'action/svg/production/ic_home_24px.svg'],
+ ['menu', 'navigation/svg/production/ic_menu_24px.svg'],
+ ['apps', 'navigation/svg/production/ic_apps_24px.svg'],
+ ['code', 'action/svg/production/ic_code_24px.svg'],
+ ['build', 'action/svg/production/ic_build_24px.svg'],
+ ['palette', 'image/svg/production/ic_palette_24px.svg'],
+] as const;
+
+materialIcons.forEach(([name, path]) =>
+ registerIcon(name, `https://unpkg.com/material-design-icons@3.0.1/${path}`, 'material')
+);
+
+@customElement('app-root')
+export default class App extends LitElement {
+ @state()
+ private drawerOpen = true;
+
+ @state()
+ private currentPath = window.location.pathname;
+
+ private mediaQuery?: MediaQueryList;
+
+ static styles = css`
+ :host {
+ display: flex;
+ height: 100%;
+ }
+
+ .app {
+ display: flex;
+ flex-flow: column nowrap;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ }
+
+ .app__navbar {
+ display: flex;
+ align-items: center;
+ flex: 0 0 auto;
+ height: 56px;
+ padding: 0 16px;
+ background: #239ef0;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, .24);
+ box-sizing: border-box;
+ }
+
+ .app__menu-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ color: #000;
+ border: 0;
+ background: transparent;
+ cursor: pointer;
+ }
+
+ .app__menu-button igc-icon {
+ font-size: 24px;
+ }
+
+ .app__title {
+ margin: 0 0 0 16px;
+ color: #000;
+ font-size: 1.25rem;
+ font-weight: 600;
+ line-height: 1;
+ }
+
+ .app__body {
+ display: flex;
+ flex: 1 1 auto;
+ min-height: 0;
+ }
+
+ .app__drawer {
+ flex: 0 0 auto;
+ height: 100%;
+ --menu-full-width: 280px;
+ }
+
+ .app--mini .app__drawer {
+ --menu-full-width: 68px;
+ }
+
+ igc-nav-drawer.app__drawer::part(base) {
+ transition: width 0.3s ease-out;
+ overflow: hidden;
+ }
+
+ .app--mini igc-nav-drawer-item::part(base) {
+ justify-content: center;
+ width: 40px;
+ min-height: 40px;
+ padding: 0;
+ margin: 4px auto;
+ border-radius: 8px;
+ }
+
+ .app--mini igc-nav-drawer-item::part(content) {
+ display: none;
+ }
+
+ igc-nav-drawer-item[active]::part(base) {
+ background: #e0f2ff;
+ color: #0075d2;
+ }
+
+ igc-nav-drawer-item[active] igc-icon {
+ color: #0075d2;
+ }
+
+ router-outlet {
+ flex: 1 1 auto;
+ display: flex;
+ align-items: stretch;
+ justify-content: center;
+ min-width: 0;
+ overflow: auto;
+ }
+
+ @media (max-width: 1024px) {
+ .app__menu-button {
+ display: none;
+ }
+ }
+ `;
+
+ render() {
+ const visibleRoutes = (routes as AppRoute[]).filter((route) => route.name);
+
+ return html`
+
+
+
+
+ ${visibleRoutes.map((route) => html`
+ this.navigate(route.path)}
+ >
+
+ ${route.name}
+
+ `)}
+
+
+
+
+ `;
+ }
+
+ connectedCallback() {
+ super.connectedCallback();
+ this.mediaQuery = window.matchMedia('(min-width: 1025px)');
+ this.updateDrawerState();
+ this.mediaQuery.addEventListener('change', this.updateDrawerState);
+ window.addEventListener('popstate', this.updateCurrentPath);
+ }
+
+ disconnectedCallback() {
+ this.mediaQuery?.removeEventListener('change', this.updateDrawerState);
+ window.removeEventListener('popstate', this.updateCurrentPath);
+ super.disconnectedCallback();
+ }
+
+ firstUpdated() {
+ const outlet = this.shadowRoot?.querySelector('router-outlet');
+ const router = new Router(outlet);
+ router.setRoutes(routes);
+ }
+
+ private toggleDrawer = () => {
+ this.drawerOpen = !this.drawerOpen;
+ };
+
+ private navigate(path: string) {
+ this.currentPath = path;
+ Router.go(path);
+ }
+
+ private updateDrawerState = () => {
+ this.drawerOpen = Boolean(this.mediaQuery?.matches);
+ };
+
+ private updateCurrentPath = () => {
+ this.currentPath = window.location.pathname;
+ };
+}
diff --git a/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/index.ts b/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/index.ts
new file mode 100644
index 000000000..6092d6526
--- /dev/null
+++ b/packages/cli/templates/webcomponents/igc-ts/projects/side-nav-mini/index.ts
@@ -0,0 +1,18 @@
+import { ProjectTemplate } from "@igniteui/cli-core";
+import * as path from "path";
+import { SideNavProject } from "../side-nav";
+
+export class SideNavMiniProject extends SideNavProject implements ProjectTemplate {
+ public id: string = "side-nav-mini";
+ public name = "Side navigation + collapsible mini nav";
+ public description = "Side navigation with a collapsible mini (icons-only) variant and responsive breakpoints";
+ public framework: string = "webcomponents";
+ public projectType: string = "igc-ts";
+ public dependencies: string[] = [];
+ public hasExtraConfiguration: boolean = false;
+
+ public get templatePaths() {
+ return [...super.templatePaths, path.join(__dirname, "files")];
+ }
+}
+export default new SideNavMiniProject();
diff --git a/packages/cli/templates/webcomponents/igc-ts/projects/side-nav/files/src/app/app.ts b/packages/cli/templates/webcomponents/igc-ts/projects/side-nav/files/src/app/app.ts
index 29a542cf0..52aeb7529 100644
--- a/packages/cli/templates/webcomponents/igc-ts/projects/side-nav/files/src/app/app.ts
+++ b/packages/cli/templates/webcomponents/igc-ts/projects/side-nav/files/src/app/app.ts
@@ -108,9 +108,6 @@ export default class App extends LitElement {
flex: 0 0 auto;
height: 100%;
--ig-nav-drawer-size: 280px;
- --ig-navdrawer-item-active-background: #e0f2ff;
- --ig-navdrawer-item-active-text-color: #0075d2;
- --ig-navdrawer-item-active-icon-color: #0075d2;
}
igc-nav-drawer-item[active]::part(base) {
diff --git a/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.config.ts b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.config.ts
new file mode 100644
index 000000000..3cd4ad001
--- /dev/null
+++ b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.config.ts
@@ -0,0 +1,29 @@
+import { ApplicationConfig, importProvidersFrom, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
+import { BrowserModule, HammerModule } from '@angular/platform-browser';
+import { provideAnimations } from '@angular/platform-browser/animations';
+import { provideRouter } from '@angular/router';
+import {
+ IgxNavigationDrawerModule,
+ IgxNavbarModule,
+ IgxIconModule,
+ IgxRippleModule
+} from '<%=igxPackage%>';
+
+import { routes } from './app.routes';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideBrowserGlobalErrorListeners(),
+ provideZoneChangeDetection({ eventCoalescing: true }),
+ provideRouter(routes),
+ importProvidersFrom(
+ BrowserModule,
+ HammerModule,
+ IgxNavigationDrawerModule,
+ IgxNavbarModule,
+ IgxIconModule,
+ IgxRippleModule
+ ),
+ provideAnimations()
+ ]
+};
diff --git a/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.html b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.html
new file mode 100644
index 000000000..2a4c499ee
--- /dev/null
+++ b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+ @for (link of topNavLinks; track link) {
+
+ {{link.icon}}
+ {{link.name}}
+
+ }
+
+
+ @for (link of topNavLinks; track link) {
+
+ {{link.icon}}
+
+ }
+
+
+
+
+
+
diff --git a/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.routes.ts b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.routes.ts
new file mode 100644
index 000000000..d86b75332
--- /dev/null
+++ b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.routes.ts
@@ -0,0 +1,11 @@
+import { Routes } from '@angular/router';
+import { Home } from './home/home';
+import { NotFound } from './error-routing/not-found/not-found';
+import { UncaughtError } from './error-routing/error/uncaught-error';
+
+export const routes: Routes = [
+ { path: '', redirectTo: '/home', pathMatch: 'full'},
+ { path: 'home', component: Home, data: { text: 'Home', icon: 'home' }},
+ { path: 'error', component: UncaughtError },
+ { path: '**', component: NotFound } // must always be last
+];
diff --git a/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.scss b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.scss
new file mode 100644
index 000000000..9a8437b9b
--- /dev/null
+++ b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.scss
@@ -0,0 +1,55 @@
+// Root element fills the viewport and stacks navbar above content
+app-root {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+// Navbar spans full width; height is determined by igx-navbar itself
+.app-navbar {
+ flex-shrink: 0;
+ width: 100%;
+}
+
+// Row container holds the nav drawer and the page content side by side
+.row-layout {
+ display: flex;
+ flex-direction: row;
+ flex: 1 1 auto;
+ min-height: 0; // allow flex children to shrink below their content height
+}
+
+// Page content fills remaining horizontal space and scrolls independently
+.view-container {
+ flex: 1 1 auto;
+ min-width: 0;
+ overflow: auto;
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: center;
+ align-items: flex-start;
+
+ > *:not(router-outlet) {
+ padding: 0 24px;
+ width: 100%;
+ }
+
+ p {
+ margin: 15px;
+ }
+}
+
+// On small screens: hide the burger button — the nav is always in mini mode
+@media only screen and (max-width: 1024px) {
+ .nav-toggle-btn {
+ display: none;
+ }
+
+ .view-container {
+ justify-content: flex-start;
+
+ > *:not(router-outlet) {
+ padding: 0 15px;
+ }
+ }
+}
diff --git a/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.spec.ts b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.spec.ts
new file mode 100644
index 000000000..a93a46d34
--- /dev/null
+++ b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.spec.ts
@@ -0,0 +1,20 @@
+import { TestBed } from '@angular/core/testing';
+import { RouterModule } from '@angular/router';
+import { App } from './app';
+
+describe('App', () => {
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [
+ RouterModule.forRoot([]),
+ App
+ ]
+ }).compileComponents();
+ });
+
+ it('should create the app', () => {
+ const fixture = TestBed.createComponent(App);
+ const app = fixture.componentInstance;
+ expect(app).toBeTruthy();
+ });
+});
diff --git a/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.ts b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.ts
new file mode 100644
index 000000000..82c79010d
--- /dev/null
+++ b/packages/igx-templates/igx-ts/projects/side-nav-mini/files/src/app/app.ts
@@ -0,0 +1,83 @@
+import { Component, HostListener, OnInit, AfterViewInit, viewChild, ViewEncapsulation, inject } from '@angular/core';
+import { NavigationStart, Router, RouterLinkActive, RouterLink, RouterOutlet } from '@angular/router';
+import {
+ IgxNavigationDrawerComponent,
+ IgxNavDrawerTemplateDirective,
+ IgxNavDrawerMiniTemplateDirective,
+ IgxNavDrawerItemDirective,
+ IgxRippleDirective,
+ IgxNavbarComponent,
+ IgxNavbarActionDirective,
+ IgxIconComponent,
+ IgxIconButtonDirective,
+} from 'igniteui-angular';
+import { filter } from 'rxjs/operators';
+import { routes } from './app.routes';
+
+const MINI_BREAKPOINT = 1024;
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.html',
+ styleUrl: './app.scss',
+ encapsulation: ViewEncapsulation.None,
+ imports: [
+ IgxNavigationDrawerComponent,
+ IgxNavDrawerTemplateDirective,
+ IgxNavDrawerMiniTemplateDirective,
+ IgxNavDrawerItemDirective,
+ IgxRippleDirective,
+ RouterLinkActive,
+ RouterLink,
+ IgxNavbarComponent,
+ IgxNavbarActionDirective,
+ IgxIconComponent,
+ IgxIconButtonDirective,
+ RouterOutlet
+ ]
+})
+export class App implements OnInit, AfterViewInit {
+ // Start open on wide screens, collapsed (mini) on narrow screens
+ public readonly initiallyOpen = window.innerWidth > MINI_BREAKPOINT;
+ public topNavLinks: Array<{ path: string; name: string; icon: string }> = [];
+
+ public navdrawer = viewChild.required(IgxNavigationDrawerComponent);
+
+ private router = inject(Router);
+
+ constructor() {
+ for (const route of routes) {
+ if (route.path && route.data && route.path.indexOf('*') === -1) {
+ this.topNavLinks.push({
+ name: route.data['text'],
+ icon: route.data['icon'] ?? 'radio_button_unchecked',
+ path: '/' + route.path
+ });
+ }
+ }
+ }
+
+ public ngOnInit(): void {
+ this.router.events.pipe(
+ filter((x): x is NavigationStart => x instanceof NavigationStart)
+ ).subscribe(() => this.updateDrawerState());
+ }
+
+ public ngAfterViewInit(): void {
+ this.updateDrawerState();
+ }
+
+ /** Burger menu toggle — only active on large screens */
+ public toggleNav(): void {
+ this.navdrawer().toggle();
+ }
+
+ @HostListener('window:resize')
+ public updateDrawerState(): void {
+ const isWide = window.innerWidth > MINI_BREAKPOINT;
+ if (!isWide && this.navdrawer().isOpen) {
+ // Collapse to mini on small screens
+ this.navdrawer().close();
+ }
+ }
+}
diff --git a/packages/igx-templates/igx-ts/projects/side-nav-mini/index.ts b/packages/igx-templates/igx-ts/projects/side-nav-mini/index.ts
new file mode 100644
index 000000000..992810c78
--- /dev/null
+++ b/packages/igx-templates/igx-ts/projects/side-nav-mini/index.ts
@@ -0,0 +1,19 @@
+import { ProjectTemplate } from "@igniteui/cli-core";
+import * as path from "path";
+import { SideNavProject } from "../side-nav";
+
+export class SideNavMiniProject extends SideNavProject implements ProjectTemplate {
+ public id: string = "side-nav-mini";
+ public name = "Side navigation + collapsible mini nav";
+ public description = "Side navigation with a collapsible mini (icons-only) variant and responsive breakpoints";
+ public dependencies: string[] = [];
+ public framework: string = "angular";
+ public projectType: string = "igx-ts";
+ public hasExtraConfiguration = false;
+
+ public get templatePaths() {
+ return [...super.templatePaths, path.join(__dirname, "files")];
+ }
+}
+
+export default new SideNavMiniProject();