| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Lines of code | 41399 |
| Technical Name |
odx_owl |
| License | LGPL-3 |
| Website | https://www.odxbuilder.com/ |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Lines of code | 41399 |
| Technical Name |
odx_owl |
| License | LGPL-3 |
| Website | https://www.odxbuilder.com/ |
The missing component library for Odoo.
60+ production-ready OWL 2 components and 1,900+ Lucide icons. Buttons, forms, charts, data tables, dialogs, sidebars, date pickers, and command palettes. Import and use.
Built from Card, LineChart, DonutChart, and DataTable
Backend
Build full application UIs inside Odoo.
Sidebar navigation, split pane layouts, sortable data tables, and rich content display. Compose them into dashboards, admin panels, or any custom view.
Built from Sidebar, DataTable, Card, Tabs, and Badge
Composition
Small components that compose into complex UIs.
Channel lists, threaded messages, reaction badges, scroll areas. Each component has a single job. Combine five or six and you get interfaces like this.
Built from Sidebar, ScrollArea, Avatar, Badge, and Separator
Portal
Same components on the website frontend.
Same API, same props, rendered on portal pages. Self-service dashboards, multi-step onboarding flows, customer-facing tools.
HR Self-Service Dashboard
Customer Onboarding Form
AI Ready
Built for LLMs to use.
Ships with CLAUDE.md and AGENTS.md context files. Point your AI coding assistant at the codebase and it writes correct component code on the first try â right imports, right props, right template syntax.
CLAUDE.md
Full component reference for Claude Code, Cursor, and Windsurf. All 60+ components with import paths, prop signatures, template patterns, and OWL pitfalls.
AGENTS.md
Compact quick reference for Copilot and other AI agents. Import examples, XML template patterns, and CSS token overrides in one file.
Reference
One pattern for every component.
Import it. Add it to static components. Use it in your template. Same steps for all 60+.
import { Button } from "@odx_owl/components/button/button";
import { Card } from "@odx_owl/components/card/card";
import { DataTable } from "@odx_owl/components/data_table/data_table";
import { LineChart } from "@odx_owl/components/chart/chart";
import { Dialog } from "@odx_owl/components/dialog/dialog";
export class MyDashboard extends Component {
static template = "my_module.MyDashboard";
static components = { Button, Card, DataTable, LineChart, Dialog };
}
| Component | Import Path | Key Props |
|---|---|---|
| Button | @odx_owl/components/button/button | variant, size, disabled, onClick |
| Input | @odx_owl/components/input/input | type, value, placeholder, onChange |
| Select | @odx_owl/components/select/select | items, value, onValueChange |
| DataTable | @odx_owl/components/data_table/data_table | columns, data, pageSize, showSearch |
| Card | @odx_owl/components/card/card | slots: header, content, footer |
| Dialog | @odx_owl/components/dialog/dialog | open, onOpenChange, slots: trigger, content |
| Tabs | @odx_owl/components/tabs/tabs | defaultValue, onValueChange |
| LineChart | @odx_owl/components/chart/chart | data, xKey, height, showDots, showGrid |
| Sidebar | @odx_owl/components/sidebar/sidebar | collapsible, side, defaultOpen |
| Badge | @odx_owl/components/badge/badge | variant, text |
| Toast | @odx_owl/components/toast/toast | useToast() hook, title, description |
| Checkbox | @odx_owl/components/checkbox/checkbox | checked, onCheckedChange |
| DatePicker | @odx_owl/components/date_picker/date_picker | value, onSelect |
| Accordion | @odx_owl/components/accordion/accordion | type, collapsible, defaultValue |
| DropdownMenu | @odx_owl/components/dropdown_menu/dropdown_menu | slots: trigger, items |
| Progress | @odx_owl/components/progress/progress | value, max |
| ScrollArea | @odx_owl/components/scroll_area/scroll_area | orientation, className |
| Popover | @odx_owl/components/popover/popover | side, align, slots: trigger, content |
| Command | @odx_owl/components/command/command | items, onSelect, placeholder |
| Form | @odx_owl/components/form/form | onSubmit, validation |
| Icon | @odx_owl/components/icon/icon | name, size, strokeWidth, color (1,900+ Lucide icons) |
Plus 40+ more: Alert, AlertDialog, Avatar, Breadcrumb, Calendar, Carousel, Collapsible, Combobox, ContextMenu, Drawer, Empty, ErrorBoundary, HoverCard, InputOtp, Kbd, Label, Menubar, NativeSelect, NavigationMenu, RadioGroup, Resizable, Separator, Sheet, Skeleton, Slider, Spinner, Switch, Table, Textarea, Toggle, ToggleGroup, Tooltip, and all their sub-components.
Templates
Props in, callbacks out.
Standard OWL patterns. Pass data as props, bind event handlers with .bind, nest content with slots.
Data Table
columns="columns"
data="rows"
showSearch="true"
showPagination="true"
pageSize="10"
/>
Dialog
<t t-set-slot="trigger"><Button>Open</Button></t>
<t t-set-slot="content">
<p>Are you sure?</p>
<Button onClick.bind="confirm">Yes</Button>
</t>
</Dialog>
Chart
<LineChart data="chartData" xKey="'date'" height="200"/>
<ChartTooltip/>
<ChartLegend/>
</ChartContainer>
Icons (1,900+ Lucide)
<Icon name="'arrow-right'"/>
<!-- Custom size and color -->
<Icon name="'check'" size="16" strokeWidth="2.5" color="'green'"/>
<!-- Inside a button -->
<Button variant="'outline'" size="'sm'">
<Icon name="'plus'" size="14"/> Add Item
</Button>
Example
A dashboard in two files.
KPI cards, a line chart, and a data table. Under 40 lines of JavaScript, under 30 lines of XML.
import { Card, CardContent, CardHeader, CardTitle } from "@odx_owl/components/card/card";
import { ChartContainer, LineChart } from "@odx_owl/components/chart/chart";
import { DataTable } from "@odx_owl/components/data_table/data_table";
import { Badge } from "@odx_owl/components/badge/badge";
export class SalesDashboard extends Component {
static template = "my_module.SalesDashboard";
static components = {
Card, CardContent, CardHeader, CardTitle,
ChartContainer, LineChart, DataTable, Badge,
};
setup() {
this.kpis = [
{ title: "Revenue", value: "$48.2K", change: "+12%" },
{ title: "Orders", value: "342", change: "+8%" },
{ title: "Avg. Value", value: "$141", change: "+3%" },
];
this.chartData = [
{ month: "Jan", revenue: 32000 },
{ month: "Feb", revenue: 36000 },
{ month: "Mar", revenue: 48200 },
];
this.columns = [
{ key: "name", label: "Product", sortable: true },
{ key: "sold", label: "Units Sold", sortable: true },
{ key: "revenue", label: "Revenue", sortable: true },
];
this.rows = [
{ name: "Widget Pro", sold: 142, revenue: "$18,460" },
{ name: "Gadget Plus", sold: 98, revenue: "$14,700" },
{ name: "Basic Kit", sold: 102, revenue: "$15,300" },
];
}
}
<div class="p-4">
<!-- KPI Cards -->
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px">
<t t-foreach="kpis" t-as="kpi" t-key="kpi.title">
<Card>
<CardHeader><CardTitle><t t-esc="kpi.title"/></CardTitle></CardHeader>
<CardContent>
<span style="font-size:24px;font-weight:700" t-esc="kpi.value"/>
<Badge variant="'success'" text="kpi.change"/>
</CardContent>
</Card>
</t>
</div>
<!-- Chart -->
<Card style="'margin-top:16px'">
<CardHeader><CardTitle>Revenue</CardTitle></CardHeader>
<CardContent>
<LineChart data="chartData" xKey="'month'" height="200" showGrid="true"/>
</CardContent>
</Card>
<!-- Table -->
<Card style="'margin-top:16px'">
<CardHeader><CardTitle>Top Products</CardTitle></CardHeader>
<CardContent>
<DataTable columns="columns" data="rows" showSearch="true"/>
</CardContent>
</Card>
</div>
</t>
Theming
One file controls every color.
All components read from CSS custom properties. Change the tokens once, every component updates. Add html[data-odx-theme="dark"] for dark mode.
--odx-background: 0 0% 100%;
--odx-foreground: 0 0% 9%;
--odx-primary: 221 83% 53%;
--odx-muted: 210 40% 96%;
--odx-border: 214 32% 91%;
--odx-radius: 0.5rem;
}
ODX UI Kit
60+ OWL 2 components for Odoo 19
Please log in to comment on this module
Great job 👏🏽👏🏽👏🏽
Very useful module and well thought out.
There are no comments yet!