Compare commits
4 Commits
2c35b781dd
...
80b40ce1c0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80b40ce1c0 | ||
|
|
36926c9974 | ||
|
|
be3181ca00 | ||
|
|
8ee524318c |
@@ -3,7 +3,7 @@ import { LoginPage } from './pages/Login'
|
|||||||
import { SignUp } from './pages/SignUp'
|
import { SignUp } from './pages/SignUp'
|
||||||
import { AuthLayout } from './layouts/AuthLayout'
|
import { AuthLayout } from './layouts/AuthLayout'
|
||||||
import { Routes, Route, Navigate } from 'react-router'
|
import { Routes, Route, Navigate } from 'react-router'
|
||||||
import MenuDockVertical from './layouts/DashLayout'
|
import Dashboard from './pages/Dashboard'
|
||||||
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
@@ -20,9 +20,7 @@ function App() {
|
|||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path="/dashboard" element={
|
<Route path="/dashboard" element={
|
||||||
// <div className="min-h-svh bg-background flex justify-start items-start">
|
<Dashboard />
|
||||||
<MenuDockVertical />
|
|
||||||
// </div>
|
|
||||||
} />
|
} />
|
||||||
<Route path="*" element={<Navigate to="/auth/login" replace />} />
|
<Route path="*" element={<Navigate to="/auth/login" replace />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ export const MenuDock = ({
|
|||||||
variant = 'default',
|
variant = 'default',
|
||||||
orientation = 'horizontal',
|
orientation = 'horizontal',
|
||||||
showLabels = true,
|
showLabels = true,
|
||||||
animated = true
|
animated = true,
|
||||||
|
showIndicator = true
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const finalItems = useMemo(() => {
|
const finalItems = useMemo(() => {
|
||||||
@@ -78,22 +79,22 @@ export const MenuDock = ({
|
|||||||
switch (variant) {
|
switch (variant) {
|
||||||
case 'compact':
|
case 'compact':
|
||||||
return {
|
return {
|
||||||
container: 'p-1',
|
container: 'p-1 gap-3',
|
||||||
item: 'p-2 min-w-12',
|
item: 'px-5 py-2',
|
||||||
icon: 'h-4 w-4',
|
icon: 'h-4 w-4',
|
||||||
text: 'text-xs'
|
text: 'text-xs'
|
||||||
};
|
};
|
||||||
case 'large':
|
case 'large':
|
||||||
return {
|
return {
|
||||||
container: 'p-3',
|
container: 'p-3 gap-4',
|
||||||
item: 'p-3 min-w-16',
|
item: 'px-6 py-4',
|
||||||
icon: 'h-6 w-6',
|
icon: 'h-6 w-6',
|
||||||
text: 'text-base'
|
text: 'text-base'
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
container: 'p-2',
|
container: 'p-2 gap-3',
|
||||||
item: 'p-2 min-w-14',
|
item: 'px-5 py-3.5',
|
||||||
icon: 'h-5 w-5',
|
icon: 'h-5 w-5',
|
||||||
text: 'text-sm'
|
text: 'text-sm'
|
||||||
};
|
};
|
||||||
@@ -105,7 +106,7 @@ export const MenuDock = ({
|
|||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative inline-flex items-center rounded-xl bg-card border shadow-sm',
|
'relative inline-flex items-center rounded-3xl bg-transparent',
|
||||||
orientation === 'horizontal' ? 'flex-row' : 'flex-col',
|
orientation === 'horizontal' ? 'flex-row' : 'flex-col',
|
||||||
styles.container,
|
styles.container,
|
||||||
className
|
className
|
||||||
@@ -116,14 +117,17 @@ export const MenuDock = ({
|
|||||||
const IconComponent = item.icon;
|
const IconComponent = item.icon;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<div
|
||||||
key={`${item.label}-${index}`}
|
key={`${item.label}-${index}`}
|
||||||
|
className="flex flex-col items-center gap-1">
|
||||||
|
<button
|
||||||
ref={(el) => { itemRefs.current[index] = el; }}
|
ref={(el) => { itemRefs.current[index] = el; }}
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative flex flex-col items-center justify-center rounded-lg transition-all duration-200',
|
'relative flex items-center justify-center rounded-full transition-all duration-300',
|
||||||
'hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
'hover:bg-primary/10 focus-visible:outline-none',
|
||||||
|
'select-none active:scale-95',
|
||||||
styles.item,
|
styles.item,
|
||||||
isActive && 'text-primary',
|
isActive && 'text-primary bg-primary/15',
|
||||||
!isActive && 'text-muted-foreground hover:text-foreground'
|
!isActive && 'text-muted-foreground hover:text-foreground'
|
||||||
)}
|
)}
|
||||||
onClick={() => handleItemClick(index, item)}
|
onClick={() => handleItemClick(index, item)}
|
||||||
@@ -132,28 +136,28 @@ export const MenuDock = ({
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center justify-center transition-all duration-200',
|
'flex items-center justify-center transition-all duration-200',
|
||||||
animated && isActive && 'animate-bounce',
|
animated && isActive && 'animate-bounce'
|
||||||
orientation === 'horizontal' && showLabels ? 'mb-1' : '',
|
|
||||||
orientation === 'vertical' && showLabels ? 'mb-1' : ''
|
|
||||||
)}>
|
)}>
|
||||||
<IconComponent className={cn(styles.icon, 'transition-colors duration-200')} />
|
<IconComponent className={cn(styles.icon, 'transition-colors duration-200')} />
|
||||||
</div>
|
</div>
|
||||||
|
</button>
|
||||||
{showLabels && (
|
{showLabels && (
|
||||||
<span
|
<span
|
||||||
ref={(el) => { textRefs.current[index] = el; }}
|
ref={(el) => { textRefs.current[index] = el; }}
|
||||||
className={cn(
|
className={cn(
|
||||||
'font-medium transition-colors duration-200 capitalize',
|
'font-medium transition-colors duration-200 capitalize',
|
||||||
styles.text,
|
styles.text,
|
||||||
'whitespace-nowrap'
|
'whitespace-nowrap',
|
||||||
|
isActive ? 'text-primary' : 'text-muted-foreground'
|
||||||
)}>
|
)}>
|
||||||
{item.label}
|
{item.label}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</button>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{/* Animated underline for horizontal orientation with labels */}
|
{/* Animated underline for horizontal orientation with labels */}
|
||||||
{showLabels && orientation === 'horizontal' && (
|
{showIndicator && showLabels && orientation === 'horizontal' && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'absolute bottom-2 h-0.5 bg-primary rounded-full transition-all duration-300 ease-out',
|
'absolute bottom-2 h-0.5 bg-primary rounded-full transition-all duration-300 ease-out',
|
||||||
@@ -165,7 +169,7 @@ export const MenuDock = ({
|
|||||||
}} />
|
}} />
|
||||||
)}
|
)}
|
||||||
{/* Active indicator for vertical orientation or no labels */}
|
{/* Active indicator for vertical orientation or no labels */}
|
||||||
{(!showLabels || orientation === 'vertical') && (
|
{showIndicator && (!showLabels || orientation === 'vertical') && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'absolute bg-primary rounded-full transition-all duration-300',
|
'absolute bg-primary rounded-full transition-all duration-300',
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
'use client';
|
|
||||||
import { MenuDock } from '@/components/ui/shadcn-io/menu-dock';
|
|
||||||
import { Home, Settings, Bell } from 'lucide-react';
|
|
||||||
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
|
|
||||||
const sidebarItems = [
|
|
||||||
{ label: 'home', icon: Home, onClick: () => console.log('Home clicked') },
|
|
||||||
{ label: 'notifications', icon: Bell, onClick: () => console.log('Notifications clicked') },
|
|
||||||
{ label: 'settings', icon: Settings, onClick: () => console.log('Settings clicked') },
|
|
||||||
];
|
|
||||||
export default function MenuDockVertical() {
|
|
||||||
return (
|
|
||||||
<div className="min-h-[180px] p-4 flex justify-start items-start">
|
|
||||||
<div className="flex flex-col items-center justify-center">
|
|
||||||
<Avatar className="mb-2 size-10 justify-center items-center">
|
|
||||||
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
|
||||||
<AvatarFallback>CN</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
<MenuDock
|
|
||||||
items={sidebarItems}
|
|
||||||
variant="compact"
|
|
||||||
orientation="vertical"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -58,6 +58,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-- Inline Sign Styles for Headers --*/
|
||||||
|
.sign-inline {
|
||||||
|
font-family: "Carry-You", cursive;
|
||||||
|
font-size: 3rem;
|
||||||
|
line-height: 1;
|
||||||
|
color: #c6e2ff;
|
||||||
|
animation: neon .08s ease-in-out infinite alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign-pink-inline {
|
||||||
|
font-family: "Carry-You", cursive;
|
||||||
|
font-size: 3rem;
|
||||||
|
line-height: 1;
|
||||||
|
color: #ffc5ec;
|
||||||
|
animation: neon-pink .08s ease-in-out infinite alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@keyframes neon {
|
@keyframes neon {
|
||||||
from {
|
from {
|
||||||
|
|||||||
83
taskncoffee-app/src/pages/Dashboard.jsx
Normal file
83
taskncoffee-app/src/pages/Dashboard.jsx
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
'use client';
|
||||||
|
import '../neon.css';
|
||||||
|
import { MenuDock } from '@/components/ui/shadcn-io/menu-dock';
|
||||||
|
import { Home, Settings, Bell } from 'lucide-react';
|
||||||
|
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
|
||||||
|
|
||||||
|
const menuItems = [
|
||||||
|
{ label: 'home', icon: Home, onClick: () => console.log('Home clicked') },
|
||||||
|
{ label: 'notify', icon: Bell, onClick: () => console.log('Notifications clicked') },
|
||||||
|
{ label: 'settings', icon: Settings, onClick: () => console.log('Settings clicked') },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Dashboard() {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen bg-background">
|
||||||
|
{/* Navigation Rail - Material Design 3 */}
|
||||||
|
<aside className="w-20 bg-card/50 flex flex-col items-center py-4 gap-4">
|
||||||
|
{/* Avatar with large M3 container */}
|
||||||
|
<div className="mb-2">
|
||||||
|
<Avatar className="size-14 rounded-2xl">
|
||||||
|
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
||||||
|
<AvatarFallback className="rounded-2xl">CN</AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<MenuDock
|
||||||
|
items={menuItems}
|
||||||
|
orientation="vertical"
|
||||||
|
animated={false}
|
||||||
|
showIndicator={false}
|
||||||
|
showLabels={true}
|
||||||
|
variant="compact"
|
||||||
|
/>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main Content Area */}
|
||||||
|
<main className="flex-1 p-6 bg-background">
|
||||||
|
<div className="max-w-7xl mx-auto space-y-6">
|
||||||
|
<h1 className="text-3xl font-bold">
|
||||||
|
<span className="sign-pink-inline">Task&</span>
|
||||||
|
<span className="sign-inline">Coffee</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{/* Material Design 3 Cards Grid */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
{/* Filled Card */}
|
||||||
|
<div className="bg-card p-6 rounded-3xl shadow-sm">
|
||||||
|
<h3 className="text-lg font-semibold mb-2">Filled Card</h3>
|
||||||
|
<p className="text-muted-foreground text-sm">
|
||||||
|
Material Design 3 filled container with large rounded corners.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Elevated Card */}
|
||||||
|
<div className="bg-card p-6 rounded-3xl shadow-lg hover:shadow-xl transition-shadow">
|
||||||
|
<h3 className="text-lg font-semibold mb-2">Elevated Card</h3>
|
||||||
|
<p className="text-muted-foreground text-sm">
|
||||||
|
Elevated surface with prominent shadow for hierarchy.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Outlined Card */}
|
||||||
|
<div className="bg-background border-2 border-border p-6 rounded-3xl">
|
||||||
|
<h3 className="text-lg font-semibold mb-2">Outlined Card</h3>
|
||||||
|
<p className="text-muted-foreground text-sm">
|
||||||
|
Outlined container with subtle border emphasis.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Example Section with M3 styling */}
|
||||||
|
<div className="bg-card/30 p-6 rounded-3xl">
|
||||||
|
<h2 className="text-xl font-semibold mb-4">Surface Container</h2>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Material Design 3 emphasizes larger border radius (rounded-3xl) and layered surfaces.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user