Cleanup assets

This commit is contained in:
adilallo
2026-05-21 22:56:34 -06:00
parent f3b73527fc
commit 28de8ef3bc
83 changed files with 506 additions and 240 deletions
@@ -7,10 +7,10 @@ export type CaseStudySurfaceValue = (typeof CASE_STUDY_SURFACE_OPTIONS)[number];
export interface CaseStudyProps {
surface: CaseStudySurfaceValue;
/**
* Alt text for built-in raster art (`public/assets/use-cases/`) when **`visual`** is omitted.
* Alt text for built-in SVG art (`public/assets/case-study/`) when **`visual`** is omitted.
*/
imageAlt?: string;
/** Overrides built-in raster with custom slot content when provided. */
/** Overrides built-in artwork with custom slot content when provided. */
visual?: ReactNode;
className?: string;
}
@@ -2,6 +2,7 @@
import Image from "next/image";
import { memo } from "react";
import { caseStudyVisualPath, getAssetPath } from "../../../../lib/assetUtils";
import type { CaseStudyProps } from "./CaseStudy.types";
const SURFACE_CLASS: Record<CaseStudyProps["surface"], string> = {
@@ -12,9 +13,9 @@ const SURFACE_CLASS: Record<CaseStudyProps["surface"], string> = {
/** Default art per tile: Figma-exported SVG composites (305×305 incl. rounded bg). */
const SURFACE_ART: Record<CaseStudyProps["surface"], string> = {
lavender: "/assets/case-study/case-study-mutual-aid.svg",
neutral: "/assets/case-study/case-study-food-not-bombs.svg",
rose: "/assets/case-study/case-study-boulder-county-street-medics.svg",
lavender: getAssetPath(caseStudyVisualPath("lavender")),
neutral: getAssetPath(caseStudyVisualPath("neutral")),
rose: getAssetPath(caseStudyVisualPath("rose")),
};
/** Figma: ~23px corner (“Card / CaseStudy” shells). */
@@ -1,6 +1,6 @@
import ListItem from "../../layout/ListItem";
import Popover from "../Popover";
import { getAssetPath } from "../../../../lib/assetUtils";
import { ASSETS, getAssetPath } from "../../../../lib/assetUtils";
import type { ModalHeaderProps } from "./ModalHeader.types";
const iconButtonClass =
@@ -37,7 +37,7 @@ export function ModalHeaderView({
>
{/* eslint-disable-next-line @next/next/no-img-element -- icon asset */}
<img
src={getAssetPath("assets/Icon_Close.svg")}
src={getAssetPath(ASSETS.ICON_CLOSE)}
alt=""
className="w-[16px] h-[16px]"
style={{
+14 -14
View File
@@ -2,6 +2,11 @@
import Image from "next/image";
import { memo } from "react";
import {
getAssetPath,
shareIconPath,
type ShareIconName,
} from "../../../../lib/assetUtils";
import ContentLockup from "../../type/ContentLockup";
import Button from "../../buttons/Button";
import ModalHeader from "../ModalHeader";
@@ -9,21 +14,16 @@ import ModalFooter from "../ModalFooter";
import { CreateModalFrameView } from "../Create/CreateModalFrame.view";
import type { ShareChannelTileProps, ShareViewProps } from "./Share.types";
/** Decorative glyphs in `public/assets/Share/` — sizes match prior inline SVGs within the 60×60 circles. */
/** Decorative glyphs in `public/assets/share/` — sizes match prior inline SVGs within the 60×60 circles. */
function ShareAssetIcon(props: {
src:
| "/assets/Share/Discord.svg"
| "/assets/Share/Link.svg"
| "/assets/Share/Mail.svg"
| "/assets/Share/Signal.svg"
| "/assets/Share/Slack.svg";
name: ShareIconName;
width: number;
height: number;
}) {
const { src, width, height } = props;
const { name, width, height } = props;
return (
<Image
src={src}
src={getAssetPath(shareIconPath(name))}
alt=""
width={width}
height={height}
@@ -111,31 +111,31 @@ export const ShareView = memo(function ShareView({
label={copyLinkLabel}
onClick={onCopyLink}
circleClassName="border-[#444444] bg-[#333333]"
icon={<ShareAssetIcon src="/assets/Share/Link.svg" width={24} height={24} />}
icon={<ShareAssetIcon name="link" width={24} height={24} />}
/>
<ShareChannelTile
label={signalLabel}
onClick={onSignalShare}
circleClassName="border-[#3a76f0] bg-[#3a76f0]"
icon={<ShareAssetIcon src="/assets/Share/Signal.svg" width={26} height={26} />}
icon={<ShareAssetIcon name="signal" width={26} height={26} />}
/>
<ShareChannelTile
label={slackLabel}
onClick={onSlackShare}
circleClassName="border-[#4a154b] bg-[#4a154b]"
icon={<ShareAssetIcon src="/assets/Share/Slack.svg" width={26} height={26} />}
icon={<ShareAssetIcon name="slack" width={26} height={26} />}
/>
<ShareChannelTile
label={discordLabel}
onClick={onDiscordShare}
circleClassName="border-[#5865f2] bg-[#5865f2]"
icon={<ShareAssetIcon src="/assets/Share/Discord.svg" width={30} height={30} />}
icon={<ShareAssetIcon name="discord" width={30} height={30} />}
/>
<ShareChannelTile
label={emailLabel}
onClick={onEmailShare}
circleClassName="border-[var(--color-surface-default-brand-kiwi)] bg-[var(--color-surface-default-brand-kiwi)]"
icon={<ShareAssetIcon src="/assets/Share/Mail.svg" width={24} height={24} />}
icon={<ShareAssetIcon name="mail" width={24} height={24} />}
/>
</div>
</div>
@@ -25,9 +25,9 @@ const NAV_SIZE_TO_MENU_ITEM_SIZE: Record<NavSize, MenuClusterSize> = {
};
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" },
{ src: getAssetPath(ASSETS.AVATAR_2), alt: "Avatar 2" },
{ src: getAssetPath(ASSETS.AVATAR_1), alt: "Avatar 1" },
];
const TopContainer = memo<TopProps>(
+4 -4
View File
@@ -3,7 +3,7 @@
import { memo } from "react";
import Script from "next/script";
import { useTranslation } from "../../../contexts/MessagesContext";
import { getAssetPath } from "../../../../lib/assetUtils";
import { ASSETS, getAssetPath } from "../../../../lib/assetUtils";
import Menu from "../Menu";
import type { TopViewProps } from "./Top.types";
@@ -61,21 +61,21 @@ function TopView({
{/* Decorative Union images for tab appearance */}
{/* eslint-disable-next-line @next/next/no-img-element -- decorative SVG, not content */}
<img
src={getAssetPath("assets/Union_xsm.svg")}
src={getAssetPath(ASSETS.UNION_XSM)}
alt=""
role="presentation"
className="absolute -bottom-[3px] -right-[52px] w-[61px] h-[24px] sm:w-[61px] sm:h-[31.5px] sm:hidden -z-10"
/>
{/* eslint-disable-next-line @next/next/no-img-element -- decorative SVG */}
<img
src={getAssetPath("assets/Union_sm_md_lg.svg")}
src={getAssetPath(ASSETS.UNION_SM_MD_LG)}
alt=""
role="presentation"
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"
/>
{/* eslint-disable-next-line @next/next/no-img-element -- decorative SVG */}
<img
src={getAssetPath("assets/Union_xlg.svg")}
src={getAssetPath(ASSETS.UNION_XLG)}
alt=""
role="presentation"
className="absolute -bottom-[6px] -right-[94px] w-[105px] h-[53px] hidden xl:block -z-10"
@@ -2,6 +2,7 @@
import { memo } from "react";
import {
ASSETS,
getAssetPath,
contentBlogHorizontalPath,
contentBlogSectionPath,
@@ -36,7 +37,7 @@ const ContentBannerContainer = memo<ContentBannerProps>(
return contentBlogHorizontalPath(blogPost.slug);
}
return getAssetPath("assets/Content_Banner.svg");
return getAssetPath(ASSETS.CONTENT_BANNER);
};
const resolveSectionImage = (blogPost: BlogPost): string => {
@@ -1,6 +1,7 @@
"use client";
import { memo, useMemo } from "react";
import { getAssetPath, featurePanelPath } from "../../../../lib/assetUtils";
import { useTranslation } from "../../../contexts/MessagesContext";
import FeatureGridView from "./FeatureGrid.view";
import type { FeatureGridProps, Feature } from "./FeatureGrid.types";
@@ -19,7 +20,7 @@ const FeatureGridContainer = memo<FeatureGridProps>(
labelLine2: t(
"pages.home.featureGrid.features.decisionMaking.labelLine2",
),
panelContent: "/assets/Feature_Support.png",
panelContent: getAssetPath(featurePanelPath("support")),
ariaLabel: t("featureGrid.features.decisionMaking.ariaLabel"),
href: "#decision-making",
},
@@ -31,7 +32,7 @@ const FeatureGridContainer = memo<FeatureGridProps>(
labelLine2: t(
"pages.home.featureGrid.features.valuesAlignment.labelLine2",
),
panelContent: "/assets/Feature_Exercises.png",
panelContent: getAssetPath(featurePanelPath("exercises")),
ariaLabel: t("featureGrid.features.valuesAlignment.ariaLabel"),
href: "#values-alignment",
},
@@ -43,7 +44,7 @@ const FeatureGridContainer = memo<FeatureGridProps>(
labelLine2: t(
"pages.home.featureGrid.features.membershipGuidance.labelLine2",
),
panelContent: "/assets/Feature_Guidance.png",
panelContent: getAssetPath(featurePanelPath("guidance")),
ariaLabel: t("featureGrid.features.membershipGuidance.ariaLabel"),
href: "#membership-guidance",
},
@@ -55,7 +56,7 @@ const FeatureGridContainer = memo<FeatureGridProps>(
labelLine2: t(
"pages.home.featureGrid.features.conflictResolution.labelLine2",
),
panelContent: "/assets/Feature_Tools.png",
panelContent: getAssetPath(featurePanelPath("tools")),
ariaLabel: t("featureGrid.features.conflictResolution.ariaLabel"),
href: "#conflict-resolution",
},
@@ -4,7 +4,7 @@ import { memo } from "react";
import { useTranslation } from "../../../contexts/MessagesContext";
import ContentLockup from "../../type/ContentLockup";
import HeroDecor from "./HeroDecor";
import { getAssetPath } from "../../../../lib/assetUtils";
import { ASSETS, getAssetPath } from "../../../../lib/assetUtils";
interface HeroBannerProps {
title?: string;
@@ -48,7 +48,7 @@ const HeroBanner = memo<HeroBannerProps>(
<div className="w-full h-full md:flex-1 rounded-[8px] overflow-hidden relative z-10 flex items-center justify-center">
{/* eslint-disable-next-line @next/next/no-img-element -- dynamic path from getAssetPath */}
<img
src={getAssetPath("assets/HeroImage.png")}
src={getAssetPath(ASSETS.HERO_IMAGE)}
alt={imageAlt}
className="w-full h-auto"
loading="eager"
@@ -1,42 +1,43 @@
"use client";
import { memo, useState, useEffect, useMemo } from "react";
import { getAssetPath, partnerLogoPath } from "../../../../lib/assetUtils";
import LogoWallView from "./LogoWall.view";
import type { LogoWallProps } from "./LogoWall.types";
const defaultLogos = [
{
src: "/assets/Section/Logo_FoodNotBombs.png",
src: getAssetPath(partnerLogoPath("food-not-bombs")),
alt: "Food Not Bombs",
size: "h-11 lg:h-14 xl:h-[70px]",
order: "order-1 sm:order-4", // Mobile: row 1 col 1, SM: row 2 col 1 (bottom left)
},
{
src: "/assets/Section/Logo_StartCOOP.png",
src: getAssetPath(partnerLogoPath("start-coop")),
alt: "Start COOP",
size: "h-[42px] lg:h-[53px] xl:h-[66px]",
order: "order-2 sm:order-2", // Mobile: row 1 col 2, SM: row 1 col 2 (top middle)
},
{
src: "/assets/Section/Logo_Metagov.png",
src: getAssetPath(partnerLogoPath("metagov")),
alt: "Metagov",
size: "h-6 lg:h-8 xl:h-[41px]",
order: "order-3 sm:order-1", // Mobile: row 2 col 1, SM: row 1 col 1 (top left)
},
{
src: "/assets/Section/Logo_OpenCivics.png",
src: getAssetPath(partnerLogoPath("open-civics")),
alt: "Open Civics",
size: "h-8 lg:h-10 xl:h-[50px]",
order: "order-4 sm:order-5 md:order-6", // Mobile: row 2 col 2, SM: row 2 col 2, MD: swapped with Mutual Aid CO
},
{
src: "/assets/Section/Logo_MutualAidCO.png",
src: getAssetPath(partnerLogoPath("mutual-aid-co")),
alt: "Mutual Aid CO",
size: "h-11 lg:h-14 xl:h-[70px]",
order: "order-5 sm:order-6 md:order-5", // Mobile: row 3 col 1, SM: row 2 col 3, MD: swapped with OpenCivics
},
{
src: "/assets/Section/Logo_CUBoulder.png",
src: getAssetPath(partnerLogoPath("cu-boulder")),
alt: "CU Boulder",
size: "h-10 lg:h-12 xl:h-[60px]",
order: "order-6 sm:order-3", // Mobile: row 3 col 2, SM: row 1 col 3 (top right)
@@ -1,6 +1,7 @@
"use client";
import { memo, useState } from "react";
import { ASSETS, getAssetPath } from "../../../../lib/assetUtils";
import { logger } from "../../../../lib/logger";
import QuoteBlockView from "./QuoteBlock.view";
import type { QuoteBlockProps, VariantConfig } from "./QuoteBlock.types";
@@ -14,9 +15,9 @@ const QuoteBlockContainer = memo<QuoteBlockProps>(
quoteSecondary,
author = "Jo Freeman",
source = "The Tyranny of Structurelessness",
avatarSrc = "/assets/Quote_Avatar.svg",
avatarSrc = getAssetPath(ASSETS.QUOTE_AVATAR),
id,
fallbackAvatarSrc = "/assets/Quote_Avatar.svg",
fallbackAvatarSrc = getAssetPath(ASSETS.QUOTE_AVATAR),
onError,
}) => {
const [imageError, setImageError] = useState(false);
+3 -14
View File
@@ -1,7 +1,7 @@
"use client";
import { memo } from "react";
import { getAssetPath } from "../../../lib/assetUtils";
import { getAssetPath, sectionNumberPath } from "../../../lib/assetUtils";
interface SectionNumberProps {
number: number;
@@ -9,19 +9,8 @@ interface SectionNumberProps {
const SectionNumber = memo<SectionNumberProps>(({ number }) => {
const getImageSrc = (num: number): string => {
const assetPath = (() => {
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 getAssetPath(assetPath);
const n = num === 2 || num === 3 ? num : 1;
return getAssetPath(sectionNumberPath(n));
};
return (
@@ -75,7 +75,7 @@ function ContentLockupView({
<>
{/* eslint-disable-next-line @next/next/no-img-element -- decorative shape SVG */}
<img
src={getAssetPath("assets/Shapes_1.svg")}
src={getAssetPath("assets/shapes/shapes-1.svg")}
alt=""
className={styles.shape}
role="presentation"