Skip to content

anephenix/ui

Repository files navigation

UI

A design system for Anephenix.

npm version Node.js CI Socket Badge

Installation

npm i @anephenix/ui --save

Dependencies

  • Node.js (24+)
  • React (18+)

Usage

Import the components and the stylesheet in your project:

import { Button, Input, NavBar } from '@anephenix/ui';
import '@anephenix/ui/dist/index.css';

Components

Components are grouped below by category.


Layout

Page

A full-page wrapper div. Wrap your entire app content inside it.

import { Page } from '@anephenix/ui';

<Page>
    <p>Your content here</p>
</Page>
Prop Type Description
children node Content to render inside the page wrapper

Hero

A hero section with a heading, description, and call-to-action buttons.

import { Hero } from '@anephenix/ui';

const ctas = [
    { href: '/get-started', text: 'Get started', buttonClass: 'primary' },
    { href: '/docs', text: 'Documentation', buttonClass: 'secondary' },
];

<Hero
    title="Welcome"
    description="A short description of your product."
    ctas={ctas}
    Link={Link}
/>
Prop Type Description
title string The main heading
description string | node A short description (string is wrapped in <p>)
ctas array Array of { href, text, buttonClass } objects
Link component Optional router link component (falls back to <a>)

Footer

A two-column footer with left and right sections.

import { Footer } from '@anephenix/ui';

<Footer
    leftSection={<span>&copy; 2026 Acme Ltd.</span>}
    rightSection={<a href="/privacy">Privacy</a>}
/>
Prop Type Description
leftSection node Content for the left side of the footer
rightSection node Content for the right side of the footer

Navigation

Breadcrumb

A navigation trail showing the user's location within a hierarchy. Follows the WAI-ARIA Breadcrumb pattern.

import { Breadcrumb } from '@anephenix/ui';

<Breadcrumb
    items={[
        { label: 'Home', href: '/' },
        { label: 'Products', href: '/products' },
        { label: 'Laptops' },
    ]}
/>
Prop Type Description
items array Array of { label, href? } objects. Omit href on the last item to mark it as the current page
separator string | node Separator rendered between items. Defaults to "/"
className string Optional additional CSS class on the list

NavBar

A responsive navigation bar with a hamburger menu for mobile and a desktop menu.

import { NavBar } from '@anephenix/ui';

const links = [
    {
        id: 'home',
        text: 'Home',
        url: '/',
        hideOnDesktop: false,
        hideOptions: ({ loggedIn }) => true,
    },
];

<NavBar
    logo={<a href="/">My App</a>}
    links={links}
    loggedIn={false}
    Link={Link}
/>
Prop Type Description
logo node Logo element rendered on the left
links array Array of link objects (see shape below)
loggedIn bool Passed to each link's hideOptions function
Link component Router link component used for internal URLs
className string Optional additional class for the nav bar element
midSection node Optional element rendered between logo and hamburger

Each link object:

Field Type Description
id string Unique identifier
text string Display text
url string Href (use onClick to render a button instead)
onClick function Click handler (renders a <button>)
hideOnDesktop bool Hide this link in the desktop menu
hideOptions function ({ loggedIn }) => bool — return true to show
target string _blank etc.
rel string Link rel attribute

Pagination

Page-number controls with first, previous, next, and last buttons. Returns null when totalPages is less than 2.

import { Pagination } from '@anephenix/ui';

const [page, setPage] = useState(1);

<Pagination
    currentPage={page}
    totalPages={20}
    onPageChange={setPage}
/>
Prop Type Description
currentPage number The currently active page (1-based)
totalPages number Total number of pages
onPageChange function Called with the new page number when any button is clicked
siblingCount number Pages shown on each side of the current page. Defaults to 1
showFirstLast bool Show First and Last buttons. Defaults to true
className string Optional additional CSS class on the nav

Forms

Button

A basic button element. Accepts a forwardRef.

import { Button } from '@anephenix/ui';

<Button text="Submit" className="button theme-default primary" onClick={handleClick} />
Prop Type Description
text string Button label
name string Name attribute
className string CSS class(es)
onClick function Click handler

