@djangocfg/ui-core
v2.1.361
Published
Pure React UI component library without Next.js dependencies - for Electron, Vite, CRA apps
Maintainers
Readme

@djangocfg/ui-core
Framework-agnostic React UI library: 70+ components on Radix + Tailwind v4, plus a router-adapter system that lets the same <Link> / <Sidebar> / <SSRPagination> work under Next.js, Vite, Electron, Wails, or plain React.
Install
pnpm add @djangocfg/ui-coreImports
import { Button, Card, Sidebar, SSRPagination } from '@djangocfg/ui-core/components';
import { useIsMobile, useNavigate, useQueryParams } from '@djangocfg/ui-core/hooks';
import { cn } from '@djangocfg/ui-core/lib';Components
Organized in components/ by category — everything re-exported from the root barrel.
| Category | Examples |
|---|---|
| Forms | Button, ButtonLink, ButtonGroup, Input, Textarea, Checkbox, RadioGroup, Switch, Slider, Label, Form, Field, InputOTP, PhoneInput, InputGroup, DownloadButton |
| Select | Select, Combobox, ComboboxAsync, MultiSelect, MultiSelectPro, MultiSelectProAsync, CountrySelect, LanguageSelect (all support icons + badges; Select accepts empty-string values; ComboboxAsync is the single-select counterpart to MultiSelectProAsync for server-side typeahead) |
| Overlay | Dialog, AlertDialog, Sheet, Drawer, Popover, Tooltip, HoverCard, ResponsiveSheet, SidePanel |
| Navigation | Link, Breadcrumb, BreadcrumbNavigation, Pagination, StaticPagination, SSRPagination, Sidebar (full shadcn primitives), Tabs, Accordion, Collapsible, Command, DropdownMenu, ContextMenu, Menubar, NavigationMenu |
| Layout | Card, Section, Sticky, ScrollArea, Resizable, Separator, Skeleton, AspectRatio |
| Data | Table, Badge, Avatar, Progress, Carousel, Calendar, DatePicker, DateRangePicker, Toggle, ToggleGroup, Chart* |
| Feedback | Alert, Spinner, Empty, Preloader, Toaster (Sonner) |
| Specialized | Kbd, CopyButton, CopyField, TokenIcon, Item, Portal, ImageWithFallback, Flag, LanguageFlag |
| Effects | GlowBackground |
Pagination, breadcrumb and sidebar live here (not in ui-nextjs).
SSRPaginationreads URL state throughuseLocation+useQueryParams, so it works under any router adapter.
Hooks
import { useIsMobile, useMediaQuery, useShortcutModLabel } from '@djangocfg/ui-core/hooks';
import { useNavigate, useLocation, useQueryParams, useRouter, useIsActive } from '@djangocfg/ui-core/hooks/router';| Group | Hooks |
|---|---|
| Router (adapter-driven) | useNavigate, useLocation, useQueryParams, useQueryState (typed), useRouter, useUrlBuilder, useSmartLink, useIsActive, useBackOrFallback + parsers (parseAsInteger, parseAsBoolean, …) |
| Media | useIsMobile, useIsPhone, useIsTabletOrBelow, useMediaQuery |
| Device | useDeviceDetect, useBrowserDetect, useShortcutModLabel |
| State | useDebounce, useDebouncedCallback, useCountdown, useImageLoader, useMounted |
| DOM | useEventListener |
| Theme | useThemeColor, useThemePalette (palette-aware hex colors for Canvas/SVG) |
| Hotkey | useHotkey, HotkeysProvider, useHotkeysContext |
| Feedback | useToast, toast (Sonner) |
| Debug | useDebugTools |
Router adapters
<Link>, <Sidebar>, <SSRPagination> and friends are wired through a small adapter system, so the same component renders correctly under any router.
// Next.js host (e.g. apps/demo)
import { LinkProvider } from '@djangocfg/ui-core/components';
import NextLink from 'next/link';
<LinkProvider value={NextLink}>{children}</LinkProvider>When no adapter is mounted, <Link> falls back to a plain <a> and routes clicks through the History API. @djangocfg/layouts/BaseApp mounts the Next adapters by default.
Schema-driven configurators
@djangocfg/ui-core/lib exports a portable JSON Schema 7 subset (CustomJsonSchema7, CustomJsonUiSchema7, CustomJsonUiGroup, CustomJsonUiDisabledWhenRule) for packages that ship configurator schemas without taking a runtime dependency on RJSF.
import type { CustomJsonSchema7, CustomJsonUiSchema7 } from '@djangocfg/ui-core/lib';@djangocfg/ui-tools/json-form accepts these directly (it's a union with RJSFSchema).
Dialog service
import { DialogProvider, useDialog, dialog } from '@djangocfg/ui-core/lib/dialog-service';
dialog.confirm({ title: 'Delete?', description: 'This is permanent.' });Logger
import { createLogger } from '@djangocfg/ui-core/lib';
const log = createLogger('MyComponent');
log.info('user logged in', { userId: 123 });Styles
@import '@djangocfg/ui-core/styles/globals.css';Requirements
- React ≥ 19
- Tailwind CSS ≥ 4
