@akhatmirzo/ui

AppShell

Admin panel va dashboard qolipi: yig'iladigan Sidebar, yopishqoq header, telefonda Drawer va skip link.

Asosiy kontentga o'tish
Bosh sahifa

Bosh sahifa

Tugma yoki Ctrl/⌘ + B sidebar'ni yig'adi. Holat localStorage'da saqlanadi.

Import

import { AppShell, Sidebar, useAppShell } from '@akhatmirzo/ui';

Qachon ishlatish

  • Admin panel, CRM, dashboard — chapda doimiy menyu, o'ngda sahifa kontenti.
  • Ko'p bo'limli ilova, foydalanuvchi bo'limlar orasida tez-tez o'tadi.
  • Marketing sahifa, blog uchun emas — u yerda yuqori navigatsiya qulayroq.
  • Qolip butun ekranni egallaydi; uni ilova layout ida bir marta qo'ying.

Tuzilishi

QismVazifasi
AppShellHolat (yig'ilgan/to'liq), saqlash, mod+B yorlig'i, skip link
SidebarDesktop'da chapdagi panel (256px ↔ 64px), < 1024px da chapdan Drawer
Sidebar.HeaderLogotip, ilova nomi
Sidebar.Content<nav aria-label="Asosiy menyu">, aylantiriladi
Sidebar.GroupSarlavha + elementlar ro'yxati; collapsible bo'lishi mumkin
Sidebar.ItemHavola (href), tugma (onClick) yoki renderLink orqali Next Link
Sidebar.FooterPastki qism: foydalanuvchi menyusi
AppShell.Main<main> — skip link shu yerga olib keladi
AppShell.HeaderYopishqoq (sticky top-0), 56px, pastki chegara
AppShell.SidebarToggleSidebar tugmasi: desktop'da yig'adi, telefonda Drawer'ni ochadi
// app/(admin)/layout.tsx
<AppShell sidebarStorageKey="sidebar">
  <Sidebar>
    <Sidebar.Header>
      <Logo />
    </Sidebar.Header>
    <Sidebar.Content>
      <Sidebar.Group label="Asosiy">
        <Sidebar.Item icon={<Home />} href="/" active={pathname === '/'}>
          Bosh sahifa
        </Sidebar.Item>
        <Sidebar.Item icon={<Box />} href="/orders" badge={12}>
          Buyurtmalar
        </Sidebar.Item>
      </Sidebar.Group>
    </Sidebar.Content>
    <Sidebar.Footer>
      <UserMenu />
    </Sidebar.Footer>
  </Sidebar>
  <AppShell.Main>
    <AppShell.Header>
      <AppShell.SidebarToggle />
      <Breadcrumb items={…} />
    </AppShell.Header>
    {children}
  </AppShell.Main>
</AppShell>

Yig'ilgan holat

Desktop'da (≥ 1024px) sidebar 64px'lik ikonkalar qatoriga yig'iladi: element nomlari yashiriladi, har birida Tooltip va aria-label paydo bo'ladi, hisoblagich nuqtaga aylanadi. Yig'ish — AppShell.SidebarToggle yoki Ctrl/⌘ + B. Animatsiya grid-template-columns orqali, prefers-reduced-motion da sakrab o'tadi.

collapsible guruh sarlavhasi bosilganda yig'iladi (Accordion uslubida); yig'ilgan panelda guruhlar doim ochiq, sarlavha o'rnida ajratuvchi chiziq.

Asosiy kontentga o'tish
Bosh sahifa

Yig'ilgan holatda faqat ikonkalar ko'rinadi — ustiga kelsangiz Tooltip chiqadi. "Hisobotlar" guruhi to'liq holatda yig'iladi.

Holatni saqlash

sidebarStorageKey berilsa, holat localStorage ga yoziladi va keyingi tashrifda tiklanadi. SSR-xavfsiz: serverda va birinchi renderda defaultSidebarOpen chiziladi, saqlangan qiymat mount'dan keyin o'qiladi (hydration xatosi bo'lmaydi). Storage taqiqlangan bo'lsa ham holat ishlayveradi.

Telefon va planshet

< 1024px da sidebar o'rniga chapdan chiqadigan Drawer ishlatiladi: AppShell.SidebarToggle uni ochadi, Sidebar.Item bosilganda (sahifa o'tishi) o'zi yopiladi. Desktop/mobil almashuvi CSS breakpoint orqali — server va brauzer bir xil HTML chizadi.

renderLink — o'z havola komponentingizni ishlatish uchun. Unga href, className, aria-current, onClick va ichki kontent beriladi — hammasini yoying.

