Numbered Cards #6
+126
-107
@@ -2,10 +2,28 @@ import Logo from "./Logo";
|
||||
import Separator from "./Separator";
|
||||
|
||||
export default function Footer() {
|
||||
// Schema markup for organization information
|
||||
const schemaData = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
name: "Media Economies Design Lab",
|
||||
email: "medlab@colorado.edu",
|
||||
url: "https://communityrule.com",
|
||||
sameAs: [
|
||||
"https://bsky.app/profile/medlabboulder",
|
||||
"https://gitlab.com/medlabboulder",
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<footer className="bg-[var(--color-surface-default-primary)] w-full">
|
||||
<div
|
||||
className="flex flex-col items-start mx-auto max-w-[1920px]
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaData) }}
|
||||
/>
|
||||
<footer className="bg-[var(--color-surface-default-primary)] w-full">
|
||||
<div
|
||||
className="flex flex-col items-start mx-auto max-w-[1920px]
|
||||
px-[var(--spacing-measures-spacing-016)]
|
||||
py-[var(--spacing-measures-spacing-040)]
|
||||
gap-[var(--spacing-measures-spacing-040)]
|
||||
@@ -15,124 +33,125 @@ export default function Footer() {
|
||||
lg:px-[var(--spacing-measures-spacing-120,120px)]
|
||||
lg:py-[var(--spacing-measures-spacing-096,96px)]
|
||||
lg:gap-[var(--spacing-measures-spacing-060,60px)]"
|
||||
>
|
||||
{/* Logo*/}
|
||||
<div className="block sm:hidden">
|
||||
<Logo />
|
||||
</div>
|
||||
<div className="hidden sm:block lg:hidden">
|
||||
<Logo size="footer" />
|
||||
</div>
|
||||
<div className="hidden lg:block">
|
||||
<Logo size="footerLg" />
|
||||
</div>
|
||||
>
|
||||
{/* Logo*/}
|
||||
<div className="block sm:hidden">
|
||||
<Logo />
|
||||
</div>
|
||||
<div className="hidden sm:block lg:hidden">
|
||||
<Logo size="footer" />
|
||||
</div>
|
||||
<div className="hidden lg:block">
|
||||
<Logo size="footerLg" />
|
||||
</div>
|
||||
|
||||
{/* Content section */}
|
||||
<div className="flex flex-col items-start w-full gap-[var(--spacing-measures-spacing-048,48px)] sm:flex-row sm:justify-between sm:gap-0">
|
||||
{/* Branding Section */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-064,64px)] order-2 sm:order-1">
|
||||
{/* Contact info */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-016,16px)]">
|
||||
<div className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal">
|
||||
Media Economies Design Lab
|
||||
{/* Content section */}
|
||||
<div className="flex flex-col items-start w-full gap-[var(--spacing-measures-spacing-048,48px)] sm:flex-row sm:justify-between sm:gap-0">
|
||||
{/* Branding Section */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-064,64px)] order-2 sm:order-1">
|
||||
{/* Contact info */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-016,16px)]">
|
||||
<div className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal">
|
||||
Media Economies Design Lab
|
||||
</div>
|
||||
<a
|
||||
href="mailto:medlab@colorado.edu"
|
||||
className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
medlab@colorado.edu
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Social media links */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-016,16px)]">
|
||||
<a
|
||||
href="#"
|
||||
className="flex items-center gap-[var(--spacing-measures-spacing-06,6px)] hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer group"
|
||||
aria-label="Follow us on Bluesky"
|
||||
>
|
||||
<img
|
||||
src="/assets/Bluesky_Logo.svg"
|
||||
alt="Bluesky"
|
||||
width={24}
|
||||
height={22}
|
||||
className="flex-shrink-0 group-hover:scale-110 transition-transform"
|
||||
/>
|
||||
<div className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal">
|
||||
medlabboulder
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="flex items-center gap-[var(--spacing-measures-spacing-06,6px)] hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer group"
|
||||
aria-label="Follow us on GitLab"
|
||||
>
|
||||
<img
|
||||
src="/assets/GitLab_Icon.png"
|
||||
alt="GitLab"
|
||||
width={22}
|
||||
height={22}
|
||||
className="flex-shrink-0 grayscale group-hover:scale-110 transition-transform"
|
||||
/>
|
||||
<div className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal">
|
||||
medlabboulder
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Section */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-032,32px)] order-1 sm:order-2 sm:items-end">
|
||||
<a
|
||||
href="mailto:medlab@colorado.edu"
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
medlab@colorado.edu
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Social media links */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-016,16px)]">
|
||||
<a
|
||||
href="#"
|
||||
className="flex items-center gap-[var(--spacing-measures-spacing-06,6px)] hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer group"
|
||||
aria-label="Follow us on Bluesky"
|
||||
>
|
||||
<img
|
||||
src="/assets/Bluesky_Logo.svg"
|
||||
alt="Bluesky"
|
||||
width={24}
|
||||
height={22}
|
||||
className="flex-shrink-0 group-hover:scale-110 transition-transform"
|
||||
/>
|
||||
<div className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal">
|
||||
medlabboulder
|
||||
</div>
|
||||
Use cases
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="flex items-center gap-[var(--spacing-measures-spacing-06,6px)] hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer group"
|
||||
aria-label="Follow us on GitLab"
|
||||
className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src="/assets/GitLab_Icon.png"
|
||||
alt="GitLab"
|
||||
width={22}
|
||||
height={22}
|
||||
className="flex-shrink-0 grayscale group-hover:scale-110 transition-transform"
|
||||
/>
|
||||
<div className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal">
|
||||
medlabboulder
|
||||
</div>
|
||||
Learn
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
About
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Section */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-032,32px)] order-1 sm:order-2 sm:items-end">
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
Use cases
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
Learn
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-primary)] font-['Inter'] text-base leading-5 font-medium tracking-[0%] lg:text-2xl lg:leading-7 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
About
|
||||
</a>
|
||||
<Separator />
|
||||
|
||||
{/* Bottom section */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-032,32px)] sm:flex-row sm:justify-between sm:items-center w-full">
|
||||
<div className="text-[var(--color-content-default-secondary)] font-['Inter'] text-sm leading-5 font-medium sm:text-xs sm:leading-4 lg:text-sm lg:leading-5 lg:font-normal">
|
||||
© All right reserved
|
||||
</div>
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-040,40px)] sm:flex-row sm:gap-[var(--spacing-measures-spacing-040,40px)]">
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-secondary)] font-['Inter'] text-sm leading-5 font-medium underline sm:text-xs sm:leading-4 sm:no-underline lg:text-sm lg:leading-5 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-secondary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
Privacy Policy
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-secondary)] font-['Inter'] text-sm leading-5 font-medium underline sm:text-xs sm:leading-4 sm:no-underline lg:text-sm lg:leading-5 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-secondary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
Terms of Service
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-secondary)] font-['Inter'] text-sm leading-5 font-medium underline sm:text-xs sm:leading-4 sm:no-underline lg:text-sm lg:leading-5 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-secondary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
Cookies Settings
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Bottom section */}
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-032,32px)] sm:flex-row sm:justify-between sm:items-center w-full">
|
||||
<div className="text-[var(--color-content-default-secondary)] font-['Inter'] text-sm leading-5 font-medium sm:text-xs sm:leading-4 lg:text-sm lg:leading-5 lg:font-normal">
|
||||
© All right reserved
|
||||
</div>
|
||||
<div className="flex flex-col items-start gap-[var(--spacing-measures-spacing-040,40px)] sm:flex-row sm:gap-[var(--spacing-measures-spacing-040,40px)]">
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-secondary)] font-['Inter'] text-sm leading-5 font-medium underline sm:text-xs sm:leading-4 sm:no-underline lg:text-sm lg:leading-5 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-secondary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
Privacy Policy
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-secondary)] font-['Inter'] text-sm leading-5 font-medium underline sm:text-xs sm:leading-4 sm:no-underline lg:text-sm lg:leading-5 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-secondary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
Terms of Service
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="text-[var(--color-content-default-secondary)] font-['Inter'] text-sm leading-5 font-medium underline sm:text-xs sm:leading-4 sm:no-underline lg:text-sm lg:leading-5 lg:font-normal hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-secondary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity p-2 -m-2 cursor-pointer"
|
||||
>
|
||||
Cookies Settings
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</footer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
+94
-74
@@ -6,6 +6,18 @@ import AvatarContainer from "./AvatarContainer";
|
||||
import Avatar from "./Avatar";
|
||||
|
||||
export default function Header({ onToggle }) {
|
||||
// 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 navigationItems = [
|
||||
{ href: "#", text: "Use cases", extraPadding: true },
|
||||
{ href: "#", text: "Learn" },
|
||||
@@ -88,96 +100,104 @@ export default function Header({ onToggle }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<header
|
||||
className="bg-[var(--color-surface-default-primary)] w-full border-b border-[var(--border-color-default-tertiary)]"
|
||||
role="banner"
|
||||
aria-label="Main navigation header"
|
||||
>
|
||||
<nav
|
||||
className="flex items-center justify-between mx-auto max-w-[1920px] h-[40px] lg:h-[84px] xl:h-[88px] px-[var(--spacing-measures-spacing-016)] py-[var(--spacing-measures-spacing-008)] lg:px-[var(--spacing-measures-spacing-64,64px)] lg:py-[var(--spacing-measures-spacing-016,16px)]"
|
||||
role="navigation"
|
||||
aria-label="Main navigation"
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaData) }}
|
||||
/>
|
||||
<header
|
||||
className="bg-[var(--color-surface-default-primary)] w-full border-b border-[var(--border-color-default-tertiary)]"
|
||||
role="banner"
|
||||
aria-label="Main navigation header"
|
||||
>
|
||||
{/* Logo - Consistent left positioning across all breakpoints */}
|
||||
<div className="flex items-center">
|
||||
{logoConfig.map((config, index) => (
|
||||
<div key={index} className={config.breakpoint}>
|
||||
{renderLogo(config.size, config.showText)}
|
||||
<nav
|
||||
className="flex items-center justify-between mx-auto max-w-[1920px] h-[40px] lg:h-[84px] xl:h-[88px] px-[var(--spacing-measures-spacing-016)] py-[var(--spacing-measures-spacing-008)] lg:px-[var(--spacing-measures-spacing-64,64px)] lg:py-[var(--spacing-measures-spacing-016,16px)]"
|
||||
role="navigation"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
{/* Logo - Consistent left positioning across all breakpoints */}
|
||||
<div className="flex items-center">
|
||||
{logoConfig.map((config, index) => (
|
||||
<div key={index} className={config.breakpoint}>
|
||||
{renderLogo(config.size, config.showText)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Navigation Links - Consistent center positioning */}
|
||||
<div className="flex items-center">
|
||||
{/* XSmall breakpoint - Navigation items moved to right section */}
|
||||
<div className="block sm:hidden">
|
||||
{/* Empty for XSmall - navigation moved to right */}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Navigation Links - Consistent center positioning */}
|
||||
<div className="flex items-center">
|
||||
{/* XSmall breakpoint - Navigation items moved to right section */}
|
||||
<div className="block sm:hidden">
|
||||
{/* Empty for XSmall - navigation moved to right */}
|
||||
</div>
|
||||
{/* Small breakpoint - All items grouped together, centered */}
|
||||
<div className="hidden sm:block md:hidden">
|
||||
<MenuBar size="default">
|
||||
{renderNavigationItems("xsmall")}
|
||||
{renderLoginButton("xsmall")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
|
||||
{/* Small breakpoint - All items grouped together, centered */}
|
||||
<div className="hidden sm:block md:hidden">
|
||||
<MenuBar size="default">
|
||||
{renderNavigationItems("xsmall")}
|
||||
{renderLoginButton("xsmall")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
<div className="hidden md:block lg:hidden">
|
||||
<MenuBar size="default">
|
||||
{renderNavigationItems("xsmall")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden md:block lg:hidden">
|
||||
<MenuBar size="default">{renderNavigationItems("xsmall")}</MenuBar>
|
||||
</div>
|
||||
<div className="hidden lg:block xl:hidden">
|
||||
<MenuBar size="large">{renderNavigationItems("large")}</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden lg:block xl:hidden">
|
||||
<MenuBar size="large">{renderNavigationItems("large")}</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden xl:block">
|
||||
<MenuBar size="large">{renderNavigationItems("xlarge")}</MenuBar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Authentication Elements - Consistent right alignment across all breakpoints */}
|
||||
<div className="flex items-center">
|
||||
{/* XSmall breakpoint - All navigation items + Create Rule button */}
|
||||
<div className="block sm:hidden">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-001)]">
|
||||
{renderNavigationItems("xsmall")}
|
||||
{renderLoginButton("xsmall")}
|
||||
{renderCreateRuleButton("xsmall", "small", "small")}
|
||||
<div className="hidden xl:block">
|
||||
<MenuBar size="large">{renderNavigationItems("xlarge")}</MenuBar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Small breakpoint - Only Create Rule button */}
|
||||
<div className="hidden sm:block md:hidden">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-004)]">
|
||||
{renderCreateRuleButton("xsmall", "small", "small")}
|
||||
{/* Authentication Elements - Consistent right alignment across all breakpoints */}
|
||||
<div className="flex items-center">
|
||||
{/* XSmall breakpoint - All navigation items + Create Rule button */}
|
||||
<div className="block sm:hidden">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-001)]">
|
||||
{renderNavigationItems("xsmall")}
|
||||
{renderLoginButton("xsmall")}
|
||||
{renderCreateRuleButton("xsmall", "small", "small")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Medium breakpoint */}
|
||||
<div className="hidden md:block lg:hidden">
|
||||
<div className="flex items-center gap-[var(--spacing-measures-spacing-010)]">
|
||||
{renderLoginButton("xsmall")}
|
||||
{renderCreateRuleButton("xsmall", "medium", "medium")}
|
||||
{/* Small breakpoint - Only Create Rule button */}
|
||||
<div className="hidden sm:block md:hidden">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-004)]">
|
||||
{renderCreateRuleButton("xsmall", "small", "small")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Large breakpoint */}
|
||||
<div className="hidden lg:block xl:hidden">
|
||||
<div className="flex items-center gap-[var(--spacing-measures-spacing-004)]">
|
||||
{renderLoginButton("large")}
|
||||
{renderCreateRuleButton("large", "xlarge", "xlarge")}
|
||||
{/* Medium breakpoint */}
|
||||
<div className="hidden md:block lg:hidden">
|
||||
<div className="flex items-center gap-[var(--spacing-measures-spacing-010)]">
|
||||
{renderLoginButton("xsmall")}
|
||||
{renderCreateRuleButton("xsmall", "medium", "medium")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* XLarge breakpoint */}
|
||||
<div className="hidden xl:block">
|
||||
<div className="flex items-center gap-[var(--spacing-measures-spacing-004)]">
|
||||
{renderLoginButton("xlarge")}
|
||||
{renderCreateRuleButton("xlarge", "xlarge", "xlarge")}
|
||||
{/* Large breakpoint */}
|
||||
<div className="hidden lg:block xl:hidden">
|
||||
<div className="flex items-center gap-[var(--spacing-measures-spacing-004)]">
|
||||
{renderLoginButton("large")}
|
||||
{renderCreateRuleButton("large", "xlarge", "xlarge")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* XLarge breakpoint */}
|
||||
<div className="hidden xl:block">
|
||||
<div className="flex items-center gap-[var(--spacing-measures-spacing-004)]">
|
||||
{renderLoginButton("xlarge")}
|
||||
{renderCreateRuleButton("xlarge", "xlarge", "xlarge")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
</nav>
|
||||
</header>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export default function HeaderTab({
|
||||
<img
|
||||
src="/assets/Union_sm_md_lg.svg"
|
||||
alt="Union"
|
||||
className="absolute -bottom-[3.5px] -right-[53px] w-[61px] h-[24px] sm:w-[61px] sm:h-[31.5px] hidden sm:block xl:hidden -z-10"
|
||||
className="absolute -bottom-[3.7px] -right-[53px] w-[61px] h-[24px] sm:w-[61px] sm:h-[31.5px] hidden sm:block xl:hidden -z-10"
|
||||
/>
|
||||
<img
|
||||
src="/assets/Union_xlg.svg"
|
||||
|
||||
+100
-80
@@ -13,6 +13,20 @@ import Header from "./Header";
|
||||
export default function HomeHeader() {
|
||||
const [showRegularHeader, setShowRegularHeader] = useState(false);
|
||||
|
||||
// Schema markup for site navigation (home page specific)
|
||||
const schemaData = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
name: "CommunityRule",
|
||||
url: "https://communityrule.com",
|
||||
description: "Build operating manuals for successful communities",
|
||||
potentialAction: {
|
||||
"@type": "SearchAction",
|
||||
target: "https://communityrule.com/search?q={search_term_string}",
|
||||
"query-input": "required name=search_term_string",
|
||||
},
|
||||
};
|
||||
|
||||
const navigationItems = [
|
||||
{ href: "#", text: "Use cases", extraPadding: true },
|
||||
{ href: "#", text: "Learn" },
|
||||
@@ -139,91 +153,97 @@ export default function HomeHeader() {
|
||||
}
|
||||
|
||||
return (
|
||||
<header
|
||||
className="w-full bg-transparent overflow-hidden"
|
||||
role="banner"
|
||||
aria-label="Home page navigation header"
|
||||
>
|
||||
<nav
|
||||
className="relative flex items-center justify-between mx-auto max-w-[1920px] h-[50px] sm:h-[62px] md:h-[68px] lg:h-[68px] xl:h-[88px] px-[var(--spacing-scale-008)] pr-[var(--spacing-scale-016)] pt-[var(--spacing-scale-010)] sm:px-[var(--spacing-scale-010)] sm:pr-[var(--spacing-scale-020)] sm:pt-[var(--spacing-scale-010)] md:px-[var(--spacing-scale-016)] md:pr-[var(--spacing-scale-032)] md:pt-[var(--spacing-scale-016)] lg:pl-[var(--spacing-scale-024)] lg:pt-[var(--spacing-scale-016)] lg:pr-[var(--spacing-scale-056)] xl:pl-[var(--spacing-scale-048)] xl:pt-[var(--spacing-scale-024)] xl:pr-[var(--spacing-scale-056)]"
|
||||
role="navigation"
|
||||
aria-label="Main navigation"
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaData) }}
|
||||
/>
|
||||
<header
|
||||
className="w-full bg-transparent overflow-hidden"
|
||||
role="banner"
|
||||
aria-label="Home page navigation header"
|
||||
>
|
||||
<HeaderTab className="flex items-center self-end" stretch={true}>
|
||||
{/* Logo - Consistent left positioning within HeaderTab */}
|
||||
<div>
|
||||
{logoConfig.map((config, index) => (
|
||||
<div key={index} className={config.breakpoint}>
|
||||
{renderLogo(config.size, config.showText)}
|
||||
<nav
|
||||
className="relative flex items-center justify-between mx-auto max-w-[1920px] h-[50px] sm:h-[62px] md:h-[68px] lg:h-[68px] xl:h-[88px] px-[var(--spacing-scale-008)] pr-[var(--spacing-scale-016)] pt-[var(--spacing-scale-010)] sm:px-[var(--spacing-scale-010)] sm:pr-[var(--spacing-scale-020)] sm:pt-[var(--spacing-scale-010)] md:px-[var(--spacing-scale-016)] md:pr-[var(--spacing-scale-032)] md:pt-[var(--spacing-scale-016)] lg:pl-[var(--spacing-scale-024)] lg:pt-[var(--spacing-scale-016)] lg:pr-[var(--spacing-scale-056)] xl:pl-[var(--spacing-scale-048)] xl:pt-[var(--spacing-scale-024)] xl:pr-[var(--spacing-scale-056)]"
|
||||
role="navigation"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
<HeaderTab className="flex items-center self-end" stretch={true}>
|
||||
{/* Logo - Consistent left positioning within HeaderTab */}
|
||||
<div>
|
||||
{logoConfig.map((config, index) => (
|
||||
<div key={index} className={config.breakpoint}>
|
||||
{renderLogo(config.size, config.showText)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* XSmall menu bar - positioned next to logo */}
|
||||
<div className="block sm:hidden -me-[2px]">
|
||||
<MenuBar size="default">
|
||||
{renderNavigationItems("xsmall")}
|
||||
{renderLoginButton("xsmall")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
</HeaderTab>
|
||||
|
||||
{/* Navigation Links - Centered in header for SM and up */}
|
||||
<div className="absolute left-1/2 transform -translate-x-1/2 hidden sm:block">
|
||||
<div className="hidden sm:block md:hidden">
|
||||
<MenuBar size="default">
|
||||
{renderNavigationItems("xsmall")}
|
||||
{renderLoginButton("xsmall")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden md:block lg:hidden">
|
||||
<MenuBar size="medium">{renderNavigationItems("homeMd")}</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden lg:block xl:hidden">
|
||||
<MenuBar size="large">{renderNavigationItems("large")}</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden xl:block">
|
||||
<MenuBar size="large">
|
||||
{renderNavigationItems("homeXlarge")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Authentication Elements - Consistent right alignment outside HeaderTab */}
|
||||
<div className="flex items-center">
|
||||
{/* XSmall and Small breakpoints - create rule button outside HeaderTab */}
|
||||
<div className="block md:hidden">
|
||||
{renderCreateRuleButton("xsmall", "small", "small")}
|
||||
</div>
|
||||
|
||||
{/* Medium breakpoint - login outside HeaderTab, create rule outside */}
|
||||
<div className="hidden md:block lg:hidden absolute right-[var(--spacing-measures-spacing-016)]">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-010)]">
|
||||
{renderLoginButton("homeMd")}
|
||||
{renderCreateRuleButton("small", "medium", "medium")}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* XSmall menu bar - positioned next to logo */}
|
||||
<div className="block sm:hidden -me-[2px]">
|
||||
<MenuBar size="default">
|
||||
{renderNavigationItems("xsmall")}
|
||||
{renderLoginButton("xsmall")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
</HeaderTab>
|
||||
{/* Large breakpoint */}
|
||||
<div className="hidden lg:flex xl:hidden items-center">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-004)]">
|
||||
{renderLoginButton("large")}
|
||||
{renderCreateRuleButton("large", "large", "large")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Links - Centered in header for SM and up */}
|
||||
<div className="absolute left-1/2 transform -translate-x-1/2 hidden sm:block">
|
||||
<div className="hidden sm:block md:hidden">
|
||||
<MenuBar size="default">
|
||||
{renderNavigationItems("xsmall")}
|
||||
{renderLoginButton("xsmall")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden md:block lg:hidden">
|
||||
<MenuBar size="medium">{renderNavigationItems("homeMd")}</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden lg:block xl:hidden">
|
||||
<MenuBar size="large">{renderNavigationItems("large")}</MenuBar>
|
||||
</div>
|
||||
|
||||
<div className="hidden xl:block">
|
||||
<MenuBar size="large">
|
||||
{renderNavigationItems("homeXlarge")}
|
||||
</MenuBar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Authentication Elements - Consistent right alignment outside HeaderTab */}
|
||||
<div className="flex items-center">
|
||||
{/* XSmall and Small breakpoints - create rule button outside HeaderTab */}
|
||||
<div className="block md:hidden">
|
||||
{renderCreateRuleButton("xsmall", "small", "small")}
|
||||
</div>
|
||||
|
||||
{/* Medium breakpoint - login outside HeaderTab, create rule outside */}
|
||||
<div className="hidden md:block lg:hidden absolute right-[var(--spacing-measures-spacing-016)]">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-010)]">
|
||||
{renderLoginButton("homeMd")}
|
||||
{renderCreateRuleButton("small", "medium", "medium")}
|
||||
{/* XLarge breakpoint */}
|
||||
<div className="hidden xl:flex items-center">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-004)]">
|
||||
{renderLoginButton("homeXlarge")}
|
||||
{renderCreateRuleButton("xlarge", "xlarge", "xlarge")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Large breakpoint */}
|
||||
<div className="hidden lg:flex xl:hidden items-center">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-004)]">
|
||||
{renderLoginButton("large")}
|
||||
{renderCreateRuleButton("large", "large", "large")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* XLarge breakpoint */}
|
||||
<div className="hidden xl:flex items-center">
|
||||
<div className="flex items-center gap-[var(--spacing-scale-004)]">
|
||||
{renderLoginButton("homeXlarge")}
|
||||
{renderCreateRuleButton("xlarge", "xlarge", "xlarge")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
</nav>
|
||||
</header>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import SectionNumber from "./SectionNumber";
|
||||
|
||||
const NumberedCard = ({ number, text, iconShape, iconColor }) => {
|
||||
return (
|
||||
<div className="bg-[var(--color-surface-inverse-primary)] rounded-[12px] p-5 shadow-lg flex flex-col gap-4 sm:p-8 sm:gap-8 sm:flex-row sm:items-center lg:p-8 lg:gap-0 lg:flex-row lg:items-stretch lg:relative lg:h-[238px]">
|
||||
{/* Section Number - Top right (lg breakpoint) */}
|
||||
<div className="flex justify-end sm:justify-start sm:flex-shrink-0 lg:absolute lg:top-8 lg:right-8">
|
||||
<SectionNumber number={number} />
|
||||
</div>
|
||||
|
||||
{/* Card Content - Bottom left (lg breakpoint) */}
|
||||
<div className="sm:flex-1 lg:absolute lg:bottom-8 lg:left-8 lg:right-16">
|
||||
<p className="font-bricolage-grotesque font-medium text-[24px] leading-[32px] sm:font-normal sm:leading-[24px] sm:text-[24px] lg:text-[24px] lg:leading-[24px] xl:text-[32px] xl:leading-[32px] text-[#141414]">
|
||||
{text}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NumberedCard;
|
||||
@@ -0,0 +1,75 @@
|
||||
"use client";
|
||||
|
||||
import NumberedCard from "./NumberedCard";
|
||||
import SectionHeader from "./SectionHeader";
|
||||
import Button from "./Button";
|
||||
|
||||
const NumberedCards = ({ title, subtitle, cards }) => {
|
||||
// Schema markup for SEO
|
||||
const schemaData = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "HowTo",
|
||||
name: title,
|
||||
description: subtitle,
|
||||
step: cards.map((card, index) => ({
|
||||
"@type": "HowToStep",
|
||||
position: index + 1,
|
||||
name: card.text,
|
||||
text: card.text,
|
||||
})),
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaData) }}
|
||||
/>
|
||||
<section className="bg-transparent py-[var(--spacing-scale-032)] px-[var(--spacing-scale-020)] sm:py-[var(--spacing-scale-048)] sm:px-[var(--spacing-scale-032)] lg:py-[var(--spacing-scale-064)] lg:px-[var(--spacing-scale-064)] xl:py-[var(--spacing-scale-076)] xl:px-[var(--spacing-scale-064)]">
|
||||
<div className="max-w-[var(--spacing-measures-max-width-lg)] mx-auto">
|
||||
<div className="grid grid-cols-1 gap-y-[var(--spacing-scale-032)] lg:gap-y-[var(--spacing-scale-056)]">
|
||||
{/* Section Header */}
|
||||
<div>
|
||||
<SectionHeader
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
titleLg="How CommunityRule helps"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Cards Container */}
|
||||
<div className="grid grid-cols-1 gap-y-[var(--spacing-scale-024)] lg:grid-cols-3 lg:gap-[var(--spacing-scale-024)]">
|
||||
{cards.map((card, index) => (
|
||||
<NumberedCard
|
||||
key={index}
|
||||
number={index + 1}
|
||||
text={card.text}
|
||||
iconShape={card.iconShape}
|
||||
iconColor={card.iconColor}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Call to Action Button */}
|
||||
<div className="text-center sm:text-left lg:text-center">
|
||||
{/* Default button for xsm and sm breakpoints */}
|
||||
<div className="block lg:hidden">
|
||||
<Button variant="default" size="large">
|
||||
Create CommunityRule
|
||||
</Button>
|
||||
</div>
|
||||
{/* Outlined button for lg and xlg breakpoints */}
|
||||
<div className="hidden lg:block">
|
||||
<Button variant="outlined" size="large">
|
||||
See how it works
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default NumberedCards;
|
||||
@@ -0,0 +1,24 @@
|
||||
"use client";
|
||||
|
||||
const SectionHeader = ({ title, subtitle, titleLg }) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-1 w-full lg:flex-row lg:justify-between lg:items-start xl:gap-[var(--spacing-scale-024)]">
|
||||
{/* Title Container - Left side (lg breakpoint) */}
|
||||
<div className="lg:w-[369px] lg:h-[120px] lg:flex lg:items-center xl:w-[452px] xl:h-[156px] xl:flex xl:items-center">
|
||||
<h2 className="font-bricolage-grotesque font-bold text-[28px] leading-[36px] sm:text-[32px] sm:leading-[40px] lg:text-[32px] lg:leading-[40px] lg:w-[369px] lg:pr-24 xl:text-[40px] xl:leading-[52px] xl:w-[452px] xl:pr-24 text-[var(--color-content-default-primary)]">
|
||||
<span className="block lg:hidden">{title}</span>
|
||||
<span className="hidden lg:block">{titleLg || title}</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Subtitle Container */}
|
||||
<div className="lg:w-[928px] lg:h-[120px] lg:flex lg:items-center lg:justify-end xl:w-[763px] xl:h-[156px] xl:flex xl:items-center xl:justify-end">
|
||||
<p className="font-inter font-normal text-[18px] leading-[130%] sm:text-[18px] sm:leading-[32px] lg:text-[24px] lg:leading-[32px] xl:text-[32px] xl:leading-[40px] xl:text-right text-[#484848] sm:text-[var(--color-content-default-tertiary)] lg:text-[var(--color-content-default-tertiary)] xl:text-[var(--color-content-default-tertiary)] tracking-[0px]">
|
||||
{subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionHeader;
|
||||
@@ -0,0 +1,33 @@
|
||||
"use client";
|
||||
|
||||
const SectionNumber = ({ number }) => {
|
||||
const getImageSrc = (num) => {
|
||||
switch (num) {
|
||||
case 1:
|
||||
return "/assets/SectionNumber_1.png";
|
||||
case 2:
|
||||
return "/assets/SectionNumber_2.png";
|
||||
case 3:
|
||||
return "/assets/SectionNumber_3.png";
|
||||
default:
|
||||
return "/assets/SectionNumber_1.png";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative size-[40px] overflow-visible -rotate-[15deg]">
|
||||
<img
|
||||
src={getImageSrc(number)}
|
||||
alt={`Section ${number}`}
|
||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 size-[47.37px] max-w-none"
|
||||
/>
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<span className="text-[var(--font-size-body-small)] font-[var(--font-weight-bold)] text-[var(--color-content-inverse-primary)]">
|
||||
{number}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionNumber;
|
||||
+29
-1
@@ -1,3 +1,31 @@
|
||||
import NumberedCards from "./components/NumberedCards";
|
||||
|
||||
export default function Page() {
|
||||
return <div>{/* home page content will go here */}</div>;
|
||||
const numberedCardsData = {
|
||||
title: "How CommunityRule works",
|
||||
subtitle: "Here's a quick overview of the process, from start to finish.",
|
||||
cards: [
|
||||
{
|
||||
text: "Document how your community makes decisions",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
{
|
||||
text: "Build an operating manual for a successful community",
|
||||
iconShape: "gear",
|
||||
iconColor: "purple",
|
||||
},
|
||||
{
|
||||
text: "Get a link to your manual for your group to review and evolve",
|
||||
iconShape: "star",
|
||||
iconColor: "orange",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<NumberedCards {...numberedCardsData} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,113 @@
|
||||
import NumberedCard from "../app/components/NumberedCard";
|
||||
|
||||
export default {
|
||||
title: "Components/NumberedCard",
|
||||
component: NumberedCard,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"Individual numbered card component that displays a step in a process with a numbered icon and descriptive text. Supports responsive layouts across different breakpoints.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
number: {
|
||||
control: { type: "number", min: 1, max: 9 },
|
||||
description: "The number to display on the card",
|
||||
},
|
||||
text: {
|
||||
control: { type: "text" },
|
||||
description: "The descriptive text for this step",
|
||||
},
|
||||
iconShape: {
|
||||
control: { type: "select" },
|
||||
options: ["blob", "gear", "star"],
|
||||
description:
|
||||
"The shape of the icon background (currently not used, uses PNG images)",
|
||||
},
|
||||
iconColor: {
|
||||
control: { type: "select" },
|
||||
options: ["green", "purple", "orange", "blue"],
|
||||
description:
|
||||
"The color theme for the icon (currently not used, uses PNG images)",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
number: 1,
|
||||
text: "Document how your community makes decisions",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
};
|
||||
|
||||
export const AllNumbers = {
|
||||
args: {
|
||||
number: 1,
|
||||
text: "Example card text",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
render: (args) => (
|
||||
<div className="space-y-4">
|
||||
<NumberedCard {...args} number={1} text="First step in the process" />
|
||||
<NumberedCard
|
||||
{...args}
|
||||
number={2}
|
||||
text="Second step with different content"
|
||||
/>
|
||||
<NumberedCard
|
||||
{...args}
|
||||
number={3}
|
||||
text="Third and final step of the workflow"
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Shows all three numbered cards with different content to demonstrate the visual hierarchy.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const LongText = {
|
||||
args: {
|
||||
number: 1,
|
||||
text: "This is a much longer piece of text that demonstrates how the card handles content that spans multiple lines and requires more space to display properly",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Demonstrates how the card handles longer text content across different breakpoints.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const ResponsiveTest = {
|
||||
args: {
|
||||
number: 2,
|
||||
text: "Test responsive behavior by resizing your browser window",
|
||||
iconShape: "gear",
|
||||
iconColor: "purple",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Test the responsive behavior by resizing your browser window or using the viewport controls in Storybook.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
import NumberedCards from "../app/components/NumberedCards";
|
||||
|
||||
export default {
|
||||
title: "Components/NumberedCards",
|
||||
component: NumberedCards,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A component system for visually communicating multi-step workflows, processes, or value propositions. The component's modular design with NumberedCard and SectionNumber sub-components makes it ideal for explaining any sequential process while maintaining brand consistency and accessibility standards across the design system.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: "text" },
|
||||
description: "The main title for the section",
|
||||
},
|
||||
subtitle: {
|
||||
control: { type: "text" },
|
||||
description: "The subtitle text below the main title",
|
||||
},
|
||||
cards: {
|
||||
control: { type: "object" },
|
||||
description:
|
||||
"Array of card objects with text, iconShape, and iconColor properties",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
title: "How CommunityRule works",
|
||||
subtitle: "Here's a quick overview of the process, from start to finish.",
|
||||
cards: [
|
||||
{
|
||||
text: "Document how your community makes decisions",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
{
|
||||
text: "Build an operating manual for a successful community",
|
||||
iconShape: "gear",
|
||||
iconColor: "purple",
|
||||
},
|
||||
{
|
||||
text: "Get a link to your manual for your group to review and evolve",
|
||||
iconShape: "star",
|
||||
iconColor: "orange",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomContent = {
|
||||
args: {
|
||||
title: "Our Process",
|
||||
subtitle: "Follow these simple steps to get started with your project.",
|
||||
cards: [
|
||||
{
|
||||
text: "Define your project requirements and goals",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
{
|
||||
text: "Collaborate with our team to create the perfect solution",
|
||||
iconShape: "gear",
|
||||
iconColor: "purple",
|
||||
},
|
||||
{
|
||||
text: "Launch and iterate based on user feedback",
|
||||
iconShape: "star",
|
||||
iconColor: "orange",
|
||||
},
|
||||
{
|
||||
text: "Scale and optimize for continued success",
|
||||
iconShape: "blob",
|
||||
iconColor: "blue",
|
||||
},
|
||||
],
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Example with custom content and four cards to show flexibility.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const ResponsiveBreakpoints = {
|
||||
args: {
|
||||
title: "Responsive Design Test",
|
||||
subtitle:
|
||||
"This story demonstrates how the component adapts across different breakpoints: xsm, sm, lg, and xl.",
|
||||
cards: [
|
||||
{
|
||||
text: "Mobile-first design approach",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
{
|
||||
text: "Tablet and desktop optimization",
|
||||
iconShape: "gear",
|
||||
iconColor: "purple",
|
||||
},
|
||||
{
|
||||
text: "Large screen layouts and spacing",
|
||||
iconShape: "star",
|
||||
iconColor: "orange",
|
||||
},
|
||||
],
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Test the responsive behavior by resizing your browser window or using the viewport controls in Storybook.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,106 @@
|
||||
import SectionHeader from "../app/components/SectionHeader";
|
||||
|
||||
export default {
|
||||
title: "Components/SectionHeader",
|
||||
component: SectionHeader,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A section header component that displays a title and subtitle with responsive typography and layout. Supports different title text for large breakpoints and maintains consistent spacing across all screen sizes.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: "text" },
|
||||
description: "The main title text (used for xsm and sm breakpoints)",
|
||||
},
|
||||
subtitle: {
|
||||
control: { type: "text" },
|
||||
description: "The subtitle text below the main title",
|
||||
},
|
||||
titleLg: {
|
||||
control: { type: "text" },
|
||||
description:
|
||||
"The title text for lg and xl breakpoints (optional, falls back to title)",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
title: "How CommunityRule works",
|
||||
subtitle: "Here's a quick overview of the process, from start to finish.",
|
||||
titleLg: "How CommunityRule helps",
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomContent = {
|
||||
args: {
|
||||
title: "Our Mission",
|
||||
subtitle:
|
||||
"We're dedicated to helping communities thrive through better decision-making processes and transparent governance structures.",
|
||||
titleLg: "Building Better Communities",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Example with custom content to show the flexibility of the component.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const LongSubtitle = {
|
||||
args: {
|
||||
title: "Complex Process",
|
||||
subtitle:
|
||||
"This is a much longer subtitle that demonstrates how the component handles extended text content across different breakpoints and layout configurations.",
|
||||
titleLg: "Complex Process Simplified",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Demonstrates how the component handles longer subtitle text across different breakpoints.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const ResponsiveTest = {
|
||||
args: {
|
||||
title: "Responsive Design",
|
||||
subtitle:
|
||||
"Test the responsive behavior by resizing your browser window or using the viewport controls in Storybook.",
|
||||
titleLg: "Responsive Design Test",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Test the responsive behavior by resizing your browser window or using the viewport controls in Storybook.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const WithoutTitleLg = {
|
||||
args: {
|
||||
title: "Simple Header",
|
||||
subtitle:
|
||||
"This example doesn't specify a titleLg prop, so it will use the same title text across all breakpoints.",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Shows the component without a titleLg prop, demonstrating the fallback behavior.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,78 @@
|
||||
import SectionNumber from "../app/components/SectionNumber";
|
||||
|
||||
export default {
|
||||
title: "Components/SectionNumber",
|
||||
component: SectionNumber,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A numbered icon component that displays a number overlaid on a PNG background image. The component uses different PNG images for numbers 1, 2, and 3, with the image extending beyond the 40px container size.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
number: {
|
||||
control: { type: "number", min: 1, max: 3 },
|
||||
description: "The number to display (1, 2, or 3)",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
};
|
||||
|
||||
export const NumberOne = {
|
||||
args: {
|
||||
number: 1,
|
||||
},
|
||||
};
|
||||
|
||||
export const NumberTwo = {
|
||||
args: {
|
||||
number: 2,
|
||||
},
|
||||
};
|
||||
|
||||
export const NumberThree = {
|
||||
args: {
|
||||
number: 3,
|
||||
},
|
||||
};
|
||||
|
||||
export const AllNumbers = {
|
||||
render: () => (
|
||||
<div className="flex space-x-4">
|
||||
<SectionNumber number={1} />
|
||||
<SectionNumber number={2} />
|
||||
<SectionNumber number={3} />
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Shows all three numbered icons side by side to demonstrate the different PNG backgrounds.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const WithBackground = {
|
||||
render: () => (
|
||||
<div className="bg-gray-100 p-8 rounded-lg">
|
||||
<div className="flex space-x-4">
|
||||
<SectionNumber number={1} />
|
||||
<SectionNumber number={2} />
|
||||
<SectionNumber number={3} />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Shows the numbered icons on a background to demonstrate how the PNG images extend beyond the container.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user