feat: Cải thiện giao diện trang chủ với thành phần Banner thông báo, cập nhật cấu trúc điều hướng và tối ưu hóa màu sắc cho phong cách tối giản.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { X } from 'lucide-react';
|
||||
import { Button } from '@/features/shared/components/ui/button';
|
||||
|
||||
/**
|
||||
* EN: Announcement Banner props
|
||||
* VI: Props cho Announcement Banner
|
||||
*/
|
||||
export interface AnnouncementBannerProps {
|
||||
/** Announcement title / Tiêu đề thông báo */
|
||||
title: string;
|
||||
/** Announcement description / Mô tả thông báo */
|
||||
description: string;
|
||||
/** Link text / Text link */
|
||||
linkText: string;
|
||||
/** Link URL / URL link */
|
||||
linkUrl: string;
|
||||
/** Show close button / Hiển thị button đóng */
|
||||
showClose?: boolean;
|
||||
/** On close callback / Callback khi đóng */
|
||||
onClose?: () => void;
|
||||
/** Additional CSS classes / CSS classes bổ sung */
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Announcement Banner - Clean banner for news/announcements (x.ai style)
|
||||
* VI: Announcement Banner - Banner sạch sẽ cho tin tức/thông báo (phong cách x.ai)
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* <AnnouncementBanner
|
||||
* title="New Feature Released"
|
||||
* description="Check out our latest AI capabilities"
|
||||
* linkText="Learn more"
|
||||
* linkUrl="/news"
|
||||
* />
|
||||
* ```
|
||||
*/
|
||||
export function AnnouncementBanner({
|
||||
title,
|
||||
description,
|
||||
linkText,
|
||||
linkUrl,
|
||||
showClose = false,
|
||||
onClose,
|
||||
className,
|
||||
}: AnnouncementBannerProps) {
|
||||
return (
|
||||
<div className={`bg-black/40 backdrop-blur-sm border-b border-white/5 ${className}`}>
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="flex items-center justify-between py-3">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-xs text-text-tertiary uppercase tracking-wider font-medium">
|
||||
News
|
||||
</span>
|
||||
</div>
|
||||
<div className="hidden sm:block w-px h-4 bg-white/20" />
|
||||
<div className="flex items-center space-x-3">
|
||||
<h3 className="text-sm font-medium text-white">
|
||||
{title}
|
||||
</h3>
|
||||
<span className="text-xs text-text-secondary">
|
||||
{description}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-4">
|
||||
<a
|
||||
href={linkUrl}
|
||||
className="text-xs text-text-secondary hover:text-white transition-colors underline"
|
||||
>
|
||||
{linkText}
|
||||
</a>
|
||||
{showClose && onClose && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onPress={onClose}
|
||||
className="p-1 h-auto hover:bg-white/10"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -24,76 +24,82 @@ export interface NavigationHeaderProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Navigation Header - Responsive header with brand logo, theme toggle, and language switcher
|
||||
* VI: Navigation Header - Header responsive với logo, theme toggle và language switcher
|
||||
*
|
||||
* EN: Navigation Header - Clean x.ai style navigation
|
||||
* VI: Navigation Header - Navigation theo phong cách x.ai sạch sẽ
|
||||
*
|
||||
* Features:
|
||||
* - Sticky header with glassmorphism
|
||||
* - Responsive design (mobile menu)
|
||||
* - Brand logo integration
|
||||
* - Theme toggle
|
||||
* - Language switcher
|
||||
* - Clean minimal design
|
||||
* - Navigation menu items
|
||||
* - CTA button
|
||||
*
|
||||
* - Responsive design
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* <NavigationHeader
|
||||
* showCTA
|
||||
* ctaText="Get Started"
|
||||
* onCTAClick={() => router.push('/auth/login')}
|
||||
* />
|
||||
* <NavigationHeader />
|
||||
* ```
|
||||
*/
|
||||
export function NavigationHeader({
|
||||
showCTA = true,
|
||||
ctaText = 'Get Started',
|
||||
onCTAClick,
|
||||
className,
|
||||
}: NavigationHeaderProps) {
|
||||
export function NavigationHeader({ className }: { className?: string }) {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
|
||||
const navItems = [
|
||||
{ name: 'Grok', href: '/chat' },
|
||||
{ name: 'API', href: '/api' },
|
||||
{ name: 'Company', href: '/company' },
|
||||
{ name: 'Careers', href: '/careers' },
|
||||
{ name: 'News', href: '/news' },
|
||||
];
|
||||
|
||||
return (
|
||||
<header
|
||||
className={cn(
|
||||
'sticky top-0 z-50 w-full border-b border-white/10',
|
||||
'bg-bg-primary/30 backdrop-blur-2xl',
|
||||
'sticky top-0 z-50 w-full border-b border-white/5',
|
||||
'bg-black/20 backdrop-blur-sm',
|
||||
'transition-all duration-normal',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="container mx-auto px-6">
|
||||
{/* EN: Main header content / VI: Nội dung header chính */}
|
||||
<div className="flex h-16 items-center justify-between">
|
||||
<div className="flex h-14 items-center justify-between">
|
||||
{/* EN: Logo / VI: Logo */}
|
||||
<BrandLogoLink variant="wordmark" size="sm" href="/" />
|
||||
|
||||
{/* EN: Desktop Navigation / VI: Navigation desktop */}
|
||||
<nav className="hidden md:flex items-center gap-4">
|
||||
<ThemeToggle />
|
||||
<LanguageSwitcher />
|
||||
{showCTA && (
|
||||
<Button
|
||||
variant="brand"
|
||||
size="md"
|
||||
onPress={onCTAClick}
|
||||
className="ml-2"
|
||||
<nav className="hidden md:flex items-center space-x-8">
|
||||
{navItems.map((item) => (
|
||||
<a
|
||||
key={item.name}
|
||||
href={item.href}
|
||||
className="text-text-secondary hover:text-white transition-colors text-sm font-medium"
|
||||
>
|
||||
{ctaText}
|
||||
</Button>
|
||||
)}
|
||||
{item.name}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* EN: CTA Button / VI: Button CTA */}
|
||||
<div className="hidden md:flex items-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onPress={() => window.location.href = '/chat'}
|
||||
className="text-white border border-white/20 hover:bg-white/10 transition-all"
|
||||
>
|
||||
Try Grok
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* EN: Mobile Menu Button / VI: Button menu mobile */}
|
||||
<button
|
||||
className="md:hidden p-2 hover:bg-bg-tertiary rounded-md transition-colors"
|
||||
className="md:hidden p-2 hover:bg-white/5 rounded-md transition-colors"
|
||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||
aria-label="Toggle mobile menu"
|
||||
aria-expanded={mobileMenuOpen}
|
||||
>
|
||||
{mobileMenuOpen ? (
|
||||
<X className="h-6 w-6" />
|
||||
<X className="h-5 w-5 text-white" />
|
||||
) : (
|
||||
<Menu className="h-6 w-6" />
|
||||
<Menu className="h-5 w-5 text-white" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
@@ -101,27 +107,33 @@ export function NavigationHeader({
|
||||
{/* EN: Mobile Menu / VI: Menu mobile */}
|
||||
{mobileMenuOpen && (
|
||||
<div
|
||||
className="md:hidden py-4 space-y-4 border-t border-border-primary animate-fadeIn"
|
||||
className="md:hidden py-4 space-y-4 border-t border-white/5 animate-fadeIn"
|
||||
role="navigation"
|
||||
aria-label="Mobile navigation"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<ThemeToggle />
|
||||
<LanguageSwitcher />
|
||||
</div>
|
||||
{showCTA && (
|
||||
<Button
|
||||
variant="brand"
|
||||
size="lg"
|
||||
onPress={() => {
|
||||
onCTAClick?.();
|
||||
setMobileMenuOpen(false);
|
||||
}}
|
||||
className="w-full"
|
||||
>
|
||||
{ctaText}
|
||||
</Button>
|
||||
)}
|
||||
<nav className="flex flex-col space-y-4">
|
||||
{navItems.map((item) => (
|
||||
<a
|
||||
key={item.name}
|
||||
href={item.href}
|
||||
className="text-text-secondary hover:text-white transition-colors text-sm font-medium py-2"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
>
|
||||
{item.name}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onPress={() => {
|
||||
window.location.href = '/chat';
|
||||
setMobileMenuOpen(false);
|
||||
}}
|
||||
className="text-white border border-white/20 hover:bg-white/10 transition-all w-full mt-4"
|
||||
>
|
||||
Try Grok
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user