Button variant classes (combine with button theme-default):

Class Alternate
primary primary alternate
secondary secondary alternate
tertiary tertiary alternate
green-one green-one alternate
green-two green-two alternate
blue-one blue-one alternate
blue-two blue-two alternate

Checkbox

A styled checkbox with a label. Accepts a forwardRef.

import { Checkbox } from '@anephenix/ui';

<Checkbox name="agree" label="I agree to the terms" defaultValue={false} />
Prop Type Description
name string Name attribute
label string Label text
className string CSS class(es)
defaultValue bool Whether the checkbox is checked by default

Switch

A toggle switch for binary on/off settings. Supports controlled and uncontrolled usage. Accepts a forwardRef.

import { Switch } from '@anephenix/ui';

// Uncontrolled
<Switch name="notifications" label="Enable notifications" defaultChecked={false} />

// Controlled
const [enabled, setEnabled] = useState(false);
<Switch
    name="darkMode"
    label="Dark mode"
    checked={enabled}
    onChange={(e) => setEnabled(e.target.checked)}
/>
Prop Type Description
name string Name attribute
label string Optional label text
checked bool Checked state in controlled mode
defaultChecked bool Initial checked state in uncontrolled mode
onChange function Change handler — receives the native input change event
disabled bool Disables interaction and dims the switch
className string Optional additional CSS class

Input

A text input element. Accepts a forwardRef.

import { Input } from '@anephenix/ui';

<Input
    name="email"
    type="email"
    placeholder="you@example.com"
    onChange={handleChange}
/>
Prop Type Default Description
type string "text" Input type
name string Name attribute
className string CSS class(es)
defaultValue string Initial value
placeholder string Placeholder text
onChange function Change handler

RadioButton

A styled radio button with a label. Accepts a forwardRef.

import { RadioButton } from '@anephenix/ui';

const [selected, setSelected] = useState('');

<RadioButton
    name="colour"
    label="Red"
    value="red"
    checked={selected === 'red'}
    onChange={() => setSelected('red')}
/>
Prop Type Description
name string Name attribute (shared across a group)
label string Label text
className string CSS class(es)
value string Value for this option (controlled mode)
checked bool Whether this option is selected (controlled mode)
onChange function Called when this option is selected
defaultValue string Value attribute for uncontrolled usage

Select

A styled <select> element. Accepts a forwardRef.

import { Select } from '@anephenix/ui';

const options = [
    { value: 'gb', label: 'United Kingdom' },
    { value: 'us', label: 'United States' },
];

<Select name="country" options={options} onChange={handleChange} />
Prop Type Description
name string Name attribute
className string CSS class(es)
defaultValue string Initially selected value
onChange function Change handler
options array Array of { value, label } objects

Dropdown

A styled dropdown using a <select> element that supports multiple selection. Accepts a forwardRef. Options use a text field (not label) to distinguish it from Select.

import { Dropdown } from '@anephenix/ui';

const options = [
    { value: 'js', text: 'JavaScript' },
    { value: 'ts', text: 'TypeScript' },
];

<Dropdown name="language" options={options} />
Prop Type Description
name string Name attribute
id string Element id
className string CSS class(es)
multiple bool Allow multiple selections
defaultValue string | array Initially selected value(s)
options array Array of { value, text } objects

ComboBox

A searchable input that filters a list of options as the user types. Supports keyboard navigation (arrow keys, Enter, Escape), outside-click dismissal, and full ARIA combobox semantics.

import { ComboBox } from '@anephenix/ui';

const options = [
    { value: 'apple', label: 'Apple' },
    { value: 'banana', label: 'Banana' },
    { value: 'cherry', label: 'Cherry' },
];

const [selected, setSelected] = useState(null);

<ComboBox
    options={options}
    placeholder="Search fruit..."
    onSelect={(option) => setSelected(option)}
/>
Prop Type Description
options array Array of { value, label } objects. Defaults to []
value string Initial text value of the input (uncontrolled seed)
onChange function Called with the current input string on every keystroke
onSelect function Called with the selected { value, label } object when an option is chosen
placeholder string Placeholder text for the input. Defaults to "Search..."
disabled bool Disables the input and prevents interaction. Defaults to false

