diff --git a/app/components/Header/Header.container.tsx b/app/components/Header/Header.container.tsx new file mode 100644 index 0000000..e451d65 --- /dev/null +++ b/app/components/Header/Header.container.tsx @@ -0,0 +1,156 @@ +"use client"; + +import { memo } from "react"; +import { usePathname } from "next/navigation"; +import MenuBarItem from "../MenuBarItem"; +import Button from "../Button"; +import AvatarContainer from "../AvatarContainer"; +import Avatar from "../Avatar"; +import Logo from "../Logo"; +import { getAssetPath, ASSETS } from "../../../lib/assetUtils"; +import { HeaderView } from "./Header.view"; +import type { HeaderProps, NavSize } from "./Header.types"; + +// Configuration data for testing +export const navigationItems = [ + { href: "#", text: "Use cases", extraPadding: true }, + { href: "/learn", text: "Learn" }, + { href: "#", text: "About" }, +]; + +export const avatarImages = [ + { src: getAssetPath(ASSETS.AVATAR_1), alt: "Avatar 1" }, + { src: getAssetPath(ASSETS.AVATAR_2), alt: "Avatar 2" }, + { src: getAssetPath(ASSETS.AVATAR_3), alt: "Avatar 3" }, +]; + +export const logoConfig = [ + { breakpoint: "block sm:hidden", size: "header" as const, showText: false }, + { + breakpoint: "hidden sm:block md:hidden", + size: "header" as const, + showText: true, + }, + { + breakpoint: "hidden md:block lg:hidden", + size: "headerMd" as const, + showText: true, + }, + { + breakpoint: "hidden lg:block xl:hidden", + size: "headerLg" as const, + showText: true, + }, + { breakpoint: "hidden xl:block", size: "headerXl" as const, showText: true }, +]; + +const HeaderContainer = memo(() => { + const pathname = usePathname(); + + // Schema markup for site navigation + const schemaData = { + "@context": "https://schema.org", + "@type": "WebSite", + name: "CommunityRule", + url: "https://communityrule.com", + potentialAction: { + "@type": "SearchAction", + target: "https://communityrule.com/search?q={search_term_string}", + "query-input": "required name=search_term_string", + }, + }; + + const renderNavigationItems = (size: NavSize) => { + return navigationItems.map((item, index) => ( + + {item.text} + + )); + }; + + const renderAvatarGroup = ( + containerSize: "small" | "medium" | "large" | "xlarge", + avatarSize: "small" | "medium" | "large" | "xlarge", + ) => { + return ( + + {avatarImages.map((avatar, index) => ( + + ))} + + ); + }; + + const renderLoginButton = (size: NavSize) => { + return ( + + Log in + + ); + }; + + const renderCreateRuleButton = ( + buttonSize: "xsmall" | "small" | "medium" | "large" | "xlarge", + containerSize: "small" | "medium" | "large" | "xlarge", + avatarSize: "small" | "medium" | "large" | "xlarge", + ) => { + return ( + + ); + }; + + const renderLogo = ( + size: + | "default" + | "homeHeaderXsmall" + | "homeHeaderSm" + | "homeHeaderMd" + | "homeHeaderLg" + | "homeHeaderXl" + | "header" + | "headerMd" + | "headerLg" + | "headerXl" + | "footer" + | "footerLg", + showText: boolean, + ) => { + return ; + }; + + return ( + + ); +}); + +HeaderContainer.displayName = "Header"; + +export default HeaderContainer; diff --git a/app/components/Header/Header.types.ts b/app/components/Header/Header.types.ts new file mode 100644 index 0000000..fd02bc9 --- /dev/null +++ b/app/components/Header/Header.types.ts @@ -0,0 +1,83 @@ +export interface HeaderProps { + // No props currently, but keeping interface for future extensibility +} + +export interface HeaderViewProps { + schemaData: { + "@context": string; + "@type": string; + name: string; + url: string; + potentialAction: { + "@type": string; + target: string; + "query-input": string; + }; + }; + navigationItems: Array<{ + href: string; + text: string; + extraPadding?: boolean; + }>; + avatarImages: Array<{ + src: string; + alt: string; + }>; + logoConfig: Array<{ + breakpoint: string; + size: + | "default" + | "homeHeaderXsmall" + | "homeHeaderSm" + | "homeHeaderMd" + | "homeHeaderLg" + | "homeHeaderXl" + | "header" + | "headerMd" + | "headerLg" + | "headerXl" + | "footer" + | "footerLg"; + showText: boolean; + }>; + pathname: string; + renderNavigationItems: (size: NavSize) => React.ReactNode; + renderAvatarGroup: ( + containerSize: "small" | "medium" | "large" | "xlarge", + avatarSize: "small" | "medium" | "large" | "xlarge", + ) => React.ReactNode; + renderLoginButton: (size: NavSize) => React.ReactNode; + renderCreateRuleButton: ( + buttonSize: "xsmall" | "small" | "medium" | "large" | "xlarge", + containerSize: "small" | "medium" | "large" | "xlarge", + avatarSize: "small" | "medium" | "large" | "xlarge", + ) => React.ReactNode; + renderLogo: ( + size: + | "default" + | "homeHeaderXsmall" + | "homeHeaderSm" + | "homeHeaderMd" + | "homeHeaderLg" + | "homeHeaderXl" + | "header" + | "headerMd" + | "headerLg" + | "headerXl" + | "footer" + | "footerLg", + showText: boolean, + ) => React.ReactNode; +} + +export type NavSize = + | "default" + | "xsmall" + | "xsmallUseCases" + | "home" + | "homeMd" + | "homeUseCases" + | "large" + | "largeUseCases" + | "homeXlarge" + | "xlarge"; diff --git a/app/components/Header.tsx b/app/components/Header/Header.view.tsx similarity index 54% rename from app/components/Header.tsx rename to app/components/Header/Header.view.tsx index 93d833f..e68759e 100644 --- a/app/components/Header.tsx +++ b/app/components/Header/Header.view.tsx @@ -1,151 +1,23 @@ -"use client"; - -import { memo } from "react"; -import { usePathname } from "next/navigation"; -import Logo from "./Logo"; -import MenuBar from "./MenuBar"; -import MenuBarItem from "./MenuBarItem"; -import Button from "./Button"; -import AvatarContainer from "./AvatarContainer"; -import Avatar from "./Avatar"; -import { getAssetPath, ASSETS } from "../../lib/assetUtils"; - -// Configuration data for testing -export const navigationItems = [ - { href: "#", text: "Use cases", extraPadding: true }, - { href: "/learn", text: "Learn" }, - { href: "#", text: "About" }, -]; - -export const avatarImages = [ - { src: getAssetPath(ASSETS.AVATAR_1), alt: "Avatar 1" }, - { src: getAssetPath(ASSETS.AVATAR_2), alt: "Avatar 2" }, - { src: getAssetPath(ASSETS.AVATAR_3), alt: "Avatar 3" }, -]; - -export const logoConfig = [ - { breakpoint: "block sm:hidden", size: "header" as const, showText: false }, - { - breakpoint: "hidden sm:block md:hidden", - size: "header" as const, - showText: true, - }, - { - breakpoint: "hidden md:block lg:hidden", - size: "headerMd" as const, - showText: true, - }, - { - breakpoint: "hidden lg:block xl:hidden", - size: "headerLg" as const, - showText: true, - }, - { breakpoint: "hidden xl:block", size: "headerXl" as const, showText: true }, -]; - -const Header = memo(() => { - const pathname = usePathname(); - - // Schema markup for site navigation - const schemaData = { - "@context": "https://schema.org", - "@type": "WebSite", - name: "CommunityRule", - url: "https://communityrule.com", - potentialAction: { - "@type": "SearchAction", - target: "https://communityrule.com/search?q={search_term_string}", - "query-input": "required name=search_term_string", - }, - }; - - type NavSize = - | "default" - | "xsmall" - | "xsmallUseCases" - | "home" - | "homeMd" - | "homeUseCases" - | "large" - | "largeUseCases" - | "homeXlarge" - | "xlarge"; - - const renderNavigationItems = (size: NavSize) => { - return navigationItems.map((item, index) => ( - - {item.text} - - )); - }; - - const renderAvatarGroup = ( - containerSize: "small" | "medium" | "large" | "xlarge", - avatarSize: "small" | "medium" | "large" | "xlarge", - ) => { - return ( - - {avatarImages.map((avatar, index) => ( - - ))} - - ); - }; - - const renderLoginButton = (size: NavSize) => { - return ( - - Log in - - ); - }; - - const renderCreateRuleButton = ( - buttonSize: "xsmall" | "small" | "medium" | "large" | "xlarge", - containerSize: "small" | "medium" | "large" | "xlarge", - avatarSize: "small" | "medium" | "large" | "xlarge", - ) => { - return ( - - ); - }; - - const renderLogo = ( - size: - | "default" - | "homeHeaderXsmall" - | "homeHeaderSm" - | "homeHeaderMd" - | "homeHeaderLg" - | "homeHeaderXl" - | "header" - | "headerMd" - | "headerLg" - | "headerXl" - | "footer" - | "footerLg", - showText: boolean, - ) => { - return ; - }; +import Logo from "../Logo"; +import MenuBar from "../MenuBar"; +import MenuBarItem from "../MenuBarItem"; +import Button from "../Button"; +import AvatarContainer from "../AvatarContainer"; +import Avatar from "../Avatar"; +import type { HeaderViewProps } from "./Header.types"; +export function HeaderView({ + schemaData, + navigationItems, + avatarImages, + logoConfig, + pathname, + renderNavigationItems, + renderAvatarGroup, + renderLoginButton, + renderCreateRuleButton, + renderLogo, +}: HeaderViewProps) { return ( <>