Loading header...

Components UI

Giới thiệu

Dự án sử dụng một hệ thống components UI đã được tối ưu và tùy chỉnh. Các components được thiết kế để dễ sử dụng, linh hoạt và nhất quán trên toàn bộ ứng dụng.

OptimizedImage

OptimizedImage là một wrapper cho next/image với các tính năng bổ sung như xử lý lỗi, tùy chọn hình ảnh và hỗ trợ tốt hơn cho lazy loading.

Cách sử dụng

1import { OptimizedImage } from "@/components/ui/optimized-image"; 2 3// Cơ bản 4<OptimizedImage 5 src="/path/to/image.jpg" 6 alt="Mô tả hình ảnh" 7 width={800} 8 height={600} 9/> 10 11// Fill container 12<div className="relative w-full h-64"> 13 <OptimizedImage 14 src="/path/to/image.jpg" 15 alt="Mô tả hình ảnh" 16 fill 17 priority 18 /> 19</div> 20 21// Với objectFit 22<OptimizedImage 23 src="/path/to/image.jpg" 24 alt="Mô tả hình ảnh" 25 fill 26 objectFit="contain" 27/>

Props

PropTypeMặc địnhMô tả
srcstring(bắt buộc)Đường dẫn đến hình ảnh
altstring(bắt buộc)Mô tả hình ảnh cho accessibility
widthnumberundefinedChiều rộng của hình ảnh
heightnumberundefinedChiều cao của hình ảnh
prioritybooleanfalseTải hình ảnh với mức ưu tiên cao hơn
classNamestringundefinedClass CSS cho component
sizesstring"100vw"Kích thước responsive cho hình ảnh
fillbooleanfalseLàm đầy container cha
objectFit"cover" | "contain" | "fill" | "none" | "scale-down""cover"Cách hình ảnh được hiển thị trong container
qualitynumber80Chất lượng hình ảnh
placeholder"blur" | "empty"undefinedLoại placeholder
blurDataURLstringundefinedURL cho blurred placeholder

Layout Components

Container

1<div className="container mx-auto px-4"> 2 Nội dung 3</div>

Grid Layout

1<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> 2 <div>Item 1</div> 3 <div>Item 2</div> 4 <div>Item 3</div> 5</div>

Flex Layout

1<div className="flex flex-col md:flex-row items-center justify-between"> 2 <div>Item bên trái</div> 3 <div>Item bên phải</div> 4</div>

Text Components

Headings

1<h1 className="text-4xl font-bold mb-6">Tiêu đề chính</h1> 2<h2 className="text-3xl font-bold mb-4">Tiêu đề phụ</h2> 3<h3 className="text-2xl font-bold mb-3">Tiêu đề cấp 3</h3> 4<h4 className="text-xl font-bold mb-2">Tiêu đề cấp 4</h4>

Paragraphs

1<p className="text-base text-gray-700 mb-4"> 2 Đoạn văn bản thông thường. 3</p> 4 5<p className="text-sm text-gray-500"> 6 Đoạn văn bản nhỏ hơn, thường dùng cho chú thích. 7</p>

Interactive Components

Buttons

1// Primary Button 2<button className="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition duration-300"> 3 Nút chính 4</button> 5 6// Secondary Button 7<button className="border border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white font-medium py-2 px-4 rounded-lg transition duration-300"> 8 Nút phụ 9</button> 10 11// Ghost Button 12<button className="text-blue-600 hover:text-blue-700 font-medium transition duration-300"> 13 Nút văn bản 14</button>

Form Controls

1// Input 2<input 3 type="text" 4 className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" 5 placeholder="Nhập thông tin..." 6/> 7 8// Textarea 9<textarea 10 className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" 11 rows={4} 12 placeholder="Nhập nội dung..." 13/> 14 15// Select 16<select className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"> 17 <option value="">Chọn một mục</option> 18 <option value="option1">Tùy chọn 1</option> 19 <option value="option2">Tùy chọn 2</option> 20</select> 21 22// Checkbox 23<div className="flex items-center"> 24 <input 25 type="checkbox" 26 id="checkbox" 27 className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" 28 /> 29 <label htmlFor="checkbox" className="ml-2 text-gray-700"> 30 Tùy chọn 31 </label> 32</div>

Cards

Blog Card

1import { OptimizedImage } from "@/components/ui/optimized-image"; 2import Link from "next/link"; 3 4function BlogCard({ post, locale }) { 5 return ( 6 <div className="bg-white rounded-lg shadow-md overflow-hidden"> 7 {post.cover?.absolute_url && ( 8 <div className="relative aspect-video overflow-hidden"> 9 <OptimizedImage 10 src={post.cover.absolute_url} 11 alt={post.title} 12 fill 13 className="transition-transform hover:scale-105 duration-300" 14 /> 15 </div> 16 )} 17 18 <div className="p-5"> 19 <h3 className="text-xl font-semibold mb-2"> 20 <Link href={`/${locale}/blog/${post.slug}`} className="hover:text-blue-600"> 21 {post.title} 22 </Link> 23 </h3> 24 25 {post.description && ( 26 <p className="text-gray-600 mb-4 line-clamp-2"> 27 {post.description} 28 </p> 29 )} 30 31 <div className="text-sm text-gray-500"> 32 {new Date(post.created_at).toLocaleDateString()} 33 </div> 34 </div> 35 </div> 36 ); 37}

Sử dụng biến Tailwind

Dự án sử dụng TailwindCSS với một số biến tùy chỉnh. Bạn có thể tham khảo file tailwind.config.ts để xem danh sách đầy đủ các biến.

1// Sử dụng màu theo brand 2<div className="bg-primary text-white"> 3 Nội dung với màu chính 4</div> 5 6// Sử dụng font sizes 7<p className="text-base md:text-lg"> 8 Văn bản responsive 9</p> 10 11// Sử dụng spacing 12<div className="p-4 md:p-6 lg:p-8"> 13 Nội dung với spacing khác nhau 14</div>

Responsive Design

Tất cả các components đều được thiết kế để responsive và hoạt động tốt trên tất cả các kích thước màn hình.

1<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"> 2 {/* Các items sẽ hiển thị 1, 2, 3 hoặc 4 cột tùy thuộc vào kích thước màn hình */} 3</div>

Khuyến nghị và thực tiễn tốt nhất

  1. Sử dụng OptimizedImage: Luôn sử dụng OptimizedImage thay vì Image từ next/image trực tiếp
  2. Tailwind Classes: Tổ chức các classes Tailwind một cách logic và nhất quán
  3. Responsive: Luôn thiết kế cho mobile-first, sau đó mở rộng cho các màn hình lớn hơn
  4. Typography: Tuân thủ hệ thống typography đã định nghĩa
  5. Tối ưu hóa: Sử dụng priority cho LCP (Largest Contentful Paint) images
  6. A11y: Đảm bảo tất cả các images có thuộc tính alt phù hợp

Đầu tư là chiến thuật. Cấu trúc là chiến lược.