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 {alt}; +} 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 zcmVXyi55xM;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 zcmV;(1~>VMP)9s4I>`wMC(!6i*Gw*FpS9Q8>-Md+C6q`Wk8q??I0Zv` zKtSrEB^Lx7>Prbh`u0jfi~wTLWH4NDyQN?$a;5)bc;*o_9 zcDLl+oo@$HEl%TGA;ej2ZF3VKFJMyv(rL0)WQC9vgMmIWU@`$lW1a#boi`bAZYPfv zJpfxRr^PL@*u~GuB#_w1C@qC#I!KuXFq?B)ylGi_x0p9{2blDTE|C_OSvf0=#sEdZ zYY`vBX3hNaAtXgQ-PR_J6!7Ffu;rTaB)K{qDP8%*#28jrmkQR{0G7dFW0}GrF0+n& zo}33b=E<~p%#6H&EiaYE$A+-tUqLhyL}zCoYHDj?v)K!HDk>->CRL-?EK5hUoXB~A z6Haq`ERI*Acp`zc!e*KB0T&*6y81A(rE=R z=cf^iMc{DMK%wVEBBic-y)Q_C0)x?nuFf7**VGm4^x0Ou3y;OdZ+ zG?({TNsYZC)^@XgZEXeN^*QwQ9)#6u&8;sl`|;DI>!_(|fzP)LyWN7&dH}M)q=rM1 zjA(3ZMpLt!yj832;fkgx93gZBrJ z+=!xXZ#kmTIC}fKv9F;CvXn$wxs{SLfKVuetq^8(5jj$da*9JRz)xza6rs_PL45kj zhuDb}MaIV;oxsLM7{epec<^8tRaLcEU5mmJQ_$4pLQ9LgU=Qn3(NdBIjD(e46kbXu zz3|o5WgI@_MtQkK_by6xy093))vLe3UR4dZ%ZUJ$;?&ej5=9%>o*>dixo<&Fab;@)`Nb^?l{Uw>6tU1k!Q_# zHZcX4%Z1t5S+r3em6cWG_UGwx$k>I9rcK@2&zEjsJ(Qr#cOo1LQ0ZCee?98!Td?9A z$I+v2;o+mlaJk*^EzF~wx>COK?IdT13ALqeCkcgaxqts5JTqZcAX}VF#Zm8UBG?XR z%&D%WGLuk47~x-8!ol`7G&I)hGy31@A`DsA$z?>$TIe+jMT}C>b{P%&M2ut)@M3xa zcm5iOkgDORGQsbkhuLCN!w`>!s0uP56N_d-)_$;6{X`;BGR&qwK-O3u;m8B>ZGPZM zW;5?gmq{mTNw?nGWTVg`!1>rdb}ZAcfe}fa?i<={p7j;xjR(ASLLY3#Ixs_2g=>w zZ{9`Q8{Im2nhqXXS+{DlFv#cmm%CIhL9*1);D$e7pagt@4380CfAu-_|H2uwveJ&( zd9|nE*BiI7x4wg{m37u@b0Sa7>KcD>U#7A90{^#G=u5J>`2gY@c3i!78*_6D>e{{r zXCV{WG&(wlU#<B3NLv=K~G&a$`P4gU9wNm2Wlk>jK#CJW**ij&A<&eU;!qH0$&e#bn_t0`w0 zENiDbVo8@%IhFp7;Q9-cN(5|-EnMEOeL3AuTqOybALVrVgk+F9#kT8trm2Y$8qo&J e2wh9Pp8pG@uETXWDJs7J0000_uX^OJ@;IJCPm7z zINahsPhh7IavLO4G#odtry!7)QVdCno3CDJijwuPKadud_i8A0Nm0^Ovz@%k%K0#VpN?pdI7WmjbtM|BQEz9zZgY zs82wWHwD94DTDPv*#pM)V_H$i?cu{mxOnjj-rTbXZYhgKB19B@eOGY&c=sZn;8n6x z>swwYhe9WzXP?sG1^CJK)z???#;#rP+-Wi{U|9=a{2s_-_wL<9;@ToKU4ua=o>0r% zF|qH}3c0dsu~5S5_zGmRImF{hT)K1_f$szHC@gR7c^$=K4y~;bluC_O3uA=IlIS7q z(+-zc9SFa;)QabM7#$t0|4woUUo-y%o@S?U=gv>4USJZPog2~Ko-`PY<-}dWc1Ulh z)+wTqY~Q{e$z%e)C(@Y*80hcEty{k!6ly`CkV7W@0FO6s!pgRI*;$#)L-LGk2pB9% zNQ&G}hjdJFa2paxCfCyyqZv!%nT;5{+mE|<2LmO+dhLkCY?B+TmzWp0l2)Znjn`JH zSpsa(aYE|Omt3SeGB)dkLafiZUP-}xM>{Gn%((xrk@WWuU}ok8Y~9*{T<(8{flIcI z965}TV=Ehn*Y1zlVbd4=9($VlkR^Nj-OLSck5z1F&s} z2nfYjR+$j$ip5qCftGpWN~S0{BCVgRH^wAo?BL)CxiLbuV1hC@jzpr3j9F9}{bDkQ zb?e%Y&(Dxv7=MjEpu&VE#P)flEz0QM0%rtrsB15tJoy*Hzh@AMw5VA+4qvue1(L>W zm1NOq3xtPJ9@WXnd|8DJcON^13twEujT`?V98udTd7>Sg zH?5~x&thiQp(Qv#9x378y&>&b<#nMlUoFFWEsqEp0`5%*)Ih>3e8`nahap&6JmaIs z4pPSJ5}nWIapA(ZiU7;xZ*ZuPxaXty!(I985 z)R_b)o-!+hfzl*9Iudw$@BVoJ5^XD2QGR3t5>?!yMvIzO!d6r)OP-Y;5l{^ShoOE^ zVlvt3r&MxTFGoA&95!rNRY6Xg*-w*AOO@Yzeoj3Hv)6qhcg+3>cweUO_akj-1r}e4aScMTrK_3PiGySqz$ryCjVNyhTqvidC<3N@jql!=K+ zeEi90w6u00000 LNkvXXu0mjf%hBKH literal 0 HcmV?d00001