'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';

function NavItem({ href, icon, children }) {
  const pathname = usePathname();
  return (
    <Sidebar.Item
      href={href}
      icon={icon}
      active={pathname.startsWith(href)}
      renderLink={(props) => <Link {...props} />}
    >
      {children}
    </Sidebar.Item>
  );
}

useAppShell

AppShell ichidagi istalgan komponent holatni o'qishi va o'zgartirishi mumkin: { sidebarOpen, setSidebarOpen, toggleSidebar, mobileOpen, setMobileOpen, collapsed }.

Hujjatdagi namunalar

Bu sahifadagi namunalar cheklangan ramka ichida: className="[--ak-app-shell-height:480px]" qolip balandligini belgilaydi (standart — 100dvh). Haqiqiy ilovada uni bermang.

Props

AppShell

<div> atributlari va ref ham qabul qilinadi.

PropTipStandartTavsif
sidebarOpenboolean—Desktop sidebar to'liq ochiqmi (boshqariladigan rejim)
defaultSidebarOpenbooleantrueBoshlang'ich holat
onSidebarOpenChange(open: boolean) => void—Yig'ilganda / yoyilganda
sidebarStorageKeystring—localStorage kaliti — holat saqlanadi (SSR-xavfsiz)
shortcutstring | false'mod+b'Yig'ish yorlig'i (useHotkeys formati); false — o'chirilgan
labels{ skipToContent?: string }{ skipToContent: "Asosiy kontentga o'tish" }Skip link matni

<aside> atributlari (desktop panel) va ref ham qabul qilinadi.

PropTipStandartTavsif
widthnumber | string256To'liq kenglik; yig'ilganda — 64px
labels{ nav?: string; drawerTitle?: string }{ nav: "Asosiy menyu", drawerTitle: "Menyu" }<nav> nomi va mobil Drawer sarlavhasi (ekran o'quvchi uchun)

Sidebar.Item

PropTipStandartTavsif
iconReactNode—Chapdagi ikonka (18px); yig'ilganda faqat shu
hrefstring—Havola manzili; berilmasa — <button>
onClick(event: MouseEvent) => void—Bosilganda (mobil Drawer baribir yopiladi)
activebooleanfalseJoriy sahifa — aria-current="page" va ajratilgan fon
badgeReactNode—Hisoblagich (12) yoki o'z elementingiz
disabledbooleanfalseO'chirilgan
labelstring—Yig'ilgandagi Tooltip va aria-label (standart — children matni)
renderLink(props: SidebarItemLinkProps) => ReactElement—O'z havola komponentingiz: (p) => <Link {...p} />

Sidebar.Group

PropTipStandartTavsif
labelReactNode—Guruh sarlavhasi
collapsiblebooleanfalseSarlavha bosilganda yig'iladi
defaultOpenbooleantruecollapsible guruh boshida ochiqmi

AppShell.SidebarToggle

IconButton prop'lari; aria-label standart — "Yon menyu", variant — ghost. children berilsa, ichki ikonka o'rniga chiziladi.

Data atributlari

AtributQayerdaQiymat
data-sidebar-stateAppShellexpanded · collapsed
data-collapsedSidebaryig'ilganda mavjud
data-activeSidebar.Itemfaol bo'lsa mavjud
data-disabledSidebar.Itemo'chirilganda mavjud

Klaviatura

TugmaHarakat
Tab (birinchi)"Asosiy kontentga o'tish" havolasi chiqadi
Ctrl/⌘ + BDesktop'da yig'ish/yoyish, telefonda menyuni ochish
EscMobil menyuni yopadi

Accessibility

  • Skip link. AppShell sahifa boshiga "Asosiy kontentga o'tish" havolasini qo'yadi — u faqat klaviatura fokusida ko'rinadi va AppShell.Main ga olib o'tadi.
  • Navigatsiya. Menyu <nav aria-label="Asosiy menyu"> ichida, faol element aria-current="page" oladi; guruhlar role="group" va sarlavha bilan bog'langan.
  • Yig'ilgan holat. Matn yashirinsa ham har element nomini saqlaydi: aria-label va Tooltip. Hisoblagich ekran o'quvchi uchun matn sifatida qoladi.
  • Toggle. AppShell.SidebarToggle aria-expanded va aria-controls oladi (desktop'da — panel, telefonda — Drawer).
  • Mobil menyu — Drawer: fokus ichida qoladi, Esc yopadi, fokus tugmaga qaytadi.

Sahifada