compoui
v2.0.1
Published
A modern, customizable React component library featuring seamless Tailwind CSS integration, interactive UI elements, and optimized for developer productivity.
Readme
Compoui
Compoui is a React UI components library built with Tailwind CSS. It provides reusable and customizable components for authentication forms, buttons, and sidebars.
📦 Installation
Install the package using npm:
npm install compoui🎨 Tailwind CSS Setup
If you are using Tailwind CSS, add the following to your tailwind.config.js file:
module.exports = {
content: ["./node_modules/compoui/dist/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};❌ Non-Tailwind Users
If you are not using Tailwind CSS, import the default styles into your project:
import "<path-to-your-node_modules>/compoui/dist/style.css";🚀 Usage
🔐 AuthForm Component
import React from "react";
import { AuthForm } from "compoui";
import { User, Phone } from "lucide-react"; // Example icons
const MyAuthForm = () => {
const handleSubmit = (data: Record<string, string>) => {
console.log("Form submitted:", data);
};
return (
<AuthForm
onSubmit={handleSubmit}
title="Sign In"
buttonText="Login"
customFields={[
{
name: "username",
type: "text",
placeholder: "Enter your username",
icon: <User />,
isRequired: true,
},
{
name: "phone",
type: "tel",
placeholder: "Enter your phone number",
icon: <Phone />,
isRequired: false,
},
]}
/>
);
};
export default MyAuthForm;Props Table
| Prop Name | Type | Description | Required? |
| --------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------ | --------- |
| onSubmit | (data: Record<string, string>) => void | Function to handle form submission | ❌ No |
| loading | boolean | Displays a loading state | ❌ No |
| error | string | Displays an error message | ❌ No |
| title | string | Sets the form title | ❌ No |
| emailPlaceholder | string | Placeholder for email input | ❌ No |
| passwordPlaceholder | string | Placeholder for password input | ❌ No |
| buttonText | string | Text for submit button | ❌ No |
| loadingText | string | Text when button is in loading state | ❌ No |
| customFields | Array<{name: string, type: string, placeholder: string, icon?: JSX.Element, isRequired?: boolean}> | Array of custom input fields | ❌ No |
| formStyle | string | Custom class for form styling | ❌ No |
| buttonStyle | string | Custom class for button styling | ❌ No |
| iconColor | string | Color for icons in custom fields | ❌ No |
🔘 Button Component
import React from "react";
import Button from "./Button";
import { ArrowRight, User } from "lucide-react";
export default function App() {
return (
<div className="p-6 space-y-4">
<Button color="purple" size="md" leftIcon={User}>
Profile
</Button>
<Button color="green" size="lg" rightIcon={ArrowRight}>
Continue
</Button>
</div>
);
}Props Table
| Prop Name | Type | Description | Required? |
| ----------- | --------------------------------------------------------- | ---------------------------------- | --------- |
| size | "sm" | "md" | "lg" | Sets button size | ❌ No |
| color | "blue" | "red" | "green" | "black" | "etc" | Button color | ❌ No |
| onClick | () => void | Function called on click | ❌ No |
| leftIcon | LucideIcon | Icon component to display on left | ❌ No |
| rightIcon | LucideIcon | Icon component to display on right | ❌ No |
📂 Sidebar Component
import { SideBar } from "compoui";
import { Home, Table, Gift, User } from "lucide-react"; // Icons
const MySidebar = () => {
return (
<SideBar
sections={[
{
title: "Home",
path: "/", // Navigates to Home
icon: <Home />,
},
{
title: "Profile",
onClick: () => alert("Profile clicked!"), // Only executes function
icon: <User />,
},
{
title: "Dashboard",
path: "/dashboard",
onClick: () => console.log("Navigating to dashboard..."), // Both navigate & run function
icon: <Table />,
},
{
title: "Gifts",
icon: <Gift />, // No action, just display the title and the icon
},
]}
/>
);
};
export default MySidebar;Props Table
| Prop Name | Type | Description | Required? |
| ------------------- | --------------------------------------------------------------------------------- | ---------------------------- | --------- |
| sections | Array<{title: string, path?: string, icon?: JSX.Element, onClick?: () => void}> | List of sidebar sections | ✅ Yes |
| sideStyle | string | Custom sidebar styling | ❌ No |
| toggleButtonStyle | string | Custom toggle button styling | ❌ No |
| navStyle | string | Custom nav styling | ❌ No |
📌 Layout Component
import React from "react";
import { Layout } from "compoui";
import { Home, Search, User, Bell } from "lucide-react";
const MyLayout = () => {
return (
<Layout
title="Dashboard"
layoutColor="blue"
isSearchVisible={true}
searchTitle="Search..."
onSearchChange={(query) => console.log("Search query:", query)}
sections={[
{ title: "Home", path: "/", icon: <Home /> },
{ title: "Profile", path: "/profile", icon: <User /> },
]}
icons={[
{
title: "Notification",
icon: <Bell />,
onClick: () => alert("Notification!"),
},
]}
>
<div className="bg-white rounded-lg shadow-sm p-6 transition-all duration-300 hover:shadow-md">
<h1 className="text-2xl font-bold mb-4 text-gray-800">
Welcome to Dashboard
</h1>
<p className="text-gray-600">
This is your main content area. The sidebar can be toggled on any
screen size.
</p>
</div>
</Layout>
);
};
export default MyLayout;Props Table
| Prop Name | Type | Description | Required? |
| ----------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | --------- |
| sections | Array<{ title: string, path?: string, icon?: JSX.Element, onClick?: () => void }> | Sidebar sections | ✅ Yes |
| icons | Array<{ title?: string, path?: string, icon?: JSX.Element, onClick?: () => void }> | Action icons | ❌ No |
| isIconsVisible | boolean | Shows/hides action icons | ❌ No |
| isSearchVisible | boolean | Shows search input | ❌ No |
| children | React.ReactNode | Page content | ✅ Yes |
| title | string | Layout title | ❌ No |
| layoutColor | string | Layout background color | ❌ No |
| searchTitle | string | Placeholder for search input | ❌ No |
| onSearchChange | (query: string) => void | Callback function for search input | ❌ No |
🔔 Alert Component
Example
import React from "react";
import Alert from "./Alert";
export default function App() {
return (
<div className="p-6 space-y-4">
<Alert message="Info message" type="info" />
<Alert message="Success! Your action worked." type="success" duration={3000} />
<Alert
message="Something went wrong!"
type="error"
onClose={() => console.log("Alert closed")}
/>
</div>
);
}Props
| Prop | Type | Default | Description |
| ----------- | --------------------------------------------- | -------- | ---------------------------------------- |
| message | React.ReactNode | — | The message to display inside the alert. |
| type | "success" \| "error" \| "warning" \| "info" | "info" | Defines the alert style. |
| duration | number | — | Auto-dismiss time (ms). |
| onClose | () => void | — | Callback when alert is closed. |
| className | string | — | Additional TailwindCSS classes. |
🃏 Card Component
Example
import React from "react";
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "./Card";
import Button from "./Button";
export default function App() {
return (
<Card className="max-w-sm mx-auto">
<CardHeader>
<CardTitle>Product Title</CardTitle>
<CardDescription>Brief description goes here</CardDescription>
</CardHeader>
<CardContent>
<p>This is the card content. You can put anything inside: text, images, or forms.</p>
</CardContent>
<CardFooter>
<Button size="sm" color="gray">Cancel</Button>
<Button size="sm" color="blue">Confirm</Button>
</CardFooter>
</Card>
);
}Props
| Component | Prop | Type | Default | Description |
| ----------------- | ----------- | ----------- | ------- | ------------------------------ |
| Card | children | ReactNode | — | Content inside the card. |
| | className | string | — | Extra TailwindCSS classes. |
| CardHeader | children | ReactNode | — | Header content. |
| CardTitle | children | ReactNode | — | Card title text. |
| CardDescription | children | ReactNode | — | Small description text. |
| CardContent | children | ReactNode | — | Main content body. |
| CardFooter | children | ReactNode | — | Footer actions (e.g. buttons). |
⬇️ Dropdown Component
Example
import React from "react";
import Dropdown from "./Dropdown";
import { User, Settings } from "lucide-react";
export default function App() {
return (
<div className="p-6">
<Dropdown
options={[
{ label: "Profile", value: "profile", icon: <User size={16} /> },
{ label: "Settings", value: "settings", icon: <Settings size={16} /> },
]}
placeholder="Choose an option"
onChange={(val) => console.log("Selected:", val)}
/>
</div>
);
}Props
| Prop | Type | Default | Description |
| -------------- | ------------------------------------------------------ | -------------------- | ----------------------------------------- |
| options | { label: string; value: string; icon?: ReactNode }[] | — | Dropdown items. |
| placeholder | string | "Select an option" | Text shown when nothing selected. |
| searchable | boolean | true | Enable search input inside dropdown. |
| notFoundText | string | "No results found" | Text shown when search yields no results. |
| onChange | (value: string) => void | — | Callback when option is selected. |
| className | string | — | Extra TailwindCSS classes. |
🪟 Modal Component
Example
import React, { useState } from "react";
import Modal from "./Modal";
export default function App() {
const [open, setOpen] = useState(false);
return (
<div className="p-6">
<button
onClick={() => setOpen(true)}
className="px-4 py-2 bg-blue-600 text-white rounded-lg"
>
Open Modal
</button>
<Modal
isOpen={open}
onClose={() => setOpen(false)}
title="Delete Item"
description="Are you sure you want to delete this item?"
cancelText="No"
confirmText="Yes, delete"
confirmColor="red"
onConfirm={() => alert("Deleted!")}
>
<p className="text-gray-700">This action cannot be undone.</p>
</Modal>
</div>
);
}Props
| Prop | Type | Default | Description |
| ----------------- | ----------------------------------------------------------- | ----------- | ------------------------------------------- |
| isOpen | boolean | — | Controls modal visibility. |
| onClose | () => void | — | Called when modal is closed. |
| title | string | — | Optional modal title. |
| description | string | — | Optional description text. |
| children | ReactNode | — | Extra content inside modal body. |
| cancelText | string | "Cancel" | Label for cancel button. |
| cancelColor | Color string ("blue", "red", "green", "gray", etc.) | "gray" | Cancel button color. |
| onCancel | () => void | — | Called when cancel is clicked. |
| confirmText | string | "Confirm" | Label for confirm button. |
| confirmColor | Color string ("blue", "red", "green", "gray", etc.) | "blue" | Confirm button color. |
| onConfirm | () => void | — | Called when confirm is clicked. |
| showCloseButton | boolean | true | Show/hide "X" close button. |
| closeOnBackdrop | boolean | true | Allow closing modal when clicking backdrop. |
📊 ProgressBar Component
Example
import React from "react";
import ProgressBar from "./ProgressBar";
export default function App() {
return (
<div className="space-y-4 p-6">
<ProgressBar value={40} label="Loading..." showLabel />
<ProgressBar value={75} color="success" size="lg" />
<ProgressBar value={20} max={200} color="error" />
</div>
);
}Props
| Prop | Type | Default | Description |
| ----------- | ---------------------------------------------------------------------------------------- | ----------- | ------------------------------------------- |
| value | number | — | Current progress value. |
| max | number | 100 | Maximum progress value. |
| size | "xs" \| "sm" \| "md" \| "lg" \| "xl" | "md" | Height of the progress bar. |
| color | "blue" \| "green" \| "red" | "blue" | Color variant. |
| showLabel | boolean | false | Show percentage text. |
| label | string | — | Custom label (replaces default percentage). |
| className | string | — | Extra TailwindCSS classes. |
🔄 Spinner
Example
import Spinner from "./Spinner";
<Spinner size="lg" color="blue" />;Props
| Prop | Type | Default | Description |
| ----------- | -------------------------------------- | ---------------- | ------------------------------- |
| size | "xs" \| "sm" \| "md" \| "lg" \| "xl" | "md" | Controls spinner size. |
| color | string | "currentColor" | CSS color value for spinner. |
| className | string | "" | Extra Tailwind/utility classes. |
🗂 Tabs
Example
import Tabs from "./Tabs";
const tabs = [
{ label: "Home", value: "home", content: <div>Welcome!</div> },
{ label: "Profile", value: "profile", content: <div>Your profile</div> },
];
<Tabs tabs={tabs} defaultValue="home" />;Props
| Prop | Type | Default | Description |
| -------------- | -------- | --------------- | ------------------------------------- |
| tabs | Tab[] | required | Array of { label, value, content }. |
| defaultValue | string | tabs[0].value | Initial active tab. |
| className | string | "" | Extra Tailwind/utility classes. |
💬 Tooltip
Example
import Tooltip from "./Tooltip";
<Tooltip content="This is a tooltip" position="top">
<button className="px-4 py-2 bg-blue-600 text-white rounded">
Hover me
</button>
</Tooltip>;Props
| Prop | Type | Default | Description |
| ----------- | ---------------------------------------- | ------------ | ----------------------------------- |
| children | ReactNode | required | Element to wrap. |
| content | ReactNode | required | Tooltip text/content. |
| position | "top" \| "bottom" \| "left" \| "right" | "top" | Tooltip placement. |
| delay | number | 200 | Delay in ms before showing tooltip. |
| className | string | "" | Extra Tailwind/utility classes. |
Perfect 👍 Since you want more detailed documentation for the Table component, we can expand the README.md with full details of TableProps, TableColumn, TableAction, TableTranslations, and TableColors.
Here’s the improved README.md section for Table:
📊 Table
A powerful, feature-rich data table with: ✅ Sorting • ✅ Searching • ✅ Pagination • ✅ Row Actions • ✅ i18n Translations • ✅ Loading state
🔹 Usage Example
import Table from "./Table";
import { Edit, Trash } from "lucide-react";
type User = { id: number; name: string; email: string };
const users: User[] = [
{ id: 1, name: "Alice", email: "[email protected]" },
{ id: 2, name: "Bob", email: "[email protected]" },
];
const columns = [
{ key: "name", label: "Name", sortable: true },
{ key: "email", label: "Email" },
];
const actions = [
{
label: "Edit",
icon: <Edit size={16} />,
onClick: (row: User) => console.log("Edit", row),
},
{
label: "Delete",
icon: <Trash size={16} />,
onClick: (row: User) => console.log("Delete", row),
color: "red",
},
];
<Table
title="Users"
data={users}
columns={columns}
actions={actions}
pageSize={5}
onCreate={() => console.log("Create new user")}
onRefresh={() => console.log("Refresh data")}
onExport={() => console.log("Export")}
onImport={() => console.log("Import")}
/>;🔹 Table Props
| Prop | Type | Default | Description |
| ----------------------- | ---------------------------- | ----------------- | -------------------------------------- |
| data | T[] | required | Array of rows to display. |
| columns | TableColumn<T>[] | required | Column definitions (see below). |
| actions | TableAction<T>[] | [] | Action buttons per row. |
| pageSize | number | 5 | Rows per page. |
| onRowClick | (row: T) => void | undefined | Called when a row is clicked. |
| className | string | "" | Extra Tailwind/utility classes. |
| title | string | "Data Table" | Table title in the header. |
| loading | boolean | false | Show loading spinner overlay. |
| head | boolean | true | Show header (title, search, controls). |
| onImport | () => void | undefined | Callback for import button. |
| onExport | () => void | undefined | Callback for export button. |
| onRefresh | () => void | undefined | Callback for refresh button. |
| onCreate | () => void | undefined | Callback for create button. |
| createButtonColor | keyof TableColors | "blue" | Color for create button. |
| importButtonColor | keyof TableColors | "red" | Color for import button. |
| exportButtonColor | keyof TableColors | "orange" | Color for export button. |
| refreshButtonColor | keyof TableColors | "black" | Color for refresh button. |
| paginationButtonColor | keyof TableColors | "white" | Color for active pagination button. |
| translations | Partial<TableTranslations> | defaults provided | Override built-in i18n translations. |
🔹 TableColumn
export interface TableColumn<T> {
key: keyof T; // Data key
label: string; // Column header label
sortable?: boolean; // Enables sorting
width?: string; // Optional column width
}Example:
const columns = [
{ key: "name", label: "Name", sortable: true },
{ key: "email", label: "Email" },
];🔹 TableAction
export interface TableAction<T> {
label: string; // Action button text
icon: React.ReactNode; // Icon to display
onClick: (row: T) => void; // Callback when clicked
color?: keyof TableColors; // Optional color
}Example:
const actions = [
{
label: "Edit",
icon: <Edit size={16} />,
onClick: (row) => console.log("Edit", row),
},
{
label: "Delete",
icon: <Trash size={16} />,
onClick: (row) => console.log("Delete", row),
color: "red",
},
];🔹 TableTranslations
Supports full i18n customization:
export interface TableTranslations {
title: string;
create: string;
import: string;
export: string;
refresh: string;
rowsPerPage: string;
total: string;
first: string;
last: string;
searchPlaceholder: string;
loading: string;
noResults: string;
showing: (start: number, end: number, total: number) => string;
}Default:
const defaultTranslations = {
title: "Data Table",
create: "Create",
import: "Import",
export: "Export",
refresh: "Refresh",
rowsPerPage: "Rows per page:",
total: "total entries",
first: "First",
last: "Last",
searchPlaceholder: "Search across all columns...",
loading: "Loading...",
noResults: "No results found",
showing: (start, end, total) =>
`Showing ${start} to ${end} of ${total} results`,
};| All animations are full-screen, responsive, and optimized for performance.
Available Colors
blue, red, green, yellow, gray, indigo, purple, pink, orange, teal, cyan, lime, emerald, fuchsia, rose, slate, zinc, neutral, stone, black, white
🎨 Customization
Some components allows style customization through props. You can override default styles using:
- Custom Tailwind classes
- Bootstrap classes
- Your own CSS styles
Example with Bootstrap:
<AuthForm formStyle="form-control" buttonStyle="btn btn-primary" />Example with CSS:
<AuthForm formStyle="my-custom-form" buttonStyle="my-custom-button" />💡 Features
✅ Fully customizable
✅ Reusable components
✅ Supports custom form fields
✅ Lightweight & easy to use
License
This project is licensed under the MIT License. See the LICENSE file for details.
