ahmedallem.
Engineering · 4 min read

Getting Started with Allem UI React: Build Accessible Interfaces in Minutes

Learn how to install @allem-ui/react, set up Tailwind CSS v4, and build your first accessible interface with 30+ production-ready components.

Ahmed Allem

Ahmed Allem

Founder & CTO · Aviation, AI & Startups

ShareShare
Getting Started with Allem UI React: Build Accessible Interfaces in Minutes

@allem-ui/react is the core web package of Allem UI. It ships 30+ accessible components built on React Aria and styled with Tailwind CSS v4. Every component includes keyboard navigation, ARIA attributes, and screen reader support out of the box.

This guide walks you through installation, Tailwind setup, and building your first interface.

Installation

Install the core React package and the theme preset:

npm install @allem-ui/react @allem-ui/theme

You also need Tailwind CSS v4 as a peer dependency:

npm install tailwindcss@4

If you want everything at once (all 9 packages), install the meta-package instead:

npm install allem-ui

Tailwind Configuration

Add the Allem UI preset to your Tailwind config:

// tailwind.config.ts
import { allemPreset } from "@allem-ui/theme";

export default {
  presets: [allemPreset],
  darkMode: "class",
  content: [
    "./src/**/*.{ts,tsx}",
    "./node_modules/@allem-ui/react/dist/**/*.{js,mjs}",
  ],
};

Then set up your globals.css with the required sources and variants:

@import "tailwindcss";
@source "@allem-ui/react";
@source "@allem-ui/theme";

/* React Aria data attribute variants */
@custom-variant selected (&[data-selected]);
@custom-variant pressed (&[data-pressed]);
@custom-variant dragging (&[data-dragging]);
@custom-variant focus-visible (&[data-focus-visible]);
@custom-variant disabled (&[data-disabled]);
@custom-variant placeholder-shown (&[data-placeholder]);

/* Dark mode */
@custom-variant dark (&:where(.dark, .dark *));

/* Animations */
@theme {
  --animate-allem-spin: spin 0.6s linear infinite;
  --animate-allem-pulse: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  --animate-allem-fade-in: allemFadeIn 0.2s ease-out;
  --animate-allem-slide-up: allemSlideUp 0.2s ease-out;
}

@keyframes allemFadeIn {
  0% { opacity: 0; }
  100% { opacity: 1; }
}

@keyframes allemSlideUp {
  0% { opacity: 0; transform: translateY(4px); }
  100% { opacity: 1; transform: translateY(0); }
}

Your First Component

All components include the "use client" directive, so they work directly in Next.js App Router server components without extra wrappers.

import { Button, Input, Card, CardBody } from "@allem-ui/react";

export default function Page() {
  return (
    <Card>
      <CardBody>
        <Input label="Email" type="email" placeholder="you@example.com" />
        <Button onPress={() => console.log("clicked")}>Submit</Button>
      </CardBody>
    </Card>
  );
}

Core Prop API

Every interactive component follows a consistent prop pattern:

Prop Values Default
variant "solid", "outline", "ghost", "link" "solid"
size "sm", "md", "lg" "md"
color "primary", "neutral", "danger", "success", "warning" "primary"
className Any Tailwind classes

This consistency means once you learn one component, you know them all:

<Button variant="solid" color="primary" size="md">Primary</Button>
<Button variant="outline" color="danger">Delete</Button>
<Button variant="ghost" size="sm">Cancel</Button>

Use onPress, Not onClick

Allem UI uses onPress instead of onClick for all interactive components. This comes from React Aria and provides proper handling across mouse, touch, and keyboard interactions:

<Button onPress={() => saveData()}>Save</Button>

Class Merging with cn()

Every component merges your custom classes with the defaults using the cn() utility, so you can always override styles:

<Button className="rounded-full px-8">Rounded Button</Button>
<Card className="border-2 border-blue-500">Custom Border</Card>

Building a Complete Form

Here is a contact form combining multiple components:

import {
  Button, Input, Textarea, Select, Card, CardHeader, CardBody, CardFooter,
} from "@allem-ui/react";

export default function ContactForm() {
  return (
    <Card variant="outline">
      <CardHeader>Contact Us</CardHeader>
      <CardBody className="space-y-4">
        <div className="grid grid-cols-2 gap-4">
          <Input label="First Name" placeholder="Ahmed" />
          <Input label="Last Name" placeholder="Allem" />
        </div>
        <Input label="Email" type="email" placeholder="you@example.com" />
        <Select label="Subject">
          <option>General Inquiry</option>
          <option>Bug Report</option>
          <option>Feature Request</option>
        </Select>
        <Textarea label="Message" placeholder="How can we help?" />
      </CardBody>
      <CardFooter>
        <Button variant="outline" onPress={() => console.log("cancel")}>
          Cancel
        </Button>
        <Button onPress={() => console.log("submit")}>Send Message</Button>
      </CardFooter>
    </Card>
  );
}

Toast Notifications

Wrap your app in ToastProvider and use the useToast hook anywhere:

import { ToastProvider, useToast, Button } from "@allem-ui/react";

// In your layout
<ToastProvider position="bottom-right">
  <App />
</ToastProvider>

// In any component
function SaveButton() {
  const { toast } = useToast();

  const handleSave = async () => {
    await saveData();
    toast({
      title: "Saved!",
      variant: "success",
      duration: 3000,
    });
  };

  return <Button onPress={handleSave}>Save</Button>;
}

Modals are built on React Aria's dialog primitive with focus trapping and Escape key handling:

import { Modal, ModalContent, Button } from "@allem-ui/react";

<Modal>
  <Button>Open Modal</Button>
  <ModalContent title="Confirm Action" size="md">
    <p>Are you sure you want to proceed?</p>
    <div className="flex gap-2 justify-end mt-4">
      <Button variant="outline">Cancel</Button>
      <Button color="danger">Confirm</Button>
    </div>
  </ModalContent>
</Modal>

Dark Mode

Allem UI supports dark mode through the class strategy. Add the dark class to your <html> element and every component adapts automatically:

<html className="dark">
  {/* All Allem UI components render in dark mode */}
</html>

Pair it with next-themes for automatic system preference detection:

import { ThemeProvider } from "next-themes";

<ThemeProvider attribute="class">
  <App />
</ThemeProvider>

Available Components

@allem-ui/react includes 30+ components across these categories:

Inputs: Button, Input, Textarea, Select, Checkbox, Radio, Switch, Slider

Display: Badge, Avatar, Spinner, Skeleton, Divider, Code

Layout: Card, Container, Flex, Grid, Box

Navigation: Breadcrumbs, Tabs, Link, Pagination

Overlay: Modal, Drawer, Dropdown, Popover, Tooltip, Context Menu

Feedback: Toast

Typography: Heading, Text

Each component is documented with live examples at kingallem.com/open-source/allem-ui/docs.

What's Next