@consus/react-ui
v3.4.42
Published
React component library used across Consus applications. Built with TypeScript, styled-components, Vite and Storybook.
Readme
@consus/react-ui
React component library used across Consus applications. Built with TypeScript, styled-components, Vite and Storybook.
The package ships ESM, UMD and full TypeScript declarations so that components, props, hooks and theme types are available to IDE inspection (VS Code, WebStorm) and AI coding assistants (Claude, Copilot, etc.) out of the box.
Install
npm install @consus/react-uiPeer dependencies
The library does not bundle React or its companion runtime libraries. Install them in the host application:
npm install react react-dom react-router-dom react-toastify react-tooltip styled-components| Peer | Version |
| --- | --- |
| react | ^18.2.0 |
| react-dom | ^18.2.0 |
| react-router-dom | ^5.3.3 |
| react-toastify | ^8.1.0 |
| react-tooltip | ^5.28.1 |
| styled-components | ^5.1.3 |
Setup
1. Import the stylesheet (once, at app entry)
Bundled CSS for react-bootstrap-typeahead, react-toastify and draft-js is shipped as a single file:
import '@consus/react-ui/styles.css';2. Provide a styled-components theme
All components rely on a theme object whose shape is defined by the exported ConsusTheme type. Wrap your app with ThemeProvider:
import { ThemeProvider } from 'styled-components';
import { ConsusGlobalStyles, type ConsusTheme } from '@consus/react-ui';
import { myTheme } from './theme';
export const App = () => (
<ThemeProvider theme={myTheme}>
<ConsusGlobalStyles />
{/* your app */}
</ThemeProvider>
);3. (Optional) Toast notifications
If you use the toast helpers, mount a ToastContainer and pass the shared config:
import { ToastContainer } from 'react-toastify';
import { toastContainerConfig } from '@consus/react-ui';
<ToastContainer {...toastContainerConfig} />Quick example
import { Button, Card, Spacing, Text } from '@consus/react-ui';
export const Demo = () => (
<Card>
<Text size="lg">Hello Consus</Text>
<Spacing size="sm" />
<Button color="primary.normal" onClick={() => alert('clicked')}>
Click me
</Button>
</Card>
);What's inside
Layout & containers
Container, FlexContainer, GridContainer, NormalContainer, Card, CardFooter, Divider (VerticalDivider, HorizontalDivider), Spacing, FormFrame, VideoFrame, ActionsPanel, ButtonsPanel, InteractiveButtonsPanel
Buttons
Button, ButtonWrapper, ButtonTabs, IconButton, EditButton, TrashButton, PlusButton, MinusButton, SubstractButton, ToggleButton, InteractiveButton, InteractiveRemoveButton, HamburgerButton
Inputs & forms
Input, SearchInput, RichInput, Select, Typeahead (+ typeaheadConfig, parseTypeaheadNewItems, allowNew), Checkbox, CheckOptionsSelector, RadioButton, RadioButtonGroup, Switch, DatePicker, RangeDatePicker
Lists & tables
List, ListItems, ListCard, EntityListCard, SelectEntityCard, NewEntityCard, OptionImageCard, SelectableCard, SimpleTable, TableContainer, Table, TableCell, TableCellHeader, TableLoader, SortOrder, BackofficeTable, BackofficeTableHead, BackofficeTableBody, BackofficeTagList
Sidebars & navigation
Sidebar, LeftSidebar, TopSidebar, SidebarProvider, useSidebar, useActiveSidebarButton, Header, useActiveHeaderButton, NavigationPanel, NavigationPanelSkeleton, Stepper (+ useSteps, Step)
Pagination
PaginationBar, ListPaginationBar
Popovers & overlays
Popover, PopoverContent, ConfirmationPopoverButton, PlusPopoverButtonForm, InteractiveRemovePopover, WithTooltip, ModalHeader
Feedback
Loader, LoaderWrapper, ProgressBar, ResultMessage, EmptyMessageCard, NotFound, NotFoundCard, NotFoundPage, ErrorPage, ActiveIndicator, Badge, Tag, TagList
Skeletons
SkeletonLoader, SkeletonButton, SkeletonButtonList, SkeletonCardList, SkeletonLabel, SkeletonPagination, SkeletonCard, SkeletonSquareCard, SkeletonSquare, SkeletonCircleImage, SkeletonText, SkeletonInput, SkeletonInputWithLabel, CardListSkeleton, SkeletonRadioButtonGroup, SkeletonList, plus the skeletonBorderAnimation, skeletonBackgroundLoading, skeletonBackgroundAnimation and borderSkeletonLoading style helpers
Headers / details
DetailsHeader, DetailsHeaderSkeleton, DetailsTitleHeader, DetailsTitleHeaderSkeleton, HeaderTitleCard, InfoCard, Description
Drag & drop
DraggableCard, DroppablePanel
Sliders
OptionsSliderContainer, CheckOptionsSlider, RadioOptionsSlider, OptionSelector
API / page layouts
ApiPageContainer, EntityCardsList, EntityDetails, entityCardsListStyles, entityDetailStyles, skeletonEntityDetailStyles, NewLink, BackofficeFilterPanel, BackofficeContainer, BackofficeFooter
Media
Image, SmartImage, CircleImage, FadeInAnimation, InteractiveCheckIcon
Icons
Icon, icons, fontAwesomeToIcon, plus the IconInterface and IconIndex types
Misc utilities
If, Text, GuardedRoute, Collapse, createToastNotifier
Hooks
useToggle, useLoadingState, useDebounce, useFocus, useOriginalDimensions, useRemoveElementHandler, useLoadingOnRemove, useSelectOption, useSelectOptions, useSingleValueFilter, useQueryParams, useQueryParamValue, useQueryParamArrayValue
Style helpers & theme
ConsusGlobalStyles, globalStyles, mobileMediaQuery, cssHorizontalScroll, cssScrollBar, discreetScrollBar, swiperScrollBar, plus the exported types ConsusTheme, ThemeColorIndex, FontSize, Size, SpacingType, Weight, ConsusRender, ComparatorFn, OptionsSliderRender, Notifier
For a live catalog of every component with controls and source, run Storybook locally (see below).
Theming
The theme follows the shape exported as ConsusTheme and is consumed via styled-components. Colors are addressable through dot-paths matching the ThemeColorIndex type, e.g. primary.normal, gray.darken, error.light, sidebar.text.active. Pass these strings to props such as Button's color.
import type { ConsusTheme } from '@consus/react-ui';
export const myTheme: ConsusTheme = {
colors: { /* ... */ },
font: { size: { /* ... */ }, weight: { /* ... */ } },
spacing: { xxs: 2, xs: 4, sm: 8, md: 12, lg: 16, xlg: 24, x1: 32, x2: 48, x3: 64, x4: 96 },
breakpoints: { mobile: { max: 768 } },
borderRadius: 6,
border: '1px solid #ddd',
boxShadow: '0 2px 6px rgba(0,0,0,.08)',
transitionDuration: '0.2s',
inputs: { borderRadius: 6 },
};Package layout
The package is published as a dual ESM/UMD bundle with one type entry that re-exports every public symbol:
dist/
├── consus-react-ui.es.js # ESM bundle (used by import)
├── consus-react-ui.umd.js # UMD bundle (used by require)
├── index.d.ts # TypeScript entry — re-exports all components/hooks/types
├── style.css # Required stylesheet (typeahead, toast, draft-js)
├── components/**/*.d.ts # Per-component declarations (sourced by IDE go-to-definition)
├── hooks/**/*.d.ts
├── styles/**/*.d.ts
└── utils/**/*.d.tspackage.json#exports declares the modern types/import/require conditions, which is what enables IDE inspection, jump-to-definition and AI assistants to discover the public API.
Development
npm install
npm run dev # Vite dev server (uses index.html as a playground)
npm run storybook # interactive component catalog at http://localhost:6006
npm test # Jest in watch mode
npm run test:coverage
npm run lint
npm run lint:fix
npm run formatAdding a new component
- Create the component under
src/components/<name>/<Component>.tsx. - (Recommended) add a
<Component>.stories.tsxfor Storybook and a<Component>.test.tsxfor Jest. - Re-export it from
src/index.ts. Anything not re-exported here will not be visible to package consumers, IDE autocompletion or AI assistants. - If you add a new public type, export it with
export type { ... }from the same file.
Build
npm run buildThis runs tsc for type-checking and vite build, which:
- emits
dist/consus-react-ui.es.jsand.umd.js, - bundles every imported third-party CSS into
dist/style.css, - emits
.d.tsdeclaration files (and source maps) for every file undersrc/viavite-plugin-dts.
To inspect what would actually be published to npm without uploading anything:
npm pack --dry-runPublishing
A patch release can be cut with the convenience script:
npm run unsafe:publishIt commits the working tree, pushes master, runs npm version patch, builds via the prepublishOnly hook, and publishes with --access public. Use the standard npm version <minor|major> + npm publish when a non-patch bump is needed.
Troubleshooting
IDE doesn't autocomplete imports / shows any
- Make sure your
tsconfig.jsonuses"moduleResolution": "Bundler"(Vite, Next 13+, modern setups) or"NodeNext"so thatpackage.json#exportsis honored. With the legacy"node"resolution, TypeScript falls back to the roottypesfield, which still works but does not benefit from per-condition resolution. - Restart the TS server after upgrading the package (in VS Code: TypeScript: Restart TS Server).
Styles look broken (typeahead, toast, calendar)
You forgot import '@consus/react-ui/styles.css' in your app entry.
ThemeProvider is missing / theme is undefined
Wrap your tree in styled-components' ThemeProvider and pass an object that satisfies ConsusTheme. Components read every value off theme, so a missing theme will throw at render time.
License
Proprietary — internal use within Consus.
