rnxcmkidd: Add the viewport-fit bento shell and a dev feed preview with fixtures
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"use client";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import type { Person } from "@/lib/auth-client";
|
||||
import { useTheme } from "@/lib/use-theme";
|
||||
import { HexAvatar } from "./HexAvatar";
|
||||
import { Logo } from "./Logo";
|
||||
|
||||
const iconProps = {
|
||||
viewBox: "0 0 24 24",
|
||||
fill: "none",
|
||||
stroke: "currentColor",
|
||||
strokeWidth: 1.7,
|
||||
strokeLinecap: "round",
|
||||
strokeLinejoin: "round",
|
||||
"aria-hidden": true,
|
||||
} as const;
|
||||
|
||||
function SunIcon() {
|
||||
return (
|
||||
<svg {...iconProps}>
|
||||
<circle cx="12" cy="12" r="4" />
|
||||
<path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function MoonIcon() {
|
||||
return (
|
||||
<svg {...iconProps}>
|
||||
<path d="M20.5 14.5A8.5 8.5 0 0 1 9.5 3.5a8.5 8.5 0 1 0 11 11z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
/** Left account panel: logo, wordmark, theme toggle, the person, live status. */
|
||||
export function AccountPanel({ person }: { person: Person }) {
|
||||
const { theme, toggleTheme } = useTheme();
|
||||
const next = theme === "dark" ? "light" : "dark";
|
||||
return (
|
||||
<section className="tile account" aria-label="Account">
|
||||
<div className="account-brand">
|
||||
<Logo size={32} />
|
||||
<span className="account-word type-wordmark">MINNECT</span>
|
||||
<button type="button" className="account-theme" aria-label={`Switch to ${next} theme`} title={`Switch to ${next} theme`} onClick={toggleTheme}>
|
||||
{theme === "dark" ? <SunIcon /> : <MoonIcon />}
|
||||
</button>
|
||||
</div>
|
||||
<div className="account-me">
|
||||
<HexAvatar name={person.name || person.email} pictureUrl={person.pictureUrl} size="lg" />
|
||||
<div className="account-me-text">
|
||||
<strong>{person.name}</strong>
|
||||
<span>{person.email}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="account-live">
|
||||
<span className="account-dot" aria-hidden="true" />
|
||||
Feed updates live
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export interface AppShellProps {
|
||||
person: Person;
|
||||
/** Find experts panel (left column, under the account panel). */
|
||||
search: ReactNode;
|
||||
/** Feed panel (center column). */
|
||||
feed: ReactNode;
|
||||
/** Featured experts and Trending minnects panels (right column). */
|
||||
discover: ReactNode;
|
||||
}
|
||||
|
||||
/** Signed-in bento shell (spec "Desktop and tablet layout", ADR 0001 section 3). */
|
||||
export function AppShell({ person, search, feed, discover }: AppShellProps) {
|
||||
return (
|
||||
<div className="app">
|
||||
<main className="bento">
|
||||
<div className="bento-col bento-left">
|
||||
<AccountPanel person={person} />
|
||||
{search}
|
||||
</div>
|
||||
<div className="bento-col bento-center">{feed}</div>
|
||||
<aside className="bento-col bento-right" aria-label="Discover">
|
||||
{discover}
|
||||
</aside>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user