Textarea

A multi-line text input. Accepts a forwardRef.

import { Textarea } from '@anephenix/ui';

<Textarea name="message" placeholder="Enter your message..." onChange={handleChange} />
Prop Type Description
name string Name attribute
className string CSS class(es)
defaultValue string Initial value
placeholder string Placeholder text
onChange function Change handler

FormField

A wrapper for form inputs that displays a validation error message below the input.

import { FormField, Input } from '@anephenix/ui';

<FormField error="This field is required">
    <Input name="email" type="email" />
</FormField>
Prop Type Description
children node The form control(s) to wrap
error string Error message to display (omit when valid)

Display

Accordion

Collapsible sections that expand and collapse to reveal content. Follows the WAI-ARIA Accordion pattern. Panels animate open and closed.

import { Accordion } from '@anephenix/ui';

const items = [
    { id: 'q1', title: 'What is this?', content: <p>An answer.</p> },
    { id: 'q2', title: 'How does it work?', content: <p>Another answer.</p> },
];

<Accordion items={items} defaultOpen="q1" />
Prop Type Description
items array Array of { id, title, content } objects
allowMultiple bool Allow more than one panel open at a time. Defaults to false
defaultOpen string | string[] Id(s) of item(s) open on first render
onChange function Called with an array of currently open ids on change
className string Optional additional CSS class

Alert

An inline status banner for contextual feedback. The role is automatically set to "alert" for error/warning variants and "status" for info/success.

import { Alert } from '@anephenix/ui';

// Persistent
<Alert variant="success" title="Saved">Your changes have been saved.</Alert>

// Dismissible
<Alert variant="warning" onClose={() => setVisible(false)}>
    Your session will expire in 5 minutes.
</Alert>
Prop Type Description
variant "info" | "success" | "warning" | "error" Visual style. Defaults to "info"
title string Optional bold heading above the body
children node The alert content
onClose function Optional dismiss callback — renders a close button when provided
className string Optional additional CSS class

Divider

A visual separator between sections of content. Supports horizontal and vertical orientations, three line styles, and an optional centred text label.

import { Divider } from '@anephenix/ui';

// Basic horizontal divider
<Divider />

// With a centred label
<Divider label="or" />

// Dashed variant
<Divider variant="dashed" />

// Vertical (inside a flex container)
<div style={{ display: 'flex', height: '2rem', alignItems: 'center', gap: '1rem' }}>
    <span>Left</span>
    <Divider orientation="vertical" />
    <span>Right</span>
</div>
Prop Type Description
orientation "horizontal" | "vertical" Direction of the divider. Defaults to "horizontal"
variant "solid" | "dashed" | "dotted" Line style. Defaults to "solid"
label string Optional text centred on the divider line
className string Optional additional CSS class on the wrapper

Avatar

A user profile picture with three automatic states: image, initials (derived from name), and a generic icon fallback. The initials background colour is consistently derived from the name.

import { Avatar } from '@anephenix/ui';

// Image
<Avatar src="/photo.jpg" alt="Alice Brown" />

// Initials fallback
<Avatar name="Alice Brown" size="lg" />

// Icon fallback
<Avatar size="md" shape="rounded" />
Prop Type Description
src string Image URL. Falls back to initials or icon on error
alt string Alt text for the image. Defaults to name if provided
name string Used to generate initials and a consistent background colour
size "sm" | "md" | "lg" | "xl" Avatar diameter. Defaults to "md"
shape "circle" | "rounded" | "square" Border radius style. Defaults to "circle"
className string Optional additional CSS class

Badge

A small inline label for counts, status indicators, and tags.

import { Badge } from '@anephenix/ui';

<Badge variant="success">Active</Badge>
<Badge variant="error" size="sm">99+</Badge>
<Badge variant="default">React</Badge>
Prop Type Description
children node The badge content
variant "default" | "primary" | "secondary" | "success" | "warning" | "info" | "error" Colour scheme. Defaults to "default"
size "sm" | "md" | "lg" Size preset. Defaults to "md"
className string Optional additional CSS class

