Entro-Zen Components
React component library for Entrolytics UI
Entro-Zen Components
The @entro314labs/entro-zen package is a React component library providing accessible, themeable UI components for Entrolytics applications.
Installation
pnpm add @entro314labs/entro-zennpm install @entro314labs/entro-zenyarn add @entro314labs/entro-zenbun add @entro314labs/entro-zenQuick Start
import { ZenProvider, Button, TextField } from '@entro314labs/entro-zen'
import '@entro314labs/entro-zen/styles.css'
function App() {
return (
<ZenProvider theme="light">
<TextField label="Email" placeholder="Enter your email" />
<Button variant="primary">Submit</Button>
</ZenProvider>
)
}Setup
Import Styles
Import the CSS file in your app entry point:
// app/layout.tsx or _app.tsx
import '@entro314labs/entro-zen/styles.css'Provider
Wrap your app with ZenProvider for theming:
import { ZenProvider } from '@entro314labs/entro-zen'
export default function RootLayout({ children }) {
return (
<ZenProvider theme="system">
{children}
</ZenProvider>
)
}Components
Layout
Box
Basic layout primitive.
import { Box } from '@entro314labs/entro-zen'
<Box padding="4" backgroundColor="gray1" borderRadius="2">
Content
</Box>Container
Centered container with max-width.
import { Container } from '@entro314labs/entro-zen'
<Container size="lg">
Page content
</Container>Row / Column
Flexbox layouts.
import { Row, Column } from '@entro314labs/entro-zen'
<Row gap="4" align="center">
<Column flex={1}>Left</Column>
<Column flex={2}>Right</Column>
</Row>Grid
CSS Grid layout.
import { Grid } from '@entro314labs/entro-zen'
<Grid columns={3} gap="4">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</Grid>Forms
TextField
Text input with label and validation.
import { TextField } from '@entro314labs/entro-zen'
<TextField
label="Email"
type="email"
placeholder="you@example.com"
error="Invalid email"
/>PasswordField
Password input with visibility toggle.
import { PasswordField } from '@entro314labs/entro-zen'
<PasswordField
label="Password"
minLength={8}
/>SearchField
Search input with clear button.
import { SearchField } from '@entro314labs/entro-zen'
<SearchField
placeholder="Search..."
onSearch={(value) => console.log(value)}
/>Select
Dropdown select.
import { Select } from '@entro314labs/entro-zen'
<Select
label="Country"
options={[
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
]}
onChange={(value) => console.log(value)}
/>Checkbox
Checkbox with label.
import { Checkbox } from '@entro314labs/entro-zen'
<Checkbox
label="I agree to the terms"
checked={agreed}
onChange={setAgreed}
/>Switch
Toggle switch.
import { Switch } from '@entro314labs/entro-zen'
<Switch
label="Enable notifications"
checked={enabled}
onChange={setEnabled}
/>RadioGroup
Radio button group.
import { RadioGroup } from '@entro314labs/entro-zen'
<RadioGroup
label="Plan"
options={[
{ value: 'free', label: 'Free' },
{ value: 'pro', label: 'Pro' },
]}
value={plan}
onChange={setPlan}
/>Buttons
Button
Primary button component.
import { Button } from '@entro314labs/entro-zen'
<Button variant="primary" size="md">
Click me
</Button>
<Button variant="secondary" disabled>
Disabled
</Button>
<Button variant="danger" loading>
Deleting...
</Button>Variants: primary, secondary, outline, ghost, danger
Sizes: sm, md, lg
LoadingButton
Button with loading state.
import { LoadingButton } from '@entro314labs/entro-zen'
<LoadingButton
loading={isSubmitting}
onClick={handleSubmit}
>
Save Changes
</LoadingButton>CopyButton
Button that copies text to clipboard.
import { CopyButton } from '@entro314labs/entro-zen'
<CopyButton text="https://example.com/tracking.js" />Feedback
AlertBanner
Alert message banner.
import { AlertBanner } from '@entro314labs/entro-zen'
<AlertBanner variant="success">
Website created successfully!
</AlertBanner>
<AlertBanner variant="error" dismissible onDismiss={() => {}}>
Failed to save changes.
</AlertBanner>Variants: info, success, warning, error
Toast
Toast notifications via hook.
import { useToast, Toaster } from '@entro314labs/entro-zen'
function App() {
return (
<>
<Toaster />
<MyComponent />
</>
)
}
function MyComponent() {
const { toast } = useToast()
return (
<Button onClick={() => toast.success('Saved!')}>
Save
</Button>
)
}Loading
Loading spinner.
import { Loading, Spinner } from '@entro314labs/entro-zen'
<Loading /> // Full page loader
<Spinner size="sm" /> // Inline spinnerProgressBar
Progress indicator.
import { ProgressBar } from '@entro314labs/entro-zen'
<ProgressBar value={75} max={100} />Overlays
Modal
Modal dialog.
import { Modal } from '@entro314labs/entro-zen'
<Modal
open={isOpen}
onOpenChange={setIsOpen}
title="Confirm Delete"
>
<p>Are you sure you want to delete this website?</p>
<Button variant="danger" onClick={handleDelete}>
Delete
</Button>
</Modal>Dialog
Alert/confirm dialog.
import { AlertDialog, ConfirmationDialog } from '@entro314labs/entro-zen'
<ConfirmationDialog
open={isOpen}
title="Delete Website"
message="This action cannot be undone."
confirmLabel="Delete"
onConfirm={handleDelete}
onCancel={() => setIsOpen(false)}
/>Popover
Popover panel.
import { Popover } from '@entro314labs/entro-zen'
<Popover
trigger={<Button>Options</Button>}
>
<div>Popover content</div>
</Popover>Tooltip
Tooltip on hover.
import { Tooltip } from '@entro314labs/entro-zen'
<Tooltip content="Copy to clipboard">
<CopyButton text="..." />
</Tooltip>Navigation
Tabs
Tab navigation.
import { Tabs } from '@entro314labs/entro-zen'
<Tabs
items={[
{ id: 'overview', label: 'Overview', content: <Overview /> },
{ id: 'events', label: 'Events', content: <Events /> },
{ id: 'settings', label: 'Settings', content: <Settings /> },
]}
/>Menu
Dropdown menu.
import { Menu } from '@entro314labs/entro-zen'
<Menu
trigger={<Button>Actions</Button>}
items={[
{ label: 'Edit', onClick: handleEdit },
{ label: 'Delete', onClick: handleDelete, variant: 'danger' },
]}
/>Breadcrumbs
Breadcrumb navigation.
import { Breadcrumbs } from '@entro314labs/entro-zen'
<Breadcrumbs
items={[
{ label: 'Dashboard', href: '/dashboard' },
{ label: 'Websites', href: '/websites' },
{ label: 'example.com' },
]}
/>Data Display
DataTable
Data table with sorting and pagination.
import { DataTable } from '@entro314labs/entro-zen'
<DataTable
columns={[
{ key: 'name', label: 'Name', sortable: true },
{ key: 'visits', label: 'Visits', sortable: true },
{ key: 'actions', label: '', render: (row) => <Actions row={row} /> },
]}
data={websites}
pagination={{ page: 1, pageSize: 10 }}
/>DataCard
Card for displaying metrics.
import { DataCard } from '@entro314labs/entro-zen'
<DataCard
title="Page Views"
value="12,345"
change={+15.2}
trend="up"
/>Typography
Heading
Heading component.
import { Heading } from '@entro314labs/entro-zen'
<Heading level={1}>Dashboard</Heading>
<Heading level={2} size="lg">Websites</Heading>Text
Text component.
import { Text } from '@entro314labs/entro-zen'
<Text size="sm" color="gray11">
Last updated 5 minutes ago
</Text>Code / CodeBlock
Code display.
import { Code, CodeBlock } from '@entro314labs/entro-zen'
<Code>npm install @entro314labs/entro-zen</Code>
<CodeBlock language="typescript">
{`const client = new Entrolytics({
websiteId: 'your-id',
})`}
</CodeBlock>Theming
Theme Provider
import { ZenProvider } from '@entro314labs/entro-zen'
// Light theme
<ZenProvider theme="light">
// Dark theme
<ZenProvider theme="dark">
// System preference
<ZenProvider theme="system">Theme Toggle
import { ThemeButton, useTheme } from '@entro314labs/entro-zen'
// Built-in toggle button
<ThemeButton />
// Custom toggle
function CustomToggle() {
const { theme, setTheme } = useTheme()
return (
<Button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</Button>
)
}CSS Variables
Customize with CSS variables:
:root {
--zen-primary: #0066cc;
--zen-radius-sm: 4px;
--zen-radius-md: 8px;
--zen-font-sans: 'Inter', sans-serif;
}Hooks
useTheme
Access theme state.
import { useTheme } from '@entro314labs/entro-zen'
const { theme, setTheme, resolvedTheme } = useTheme()useToast
Toast notifications.
import { useToast } from '@entro314labs/entro-zen'
const { toast } = useToast()
toast.success('Success!')
toast.error('Error!')
toast.info('Info')
toast.warning('Warning')useDebounce
Debounced value.
import { useDebounce } from '@entro314labs/entro-zen'
const debouncedSearch = useDebounce(searchTerm, 300)useBreakpoint
Responsive breakpoints.
import { useBreakpoint } from '@entro314labs/entro-zen'
const { isMobile, isTablet, isDesktop } = useBreakpoint()Accessibility
All components are built with accessibility in mind:
- Full keyboard navigation
- ARIA attributes
- Focus management
- Screen reader support
- Built on React Aria Components
Requirements
- React >= 18.0.0
- React DOM >= 18.0.0
License
MIT