Files
community-rule/app/components/modals/Share/Share.view.tsx
T
adilallo da453f6108 Replace remaining hardcoded hex colors with color tokens (CR-27)
Map leftover component hex values onto the existing color scale, and leave third-party share brands and the Avatar white-alpha border documented as intentional exceptions.
2026-08-17 14:31:28 -06:00

167 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
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";
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. */
function ShareAssetIcon(props: {
name: ShareIconName;
width: number;
height: number;
}) {
const { name, width, height } = props;
return (
<Image
src={getAssetPath(shareIconPath(name))}
alt=""
width={width}
height={height}
className="shrink-0"
unoptimized
aria-hidden
/>
);
}
function ShareChannelTile({ label, onClick, circleClassName, icon }: ShareChannelTileProps) {
return (
<button
type="button"
onClick={() => void onClick()}
className="flex w-16 shrink-0 flex-col items-center gap-2 rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-invert-primary)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-default-primary)]"
>
<div
className={`flex h-[60px] w-[60px] items-center justify-center rounded-full border border-solid ${circleClassName}`}
>
{icon}
</div>
<span className="max-w-[4.5rem] text-center text-x-small-label text-[var(--color-content-default-tertiary)]">
{label}
</span>
</button>
);
}
export const ShareView = memo(function ShareView({
isOpen,
onClose,
onCopyLink,
onEmailShare,
onSignalShare,
onSlackShare,
onDiscordShare,
className = "",
backdropVariant = "blurredYellow",
dialogRef,
overlayRef,
titleId,
title,
description,
copyLinkLabel,
signalLabel,
slackLabel,
discordLabel,
emailLabel,
doneLabel,
closeDialogAriaLabel,
moreOptionsAriaLabel,
}: ShareViewProps) {
return (
<CreateModalFrameView
isOpen={isOpen}
onOverlayClick={onClose}
backdropVariant={backdropVariant}
className={`max-h-[90vh] w-[min(546px,calc(100vw-32px))] max-w-[546px] min-h-0 ${className}`}
ariaLabel={title}
ariaLabelledBy={titleId}
overlayRef={overlayRef}
dialogRef={dialogRef}
>
<ModalHeader
onClose={onClose}
onMoreOptions={onClose}
closeButtonAriaLabel={closeDialogAriaLabel}
moreOptionsAriaLabel={moreOptionsAriaLabel}
/>
<div className="shrink-0 bg-[var(--color-surface-default-primary)] px-[24px] py-[12px]">
<ContentLockup
title={title}
description={description}
variant="modal"
alignment="left"
titleId={titleId}
/>
</div>
<div className="scrollbar-design flex min-h-0 flex-1 flex-col overflow-x-clip overflow-y-auto px-[24px] pb-6 pt-0">
{/* Channel circle hexes are third-party brand colors (copy/link, Signal, Slack, Discord), not DS tokens. */}
<div className="flex flex-wrap gap-4">
<ShareChannelTile
label={copyLinkLabel}
onClick={onCopyLink}
circleClassName="border-[#444444] bg-[#333333]"
icon={<ShareAssetIcon name="link" width={24} height={24} />}
/>
<ShareChannelTile
label={signalLabel}
onClick={onSignalShare}
circleClassName="border-[#3a76f0] bg-[#3a76f0]"
icon={<ShareAssetIcon name="signal" width={26} height={26} />}
/>
<ShareChannelTile
label={slackLabel}
onClick={onSlackShare}
circleClassName="border-[#4a154b] bg-[#4a154b]"
icon={<ShareAssetIcon name="slack" width={26} height={26} />}
/>
<ShareChannelTile
label={discordLabel}
onClick={onDiscordShare}
circleClassName="border-[#5865f2] bg-[#5865f2]"
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 name="mail" width={24} height={24} />}
/>
</div>
</div>
<ModalFooter
showBackButton={false}
showNextButton={false}
stepper={false}
footerContent={
<div className="absolute right-[16px] top-[12px] flex max-w-[calc(100%-32px)] flex-wrap items-center justify-end gap-3">
<Button
buttonType="filled"
palette="default"
size="medium"
type="button"
onClick={onClose}
>
{doneLabel}
</Button>
</div>
}
/>
</CreateModalFrameView>
);
});
ShareView.displayName = "ShareView";