@qtalo/qt-ui-library
v0.1.3
Published
Type-safe React component library built with React 19, TypeScript, Vite, and TailwindCSS 4. This library provides reusable UI primitives, components, patterns, and design tokens for building consistent user interfaces.
Readme
QT UI Library
A modern, type-safe React component library built with React 19, TypeScript, Vite, and TailwindCSS 4. This library provides reusable UI primitives, components, patterns, and design tokens for building consistent user interfaces.
Project Overview
The QT UI Library is a component library that organizes UI elements into three main categories: primitives (low-level building blocks), components (composed elements), and patterns (higher-level combinations). It uses TailwindCSS 4 for styling and Ladle for component development and documentation.
Project Structure (High-Level)
src/
primitives/ # Low-level, reusable UI building blocks
components/ # Composed elements built from primitives
patterns/ # Higher-level combinations for common use cases
icons/ # SVG icon components
tokens/ # Design tokens (colors, spacing, etc.)
utils/ # Shared utility functions
types/ # Shared TypeScript types and interfaces used across the UI library- Primitives: Basic building blocks with minimal dependencies (e.g., Button, Input, Checkbox)
- Components: Composed elements that combine primitives (e.g., Card, Accordion, Badge)
- Patterns: Higher-level UI patterns that solve specific use cases (e.g., FilterBar, ActionMenu, StatusBadge)
- Icons: Reusable SVG icon components organized by category
- Tokens: Design system values that serve as the single source of truth
- Utils: Shared utilities like classname merging and helper functions
- Types: Shared TypeScript types and interfaces that define global UI contracts such as density, size scales, orientation, theming, and reusable behavioral patterns. This folder contains system-level types, not component-specific props.
Creating UI Elements
Primitives
Primitives are low-level, headless UI building blocks with minimal styling and dependencies. They provide core functionality and accessibility features.
When to create a primitive:
- You need a basic, reusable UI element (button, input, checkbox)
- The element should be highly flexible and composable
- It serves as a foundation for other components
Where they live: src/primitives/
Components
Components are composed elements built from primitives. They provide more structure and styling out of the box.
When to create a component:
- You need a composed UI element that combines multiple primitives
- The element has a specific structure and visual design
- It's a common UI pattern that benefits from a consistent API
Where they live: src/components/
Patterns
Patterns are higher-level combinations of components and primitives that solve specific use cases or workflows.
When to create a pattern:
- You need a complete UI solution for a specific use case
- The pattern combines multiple components in a meaningful way
- It represents a reusable workflow or interaction pattern
Where they live: src/patterns/
Stories
This library uses Ladle for component development and documentation. Stories allow you to develop and test components in isolation.
Naming convention: Story files use the .story.tsx extension and live alongside their component files.
Example story:
// src/primitives/button.story.tsx
import type { Story } from "@ladle/react";
import { Button } from "./button";
export default {
title: "Primitives/Button",
};
export const Overview: Story = () => (
<Button>Click me</Button>
);Run npm run dev to start the Ladle development server and view all stories.
Installation & Usage
Installation
This package is published publicly on npmjs.org.
npm install @qtalo/qt-ui-libraryPeer Dependencies
This library requires the following peer dependencies:
npm install react@^19.2.3 react-dom@^19.2.3 clsx@^2.1.1 tailwind-merge@^3.4.0 tailwind-variants@^3.2.2 tailwindcss@^4.1.18Usage
Import components, primitives, patterns, icons, and tokens from the main entry point:
import { Button, Card, StatusBadge, Logo } from "@qtalo/qt-ui-library";Styles are automatically included! This library uses vite-plugin-lib-inject-css to automatically inject styles when you import components. No manual CSS import is needed.
Tailwind CSS v4 Configuration
This library is built with Tailwind CSS v4 and uses the modern @theme directive for design tokens. The styles are automatically injected into your application when you import components.
For Next.js projects, ensure you have Tailwind CSS v4 installed and configured:
npm install -D tailwindcss@^4.1.18 @tailwindcss/postcss@^4.1.18In your app/globals.css:
Option 1: Auto-injection (Recommended) Styles are automatically injected when you import components. You only need to import Tailwind CSS:
@import "tailwindcss";
@theme {
/* Your custom design tokens (optional) */
--color-background: oklch(1 0 0);
--color-foreground: oklch(0.1 0 0);
}Option 2: Manual import If auto-injection doesn't work or you prefer manual control, you can import the library's CSS explicitly:
@import "tailwindcss";
@import "@qtalo/qt-ui-library/styles.css";
@theme {
/* Your custom design tokens (optional) */
--color-background: oklch(1 0 0);
--color-foreground: oklch(0.1 0 0);
}Note: The library exports ./styles.css which points to the source CSS file (not compiled). This allows your Tailwind to process it and generate utilities for ALL colors. Always import tailwindcss first, as it's required for Tailwind CSS v4 to work properly.
Using All Color Utilities
✨ Automatic - No Manual Work Required!
In Tailwind CSS 4, all colors defined in @theme automatically generate utilities for all utility types. You don't need to maintain any safelist or manually add colors - just add them to @theme and they're immediately available!
How it works:
- Import the library CSS in your main CSS file (this imports the SOURCE CSS, not compiled):
@import "tailwindcss";
@import "@qtalo/qt-ui-library/styles.css";Tailwind will process the library's
@themeand automatically generate utilities for ALL colors.That's it! All colors from
@themeare now available as utilities in your app.
Every color works with ALL Tailwind utility types automatically:
bg-{color}- Background colorstext-{color}- Text colorsborder-{color}- Border colorsring-{color}- Ring colorsoutline-{color}- Outline colorsdivide-{color}- Divide colorsaccent-{color}- Accent colorscaret-{color}- Caret colorsfill-{color}- Fill colorsstroke-{color}- Stroke colors
Example usage:
// All these work automatically for ANY color in @theme
<div className="bg-surface-dark text-white border-primary-deep ring-primary-500">
All utility types work with all colors
</div>
<input className="accent-primary-500 caret-primary-500" />
<svg className="fill-success-base stroke-error-base" />
// Add a new color to @theme? It's immediately available!
// --color-brand-new: #ff0000; → bg-brand-new, text-brand-new, etc. all work!What colors are available?
Every color defined in the library's @theme block is automatically available, including:
- Surface colors (
surface-dark,surface-darker, etc.) - Primary colors (all variants)
- Tertiary colors (all variants)
- Success and error colors
- All neutral colors (50-900 with all variants)
- White and black variants
- Any new colors you add to
@theme- they work automatically!
Note: When using vite-plugin-lib-inject-css, styles are automatically injected. For full utility access, import the CSS explicitly as shown above. The base styles (html background, text colors) are always included automatically.
In your next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ['@qtalo/qt-ui-library'],
};
module.exports = nextConfig;Next.js Usage
This library is built with React Server Components in mind. All components that use React hooks or accept event handlers are marked as Client Components.
⚠️ Important: When using this library in a Next.js app, you MUST mark your component as a Client Component if you're passing event handlers (like onClick, onChange, etc.):
"use client"; // ← REQUIRED when passing event handlers
import { Button } from "@qtalo/qt-ui-library";
export function MyComponent() {
return (
<Button onClick={() => console.log("clicked")}>
Click me
</Button>
);
}Why? Next.js cannot serialize functions from Server Components to Client Components. Even though library components are Client Components, the component that imports and uses them must also be a Client Component when passing event handlers.
If you see this error:
Event handlers cannot be passed to Client Component props.Solution: Add "use client" at the top of the file that's using the library component with event handlers.
Usage with Other Frameworks
Vite + React:
// main.tsx or App.tsx
import { Button } from "@qtalo/qt-ui-library";
function App() {
return <Button>Click me</Button>;
}Styles are automatically included - no additional setup needed!
Create React App:
This library works with CRA, but requires Tailwind CSS v4 to be configured in your project.
Design Tokens
This library uses Tailwind CSS v4's @theme directive for design tokens. You can access these tokens in your consuming application:
@theme {
/* Library tokens are automatically available */
--color-brand-primary: oklch(0.5 0.2 250);
--color-brand-secondary: oklch(0.6 0.15 180);
}You can override these tokens in your own application's CSS by redefining them in your @theme block.
Release & Publishing Workflow
Versioning is handled via npm's version command, which automatically updates package.json, creates a commit, and creates a git tag.
Supported Commands
npm version patch --message "Update version to %s"
npm version minor --message "Update version to %s"
npm version major --message "Update version to %s"When to use each version type:
patch
Use for small changes such as bug fixes, minor UI tweaks, or internal refactors that do not affect the public API.Example:
- Fix a padding issue in
Button - Improve internal styles of
StatusBadge - Refactor code without changing component props
0.1.0 → 0.1.1
- Fix a padding issue in
minor
Use when adding new components, patterns, or features in a backward-compatible way. Existing usage should continue to work without changes.Example:
- Add a new
FilterBarpattern - Introduce a new optional prop to an existing component
- Add new icons or tokens
0.1.1 → 0.2.0
- Add a new
major
Use when introducing breaking changes, such as API changes, removed components, or significant behavior updates that require changes in consuming applications.Example:
- Rename or remove component props
- Change component behavior in a non-compatible way
- Remove or restructure patterns
0.2.0 → 1.0.0
The npm version command automatically:
- Updates the version in
package.json - Creates a commit with your message
- Creates a git tag matching the version
Release Flow
Commit your changes:
git add . git commit -m "Your changes"Bump the version:
npm version patch --message "Update version to %s" # or minor/major as neededPush commits and tags:
git push --follow-tagsCreate a GitHub Release:
- Go to GitHub → Releases
- Click "Create a new release"
- Select the tag that was just created
- Add release notes
- Click "Publish release"
Publishing happens automatically:
- When you publish the GitHub Release, the GitHub Actions workflow triggers
- The workflow builds the package and publishes it to npmjs.org
- Publishing only occurs when a GitHub Release is published
Note: The GitHub Actions workflow verifies that the tag version matches the package.json version before publishing.
Troubleshooting
Styles not appearing
- Ensure
transpilePackages: ['@qtalo/qt-ui-library']is in yournext.config.js - Verify Tailwind CSS v4 is installed:
npm list tailwindcss - Clear cache:
rm -rf .next node_modules/.cache - Rebuild:
npm run dev
Type errors
Ensure you have the correct peer dependencies installed with compatible versions.
Components not rendering
Check that you're using React 19+. This library requires React 19.2.3 or higher.
Contributing
See CONTRIBUTING.md for guidelines on contributing to this library.
License
MIT
