pressly-ui
v0.2.1
Published
React UI component library with dynamic theming and CMS
Downloads
6
Maintainers
Readme
@pressly/ui
A React UI component library with dynamic theming capabilities. Built with TypeScript, Tailwind CSS, and Radix UI primitives.
Features
- 🎨 Dynamic Theming - Apply colors, fonts, and branding at runtime via CSS variables
- 🧩 Pre-built Components - Comprehensive set of accessible UI components
- 📦 Tree Shakeable - Only bundle what you use
- 🔷 TypeScript First - Full type definitions included
- 🎯 Tailwind CSS - Built with utility-first CSS
- ⚡ React 18 & 19 - Compatible with both versions
Installation
npm install @pressly/uiPeer Dependencies
This library requires the following peer dependencies to be installed in your project:
npm install react react-dom @radix-ui/react-accordion @radix-ui/react-avatar @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-navigation-menu @radix-ui/react-separator @radix-ui/react-slot @radix-ui/react-toast lucide-reactMinimum Required Versions:
react: ^18.0.0 || ^19.0.0react-dom: ^18.0.0 || ^19.0.0@radix-ui/react-accordion: ^1.0.0@radix-ui/react-avatar: ^1.0.0@radix-ui/react-dialog: ^1.0.0@radix-ui/react-dropdown-menu: ^2.0.0@radix-ui/react-label: ^2.0.0@radix-ui/react-navigation-menu: ^1.0.0@radix-ui/react-separator: ^1.0.0@radix-ui/react-slot: ^1.0.0@radix-ui/react-toast: ^1.0.0lucide-react: ^0.300.0
Quick Start
1. Configure Tailwind CSS
Add the library's Tailwind preset to your tailwind.config.ts:
import type { Config } from 'tailwindcss';
import uiPreset from '@pressly/ui/tailwind-preset';
const config: Config = {
presets: [uiPreset],
content: [
'./src/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
'./node_modules/@pressly/ui/dist/**/*.{js,mjs}',
],
};
export default config;2. Import Styles
Import the library's CSS in your root layout or global CSS file:
/* app/globals.css or src/styles/globals.css */
@import '@pressly/ui/styles';
@tailwind base;
@tailwind components;
@tailwind utilities;3. Wrap Your App with ThemeProvider
import { ThemeProvider } from '@pressly/ui';
function App() {
return (
<ThemeProvider>
{/* Your app content */}
</ThemeProvider>
);
}Usage
ThemeProvider
The ThemeProvider component accepts business settings and applies them as CSS variables throughout your application.
Basic Usage
import { ThemeProvider } from '@pressly/ui';
function App() {
return (
<ThemeProvider
theme={{
primaryColor: '#0ea5e9',
secondaryColor: '#64748b',
accentColor: '#f59e0b',
backgroundColor: '#ffffff',
textColor: '#0f172a',
headingFont: 'Inter',
bodyFont: 'Inter',
brandName: 'My Company',
logo: '/logo.png',
}}
>
{/* Your app content */}
</ThemeProvider>
);
}Dynamic Theme from API
import { ThemeProvider } from '@pressly/ui';
import { useEffect, useState } from 'react';
function App() {
const [settings, setSettings] = useState(null);
useEffect(() => {
// Fetch business settings from your API
fetch('/api/business-settings')
.then(res => res.json())
.then(setSettings);
}, []);
return (
<ThemeProvider theme={settings}>
{/* Your app content */}
</ThemeProvider>
);
}Business Settings Object Structure
The BusinessSettings interface defines all available theme configuration options:
interface BusinessSettings {
// Colors (hex format)
primaryColor?: string; // Main brand color
secondaryColor?: string; // Secondary brand color
accentColor?: string; // Accent/highlight color
backgroundColor?: string; // Page background color
textColor?: string; // Primary text color
// Typography
headingFont?: string; // Font family for headings
bodyFont?: string; // Font family for body text
// Branding
brandName?: string; // Company/brand name
logo?: string; // Logo URL or path
// Header Configuration
globalHeader?: {
fields: {
logo?: string;
show_cta?: boolean;
brand_name?: string;
cta_button_link?: string;
cta_button_text?: string;
navigation_links?: Array<{
url: string;
label: string;
external?: boolean;
}>;
};
componentSlug: string;
};
// Footer Configuration
globalFooter?: {
fields: {
logo?: string;
brand_name?: string;
tagline?: string;
copyright_text?: string;
hours?: string;
contact_info?: Array<{
type: string;
label: string;
value: string;
}>;
social_links?: Array<{
url: string;
icon: string;
platform: string;
}>;
footer_links?: Array<{
url: string;
label: string;
}>;
terms_url?: string;
privacy_url?: string;
};
componentSlug: string;
};
}Component Examples
Button
import { Button } from '@pressly/ui';
function MyComponent() {
return (
<div>
<Button>Default Button</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
</div>
);
}Card
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@pressly/ui';
function MyComponent() {
return (
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card description goes here</CardDescription>
</CardHeader>
<CardContent>
<p>Card content</p>
</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>
);
}Form Components
import { Input, Label } from '@pressly/ui';
function MyForm() {
return (
<div className="space-y-4">
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="Enter your email" />
</div>
<div>
<Label htmlFor="password">Password</Label>
<Input id="password" type="password" placeholder="Enter your password" />
</div>
</div>
);
}Typography
import { Heading, Text } from '@pressly/ui';
function MyComponent() {
return (
<div>
<Heading level={1}>Main Heading</Heading>
<Heading level={2}>Subheading</Heading>
<Text>Regular paragraph text</Text>
<Text variant="muted">Muted text</Text>
<Text variant="small">Small text</Text>
</div>
);
}Layout Components
import { Container, Section, Grid } from '@pressly/ui';
function MyPage() {
return (
<Section>
<Container>
<Grid cols={3} gap={4}>
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
</Grid>
</Container>
</Section>
);
}Header and Footer
import { ThemeProvider, Header, Footer } from '@pressly/ui';
function App() {
const settings = {
primaryColor: '#0ea5e9',
brandName: 'My Company',
globalHeader: {
fields: {
logo: '/logo.png',
brand_name: 'My Company',
show_cta: true,
cta_button_text: 'Get Started',
cta_button_link: '/signup',
navigation_links: [
{ url: '/', label: 'Home' },
{ url: '/about', label: 'About' },
{ url: '/contact', label: 'Contact' },
],
},
componentSlug: 'global-header',
},
globalFooter: {
fields: {
logo: '/logo.png',
brand_name: 'My Company',
tagline: 'Building amazing products',
copyright_text: '© 2024 My Company. All rights reserved.',
social_links: [
{ url: 'https://twitter.com/mycompany', icon: 'twitter', platform: 'Twitter' },
{ url: 'https://github.com/mycompany', icon: 'github', platform: 'GitHub' },
],
footer_links: [
{ url: '/privacy', label: 'Privacy Policy' },
{ url: '/terms', label: 'Terms of Service' },
],
},
componentSlug: 'global-footer',
},
};
return (
<ThemeProvider theme={settings}>
<Header />
<main>
{/* Your page content */}
</main>
<Footer />
</ThemeProvider>
);
}Dialog
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, Button } from '@pressly/ui';
function MyComponent() {
return (
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
<DialogDescription>Dialog description goes here</DialogDescription>
</DialogHeader>
<div>Dialog content</div>
</DialogContent>
</Dialog>
);
}Toast Notifications
import { Toaster, useToast } from '@pressly/ui';
function App() {
return (
<>
<MyComponent />
<Toaster />
</>
);
}
function MyComponent() {
const { toast } = useToast();
return (
<Button
onClick={() => {
toast({
title: 'Success',
description: 'Your action was completed successfully.',
});
}}
>
Show Toast
</Button>
);
}Available Components
UI Components
Button- Button with multiple variants and sizesCard,CardHeader,CardTitle,CardDescription,CardContent,CardFooter- Card componentsInput- Text input fieldLabel- Form labelHeading- Heading component with levels 1-6Text- Text component with variantsAvatar,AvatarImage,AvatarFallback- Avatar componentsBadge- Badge componentSeparator- Visual separatorSkeleton- Loading skeletonLoading- Loading spinner
Layout Components
Container- Responsive containerSection- Page section wrapperGrid- Grid layoutHeader- Site header with navigationFooter- Site footerNavigation- Navigation menu
Interactive Components
Dialog,DialogTrigger,DialogContent,DialogHeader,DialogTitle,DialogDescription,DialogFooter- Dialog/modalDropdownMenu,DropdownMenuTrigger,DropdownMenuContent,DropdownMenuItem,DropdownMenuSeparator- Dropdown menuAccordion,AccordionItem,AccordionTrigger,AccordionContent- AccordionToast,Toaster,useToast- Toast notifications
Providers & Hooks
ThemeProvider- Theme context provideruseTheme- Hook to access theme context
Utilities
cn()- Class name merging utility
Customization
Using Your Own Components with Theme
You can use the theme CSS variables in your own components:
import { useTheme } from '@pressly/ui';
function MyCustomComponent() {
const theme = useTheme();
return (
<div className="bg-primary text-primary-foreground p-4 rounded-lg">
<h2 className="font-heading text-2xl">{theme.brandName}</h2>
<p className="font-body">Custom component using theme variables</p>
</div>
);
}Overriding CSS Variables
You can override CSS variables in your own CSS:
:root {
--primary: 200 100% 50%; /* HSL format */
--radius: 0.5rem;
}Extending Tailwind Configuration
You can extend the Tailwind preset with your own customizations:
import type { Config } from 'tailwindcss';
import uiPreset from '@pressly/ui/tailwind-preset';
const config: Config = {
presets: [uiPreset],
content: [
'./src/**/*.{js,ts,jsx,tsx,mdx}',
'./node_modules/@pressly/ui/dist/**/*.{js,mjs}',
],
theme: {
extend: {
colors: {
custom: '#ff0000',
},
},
},
};
export default config;TypeScript Support
All components and utilities are fully typed. Import types as needed:
import type { BusinessSettings, ThemeContextValue } from '@pressly/ui';
const settings: BusinessSettings = {
primaryColor: '#0ea5e9',
brandName: 'My Company',
};License
MIT
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
Support
For issues and questions, please open an issue on GitHub.