Card

A flexible content container with optional image, header, body, and footer sections. Width fills the parent.

import { Card } from '@anephenix/ui';

<Card
    title="Getting started"
    subtitle="Up and running in minutes"
    footer={<Button text="View docs" className="button theme-default primary" />}
>
    <p>Build consistent UIs with a plain-CSS design system.</p>
</Card>
Prop Type Description
title string Optional heading in the card header
subtitle string Optional secondary line below the title
image string Optional URL for a cover image at the top
imageAlt string Alt text for the image. Defaults to ""
children node Main body content
footer node Optional footer content
className string Optional additional CSS class

Code

A code block with syntax highlighting, line numbers, a title bar, and a copy button.

import { Code } from '@anephenix/ui';

const snippet = `const greet = (name) => \`Hello, \${name}!\`;`;

<Code title="greet.js" code={snippet} language="javascript" />
Prop Type Default Description
title string Title shown in the bar above the code
code string The code string to display
language string "javascript" Syntax highlighting language

Popover

A click-triggered floating panel for richer interactive content such as forms, switches, or option lists. Closes on Escape, outside click, or the × button.

import { Popover } from '@anephenix/ui';

<Popover
    trigger={<Button text="Options" className="button theme-default secondary" />}
    title="Display options"
    content={<p>Popover body content.</p>}
    position="bottom"
/>
Prop Type Description
trigger element The element that toggles the popover
content node Content rendered in the popover body
title string Optional heading shown in the popover header
position "bottom" | "top" | "left" | "right" Placement relative to the trigger. Defaults to "bottom"
className string Optional additional CSS class

ProgressBar

A horizontal bar that communicates the completion state of an operation. Supports four colour variants, three sizes, an optional label and percentage display, and an indeterminate animated state for operations of unknown duration.

import { ProgressBar } from '@anephenix/ui';

<ProgressBar value={75} label="Uploading..." showValue />

<ProgressBar value={100} variant="success" label="Complete" showValue />

<ProgressBar indeterminate label="Processing..." />
Prop Type Description
value number Current progress value. Defaults to 0
max number Maximum value. Defaults to 100
variant "default" | "success" | "warning" | "error" Colour of the fill. Defaults to "default"
size "sm" | "md" | "lg" Height of the bar. Defaults to "md"
label string Optional label rendered above the bar
showValue bool Show the computed percentage to the right of the label. Defaults to false
indeterminate bool Animates the bar for operations of unknown duration. Defaults to false
className string Optional additional CSS class on the wrapper

Skeleton

A shimmer placeholder that mimics the shape of content while it loads.

import { Skeleton } from '@anephenix/ui';

// Single text line
<Skeleton width="60%" />

// Paragraph
<Skeleton lines={3} />

// Avatar circle
<Skeleton width={48} height={48} borderRadius="50%" />
Prop Type Description
width string | number Width. Numbers are converted to px. Defaults to "100%"
height string | number Height. Numbers are converted to px. Defaults to "1rem"
borderRadius string Border radius. Use "50%" for circles. Defaults to "4px"
lines number Render multiple stacked lines. The last line is 70% wide. Defaults to 1
className string Optional additional CSS class

Spinner

An animated loading indicator for indeterminate progress.

import { Spinner } from '@anephenix/ui';

<Spinner size="md" label="Loading..." />
Prop Type Description
size "sm" | "md" | "lg" Controls the diameter and border width. Defaults to "md"
label string Accessible aria-label for screen readers. Defaults to "Loading..."
className string Optional additional CSS class

Table

A data table with column definitions and optional custom cell renderers. Horizontally scrollable on small screens.

import { Table } from '@anephenix/ui';

const columns = [
    { key: 'name', header: 'Name' },
    { key: 'role', header: 'Role' },
    {
        key: 'status',
        header: 'Status',
        render: (value) => <strong>{value}</strong>,
    },
];

const rows = [
    { id: 1, name: 'Alice Chen', role: 'Engineer', status: 'Active' },
    { id: 2, name: 'Bob Smith', role: 'Designer', status: 'Inactive' },
];

