Skip to main content

Component Inventory


title: Component Inventory owner: vizu last-updated: 2026-05-16 supersedes: docs/frontend/COMPONENT-INVENTORY.md (2026-02-20) status: canonical

Bilko Component Inventory

Organized

by Project:Atomic Design {{PROJECT_NAME}}hierarchy Version:(Brad {{VERSION}}Frost). Date:All {{DATE}}components Author: {{AUTHOR}} Status: Draft | In Review | Approved Reviewers: {{REVIEWERS}}

Document History

VersionDateAuthorChanges
0.1{{DATE}}{{AUTHOR}}Initial draft

1. Overview

Total components: {{N}} Library location: src/components/ Storybook: {{https://storybook.PROJECT_NAME.example.com}} Design source: {{Figma file URL}} Owner team: {{TEAM_NAME}}

This inventory tracks every reusable componentlive in {{PROJECT_NAME}}apps/web/. ItVerified followsagainst Atomicfilesystem Designas categorization:of atoms → molecules → organisms → templates → pages.2026-05-16.


2. Component Hierarchy DiagramAtoms

The

smallest indivisible UI units. Wrap a single HTML element or a Radix UI primitive. All shadcn/ui atoms use graphcva TBfor subgraphvariant Pagescomposition PageLogin["LoginPage"]and PageDashboard["DashboardPage"]cn() endfor subgraphclass Templates
        TplAuth["AuthLayout"]
        TplApp["AppLayout"]
    end
    subgraph Organisms
        OrgNavbar["Navbar"]
        OrgSidebar["Sidebar"]
        OrgDataTable["DataTable"]
        OrgUserForm["UserForm"]
    end
    subgraph Molecules
        MolFormField["FormField"]
        MolCard["Card"]
        MolSearchBar["SearchBar"]
        MolDropdown["Dropdown"]
        MolPagination["Pagination"]
    end
    subgraph Atoms
        AtomButton["Button"]
        AtomInput["Input"]
        AtomBadge["Badge"]
        AtomSpinner["Spinner"]
        AtomAvatar["Avatar"]
        AtomIcon["Icon"]
    end

    Pages --> Templates
    Templates --> Organisms
    Organisms --> Molecules
    Molecules --> Atoms

TODO: Update diagram to reflect actual component tree.merging.


3.

shadcn/ui Atoms (Primitivein Components)

3.1 Buttoncomponents/ui/)

Radix
PropertyComponent Value
CategoryAtom
Status`{{Done
File pathsrc/components/ui/Button/Button.tsx
Storybook{{URL}}
Design ref{{Figma frame URL}}

Props API:

for,aria-describedby Samearia Invoicestatus,withPulseanimationUserinitials
Propprimitive TypeDefaultRequiredDescriptionNotes
variantbutton.tsx 'primary' | 'secondary' | 'ghost' | 'danger' | 'link'@radix-ui/react-slot 6 variants (default, destructive, outline, secondary, ghost, link), 4 sizes. 'primary'asChild No Visualpolymorphic style variantrendering
sizeinput.tsx native 'sm' | 'md' | 'lg'<input> Accepts 'md'aria-invalid No Buttonfor sizeRHF integration
disabledlabel.tsx boolean@radix-ui/react-label Associates with input via falsehtmlForNoDisables interaction
loadingtextarea.tsx native boolean<textarea> false No Showspattern spinner,as disables clickInput
leftIconselect.tsx ReactNode@radix-ui/react-select Keyboard nav + ARIA listbox built-in. Do not use native undefined<select>NoIcon before label
rightIconbadge.tsx native ReactNode<span> undefined No Iconmarket after labellabels
onClickseparator.tsx (e: MouseEvent) => void@radix-ui/react-separator Semantic undefined<hr> No ClickARIA handlerrole
typeskeleton.tsx native 'button' | 'submit' | 'reset'<div> 'button' No HTMLfor buttonloading typestates. Use instead of spinner for content areas
fullWidthavatar.tsx boolean@radix-ui/react-avatar false No 100%fallback widthwhen image unavailable

Variants

Custom & States: primary, secondary, ghost, danger, link × default, hover, focus, active, disabled, loading

Accessibility:

  • Renders as <button> — never <div> or <span>
  • loading state: aria-busy="true", spinner has aria-label="Loading"
  • disabled: aria-disabled="true", not removed from tab order
  • Focus ring: 2px offset, brand color

Dependencies: Icon component, Spinner component


3.2 InputAtoms

trialcountdown
PropertyComponent ValueFileNotes
CategoryLocaleSwitcher Atomcomponents/locale-switcher.tsxsr-Latn / hr / bs toggle. aria-label required
StatusTrialBanner {{Status}}
File pathsrc/components/ui/Input/Input.TrialBanner.tsx
Subscription
Storybook {{URL}}notice

Molecules

PropsAtoms API:composed into a functional unit. May contain local useState. No external data fetching.

shadcn/ui Molecules

FocustrapKeyboardARIAARIArole="tabpanel".Slide-insideforCardHeader,CardContent, forscreen
PropComponent TypeRadix primitive DefaultRequiredDescriptionNotes
typedialog.tsx 'text' | 'email' | 'password' | 'number' | 'search' | 'tel' | 'url'@radix-ui/react-dialog 'text' No Inputon typeopen, ESC dismiss, scroll lock. Use for all modal flows
valuedropdown-menu.tsx string@radix-ui/react-dropdown-menu Yesnav, (controlled) Inputrole="menu". valueUse for action menus, not navigation
onChangetabs.tsx (e: ChangeEvent) => void@radix-ui/react-tabs Yes ChangeUse handlerfor report views, settings sections
placeholdersheet.tsx string@radix-ui/react-dialog '' No Placeholderpanel. textBuilt on Dialog primitive
disabledtoast.tsx booleancustom falserole="status" No Disabledinformational statetoasts, role="alert" for errors
errorcard.tsx booleannative false No TriggersCardTitle errorsub-components. visualStandard statecontainer
errorMessagetable.tsx native string<table> Always include undefined<caption> NoError text (also setsor aria-describedbylabel)
leftAdornmentReactNodeundefinedNoIcon or element left of input
rightAdornmentReactNodeundefinedNoIcon or element right of input
size'sm' | 'md' | 'lg''md'NoInput height/font sizereaders

Variants

Custom & States: default, focused, error, disabled, with-left-icon, with-right-icon

Accessibility:

  • Must always be paired with <label> (use FormField molecule)
  • Error: aria-invalid="true" + aria-describedby pointing to error message id
  • Password: toggle visibility button must have aria-label

3.3 BadgeMolecules

PropertyComponent ValueFileNotes
CategoryTwoFactorDialog Atomcomponents/settings/TwoFactorDialog.tsx2FA TOTP setup and verification flow
StatusBetaInterestDialog {{Status}}components/beta-interest-dialog.tsxWaitlist capture dialog
File pathCreditNoteModal src/components/ui/Badge/Badge.CreditNoteModal.tsxCredit note creation (uses Dialog)
UpsellModalcomponents/UpsellModal.tsxPlan upgrade prompt
ComplianceWidgetcomponents/ComplianceWidget.tsxPer-market compliance status badge
ChatMessagecomponents/chatbot/ChatMessage.tsxAI chatbot message bubble
ChatInputcomponents/chatbot/ChatInput.tsxAI chatbot text input with send

Organisms

PropsComplex API:UI sections with their own data dependencies. May call Zustand stores or receive server-fetched data as props.

Darkplum Useravatar, FloatingAI Taxestimate
PropComponent TypeFile DefaultData source RequiredDescriptionNotes
Sidebarvariantcomponents/sidebar.tsx 'success' | 'warning' | 'error' | 'info' | 'neutral'useAuthStore 'neutral' No Semanticnavigation, coloractive variantroute highlighting, RBAC-aware nav items
TopBarsizecomponents/top-bar.tsx 'sm' | 'md'useAuthStore 'md' No Badgelocale sizeswitcher, notification bell
ChatWidgetdotcomponents/chatbot/ChatWidget.tsx booleanAnthropic SDK false No Showsaccounting colored dot instead of textassistant
PausalTeaserCalculatorchildrencomponents/pausal/PausalTeaserCalculator.tsx ReactNodelocal state Yes Badgecalculator contentfor pausal businessmen

TODO:

Landing AddPage remaining atom components following the same patternOrganisms (Select, Checkbox, Radio, Toggle, Textarea, Avatar, Tooltip, Spinner, Divider).


4. Molecules (Composite Components)

4.1 FormFieldcomponents/landing/)

PropertyComponent ValueFile
CategoryMolecule
StatusNavbar {{Status}}
File pathsrc/components/ui/FormField/FormField.landing/navbar.tsx
ComposesInput, Label, ErrorMessage, HelpText

Props API:

PropTypeDefaultRequiredDescription
labelHero stringYesVisible label text
htmlForstringYesLinks label to input id
errorstringundefinedNoError message text
helpTextstringundefinedNoHelper text below input
requiredbooleanfalseNoShows required indicator
childrenReactNodeYesInput component

Accessibility: Label always associated with input via htmlFor/id pair.


4.2 Card

PropertyValue
CategoryMolecule
Status{{Status}}
File pathsrc/components/ui/Card/Card.tsx

Props API:

PropTypeDefaultRequiredDescription
variant'default' | 'bordered' | 'elevated''default'NoVisual style
padding'sm' | 'md' | 'lg' | 'none''md'NoInternal padding
asElementType'div'NoPolymorphic render element
childrenReactNodeYesCard content

Sub-components: Card.Header, Card.Body, Card.Footer

TODO: Add remaining molecule components: Modal, Dropdown, Table, Pagination, Toast, SearchBar, Breadcrumb, Tabs, Accordion, DatePicker.


5. Organisms (Complex Components)

5.1 DataTable

PropertyValue
CategoryOrganism
Status{{Status}}
File pathsrc/components/features/DataTable/DataTable.landing/hero.tsx
DependenciesTable (molecule), Pagination, SearchBar, Spinner, Badge

Features:

  • Sortable columns (client + server-side)
  • Pagination (configurable page sizes)
  • Row selection (single + multi)
  • Column visibility toggle
  • Export action slot
  • Loading skeleton state
  • Empty state slot
  • Row action slot (per-row dropdown)

TODO: Document full props API for DataTable.


5.2 Navigation / Sidebar

PropertyValue
CategoryOrganism
StatusFeatures {{Status}}components/landing/features.tsx
File pathTestimonials src/components/layouts/Sidebar/Sidebar.landing/testimonials.tsx

TODO: Add remaining organism components.


6. Shared Hooks / Composables Inventory

HookFilePurposeUsed By
useDebouncesrc/hooks/useDebounce.tsDebounce value changesSearchBar, Input
useLocalStoragePricing src/hooks/useLocalStorage.tscomponents/landing/pricing.tsxPersistent local stateTheme, preferences
useMediaQueryFooter src/hooks/useMediaQuery.tsResponsive breakpoint checksLayout components
useClickOutsidesrc/hooks/useClickOutside.tsClose on outside clickDropdown, Modal
useFocusTrapsrc/hooks/useFocusTrap.tsTrap focus inside elementModal, Drawer
useToastsrc/hooks/useToast.tsTrigger toast notificationsGlobal
usePermissionsrc/hooks/usePermission.tsCheck user permissionsAuth-gated components
{{HOOK_NAME}}{{PATH}}{{PURPOSE}}{{CONSUMERS}}components/landing/footer.tsx

7. Third-Party Component UsageTemplates

Route layouts that define the page skeleton. No data logic — only layout composition.

SidebarTopBar Simplelayout, ,font
PackageTemplate VersionFile Components UsedWrapping StrategyNotes
Dashboard Layout{{@radix-ui/react-dialog}}app/(dashboard)/layout.tsx {{1.x}} Modal+ base Wrapped in+ src/components/ui/Modal<main — custom styling
{{@radix-ui/react-select}}{{2.x}}Select baseWrapped in src/components/ui/Selectid="main-content">
Legal Layout{{react-hook-form}}app/(legal)/layout.tsx {{7.x}} Formcentered state Usedno directly + FormField wrappersidebar
Root Layout{{recharts}}app/layout.tsx {{2.x}}<html lang> Charts Wrappedloading, inglobal src/components/charts/providers (QueryProvider, AuthProvider)

Policy:


Never

Composition usePatterns

third-party

Pattern components directly in feature code1alwaysIcon-only wrapButton

in

Every localicon-only componentbutton toMUST controlhave APIaria-label. surfaceThe andicon allowitself futuremust swap.be aria-hidden.


8. Component Deprecation Process

Active<Button variant="ghost" Deprecatedsize="icon" (soft)aria-label="Ukloni stavku">
  Deprecated<X (hard)className="h-4 w-4" Removedaria-hidden="true" />
</Button>

Pattern

2RSCClientBoundarySplit

Keep

data theClientchild.

sharedpackage?Recommendedtrigger:component(currentlyduplicating
Stage Action+ Required
Deprecated (soft)Add @deprecated JSDoc comment, console warningfetching in dev,the migrationRSC guideparent; interactive behavior in Storybook
Deprecated
// RSC parent — no "use client"
export default async function InvoiceDetailPage({ params }: { params: { id: string } }) {
  const invoice = await fetchInvoice(params.id)
  return <InvoiceDetailClient invoice={invoice} />
}

// Client child
;('use client')
export function InvoiceDetailClient({ invoice }: { invoice: Invoice }) {
  const [status, setStatus] = useState(invoice.status)
  // interactive status changes, optimistic updates
}

Pattern 3 — Loading Skeleton via Suspense

export default function InvoicesPage() {
  return (hard)
TypeScript<Suspense fallback={<TableSkeleton rows={10} />}> <InvoiceTableServer /> </Suspense> ) }

Pattern 4 — @deprecatedcva annotationCustom triggersVariant

IDE
import warning,{ addedcva } from 'class-variance-authority'

const statusBadge = cva('inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium', {
  variants: {
    status: {
      paid: 'bg-green-100 text-green-800',
      pending: 'bg-yellow-100 text-yellow-800',
      overdue: 'bg-red-100 text-red-800',
      draft: 'bg-gray-100 text-gray-600',
    },
  },
})

export function InvoiceStatusBadge({ status }: { status: InvoiceStatus }) {
  return <span className={statusBadge({ status })}>{statusLabel[status]}</span>
}

OPEN QUESTION OQ-4: packages/ui/ is an empty scaffold. When should components graduate from apps/web/components/ to removalthe milestone

Removed Deletewhen component,apps/landing-hr updateor CHANGELOG,apps/landing-ba runneeds codemodthe ifsame available
landing

Deprecation notice minimum period: 2 sprint cycles before hard removal.organisms).


Approval

RoleNameDateSignature
Author
Frontend Lead
Design System Owner