Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 52 additions & 28 deletions docs/app/(home)/components/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,46 @@
"use client";

import { AnimatePresence, motion, type TargetAndTransition, type Transition } from "motion/react";
import type { ReactNode } from "react";
import type { CSSProperties, ReactNode } from "react";

const NO_SHADOW = "0px 0px 0px rgba(0,0,0,0)";
const DEFAULT_PANEL_INITIAL = { height: 0, opacity: 0 };
const DEFAULT_PANEL_ANIMATE = { height: "auto", opacity: 1 };
const DEFAULT_PANEL_EXIT = { height: 0, opacity: 0 };

interface Transition {
duration?: number;
delay?: number;
ease?: readonly number[] | string;
}

interface PanelTarget {
height?: CSSProperties["height"];
opacity?: CSSProperties["opacity"];
scale?: number;
y?: number;
}

function transitionStyle(transition?: Transition): string | undefined {
if (!transition) return undefined;
const duration = transition.duration ?? 0.3;
const delay = transition.delay ?? 0;
const easing =
Array.isArray(transition.ease) && transition.ease.length === 4
? `cubic-bezier(${transition.ease.join(",")})`
: (transition.ease ?? "ease");
return `all ${duration}s ${easing} ${delay}s`;
}

function panelStyle(target: PanelTarget, transition?: Transition): CSSProperties {
const transforms = [
target.y !== undefined ? `translateY(${target.y}px)` : "",
target.scale !== undefined ? `scale(${target.scale})` : "",
].filter(Boolean);

return {
height: target.height,
opacity: target.opacity,
transform: transforms.length > 0 ? transforms.join(" ") : undefined,
transition: transitionStyle(transition),
};
}