<Table columns={columns} rows={rows} caption="Team members" />
Prop Type Description
columns array Array of column definition objects (see shape below)
rows array Array of row data objects
rowKey string Field name used as the React key for each row. Defaults to "id"
caption string Optional accessible caption rendered above the table
className string Optional additional CSS class on the <table> element

Each column object:

Field Type Description
key string Field name from the row object
header string Column header label
render function Optional (value, row) => node custom cell renderer

Tabs

Content-switching tabs with full WAI-ARIA keyboard support (arrow keys, roving tabIndex).

import { Tabs } from '@anephenix/ui';

const tabs = [
    { id: 'overview', label: 'Overview', content: <p>Overview content.</p> },
    { id: 'specs', label: 'Specifications', content: <p>Specs here.</p> },
];

<Tabs tabs={tabs} defaultTab="overview" onChange={(id) => console.log(id)} />
Prop Type Description
tabs array Array of { id, label, content } objects
defaultTab string Id of the initially selected tab. Defaults to the first tab
onChange function Optional (id) => void called when the active tab changes
className string Optional additional CSS class on the wrapper

Terminal

A terminal-style block for showing shell commands or plain-text output. Includes a copy button.

import { Terminal } from '@anephenix/ui';

<Terminal title="Install" code="npm i @anephenix/ui" />
Prop Type Description
title string Title shown in the bar above the output
code string The text to display

Tooltip

A small floating label that appears on hover and keyboard focus. Shown and hidden entirely via CSS (:hover and :focus-within).

import { Tooltip } from '@anephenix/ui';

<Tooltip content="Save your changes" position="top">
    <button type="button">Save</button>
</Tooltip>
Prop Type Description
content string | node The tooltip text or content
position "top" | "bottom" | "left" | "right" Placement relative to the child. Defaults to "top"
children node The element the tooltip is attached to
className string Optional additional CSS class on the tooltip bubble

Overlays

Modal

A dialog overlay built on the native <dialog> element. Traps focus, closes on Escape, and supports an optional footer for action buttons.

import { Modal } from '@anephenix/ui';

const [isOpen, setIsOpen] = useState(false);

<Modal
    isOpen={isOpen}
    onClose={() => setIsOpen(false)}
    title="Confirm action"
    footer={
        <>
            <Button text="Cancel" className="button theme-default secondary alternate" onClick={() => setIsOpen(false)} />
            <Button text="Confirm" className="button theme-default primary" onClick={() => setIsOpen(false)} />
        </>
    }
>
    <p>Are you sure you want to do this?</p>
</Modal>
Prop Type Description
isOpen bool Controls whether the modal is shown
onClose function Called when the user dismisses the modal
title string Heading shown in the modal header
children node Content rendered in the modal body
footer node Optional footer content

Toast

A fixed-position notification with four variants and optional auto-dismiss.

import { Toast } from '@anephenix/ui';

const [isVisible, setIsVisible] = useState(false);

<Toast
    isVisible={isVisible}
    title="Saved"
    message="Your changes have been saved."
    variant="success"
    duration={4000}
    onClose={() => setIsVisible(false)}
/>
Prop Type Description
isVisible bool Controls whether the toast is shown
message string The notification text
title string Optional bold heading above the message
variant "info" | "success" | "warning" | "error" Visual style. Defaults to "info"
position "top-right" | "top-left" | "bottom-right" | "bottom-left" | "top-center" | "bottom-center" Corner of the viewport. Defaults to "top-right"
duration number Milliseconds before auto-dismissing. Pass 0 to disable. Defaults to 4000
onClose function Called when the close button is clicked or the duration elapses

Utilities

handleErrors

A helper that extracts validation errors from an Axios-style API response and normalises them into an array.

import { handleErrors } from '@anephenix/ui';

try {
    await api.post('/login', data);
} catch (err) {
    handleErrors(setError, err);
}

setError receives an array of { name, message } objects corresponding to the server-returned field errors.


Tests

npm t

License and credits

©2026 Anephenix Ltd. UI is licenced under the MIT Licence.

About

A collection of UI components for React web applications

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages