This repository contains a reusable frontend codebase built with Nextjs. It includes a collection of modular UI components designed for consistency across the web app, along with Zustand-based state management stores for efficient global state handling. The components are styled with TailwindCSS mostly and focus on accessibility, responsiveness, and developer experience.
Key features:
- Reusable, customizable UI components (e.g., buttons, loaders, pagination).
- Lightweight state management with Zustand to minimize boilerplate and optimize rerenders.
- Easy setup for development and production.
- Node.js (v22.18.0 recommended)
- npm or yarn
-
Clone the repository:
git clone git@github.com:taolaktech/amplify-ui.git cd amplify-ui -
Install dependencies:
npm install
Start the development server with hot reloading:
npm run dev
This will launch the app at http://localhost:3000 (or the port specified in your config).
Create an optimized production build:
npm run build
or
yarn build
The build artifacts will be in the dist or build folder. Serve them with any static server (e.g., npx serve -s build).
Run lint
npm run lint
This codebase provides a set of battle-tested, reusable components. Import them from ./lib/ui. Below is a summary of key components, including props and usage examples. All components are functional React components and support TypeScript for type safety.
A versatile button component with support for icons, loading states, variants, and custom sizing.
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
text |
string |
- | Button text label. |
icon |
React.ReactNode |
- | Optional icon (e.g., from react-icons). |
iconPosition |
"left" | "right" |
"left" |
Position of the icon relative to text. |
secondary |
boolean |
false |
Use secondary styling (outline or lighter variant). |
tertiary |
boolean |
false |
Use tertiary styling (minimal or ghost variant). |
buttonSize |
"small" | "medium" | "large" |
"medium" |
Size variant for the button. |
height |
number |
- | Custom height in pixels. |
gradientBorder |
boolean |
false |
Apply a gradient border effect. |
disabled |
boolean |
false |
Disable the button and its action. |
action |
() => void |
() => {} |
Click handler. |
showShadow |
boolean |
false |
Add a box shadow. |
loading |
boolean |
false |
Show loading spinner inside the button. |
hasIconOrLoader |
boolean |
false |
Flag for internal layout adjustments when icon or loader is present. |
iconSize |
number |
18 |
Size of the icon in pixels. |
Example:
import Button from './components/Button';
<Button
text="Click Me"
icon={<SomeIcon />}
iconPosition="left"
secondary
action={() => console.log('Clicked!')}
loading={isLoading}
/>A styled link component that behaves like a button but navigates via href. Supports similar styling to Button.
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
text |
string |
- | Link text label. |
icon |
React.ReactNode |
- | Optional icon. |
iconPosition |
"left" | "right" |
- | Position of the icon. |
secondary |
boolean |
false |
Secondary styling. |
buttonSize |
"small" | "medium" | "large" |
"medium" |
Size variant. |
height |
number |
- | Custom height. |
hasIconOrLoader |
boolean |
false |
Layout flag for icon/loader. |
href |
string |
"#" |
Destination URL. |
Example:
import DefaultLink from './components/DefaultLink';
<DefaultLink
text="Go to Home"
href="/"
icon={<HomeIcon />}
secondary
/>A standard text input field with validation support. (Full props not detailed here; extend as needed with value, onChange, placeholder, etc.)
Example:
import Input from './components/Input';
<Input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Enter text..."
/>A dropdown select component for choosing from options.
Props: (Common: value, onChange, options as array of {label, value}.)
Example:
import SelectInput from './components/SelectInput';
<SelectInput
options={[{ label: 'Option 1', value: '1' }, { label: 'Option 2', value: '2' }]}
value={selected}
onChange={(val) => setSelected(val)}
/>A placeholder loader for content while data is fetching. Customizable shape and size.
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
width |
string |
"100%" |
Width (e.g., "200px" or "50%"). |
height |
string |
"100px" |
Height. |
borderRadius |
string |
"10px" |
Border radius for rounded edges. |
style |
React.CSSProperties |
- | Inline styles override. |
Example:
import Skeleton from './components/Skeleton';
<Skeleton width="300px" height="20px" />A notification toast for success/error messages. You can show toast message with an showToast function from toastStore
Usage: showToast({title, message, type }).
A simple paginator for lists/tables.
Props:
| Prop | Type | Description |
|---|---|---|
pageCount |
number |
Total number of pages. |
setCurrentPage |
(page: number) => void |
Handler to update current page. |
currentPage |
number |
Active page number. |
Example:
import Pagination from './components/Pagination';
<Pagination
pageCount={10}
currentPage={1}
setCurrentPage={setPage}
/>A linear progress indicator.
Props:
| Prop | Type | Description |
|---|---|---|
width |
number |
Progress percentage (0-100). |
Example:
import ProgressBar from './components/ProgressBar';
<ProgressBar width={75} />A cloud-themed animated loader for async operations.
Usage: Render standalone; no major props.
A circular spinner loader.
Usage: Similar to CloudLoader; customizable via size prop if extended.
A switch toggle for boolean states.
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
on |
boolean |
- | Current toggle state. |
toggle |
() => void |
- | Handler to flip the state. |
large |
boolean |
false |
Use larger size. |
Example:
import Toggle from './components/Toggle';
<Toggle on={isEnabled} toggle={() => setEnabled(!isEnabled)} large />We use Zustand for lightweight, hook-based state management. Stores are defined in ./lib/stores (e.g., useUIStore).
To avoid unnecessary rerenders, always use primitive selectors instead of destructuring objects:
❌ Avoid:
const { isToggled } = useUIStore((state) => state); // Rerenders on any state change✅ Do:
const isToggled = useUIStore((state) => state.isToggled); // Only rerenders when `isToggled` changesThis optimizes performance by subscribing only to the specific slice of state.
Example store setup (in ./stores/uiStore.ts):
import { create } from 'zustand';
interface UIState {
isToggled: boolean;
actions: {
toggle: () => void;
}
}
export const useUIStore = create<UIState>((set) => ({
isToggled: false,
actions: {
toggle: () => set((state) => ({ isToggled: !state.isToggled })),
}
}));Usage:
import { useUIStore } from './stores/uiStore';
const {isToggled} = useUIStore((state) => state.actions.isToggled);
const toggle = useUIStore((state) => state.toggle);Most icons referenced in Figma designs leverage the Iconsax library (@iconsax/react), which is pre-installed in the project. Iconsax provides a comprehensive, customizable set of 1,200+ line icons optimized for React, ensuring consistency in stroke weight, alignment, and theming.
- Check Iconsax First: Before importing external or custom icons (e.g., from react-icons or SVGs), search the Iconsax library for an equivalent. This promotes design system consistency, reduces bundle size, and simplifies maintenance.
Import icons directly and render them as React components. No additional setup required. Example:
import { Home, Heart, SearchNormal1 } from '@iconsax/react';
// Basic usage
<Home size={24} color="currentColor" variant="Linear" />
// In a component (e.g., Button)
<Button
text="Home"
icon={<Home size={18} color="white" variant="Bold" />}
iconPosition="left"
action={() => navigate('/home')}
/>
// Conditional rendering
{isFavorite ? (
<Heart size={20} color="#ff6b6b" variant="TwoTone" />
) : (
<Heart size={20} color="#9ca3af" variant="Outline" />
)}If an icon isn't available in Iconsax and must be custom:
Add it to ./public as an SVG.
- Clone the repo and create a feature branch.
- Make changes and run tests.
- Submit a PR with a clear description.