From eff5dc9f978260213421b6d737f72749704c9113 Mon Sep 17 00:00:00 2001
From: adilallo <39313955+adilallo@users.noreply.github.com>
Date: Fri, 1 Aug 2025 12:55:52 -0600
Subject: [PATCH] Implemented smallest header breakpoint
---
app/components/Avatar.js | 17 ++++++
app/components/AvatarContainer.js | 20 +++++++
app/components/Button.js | 86 ++++++++++++++++++++++++++++++
app/components/Header.js | 63 ++++++++++++++++++++++
app/components/Logo.js | 40 ++++++++++----
app/components/NavigationItem.js | 55 +++++++++++++++++++
app/globals.css | 5 +-
app/layout.js | 5 +-
package-lock.json | 1 +
package.json | 1 +
postcss.config.mjs | 9 ++--
public/assets/Avatar_1.png | Bin 0 -> 2802 bytes
public/assets/Avatar_2.png | Bin 0 -> 1736 bytes
public/assets/Avatar_3.png | Bin 0 -> 1561 bytes
14 files changed, 286 insertions(+), 16 deletions(-)
create mode 100644 app/components/Avatar.js
create mode 100644 app/components/AvatarContainer.js
create mode 100644 app/components/Button.js
create mode 100644 app/components/Header.js
create mode 100644 app/components/NavigationItem.js
create mode 100644 public/assets/Avatar_1.png
create mode 100644 public/assets/Avatar_2.png
create mode 100644 public/assets/Avatar_3.png
diff --git a/app/components/Avatar.js b/app/components/Avatar.js
new file mode 100644
index 0000000..7ceeda4
--- /dev/null
+++ b/app/components/Avatar.js
@@ -0,0 +1,17 @@
+export default function Avatar({
+ src,
+ alt,
+ size = "small",
+ className = "",
+ ...props
+}) {
+ // Size styles - avatars scale to fit inside the 60px container
+ const sizeStyles = {
+ small: "w-4 h-4", // 16px x 16px to fit in 60px container
+ // Add more sizes as needed: medium, large, xlarge
+ };
+
+ const baseStyles = `rounded-[var(--radius-measures-radius-full)] object-cover ${sizeStyles[size]} ${className}`;
+
+ return
;
+}
diff --git a/app/components/AvatarContainer.js b/app/components/AvatarContainer.js
new file mode 100644
index 0000000..608b4d2
--- /dev/null
+++ b/app/components/AvatarContainer.js
@@ -0,0 +1,20 @@
+export default function AvatarContainer({
+ children,
+ size = "small",
+ className = "",
+ ...props
+}) {
+ // Size styles - container sizes to fit content, not fixed dimensions
+ const sizeStyles = {
+ small: "flex -space-x-2", // Just flex with -8px spacing, no fixed width/height
+ // Add more sizes as needed: medium, large, xlarge
+ };
+
+ const baseStyles = `items-center ${sizeStyles[size]} ${className}`;
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/app/components/Button.js b/app/components/Button.js
new file mode 100644
index 0000000..1294952
--- /dev/null
+++ b/app/components/Button.js
@@ -0,0 +1,86 @@
+export default function Button({
+ children,
+ variant = "default",
+ size = "xsmall",
+ className = "",
+ disabled = false,
+ type = "button",
+ onClick,
+ href,
+ target,
+ rel,
+ ariaLabel,
+ ...props
+}) {
+ // Size styles
+ const sizeStyles = {
+ xsmall:
+ "px-[var(--spacing-scale-006)] py-[var(--spacing-scale-004)] gap-[var(--spacing-scale-001)]",
+ small:
+ "px-[var(--spacing-measures-spacing-008)] py-[var(--spacing-measures-spacing-008)] gap-[var(--spacing-scale-004)]",
+ // Add more sizes as needed: medium, large, xlarge
+ };
+
+ // Font styles based on size
+ const fontStyles = {
+ xsmall:
+ "font-['Inter'] text-[10px] leading-[12px] font-medium tracking-[0%]",
+ small:
+ "font-['Inter'] text-[10px] leading-[12.5px] font-medium tracking-[0%]",
+ };
+
+ // Variant styles
+ const variantStyles = {
+ default:
+ "bg-[var(--color-surface-inverse-primary)] text-[var(--color-content-inverse-primary)] border-2 border-transparent hover:bg-[var(--color-surface-inverse-primary)] hover:text-[var(--color-content-inverse-brand-primary)] hover:border-[var(--border-color-default-brandprimary)] active:bg-[var(--color-surface-inverse-brand-primary)] active:text-[var(--color-content-inverse-primary)] active:border-[var(--border-color-default-brandprimary)] focus:bg-[var(--color-surface-inverse-primary)] focus:text-[var(--color-content-inverse-primary)] focus:shadow-[0_0_10px_#FFFDD2] focus:outline-none disabled:bg-[var(--color-surface-default-secondary)] disabled:text-[var(--color-content-inverse-tertiary)] disabled:cursor-not-allowed disabled:opacity-50",
+ secondary:
+ "bg-transparent text-[var(--color-content-default-primary)] border-2 border-[var(--color-content-default-primary)] hover:bg-[var(--color-surface-default-tertiary)] hover:text-[var(--color-content-default-primary)] active:bg-[var(--color-surface-default-secondary)] active:text-[var(--color-content-default-primary)] focus:bg-transparent focus:text-[var(--color-content-default-primary)] focus:shadow-[0_0_10px_#FFFDD2] focus:outline-none disabled:bg-[var(--color-surface-default-tertiary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-[var(--color-content-default-tertiary)] disabled:cursor-not-allowed disabled:opacity-50",
+ };
+
+ const baseStyles = `inline-flex items-center justify-start ${sizeStyles[size]} rounded-[var(--radius-measures-radius-full)] ${fontStyles[size]} transition-all duration-200 cursor-pointer`;
+
+ // Determine which variant to use
+ let finalVariant = variant;
+ if (disabled) {
+ finalVariant = "default"; // The disabled state is handled by disabled: utilities
+ }
+
+ const combinedStyles = `${baseStyles} ${variantStyles[finalVariant]} ${className}`;
+
+ // Accessibility attributes
+ const accessibilityProps = {
+ ...(ariaLabel && { "aria-label": ariaLabel }),
+ ...(disabled && { "aria-disabled": true }),
+ ...(onClick && { role: "button", tabIndex: 0 }),
+ };
+
+ // If href is provided, render as anchor tag
+ if (href && !disabled) {
+ return (
+
+ {children}
+
+ );
+ }
+
+ // Render as button
+ return (
+
+ );
+}
diff --git a/app/components/Header.js b/app/components/Header.js
new file mode 100644
index 0000000..43962c9
--- /dev/null
+++ b/app/components/Header.js
@@ -0,0 +1,63 @@
+import Logo from "./Logo";
+import NavigationItem from "./NavigationItem";
+import Button from "./Button";
+import AvatarContainer from "./AvatarContainer";
+import Avatar from "./Avatar";
+
+export default function Header() {
+ return (
+
+
+ {/* Logo */}
+
+
+ {/* Navigation */}
+
+
+
+
+
+
+
+ );
+}
diff --git a/app/components/Logo.js b/app/components/Logo.js
index e26070f..585fa0a 100644
--- a/app/components/Logo.js
+++ b/app/components/Logo.js
@@ -1,4 +1,4 @@
-export default function Logo({ size = "default" }) {
+export default function Logo({ size = "default", showText = true }) {
// Size configurations
const sizes = {
default: {
@@ -8,6 +8,20 @@ export default function Logo({ size = "default" }) {
lineHeight: "leading-[27.05px]",
iconSize: "w-[27.05px] h-[27.05px]",
},
+ header: {
+ containerHeight: "h-[14.24px]",
+ gap: "gap-[2.11px]",
+ textSize: "text-[18px]",
+ lineHeight: "leading-[22px]",
+ iconSize: "w-[22px] h-[22px]",
+ },
+ headerLg: {
+ containerHeight: "h-[36px]",
+ gap: "gap-[7px]",
+ textSize: "text-[20px]",
+ lineHeight: "leading-[24px]",
+ iconSize: "w-[24px] h-[24px]",
+ },
footer: {
containerHeight: "h-[calc(40px*1.37)]",
gap: "gap-[calc(8px*1.37)]",
@@ -25,7 +39,11 @@ export default function Logo({ size = "default" }) {
};
const config =
- size === "footer"
+ size === "header"
+ ? sizes.header
+ : size === "headerLg"
+ ? sizes.headerLg
+ : size === "footer"
? sizes.footer
: size === "footerLg"
? sizes.footerLg
@@ -33,14 +51,18 @@ export default function Logo({ size = "default" }) {
return (
- {/* Logo Text */}
-
- CommunityRule
-
+ {/* Logo Text - only show if showText is true */}
+ {showText && (
+
+ CommunityRule
+
+ )}
{/* Vector Icon */}
![]()
+ {children}
+
+ );
+ }
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/app/globals.css b/app/globals.css
index f1d8c73..d13c9fc 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1 +1,4 @@
-@import "tailwindcss";
+@import "./tailwind.css";
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/app/layout.js b/app/layout.js
index 668759b..20c7983 100644
--- a/app/layout.js
+++ b/app/layout.js
@@ -1,11 +1,11 @@
import { Inter, Bricolage_Grotesque } from "next/font/google";
import "./globals.css";
-import "./tailwind.css";
+import Header from "./components/Header";
import Footer from "./components/Footer";
const inter = Inter({
subsets: ["latin"],
- weight: ["400"],
+ weight: ["400", "500"],
variable: "--font-inter",
});
@@ -20,6 +20,7 @@ export default function RootLayout({ children }) {
+
{children}
diff --git a/package-lock.json b/package-lock.json
index 46d0cfe..7205d1a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
"@tailwindcss/postcss": "^4.1.11",
"eslint": "^9",
"eslint-config-next": "15.2.4",
+ "postcss": "^8.5.6",
"tailwindcss": "^4.0.0"
}
},
diff --git a/package.json b/package.json
index 3669805..ac880e0 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"@tailwindcss/postcss": "^4.1.11",
"eslint": "^9",
"eslint-config-next": "15.2.4",
+ "postcss": "^8.5.6",
"tailwindcss": "^4.0.0"
}
}
diff --git a/postcss.config.mjs b/postcss.config.mjs
index c7bcb4b..2df6729 100644
--- a/postcss.config.mjs
+++ b/postcss.config.mjs
@@ -1,5 +1,6 @@
-const config = {
- plugins: ["@tailwindcss/postcss"],
+/** @type {import('postcss-load-config').Config} */
+export default {
+ plugins: {
+ "@tailwindcss/postcss": {},
+ },
};
-
-export default config;
diff --git a/public/assets/Avatar_1.png b/public/assets/Avatar_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..30ab7100805b74da1072b55c8929ce9bf3fa13ac
GIT binary patch
literal 2802
zcmV
Xyi55xM;QTn*()C7HoAr&9zjK=5}vCDnl0dj0Zq5Ly&+`&zU
z{Q8sSGQ$2|I=-Gc8(ld*Qp@?t(>QDs*5#=S3&_}#s(gi6ua3eIh8#wPF=f?!+%vdhJ
z39WN#8llMcqBlZQ;?Y^(hYF+r4Y^c~}najiyN?vi@Qb*LO|gjmPw1AJuctOSunzr_
z;FK|Z9rpBU5Uva3l(`(vvmYWFi(&U;-$pDH!tl{I(bv(1xzH*e{`r$w96OJdB^M?}
z#)yAX)DjBT=4R~s(SeWg-rxkg$|5^wF}f-oCy0|HSx+e+BV*7kn3Ikjmv?
zt+ybsu!O|a7046{tcHS!tpsrDkI$n(S$2H&Zp89A!PIInh-@^5R4jfSkA!X#f+-&o
zNGK>A>scX?^&iPtb}al8!cb$ES%N1q|%E6+N9@xNFZ|Y_V7{
zKRkw2Lg1mtzK>8c4pFXvWH^E{BjGhyk?93%QxOg@-x3r`4+_n|>RsN5v<$D?jp@lL
zm`o<5#T**sO8oESDGUt{L#}FCuMFVf+5Q&`ag;UYfzSfqlp<
zui$KO4b{awlyU{41aC`A3oM2zOwBp55?Dhvor0JY@Pngo!M?Q(?z0!b=`>hlr3gh3
z&1cd6$OBLs^c%eB5s_~jYXq3f*N{e=hyCmvAP;c
z(h{K^D?MnV5`@=#E`ue?_J!X*i@Uq~aDI9cqGDOd(&=BuIp+*?3MDKAw@RbIww5+1
zskUON4DJ;_@_Y&Is~!}I7pz_DYD}
z-r0c`a~*=QC^5Z=B*AT`_Uos9Z>g(?oXF>*nm5&2(B9C5xfLHIbncEF{qU`=L7Jx^
z0;}Mt{`FKEW;{X9%Sgz=fdD@G*GVXnCf;7QQ@a7766sTk5#HD7N9a@JC*19_A
zv^p56d@QkAQ*A~5SZDBvvH)B{`^h9&n_EKDjvg5G2DEPLL^TDm;Bliwgqd^B5f7q-
zf(m&$`^MO5$PGHIEH4v(%fu-j>0$wPjS;?J02-PFG3O%sX+pN{xdkF~HQKgr#Uk;e
z5Q%RHo=ZYElgU`DXXu5$Vs&u|W~&v|?Jd~-$RHBIFs3Nu!5z0kE|=59=LOMG&@S)?
z`!7+W)=&$Ykk98yL`(v?57DQxjap7!4UW!_qYqOASO;h7A
z@uYOzWHue1o4jZ!Qrpb?eNa=jQLi7aKfj1a_uc_dDh3A;Pp?v=L@4MrTEw$y+-!H?
z#KBQ1JZr?`aC6uz1t)5ypO#`Y#$VxRT+}zU*5w)(&VtSeR78GH@IsIHP
z9HPh-kkGtOFtX{i!i<-Q#c(cr;G(*Iu)K(`-*peJEY3qiEh(bkbOf!KvSsiG$cB>c
zFU-#1y{U0wsOe=2jC^=r5UdQ%n0Tpx7;ROmXyO^>Ti6=k8Xb)u+<&K$4BoqB$8hZM$L9SJfS2Z`r7_l4ElY0
zV750RvE*^>>fYJQ4fIB@3xHiS$KJ6OQmLV0JYfraeDFCJu(-H@UYh%vbQ*qwczZ`D
zj3iEFg0nz%We&2L4041>I2uKi)-+nVprjH;C?E+9r}mwFsIxU9oJzXpR{R5x|Nd#$
zrU2s;*Yay8dcyI*u}mgwE0b7c-CiurFCa}BpK;B@6Q|*#)(X3#gj%phO=6Ue!z@(_
zWs^|{)oOI;wKSkiLuc!){U{RCJ!$scs7G5S4Qj3?P%)jK@FX;Qd{#9(UEG4q4!44KNW#%FWw)qg}mOUvysSwC~d=6
zY4~Vq?&pc1dFl`~^>l{PXfl~0Ci04@1TwWMsyElZqH#1l$0?Pr&$9oy0c-}cM9Zs!
z_D2zJCjsb2<{9
literal 0
HcmV?d00001
diff --git a/public/assets/Avatar_2.png b/public/assets/Avatar_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..2127a01618f382be7f2977455432d91a2b2d459d
GIT binary patch
literal 1736
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
LNkvXXu0mjf%hBKH
literal 0
HcmV?d00001