-
-
Save shricodev/0a77fdb7a5f9b95cfd7aa85e822e0e46 to your computer and use it in GitHub Desktop.
Figma MCP Implementation - Grok 4 - Blog Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @import "tailwindcss"; | |
| :root { | |
| --background: #ffffff; | |
| --foreground: #171717; | |
| --dashboard-bg: #101010; | |
| --sidebar-bg: #101010; | |
| --main-bg: #ffffff; | |
| --right-panel-bg: #f9fafc; | |
| --text-primary: #262a41; | |
| --text-secondary: #273240; | |
| --text-muted: #404852; | |
| --blue-primary: #157aff; | |
| --green-primary: #31ba96; | |
| --orange-primary: #ff8700; | |
| --red-primary: #dc3434; | |
| --purple-primary: #b548c6; | |
| --light-blue: #32a7e2; | |
| --light-green: #4ba83d; | |
| --border-color: #eceff5; | |
| --tips-bg: #edf0f6; | |
| } | |
| @theme inline { | |
| --color-background: var(--background); | |
| --color-foreground: var(--foreground); | |
| --font-sans: var(--font-geist-sans); | |
| --font-mono: var(--font-geist-mono); | |
| --font-poppins: var(--font-poppins); | |
| --color-dashboard-bg: var(--dashboard-bg); | |
| --color-sidebar-bg: var(--sidebar-bg); | |
| --color-main-bg: var(--main-bg); | |
| --color-right-panel-bg: var(--right-panel-bg); | |
| --color-text-primary: var(--text-primary); | |
| --color-text-secondary: var(--text-secondary); | |
| --color-text-muted: var(--text-muted); | |
| --color-blue-primary: var(--blue-primary); | |
| --color-green-primary: var(--green-primary); | |
| --color-orange-primary: var(--orange-primary); | |
| --color-red-primary: var(--red-primary); | |
| --color-purple-primary: var(--purple-primary); | |
| --color-light-blue: var(--light-blue); | |
| --color-light-green: var(--light-green); | |
| --color-border-color: var(--border-color); | |
| --color-tips-bg: var(--tips-bg); | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| :root { | |
| --background: #0a0a0a; | |
| --foreground: #ededed; | |
| } | |
| } | |
| body { | |
| background: var(--background); | |
| color: var(--foreground); | |
| font-family: var(--font-poppins), Arial, Helvetica, sans-serif; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { Metadata } from "next"; | |
| import { Geist, Geist_Mono, Poppins } from "next/font/google"; | |
| import "./globals.css"; | |
| const geistSans = Geist({ | |
| variable: "--font-geist-sans", | |
| subsets: ["latin"], | |
| }); | |
| const geistMono = Geist_Mono({ | |
| variable: "--font-geist-mono", | |
| subsets: ["latin"], | |
| }); | |
| const poppins = Poppins({ | |
| variable: "--font-poppins", | |
| subsets: ["latin"], | |
| weight: ["300", "400", "500", "600", "700"], | |
| }); | |
| export const metadata: Metadata = { | |
| title: "Expense Dashboard", | |
| description: "Dashboard for tracking expenses and financial insights", | |
| }; | |
| export default function RootLayout({ | |
| children, | |
| }: Readonly<{ | |
| children: React.ReactNode; | |
| }>) { | |
| return ( | |
| <html lang="en"> | |
| <body | |
| className={`${geistSans.variable} ${geistMono.variable} ${poppins.variable} antialiased`} | |
| > | |
| {children} | |
| </body> | |
| </html> | |
| ); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Image from "next/image"; | |
| export default function Dashboard() { | |
| return ( | |
| <div className="min-h-screen bg-[#101010] p-5"> | |
| <div className="max-w-[1440px] mx-auto bg-[#101010] rounded-[30px] h-[900px] flex"> | |
| {/* Left Sidebar */} | |
| <div className="w-[280px] p-16 pt-16 pb-16 flex flex-col"> | |
| <Sidebar /> | |
| </div> | |
| {/* Main Content */} | |
| <div className="flex-1 bg-white rounded-[30px] p-20 pt-16 pb-16 mr-5 relative overflow-hidden"> | |
| {/* Background SVG */} | |
| <div className="absolute inset-0 opacity-5"> | |
| <Image | |
| src="/images/background-content.svg" | |
| alt="Background" | |
| fill | |
| className="object-cover" | |
| /> | |
| </div> | |
| <div className="relative z-10"> | |
| <MainContent /> | |
| </div> | |
| </div> | |
| {/* Right Panel */} | |
| <div className="w-[350px] bg-[#f9fafc] rounded-[30px] p-12 pt-16 pb-16"> | |
| <RightPanel /> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function Sidebar() { | |
| return ( | |
| <div className="flex flex-col h-full text-white"> | |
| {/* Profile Section */} | |
| <div className="mb-8"> | |
| <div className="w-[72px] h-[72px] rounded-[13px] bg-white mb-4 overflow-hidden"> | |
| <Image | |
| src="/images/profile-picture.png" | |
| alt="Profile" | |
| width={72} | |
| height={72} | |
| className="w-full h-full object-cover" | |
| /> | |
| </div> | |
| <h3 className="text-[30px] font-semibold leading-[35px] mb-1">Samantha</h3> | |
| <p className="text-[17px] opacity-60">samantha@email.com</p> | |
| </div> | |
| {/* Navigation */} | |
| <nav className="flex-1 space-y-8"> | |
| <div className="text-[25px] font-semibold opacity-50">Dashboard</div> | |
| <div className="text-[25px] font-semibold">Expenses</div> | |
| <div className="text-[25px] font-semibold opacity-50">Wallets</div> | |
| <div className="text-[25px] font-semibold opacity-50">Summary</div> | |
| <div className="text-[25px] font-semibold opacity-50">Accounts</div> | |
| <div className="text-[25px] font-semibold opacity-50">Settings</div> | |
| </nav> | |
| {/* Notification Badge */} | |
| <div className="mt-auto"> | |
| <div className="relative w-[29px] h-[29px] bg-[#dc3434] rounded-full flex items-center justify-center"> | |
| <span className="text-[13px] font-semibold text-white">4</span> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function MainContent() { | |
| return ( | |
| <div className="h-full flex flex-col"> | |
| {/* Header */} | |
| <div className="mb-8"> | |
| <div className="flex items-center justify-between mb-4"> | |
| <h1 className="text-[40px] font-semibold text-[#262a41] leading-[50px]">Expenses</h1> | |
| <div className="flex items-center space-x-4"> | |
| <UserAvatars /> | |
| <div className="w-6 h-6 border-2 border-[#d2dce8] rounded-full flex items-center justify-center"> | |
| <span className="text-[12px] text-[#d8d8d8] font-light">+</span> | |
| </div> | |
| </div> | |
| </div> | |
| <p className="text-[16px] text-[#101010] opacity-50">01 - 25 March, 2020</p> | |
| </div> | |
| {/* Chart */} | |
| <div className="mb-12"> | |
| <ExpenseChart /> | |
| </div> | |
| {/* Transaction List */} | |
| <div className="flex-1 overflow-y-auto"> | |
| <TransactionList /> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function UserAvatars() { | |
| return ( | |
| <div className="flex items-center space-x-[-8px]"> | |
| <div className="w-[31px] h-[31px] rounded-full border-2 border-white overflow-hidden"> | |
| <Image | |
| src="/images/user-avatar-1.png" | |
| alt="User 1" | |
| width={31} | |
| height={31} | |
| className="w-full h-full object-cover" | |
| /> | |
| </div> | |
| <div className="w-[31px] h-[31px] rounded-full border-2 border-white overflow-hidden"> | |
| <Image | |
| src="/images/user-avatar-2.png" | |
| alt="User 2" | |
| width={31} | |
| height={31} | |
| className="w-full h-full object-cover" | |
| /> | |
| </div> | |
| <div className="w-[31px] h-[31px] rounded-full border-2 border-white overflow-hidden"> | |
| <Image | |
| src="/images/user-avatar-3.png" | |
| alt="User 3" | |
| width={31} | |
| height={31} | |
| className="w-full h-full object-cover" | |
| /> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function ExpenseChart() { | |
| const chartData = [ | |
| { height: 35, opacity: 0.2 }, | |
| { height: 52, opacity: 0.2 }, | |
| { height: 44, opacity: 0.2 }, | |
| { height: 27, opacity: 0.2 }, | |
| { height: 35, opacity: 0.2 }, | |
| { height: 30, opacity: 0.2 }, | |
| { height: 44, opacity: 0.2 }, | |
| { height: 27, opacity: 0.2 }, | |
| { height: 35, opacity: 0.2 }, | |
| { height: 52, opacity: 0.2 }, | |
| { height: 44, opacity: 0.2 }, | |
| { height: 35, opacity: 0.2 }, | |
| { height: 30, opacity: 0.2 }, | |
| { height: 44, opacity: 0.2 }, | |
| { height: 27, opacity: 0.2 }, | |
| { height: 35, opacity: 0.2 }, | |
| { height: 52, opacity: 0.2 }, | |
| { height: 44, opacity: 0.2 }, | |
| { height: 35, opacity: 0.2 }, | |
| { height: 30, opacity: 0.2 }, | |
| { height: 60, opacity: 1 }, // Highlighted bar | |
| { height: 44, opacity: 0.2 }, | |
| { height: 27, opacity: 0.2 }, | |
| ]; | |
| return ( | |
| <div className="flex items-end space-x-[6px] h-[60px]"> | |
| {chartData.map((bar, index) => ( | |
| <div | |
| key={index} | |
| className="w-[16px] bg-[#157aff] transition-all duration-300 hover:opacity-80" | |
| style={{ | |
| height: `${bar.height}px`, | |
| opacity: bar.opacity | |
| }} | |
| /> | |
| ))} | |
| </div> | |
| ); | |
| } | |
| function TransactionIcon({ type }: { type: string }) { | |
| const iconComponents = { | |
| grocery: ( | |
| <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M3 3h2l.4 2M7 13a1 1 0 1 0 2 0 1 1 0 0 0-2 0ZM11 13a1 1 0 1 0 2 0 1 1 0 0 0-2 0ZM5 5h9l-1 6H6L5 5Z" | |
| stroke="rgba(0, 0, 0, 0.7)" strokeWidth="1" fill="none"/> | |
| </svg> | |
| ), | |
| transportation: ( | |
| <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M3 6h10v6H3V6Z" stroke="rgba(0, 0, 0, 0.7)" strokeWidth="1" fill="none"/> | |
| <path d="M5 4h6v2H5V4Z" stroke="rgba(0, 0, 0, 0.7)" strokeWidth="1" fill="none"/> | |
| <circle cx="5" cy="13" r="1" stroke="rgba(0, 0, 0, 0.7)" strokeWidth="1" fill="none"/> | |
| <circle cx="11" cy="13" r="1" stroke="rgba(0, 0, 0, 0.7)" strokeWidth="1" fill="none"/> | |
| </svg> | |
| ), | |
| housing: ( | |
| <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M3 12h10v2H3v-2Z" fill="rgba(0, 0, 0, 0.7)"/> | |
| <path d="M8 2l6 6h-2v6H4V8H2l6-6Z" stroke="rgba(0, 0, 0, 0.7)" strokeWidth="1" fill="none"/> | |
| </svg> | |
| ), | |
| food: ( | |
| <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M3 8h10v5H3V8Z" stroke="#2D4E76" strokeWidth="1" fill="#2D4E76"/> | |
| <path d="M5 5v3M7 5v3M9 5v3" stroke="#2D4E76" strokeWidth="1"/> | |
| <path d="M3 8h10" stroke="#2D4E76" strokeWidth="1"/> | |
| </svg> | |
| ), | |
| entertainment: ( | |
| <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M2 4h12v8H2V4Z" stroke="rgba(0, 0, 0, 0.7)" strokeWidth="1" fill="none"/> | |
| <path d="M6 7l4 2-4 2V7Z" fill="rgba(0, 0, 0, 0.7)"/> | |
| </svg> | |
| ), | |
| }; | |
| return ( | |
| <div className="w-4 h-4 flex items-center justify-center"> | |
| {iconComponents[type as keyof typeof iconComponents] || iconComponents.grocery} | |
| </div> | |
| ); | |
| } | |
| function TransactionList() { | |
| const transactions = [ | |
| { | |
| id: 1, | |
| title: "Today", | |
| items: [ | |
| { name: "Grocery", time: "5:12 pm", detail: "Belanja di pasar", amount: "-326.800", icon: "grocery", color: "bg-[#32a7e2]" }, | |
| { name: "Transportation", time: "5:12 pm", detail: "Naik bus umum", amount: "-15.000", icon: "transportation", color: "bg-[#b548c6]" }, | |
| { name: "Housing", time: "5:12 pm", detail: "Bayar Listrik", amount: "-185.750", icon: "housing", color: "bg-[#ff8700]" }, | |
| { name: "Food and Drink", time: "5:12 pm", detail: "Makan Steak", amount: "-156.000", icon: "food", color: "bg-[#dc3434]" }, | |
| ] | |
| }, | |
| { | |
| id: 2, | |
| title: "Monday, 23 March 2020", | |
| items: [ | |
| { name: "Entertainment", time: "5:12 pm", detail: "Nonton Bioskop", amount: "-35.200", icon: "entertainment", color: "bg-[#4ba83d]" }, | |
| ] | |
| } | |
| ]; | |
| return ( | |
| <div className="space-y-8"> | |
| {transactions.map((section) => ( | |
| <div key={section.id}> | |
| <div className="flex items-center mb-6"> | |
| <h3 className="text-[18px] font-normal text-[#262a41] mr-6">{section.title}</h3> | |
| <div className="flex items-center space-x-2"> | |
| <div className="flex space-x-2"> | |
| <div className="w-1 h-1 bg-[#d8d8d8] rounded-full"></div> | |
| <div className="w-1 h-1 bg-[#d8d8d8] rounded-full"></div> | |
| <div className="w-1 h-1 bg-[#d8d8d8] rounded-full"></div> | |
| </div> | |
| <div className="w-full h-px bg-[#dedede] flex-1"></div> | |
| </div> | |
| </div> | |
| <div className="space-y-6"> | |
| {section.items.map((item, index) => ( | |
| <div key={index} className="flex items-center space-x-4 hover:bg-gray-50 p-2 rounded-lg transition-colors"> | |
| <div className={`w-12 h-12 rounded-full ${item.color} flex items-center justify-center text-white`}> | |
| <TransactionIcon type={item.icon} /> | |
| </div> | |
| <div className="flex-1"> | |
| <div className="text-[16px] font-medium text-[#273240]">{item.name}</div> | |
| <div className="text-[14px] text-[#404852] opacity-50">{item.time} • {item.detail}</div> | |
| </div> | |
| <div className="text-[16px] font-semibold text-[#273240]">{item.amount}</div> | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| } | |
| function RightPanel() { | |
| return ( | |
| <div className="h-full flex flex-col"> | |
| {/* Statistics */} | |
| <div className="mb-8"> | |
| <h3 className="text-[20px] font-normal text-[#262a41] mb-8">Where your money go?</h3> | |
| <StatsSection /> | |
| </div> | |
| {/* Tips Section */} | |
| <div className="flex-1"> | |
| <TipsSection /> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| function StatsSection() { | |
| const stats = [ | |
| { name: "Food and Drinks", amount: "872.400", percentage: 28 }, | |
| { name: "Shopping", amount: "1.378.200", percentage: 44 }, | |
| { name: "Housing", amount: "928.500", percentage: 36 }, | |
| { name: "Transportation", amount: "420.700", percentage: 24 }, | |
| { name: "Vehicle", amount: "520.000", percentage: 36 }, | |
| ]; | |
| return ( | |
| <div className="space-y-8"> | |
| {stats.map((stat, index) => ( | |
| <div key={index} className="group"> | |
| <div className="flex justify-between items-center mb-2"> | |
| <span className="text-[13px] font-medium text-[#273240]">{stat.name}</span> | |
| <span className="text-[13px] text-[#273240]">{stat.amount}</span> | |
| </div> | |
| <div className="w-full bg-[#eceff5] rounded-[5px] h-[5px] overflow-hidden"> | |
| <div | |
| className="bg-[#31ba96] h-full rounded-[5px] transition-all duration-300 group-hover:bg-[#2ba086]" | |
| style={{ width: `${stat.percentage}%` }} | |
| /> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| } | |
| function TipsSection() { | |
| return ( | |
| <div className="bg-[#edf0f6] rounded-[15px] p-6 h-[292px] flex flex-col hover:bg-[#e5ecf3] transition-colors"> | |
| <div className="flex-1 flex items-center justify-center"> | |
| <div className="text-center"> | |
| <div className="mb-4 flex justify-center"> | |
| <div className="w-20 h-20 flex items-center justify-center"> | |
| <Image | |
| src="/images/tips-illustration.svg" | |
| alt="Tips illustration" | |
| width={80} | |
| height={80} | |
| className="w-full h-full object-contain" | |
| /> | |
| </div> | |
| </div> | |
| <h4 className="text-[16px] font-semibold text-[#273240] mb-2">Save more money</h4> | |
| <p className="text-[12px] text-[#404852] opacity-70 mb-6 leading-relaxed"> | |
| eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim. | |
| </p> | |
| </div> | |
| </div> | |
| <button className="bg-[#101010] text-white rounded-[8px] py-3 px-6 text-[13px] font-semibold tracking-[0.115em] hover:bg-gray-800 transition-colors"> | |
| VIEW TIPS | |
| </button> | |
| </div> | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment