Utility Functions¶
Breadcrumbs: Documentation > Guides > Utilities > Utility Functions
This guide documents the utility functions in lib/utils.ts.
Available Utilities¶
cn()¶
Purpose: Merge Tailwind CSS classes with conflict resolution.
Signature:
Usage:
import { cn } from '@/lib/utils';
// Basic usage
cn('px-4 py-2', 'rounded-lg'); // "px-4 py-2 rounded-lg"
// Conditional classes
cn('base-class', isActive && 'active-class', isDisabled && 'disabled-class');
// Override classes (last wins)
cn('px-4', 'px-6'); // "px-6"
// In components
<div className={cn('default-classes', className)}>
How it works:
- Uses
clsxfor conditional classes - Uses
tailwind-mergeto resolve conflicts - Returns single class string
Example in component:
interface ButtonProps {
variant?: 'default' | 'outline';
className?: string;
}
export function Button({ variant = 'default', className }: ButtonProps) {
return (
<button
className={cn(
'rounded-lg px-4 py-2 font-medium transition-colors',
variant === 'default' && 'bg-primary text-primary-foreground',
variant === 'outline' && 'border border-primary',
className // Allow override from props
)}
>
{children}
</button>
);
}
isVideoFile()¶
Purpose: Check if a file path is a video file.
Signature:
Supported formats:
.mp4.webm.mov
Usage:
import { isVideoFile } from '@/lib/utils';
// Filter videos from project images
const images = project.images.filter((img) => !isVideoFile(img.src));
const videos = project.images.filter((img) => isVideoFile(img.src));
// Conditional rendering
{
isVideoFile(src) ? (
<video src={src} controls />
) : (
<Image src={src} alt={alt} width={800} height={600} />
);
}
Implementation:
export function isVideoFile(src: string): boolean {
return (
src.toLowerCase().endsWith(".mp4") ||
src.toLowerCase().endsWith(".webm") ||
src.toLowerCase().endsWith(".mov")
);
}
Implementation¶
File: lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function isVideoFile(src: string): boolean {
return (
src.toLowerCase().endsWith(".mp4") ||
src.toLowerCase().endsWith(".webm") ||
src.toLowerCase().endsWith(".mov")
);
}
Adding Custom Utilities¶
Example: Format date:
// lib/utils.ts
export function formatDate(date: string | Date): string {
const d = typeof date === "string" ? new Date(date) : date;
return d.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
}
// Usage
formatDate("2024-02-09"); // "February 9, 2024"
Example: Truncate text:
export function truncate(text: string, length: number = 100): string {
if (text.length <= length) return text;
return text.slice(0, length) + "...";
}
// Usage
truncate("Long description here", 50);
Testing Utilities¶
// lib/__tests__/utils.test.ts
import { cn, isVideoFile } from "@/lib/utils";
describe("cn", () => {
it("should merge classes", () => {
expect(cn("px-4", "py-2")).toBe("px-4 py-2");
});
it("should handle conflicts", () => {
expect(cn("px-4", "px-6")).toBe("px-6");
});
});
describe("isVideoFile", () => {
it("should detect video files", () => {
expect(isVideoFile("video.mp4")).toBe(true);
expect(isVideoFile("image.jpg")).toBe(false);
});
});
See Also¶
Last Updated: February 2026