@bpfdev/oly-ui
v1.0.15
Published
Falcon Oly Design System — React component library
Readme
@bpfdev/oly-ui
npm: @bpfdev/oly-ui · private (requires membership of the
@bpfdev/oly-uinpm org)Live docs: falcon-oly-storybook.web.app — interactive component playground with controls, code snippets, and prop tables for every exported component.
A production-ready React component library built on top of MUI, designed for data-heavy dashboards and enterprise UIs. Ships with full TypeScript types, tree-shakeable ESM + CJS bundles, and an optional Tailwind CSS preset.
Installation
npm install @bpfdev/oly-uiPeer dependencies
The following packages must be installed in your project:
npm install react react-dom \
@mui/material @mui/icons-material @mui/x-data-grid @mui/utils \
@emotion/react @emotion/styled \
@iconify/reactQuick start
Wrap your application (or Storybook preview) with FalconThemeProvider to apply the Falcon design tokens:
import { FalconThemeProvider } from '@bpfdev/oly-ui';
function App() {
return (
<FalconThemeProvider
settings={{
mode: 'light',
direction: 'ltr',
appBarBlur: true,
navCollapsed: false,
}}
>
{/* your app */}
</FalconThemeProvider>
);
}Components
For live interactive examples, prop tables, and copy-paste code snippets for every component, visit the Storybook documentation →
FalconButton
A MUI Button wrapper with a built-in loading state.
import { FalconButton } from '@bpfdev/oly-ui';
<FalconButton variant="contained" loading={isSubmitting} onClick={handleSave}>
Save
</FalconButton>;| Prop | Type | Default | Description |
| ----------- | ------------------------------------- | ------------- | --------------------------------------- |
| variant | 'contained' \| 'outlined' \| 'text' | 'contained' | MUI button variant |
| size | 'small' \| 'medium' \| 'large' | 'large' | Button size |
| loading | boolean | false | Shows a spinner and disables the button |
| disabled | boolean | — | Disables the button |
| fullWidth | boolean | true | Stretches to container width |
| type | 'submit' \| 'button' \| 'reset' | 'submit' | HTML button type |
FalconMultiSelect
A controlled multi-select autocomplete with apply/clear actions.
import { FalconMultiSelect } from '@bpfdev/oly-ui';
import type { FalconMultiSelectOption } from '@bpfdev/oly-ui';
const regions: FalconMultiSelectOption[] = [
{ id: 1, name: 'North' },
{ id: 2, name: 'South' },
{ id: 3, name: 'East' },
];
function Example() {
const [selected, setSelected] = React.useState<FalconMultiSelectOption[]>([]);
return (
<FalconMultiSelect
label="Region"
list={regions}
data={selected}
setData={setSelected}
/>
);
}| Prop | Type | Description |
| --------- | -------------------------------------------- | --------------------------------------- |
| label | string | Placeholder / trigger label |
| list | FalconMultiSelectOption[] | All available options |
| data | FalconMultiSelectOption[] | Currently selected options (controlled) |
| setData | (value: FalconMultiSelectOption[]) => void | Called when Apply or Clear is clicked |
FalconSelect
A single-value select built on MUI TextField.
import { FalconSelect } from '@bpfdev/oly-ui';
<FalconSelect
label="Status"
value={status}
onChange={setStatus}
options={['Active', 'Inactive', 'Pending']}
clearable
/>;| Prop | Type | Default | Description |
| ----------- | ---------------------------------- | ------- | --------------------------- |
| label | string | — | Field label |
| value | string | — | Selected value (controlled) |
| onChange | (value: string) => void | — | Change callback |
| options | string[] \| FalconSelectOption[] | — | Options list |
| disabled | boolean | false | Disables the field |
| clearable | boolean | false | Adds a clear button |
FalconPagination
A combined page-number + page-size selector.
import { FalconPagination } from '@bpfdev/oly-ui';
<FalconPagination
pageNo={page}
setPageNo={setPage}
perPage={rowsPerPage}
setPerPage={setRowsPerPage}
totalItems={totalCount}
perPageOptions={[10, 25, 50]}
/>;| Prop | Type | Default | Description |
| ---------------- | --------------------- | -------------- | ----------------------------- |
| pageNo | number | — | Current page (1-based) |
| setPageNo | (n: number) => void | — | Page change callback |
| perPage | number | — | Rows per page |
| setPerPage | (n: number) => void | — | Rows-per-page change callback |
| totalItems | number | — | Total record count |
| perPageOptions | number[] | [10, 25, 50] | Dropdown options |
FalconTable
A thin wrapper around MUI X DataGrid with sensible defaults.
import { FalconTable } from '@bpfdev/oly-ui';
import type { GridColDef } from '@mui/x-data-grid';
const columns: GridColDef[] = [
{ field: 'id', headerName: 'ID', width: 90 },
{ field: 'name', headerName: 'Name', flex: 1 },
];
<FalconTable
rows={data}
columns={columns}
getRowId={row => row.id}
pageSizeOptions={[10, 25]}
initialState={{ pagination: { paginationModel: { pageSize: 10 } } }}
/>;| Prop | Type | Description |
| ----------------- | ------------------------------ | -------------------------- |
| rows | T[] | Row data array |
| columns | GridColDef[] | Column definitions |
| getRowId | (row: T) => string \| number | Row identity function |
| pageSizeOptions | number[] | Page size options |
| initialState | object | MUI DataGrid initial state |
FalconGrayButton
A secondary action button styled with a gray palette.
import { FalconGrayButton } from '@bpfdev/oly-ui';
<FalconGrayButton onClick={handleCancel}>Cancel</FalconGrayButton>;ButtonWithIcon
A button that places an icon alongside a label.
import { ButtonWithIcon } from '@bpfdev/oly-ui';
<ButtonWithIcon icon={<AddIcon />} label="Add Item" onClick={handleAdd} />;FalconSingleSwitch
A labeled toggle switch.
import { FalconSingleSwitch } from '@bpfdev/oly-ui';
<FalconSingleSwitch
label="Enable notifications"
checked={enabled}
onChange={setEnabled}
/>;FalconDIstrictFilter
A district-level filter selector.
import { FalconDIstrictFilter } from '@bpfdev/oly-ui';
import type { FalconDIstrictFilterOption } from '@bpfdev/oly-ui';
const districts: FalconDIstrictFilterOption[] = [
{ id: 1, name: 'Downtown' },
{ id: 2, name: 'Uptown' },
];
<FalconDIstrictFilter list={districts} data={selected} setData={setSelected} />;FalconTicketFilter / FalconTicketColumsFilter
Ticket management filters for status, priority, and column visibility toggles.
import { FalconTicketFilter, FalconTicketColumsFilter } from '@bpfdev/oly-ui';AdvancedFiltersDialog
A modal dialog for composing multi-criteria filter rules.
import { AdvancedFiltersDialog } from '@bpfdev/oly-ui';HeatMapChartLegend
A color-scale legend for heat map charts.
import { HeatMapChartLegend } from '@bpfdev/oly-ui';
import type { HeatMapLegendItem } from '@bpfdev/oly-ui';
const items: HeatMapLegendItem[] = [
{ color: '#f7f7f7', label: 'Low' },
{ color: '#EE8B3A', label: 'High' },
];
<HeatMapChartLegend items={items} />;ProgressBarNumber
A numeric value displayed alongside a progress bar.
import { ProgressBarNumber } from '@bpfdev/oly-ui';
<ProgressBarNumber value={72} max={100} label="Completion" />;AddCommentInput
A text input designed for threaded comment submissions.
import { AddCommentInput } from '@bpfdev/oly-ui';
<AddCommentInput onSubmit={text => postComment(text)} />;WidgetHeaderFilter
A compact trigger + popover filter designed to sit in a widget header row. Supports single and multi-select modes.
import { WidgetHeaderFilter } from '@bpfdev/oly-ui';
const GENDER_OPTIONS = [
{ id: 1, name: 'All' },
{ id: 2, name: 'Male' },
{ id: 3, name: 'Female' },
];
function GenderFilter() {
const [selected, setSelected] = React.useState([GENDER_OPTIONS[0]]);
return (
<WidgetHeaderFilter
label="Select Gender"
list={GENDER_OPTIONS}
data={selected}
setData={setSelected}
triggerMinWidth={140}
/>
);
}TimePeriodFilter
A date-range / time-period selector with preset options (today, week, month, custom range).
import { TimePeriodFilter } from '@bpfdev/oly-ui';
<TimePeriodFilter value={period} onChange={setPeriod} />;ChartWidgetSegmentedTabs
A segmented tab control for switching between chart views within a widget.
import { ChartWidgetSegmentedTabs } from '@bpfdev/oly-ui';
import type { ChartWidgetSegmentedTab } from '@bpfdev/oly-ui';
const tabs: ChartWidgetSegmentedTab[] = [
{ value: 'daily', label: 'Daily' },
{ value: 'weekly', label: 'Weekly' },
{ value: 'monthly', label: 'Monthly' },
];
<ChartWidgetSegmentedTabs
tabs={tabs}
value={activeTab}
onChange={setActiveTab}
/>;ChartWidgetInfoButton
A compact info icon button that opens a popover with a title, description, and help bullets. Designed for widget headers.
import { ChartWidgetInfoButton } from '@bpfdev/oly-ui';
<ChartWidgetInfoButton
density="compact"
popover={{
title: 'Customer Journey Analysis',
description:
'Tracks the progression of customers from walk-ins to billing.',
helpBullets: [
'Walk-in → Billing: % of walk-ins that complete a billing visit.',
'Trial → Billing: % of trial visits that result in billing.',
],
}}
/>;ChartWidgetHeaderSeparator
A thin vertical divider used to separate controls in a widget header row.
import { ChartWidgetHeaderSeparator } from '@bpfdev/oly-ui';
<Stack direction="row" alignItems="center" gap={1}>
<GenderFilter />
<ChartWidgetHeaderSeparator />
<ChartWidgetInfoButton ... />
</Stack>;ChartEmptyState
A centered empty-state illustration and message shown when a chart has no data.
import { ChartEmptyState } from '@bpfdev/oly-ui';
<ChartEmptyState message="No data available for the selected period." />;FalconStatBanner / FalconStatBannerGroup
A stat banner for displaying a labeled metric inline. Group multiple banners with FalconStatBannerGroup.
import { FalconStatBanner, FalconStatBannerGroup } from '@bpfdev/oly-ui';
<FalconStatBannerGroup>
<FalconStatBanner label="Total Walk-ins" value={1430} />
<FalconStatBanner label="Conversion Rate" value="36.9%" />
<FalconStatBanner label="Avg. Dwell Time" value="4m 12s" />
</FalconStatBannerGroup>;FalconAuditTimeline
A timeline widget for visualising audit activity across months.
import { FalconAuditTimeline } from '@bpfdev/oly-ui';
import type { MonthData } from '@bpfdev/oly-ui';
const months: MonthData[] = [
{ month: 'Jan', completed: 12, pending: 3, failed: 1 },
{ month: 'Feb', completed: 18, pending: 2, failed: 0 },
];
<FalconAuditTimeline months={months} />;FalconExportDialog
A dialog for selecting export format and date range before downloading a report.
import { FalconExportDialog } from '@bpfdev/oly-ui';
<FalconExportDialog
open={isOpen}
onClose={() => setIsOpen(false)}
onExport={handleExport}
/>;FalconExportReportDialog
An extended export dialog that includes filter options (e.g. location, gender) alongside format and date selection.
import { FalconExportReportDialog } from '@bpfdev/oly-ui';
import type { FilterOption } from '@bpfdev/oly-ui';
const locationOptions: FilterOption[] = [
{ id: 1, name: 'Mall A' },
{ id: 2, name: 'Mall B' },
];
<FalconExportReportDialog
open={isOpen}
onClose={() => setIsOpen(false)}
onExport={handleExport}
filterOptions={locationOptions}
/>;KpiStatCard
A KPI stat card showing a label, numeric value, optional trend indicator, and an icon. Supports inline (compact) and detailed (icon backdrop) layouts.
import { KpiStatCard } from '@bpfdev/oly-ui';
<KpiStatCard
label="Total Walk-ins"
value={1430}
trend={{ value: 12.5, direction: 'up' }}
icon="tabler:users"
/>;| Prop | Type | Default | Description |
| ----------- | ------------------ | ------- | ------------------------------- |
| label | string | — | Card label text |
| value | number \| string | — | Primary metric value |
| trend | KpiTrend | — | Optional { value, direction } |
| icon | string | — | Iconify icon id |
| isLoading | boolean | false | Shows skeleton when true |
JourneyStatCard
A coloured stat card with an Iconify icon, uppercase label, and large numeric value. Used inside CustomerJourneyAnalysis but works standalone in any layout.
import { JourneyStatCard } from '@bpfdev/oly-ui';
// Standalone (rounded corners)
<JourneyStatCard
icon="tabler:users"
bg="#6DA0EF"
label="Walk-ins"
value={143}
borderRadius={2}
/>
// Flush strip — wrap three cards in a clipped flex container
<Box sx={{ display: 'flex', borderRadius: '12px', overflow: 'hidden' }}>
<JourneyStatCard icon="tabler:users" bg="#6DA0EF" label="Walk-ins" value={143} />
<JourneyStatCard icon="tabler:door-enter" bg="#F5A334" label="Trial Visits" value={357} />
<JourneyStatCard icon="tabler:shopping-bag" bg="#5EC45E" label="Billing Visits" value={89} />
</Box>| Prop | Type | Default | Description |
| --------------- | ------------------ | ----------------------- | -------------------------------------------------------- |
| icon | string | — | Iconify icon id (e.g. tabler:users) |
| bg | string | — | Card background color |
| label | string | — | Uppercase label shown below the icon |
| value | number \| string | — | Numeric value shown prominently |
| iconSize | number | 52 | Icon size (px) |
| iconColor | string | #ffffff | Icon color |
| labelColor | string | rgba(255,255,255,0.9) | Label text color |
| labelFontSize | number | 13 | Label font size (px) |
| valueColor | string | #ffffff | Value text color |
| valueFontSize | number | 40 | Value font size (px) |
| borderRadius | number \| string | 0 | Card border radius. Set 2 for standalone rounded style |
| minHeight | number | 200 | Minimum card height (px) |
| isLoading | boolean | false | Shows skeleton shimmer |
| showOuterCard | boolean | false | Wraps card in a white outer container |
| sx | SxProps | — | Extra MUI sx on the root |
JourneyMetricCard
A metric display card showing a label and a large formatted value. Used in the 2×2 metrics grid inside CustomerJourneyAnalysis.
import { JourneyMetricCard } from '@bpfdev/oly-ui';
<JourneyMetricCard
label="Walk-in → Billing Conversion"
value="36.9%"
valueColor="#1E293B"
labelColor="#6B7280"
/>;| Prop | Type | Default | Description |
| ----------------- | ------------------------------- | ---------- | -------------------------- |
| label | string | — | Descriptor text |
| value | string | — | Formatted metric value |
| labelColor | string | #6B7280 | Label text color |
| labelFontSize | number | 13 | Label font size (px) |
| valueColor | string | #111827 | Value text color |
| valueFontSize | number | 28 | Value font size (px) |
| valueFontWeight | number | 700 | Value font weight |
| textAlign | 'left' \| 'center' \| 'right' | 'center' | Text alignment |
| isLoading | boolean | false | Shows skeleton shimmer |
| sx | SxProps | — | Extra MUI sx on the root |
CustomerJourneyAnalysis
A full-width customer journey funnel widget. Shows walk-in, trial visit, and billing visit counts in coloured stat cards alongside a 2×2 conversion metrics grid. Every label, number, color, font, icon, and layout value is customisable via props.
import { CustomerJourneyAnalysis } from '@bpfdev/oly-ui';
<CustomerJourneyAnalysis
walkIns={143}
trialVisits={357}
billingVisits={89}
walkInToBillingConversion={36.9}
trialToBillingConversion={27}
avgTrialsPerWalkIn={3.2}
avgBillingPerTrial={2.4}
headerActions={<GenderFilter />}
/>;Required props
| Prop | Type | Description |
| --------------------------- | -------- | ------------------------------------- |
| walkIns | number | Walk-in visit count |
| trialVisits | number | Trial visit count |
| billingVisits | number | Billing visit count |
| walkInToBillingConversion | number | Walk-in → billing conversion rate (%) |
| trialToBillingConversion | number | Trial → billing conversion rate (%) |
| avgTrialsPerWalkIn | number | Avg. trial visits per walk-in |
| avgBillingPerTrial | number | Avg. billing visits per trial |
Key optional props
| Prop | Type | Default | Description |
| ------------------------- | ------------------- | ------------------------------ | ------------------------------------------------- |
| title | string | 'Customer Journey Analysis' | Widget heading |
| walkInsLabel | string | 'Walk-ins' | Label on the first stat card |
| trialVisitsLabel | string | 'Trial Visits' | Label on the second stat card |
| billingVisitsLabel | string | 'Billing Visits' | Label on the third stat card |
| walkInsBg | string | #5B8DEF | Walk-ins card background color |
| trialVisitsBg | string | #F59E42 | Trial Visits card background color |
| billingVisitsBg | string | #6EBE7A | Billing Visits card background color |
| walkInsIcon | string | tabler:users | Iconify icon for Walk-ins card |
| trialVisitsIcon | string | mynaui:door-open | Iconify icon for Trial Visits card |
| billingVisitsIcon | string | mingcute:shopping-bag-3-line | Iconify icon for Billing Visits card |
| metricsCardBg | string | #F9FAFB | Background color of each metric card |
| isLoading | boolean | false | Shows skeleton shimmers across all cards |
| headerActions | ReactNode | — | Slot for filters / info button in the header row |
| walkInsCardConfig | JourneyStatConfig | — | Per-card overrides for the Walk-ins stat card |
| trialVisitsCardConfig | JourneyStatConfig | — | Per-card overrides for the Trial Visits stat card |
| billingVisitsCardConfig | JourneyStatConfig | — | Per-card overrides for the Billing Visits card |
| statCardDefaults | JourneyStatConfig | — | Shared defaults applied to all three stat cards |
| cardSx | SxProps | — | Extra sx on the outer card wrapper |
RankedBarList
A horizontal ranked bar chart with optional segmented bars, tooltips, and a configurable legend.
import { RankedBarList } from '@bpfdev/oly-ui';
import type { RankedBarListItem } from '@bpfdev/oly-ui';
const items: RankedBarListItem[] = [
{ label: 'Store A', value: 1200 },
{ label: 'Store B', value: 850 },
{ label: 'Store C', value: 640 },
];
<RankedBarList items={items} />;FootfallByGender
A bar/line chart widget showing footfall broken down by gender over time.
import { FootfallByGender } from '@bpfdev/oly-ui';
import type { FootfallByGenderRow } from '@bpfdev/oly-ui';
const rows: FootfallByGenderRow[] = [
{ label: 'Mon', male: 320, female: 280 },
{ label: 'Tue', male: 410, female: 360 },
];
<FootfallByGender rows={rows} />;FootfallByAgeGroups
A bar/line chart widget showing footfall broken down by age group over time.
import { FootfallByAgeGroups } from '@bpfdev/oly-ui';
import type { FootfallByAgeGroupsRow } from '@bpfdev/oly-ui';
const rows: FootfallByAgeGroupsRow[] = [
{ label: 'Mon', youth: 120, adult: 300, senior: 80 },
{ label: 'Tue', youth: 150, adult: 340, senior: 90 },
];
<FootfallByAgeGroups rows={rows} />;PasserbyConversion
A chart widget comparing passerby count to walk-in conversion over time.
import { PasserbyConversion } from '@bpfdev/oly-ui';
import type { PasserbyConversionRow } from '@bpfdev/oly-ui';
const rows: PasserbyConversionRow[] = [
{ label: 'Mon', passerby: 1200, walkIns: 320 },
{ label: 'Tue', passerby: 1500, walkIns: 410 },
];
<PasserbyConversion rows={rows} />;WalkinAnalysis
A donut/pie chart widget breaking down walk-in visits by category (new vs. repeat, or custom slices).
import { WalkinAnalysis } from '@bpfdev/oly-ui';
import type { WalkinAnalysisSlice } from '@bpfdev/oly-ui';
const slices: WalkinAnalysisSlice[] = [
{ label: 'New', value: 420, color: '#6DA0EF' },
{ label: 'Repeat', value: 280, color: '#F5A334' },
];
<WalkinAnalysis slices={slices} />;WalkinTraffic
A time-series chart widget showing walk-in traffic by hour or day.
import { WalkinTraffic } from '@bpfdev/oly-ui';
import type { WalkinTrafficRow } from '@bpfdev/oly-ui';
const rows: WalkinTrafficRow[] = [
{ label: '09:00', value: 45 },
{ label: '10:00', value: 78 },
{ label: '11:00', value: 112 },
];
<WalkinTraffic rows={rows} />;BillingCounterAnalytics
A widget visualising billing counter activity — queue lengths, service times, and counter utilisation.
import { BillingCounterAnalytics } from '@bpfdev/oly-ui';QueueTimeBreakdown
A widget displaying queue time distribution by area or counter, with area, donut, and stacked-bar chart variants.
import { QueueTimeBreakdown } from '@bpfdev/oly-ui';FootFallHeatMap
A heat-map chart showing footfall intensity by hour and day of week.
import { FootFallHeatMap } from '@bpfdev/oly-ui';PeakBillingHours
A chart widget highlighting the peak billing hours within a selected time window.
import { PeakBillingHours } from '@bpfdev/oly-ui';Tailwind CSS preset
If you use Tailwind, extend your config with the Falcon color tokens:
// tailwind.config.js
module.exports = {
presets: [require('@bpfdev/oly-ui/tailwind.preset')],
// ...
};This exposes Falcon's primary palette as falcon-* utility classes (e.g. bg-falcon-500).
Note: The preset reads from the built
dist/folder — runnpm run buildin the package before using the preset in a fresh clone.
FalconThemeProvider settings
| Prop | Type | Default | Description |
| -------------- | ------------------- | --------- | ---------------------------- |
| mode | 'light' \| 'dark' | 'light' | Color scheme |
| direction | 'ltr' \| 'rtl' | 'ltr' | Text direction |
| appBarBlur | boolean | true | Frosted-glass app bar effect |
| navCollapsed | boolean | false | Collapsed sidebar state |
Development
# build once
npm run build
# watch mode
npm run dev
# run tests
npm run test
# type-check without emitting
npm run typecheckLicense
MIT © @bpfdev/oly-ui