interface AccordionItemProps {
open: boolean;
Expand Down Expand Up @@ -36,54 +70,44 @@ export function AccordionItem({
children,
}: AccordionItemProps) {
return (
<motion.div
<div
className={className}
animate={{
style={{
height: open ? expandedHeight : collapsedHeight,
boxShadow: open ? activeShadow : NO_SHADOW,
zIndex: open ? zIndexOpen : zIndexClosed,
transition: transitionStyle(transition),
}}
transition={transition}
onClick={onActivate}
onMouseEnter={activateOnHover ? onActivate : undefined}
>
{children}
</motion.div>
</div>
);
}

interface AccordionPanelProps {
open: boolean;
className?: string;
transition?: Transition;
initial?: TargetAndTransition;
animate?: TargetAndTransition;
exit?: TargetAndTransition;
initial?: PanelTarget;
animate?: PanelTarget;
exit?: PanelTarget;
children: ReactNode;
}

export function AccordionPanel({
open,
className,
transition,
initial = DEFAULT_PANEL_INITIAL,
animate = DEFAULT_PANEL_ANIMATE,
exit = DEFAULT_PANEL_EXIT,
animate = { height: "auto", opacity: 1 },
children,
}: AccordionPanelProps) {
if (!open) return null;

return (
<AnimatePresence>
{open && (
<motion.div
className={className}
initial={initial}
animate={animate}
exit={exit}
transition={transition}
>
{children}
</motion.div>
)}
</AnimatePresence>
<div className={className} style={panelStyle(animate, transition)}>
{children}
</div>
);
}
47 changes: 40 additions & 7 deletions docs/app/(home)/components/GitHubButton/GitHubButton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import type { JSX, ReactNode } from "react";
import { GitHubIcon, useGitHubStarCount } from "@/components/brand-logo";
import type { JSX, ReactNode } from "react";
import { PillLink } from "../Button/Button";
import styles from "./GitHubButton.module.css";

Expand All @@ -25,9 +25,12 @@ export function parseRepoFromUrl(href: string): string {
* (count-up via requestAnimationFrame) and folds in the repo-parse + fallback
* that Hero duplicated in two places.
*/
export function useGitHubStars(hrefOrRepo: string, options?: { fallback?: number }): number {
export function useGitHubStars(
hrefOrRepo: string,
options?: { fallback?: number; live?: boolean },
): number {
const repo = hrefOrRepo.includes("github.com/") ? parseRepoFromUrl(hrefOrRepo) : hrefOrRepo;
const count = useGitHubStarCount(repo);
const count = useGitHubStarCount(repo, options?.live ?? true);
return count ?? options?.fallback ?? GITHUB_STAR_FALLBACK;
}

Expand Down Expand Up @@ -73,6 +76,8 @@ export interface GitHubButtonProps {
compact?: boolean;
/** desktopGlow only: keep the black pill appearance in dark mode (skip the white flip). */
keepBlack?: boolean;
/** Fetch the live star count. Disable for critical navigation chrome. */
liveCount?: boolean;
}

function cx(...classNames: Array<string | undefined>): string {
Expand All @@ -88,14 +93,40 @@ export function GitHubButton({
classes,
compact,
keepBlack,
liveCount = true,
}: GitHubButtonProps): JSX.Element {
if (variant === "desktopPill") {
return <DesktopPillVariant href={href} label={label} className={className} arrow={arrow} classes={classes} />;
return (
<DesktopPillVariant
href={href}
label={label}
className={className}
arrow={arrow}
classes={classes}
/>
);
}
if (variant === "desktopGlow") {
return <DesktopGlowVariant href={href} className={className} compact={compact} keepBlack={keepBlack} arrow={arrow} />;
return (
<DesktopGlowVariant
href={href}
className={className}
compact={compact}
keepBlack={keepBlack}
arrow={arrow}
liveCount={liveCount}
/>
);
}
return <MobileBannerVariant href={href} label={label} className={className} arrow={arrow} classes={classes} />;
return (
<MobileBannerVariant
href={href}
label={label}
className={className}
arrow={arrow}
classes={classes}
/>
);
}

// --- desktopPill (= HeroSection's DesktopGithubButton) ----------------------
Expand Down Expand Up @@ -129,14 +160,16 @@ function DesktopGlowVariant({
compact,
keepBlack,
arrow,
liveCount,
}: {
href: string;
className?: string;
compact?: boolean;
keepBlack?: boolean;
arrow?: ReactNode;
liveCount: boolean;
}): JSX.Element {
const count = useGitHubStars(href);
const count = useGitHubStars(href, { live: liveCount });
const label = String(count);

return (
Expand Down
22 changes: 7 additions & 15 deletions docs/app/(home)/sections/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
"use client";
import svgPaths from "@/imports/svg-urruvoh2be";
import { useId } from "react";
import styles from "./Footer.module.css";

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -55,9 +53,8 @@ const SOCIAL_LINKS: SocialLink[] = [
// Sub-components
// ---------------------------------------------------------------------------

function SocialIcon({ link }: { link: SocialLink }) {
const uniqueId = useId();
const clipPathId = link.clipId ? `${link.clipId}-${uniqueId}` : undefined;
function SocialIcon({ link, idPrefix }: { link: SocialLink; idPrefix: string }) {
const clipPathId = link.clipId ? `${idPrefix}-${link.clipId}` : undefined;

const svgContent = clipPathId ? (
<svg className={styles.absoluteSvg} fill="none" viewBox={link.viewBox}>
Expand Down Expand Up @@ -95,11 +92,11 @@ function SocialIcon({ link }: { link: SocialLink }) {
);
}

function SocialIcons() {
function SocialIcons({ idPrefix }: { idPrefix: string }) {
return (
<div className={styles.socialIcons}>
{SOCIAL_LINKS.map((link) => (
<SocialIcon key={link.label} link={link} />
<SocialIcon key={link.label} link={link} idPrefix={idPrefix} />
))}
</div>
);
Expand All @@ -123,12 +120,7 @@ function ThesysLogo() {
function HandcraftedMascot() {
return (
// eslint-disable-next-line @next/next/no-img-element
<img
className={styles.handcraftedMascot}
src="/shiro-logo.svg"
alt=""
aria-hidden="true"
/>
<img className={styles.handcraftedMascot} src="/shiro-logo.svg" alt="" aria-hidden="true" />
);
}

Expand Down Expand Up @@ -170,14 +162,14 @@ export function Footer() {
<div className={styles.bottomBar}>
<div className={styles.desktopBottomBar}>
<p className={styles.desktopMetaLeft}>355 Bryant St, San Francisco, CA 94107</p>
<SocialIcons />
<SocialIcons idPrefix="footer-desktop" />
<p className={styles.desktopMetaRight}>
© {new Date().getFullYear()} Thesys Inc. All Rights Reserved
</p>
</div>

<div className={styles.mobileBottomBar}>
<SocialIcons />
<SocialIcons idPrefix="footer-mobile" />
<div className={styles.mobileMeta}>
<p className={styles.mobileMetaText}>
© {new Date().getFullYear()} Thesys Inc. All Rights Reserved
Expand Down
2 changes: 0 additions & 2 deletions docs/app/(home)/sections/Navbar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"use client";

import { SiteMarketingHeader } from "@/components/site-marketing-header";

export function Navbar() {
Expand Down
Loading
Loading