Consumer applications need buttons, cards, and modals. Enterprise applications need data grids with inline editing, pivot tables with drill-down, org charts with drag-and-drop, workflow builders with conditional branching, and audit logs with filtering. These are the components that cost $500-2,000 per year for a commercial React library license. In FLIN, they are built-in.
Session 044 added 40 enterprise components to FlinUI. Not simplified versions. Not "good enough for prototypes" approximations. Full-featured components that a chartered accountant, a legal professional, or a project manager would recognize as production tools.
DataGrid: The Enterprise Workhorse
The DataGrid is the most complex component in FlinUI. It handles everything a business application needs for tabular data:
<DataGrid
data={invoices}
columns={[
{ key: "id", label: "Invoice #", width: 100, frozen: true },
{ key: "client", label: "Client", sortable: true, filterable: true },
{ key: "amount", label: "Amount", format: "currency", align: "right" },
{ key: "status", label: "Status", filterable: true,
render: row => <Badge variant={status_color(row.status)}>{row.status}</Badge> },
{ key: "due_date", label: "Due Date", format: "date", sortable: true },
{ key: "actions", label: "",
render: row => <ActionMenu items={row_actions(row)} /> }
]}
sortable={true}
filterable={true}
searchable={true}
paginated={true}
page_size={50}
selectable={true}
onSelect={handle_selection}
editable={true}
onEdit={handle_edit}
exportable={true}
resizable={true}
/>Features:
- Column freezing. The
frozen: trueprop keeps a column visible while scrolling horizontally. Essential for tables with many columns where the identifier column must always be visible.
- Inline editing. The
editableprop enables click-to-edit on cells. TheonEdithandler receives the row, column, and new value. The DataGrid optimistically updates the UI while the handler persists the change.
- Custom cell rendering. The
renderfunction in column definitions allows any component inside a cell. Badges for status indicators. Action menus for row operations. Progress bars for completion percentages.
- Multi-column sorting. Click a column header to sort. Shift-click to add a secondary sort. The sort indicator shows the current sort columns and directions.
- Column filtering. Each filterable column gets a dropdown with the unique values in that column. Select one or more values to filter the rows. Filters combine with AND logic.
- Full-text search. The search bar searches across all visible columns simultaneously.
- Row selection. Checkboxes for selecting multiple rows. A "select all" checkbox in the header. The selection state is available for bulk operations (delete selected, export selected, etc.).
- Column resizing. Drag column borders to resize. Double-click to auto-fit the column width to its content.
- Data export. The export button generates CSV or JSON from the current (filtered, sorted) data.
Pivot Table
For financial analysis and reporting, the Pivot component transforms flat data into multi-dimensional summaries:
<Pivot
data={sales_data}
rows={["region", "product"]}
columns={["quarter"]}
values={[
{ field: "revenue", aggregate: "sum", format: "currency" },
{ field: "units", aggregate: "sum" }
]}
expandable={true}
show_totals={true}
/>The Pivot component: - Groups data by row fields (region, then product within each region) - Creates columns from the column field values (Q1, Q2, Q3, Q4) - Aggregates values at each intersection (sum of revenue for Region A / Product X / Q1) - Shows subtotals for each group and grand totals at the bottom - Supports drill-down (click a region to expand its products)
This is the component that every accounting firm, financial analyst, and business intelligence dashboard needs. In Excel, it is a Pivot Table. In FLIN, it is a single component with five props.
Organization Chart
<OrgChart
data={org_structure}
root="CEO"
node_render={person =>
<Card>
<Stack direction="horizontal" gap={2} align="center">
<Avatar name={person.name} size="sm" />
<Stack gap={0}>
<Text weight="bold">{person.name}</Text>
<Text size="sm" color="muted">{person.title}</Text>
</Stack>
</Stack>
</Card>
}
show_count={true}
collapsible={true}
/>The OrgChart renders a hierarchical tree with connecting lines. Each node is customizable through the node_render prop. Branches can be collapsed and expanded. The show_count prop displays the number of reports under each node.
Workflow Builder
<Workflow
steps={[
{ id: "submit", label: "Submit Request", type: "start" },
{ id: "review", label: "Manager Review", type: "approval",
assignee: "manager" },
{ id: "condition", label: "Amount Check", type: "condition",
condition: "amount > 10000" },
{ id: "finance", label: "Finance Approval", type: "approval",
assignee: "finance_team" },
{ id: "complete", label: "Completed", type: "end" }
]}
edges={[
{ from: "submit", to: "review" },
{ from: "review", to: "condition", label: "Approved" },
{ from: "review", to: "submit", label: "Rejected" },
{ from: "condition", to: "finance", label: "Yes" },
{ from: "condition", to: "complete", label: "No" },
{ from: "finance", to: "complete", label: "Approved" }
]}
current_step="review"
interactive={false}
/>The Workflow component renders a flowchart with nodes and directed edges. Node types (start, approval, condition, action, end) have distinct visual styles. The current_step prop highlights the active node. When interactive is true, users can click nodes to view details or take actions.
Audit Log
<AuditLog
entries={audit_entries}
columns={["timestamp", "user", "action", "entity", "details"]}
filterable={true}
searchable={true}
group_by="date"
/>The AuditLog component is a specialized list for displaying who did what, when. Entries are grouped by date (today, yesterday, this week, older). Each entry shows a timestamp, user avatar, action description, affected entity, and expandable details.
For compliance-heavy applications (SYSCOHADA accounting, legal document management, medical records), the audit log is not optional -- it is a regulatory requirement. Having it as a built-in component means developers include it from day one instead of adding it as an afterthought.
Activity Feed
<ActivityFeed
items={activities}
show_avatars={true}
show_timestamps={true}
group_by="date"
load_more={load_more_activities}
/>The ActivityFeed is a social-media-style feed of events. User X created a document. User Y approved an invoice. User Z commented on a task. Each item shows an avatar, a description with linked entity names, and a relative timestamp. Infinite scrolling loads more items on demand.
KPI Dashboard
<KPIDashboard
metrics={[
{ label: "Monthly Revenue", value: revenue, target: 50000,
format: "currency", trend: revenue_trend },
{ label: "Active Users", value: active_users, target: 1000,
trend: user_trend },
{ label: "Churn Rate", value: churn_rate, target: 5,
format: "percent", inverse: true, trend: churn_trend },
{ label: "NPS Score", value: nps, target: 50,
trend: nps_trend }
]}
period="monthly"
show_targets={true}
show_trends={true}
/>The KPIDashboard component renders a row of metric cards with:
- Current value with formatting (currency, percent, number)
- Target comparison (green if meeting target, red if below)
- Trend sparkline (last 30 data points)
- Period selector (daily, weekly, monthly, quarterly)
- The inverse flag means lower is better (for metrics like churn rate and error rate)
Bulk Actions
<BulkAction
selected={selected_items}
actions={[
{ label: "Export CSV", icon: "download", onClick: export_csv },
{ label: "Delete", icon: "trash", variant: "danger",
confirm: "Delete {selected_items.len} items?" },
{ label: "Change Status", icon: "edit",
submenu: [
{ label: "Active", onClick: set_status("active") },
{ label: "Archived", onClick: set_status("archived") }
]}
]}
/>The BulkAction toolbar appears when items are selected in a DataGrid or list. It shows the count of selected items and available actions. Dangerous actions (delete) require confirmation. Actions with sub-options show a dropdown menu.
Import/Export Wizard
<ImportWizard
entity="User"
fields={["name", "email", "role", "department"]}
required={["name", "email"]}
on_import={handle_import}
accept={[".csv", ".xlsx"]}
max_rows={10000}
show_preview={true}
/>The ImportWizard guides users through importing data from CSV or Excel files:
1. Upload -- drag and drop or file picker 2. Map columns -- match file columns to entity fields 3. Preview -- show the first 10 rows with validation results 4. Import -- process the data with progress indicator 5. Summary -- show success/error counts
This component handles the entire import flow that every enterprise application needs. Without it, developers spend days building file parsers, column mappers, and progress indicators from scratch.
Permission Components
<PermissionEditor
roles={["admin", "manager", "user", "viewer"]}
permissions={[
{ resource: "users", actions: ["create", "read", "update", "delete"] },
{ resource: "invoices", actions: ["create", "read", "update", "delete", "approve"] },
{ resource: "reports", actions: ["read", "export"] }
]}
current={role_permissions}
onChange={update_permissions}
/>The PermissionEditor renders a matrix of roles vs. permissions with checkboxes. It is the standard interface for role-based access control configuration. Toggle a checkbox, and the role gains or loses that permission. The component handles bulk operations (grant all, revoke all) and shows inherited permissions (from parent roles) with distinct visual treatment.
Why Enterprise Components Matter
Consumer-facing applications can afford to be minimal. A landing page needs a hero section, some feature cards, and a call-to-action button. An enterprise application needs data grids, pivot tables, audit logs, permission editors, workflow visualizations, and bulk operation interfaces.
These components are the reason enterprise software licenses cost thousands of dollars per seat. Not because the underlying technology is expensive -- because the UI components took years to develop. AG Grid alone has been in development for over a decade. The commercial license costs $1,500 per developer per year.
FlinUI includes these components at no additional cost. They are part of the standard library. They use the same design tokens, the same zero-import system, and the same reactive rendering as every other FlinUI component. A developer building an accounting application in Abidjan has access to the same UI components as a developer at a Fortune 500 company using $50,000/year enterprise software.
That is the kind of equity in tooling that FLIN exists to create.
The SYSCOHADA Connection
FLIN was born in Abidjan. Deblo Pro, one of ZeroSuite's products, serves chartered accountants and auditors who work with the SYSCOHADA accounting framework used across francophone Africa. For these professionals, enterprise UI components are not a nice-to-have -- they are essential tools.
A chartered accountant reviewing a client's financial statements needs a pivot table that groups transactions by account, sub-account, and period. An auditor tracking compliance needs an audit log that records every change to every document. A legal professional managing case files needs a workflow visualization that shows which approvals are pending.
These use cases drove the design of FlinUI's enterprise components. The Pivot component supports SYSCOHADA account hierarchies. The AuditLog component timestamps conform to WAT (West Africa Time). The Invoice and Receipt components format CFA franc amounts with the correct separators and symbols.
Enterprise components that understand the specific needs of African professionals -- that is not something AG Grid or Ant Design offers. It is something FlinUI provides because FLIN was built by someone who understands the market.
Implementation Complexity
Enterprise components are the most complex in FlinUI. The DataGrid component alone is 400+ lines of FLIN code. The Pivot Table requires a multi-pass aggregation algorithm. The Workflow component requires a graph layout algorithm.
But they follow the same patterns as every other FlinUI component: props for configuration, design tokens for styling, scoped CSS for isolation, and the zero-import system for discovery. A developer who knows how to use can use . The API complexity is in the props, not in the usage pattern.
// Simple usage
<DataGrid data={users} />// Complex usage
The simple case (just pass data) works immediately. The complex case (full configuration) is additive -- each prop enables one feature. The developer does not need to understand all features to use the component. They start simple and add capabilities as needed.
---
This is Part 88 of the "How We Built FLIN" series, documenting how a CEO in Abidjan and an AI CTO built enterprise-grade UI components into a free, open-source UI library.
Series Navigation: - [87] Icons Library Integration - [88] FlinUI Enterprise Components (you are here) - [89] Scoped CSS and Computed Styles - [90] The Component Lifecycle