Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ComponentType, ReactElement, ReactNode } from 'react';
import React, { useState } from 'react';
import React from 'react';
import classNames from 'classnames';
import {
Typography,
Expand All @@ -15,6 +15,7 @@ import type { ContributionAction } from '../types';
import { ContributionSubmissionStatus } from '../types';
import { formatDonationAmount } from '../utils';
import { getActionPlatformVisual } from '../actionPlatform';
import { GivebackPlatformLogo } from './GivebackPlatformLogo';

interface GivebackActionCardProps {
action: ContributionAction;
Expand All @@ -39,48 +40,7 @@ const formatCooldownRemaining = (endsAt: string): string => {
return `${Math.max(1, minutes)}m`;
};

interface PlatformLogoProps {
logoUrl?: string;
Icon: ComponentType<IconProps>;
forceDark?: boolean;
isDimmed: boolean;
}

// Prefers the real brand logo (an SVG from the logo CDN) and falls back to the
// internal glyph if there is no logo for the surface or the remote one fails to
// load — so a tile is never broken or blank. The parent tile already pins the
// background and applies the dimmed/grayscale treatment.
const PlatformLogo = ({
logoUrl,
Icon,
forceDark,
isDimmed,
}: PlatformLogoProps): ReactElement => {
const [failed, setFailed] = useState(false);

if (logoUrl && !failed) {
return (
<img
src={logoUrl}
alt=""
aria-hidden
loading="lazy"
onError={() => setFailed(true)}
className="size-6 object-contain"
/>
);
}

return (
<Icon
secondary
size={IconSize.Small}
className={classNames(!isDimmed && forceDark && 'brightness-0')}
/>
);
};

// One sharp, explicit title carries the ask — no competing subtitle. The
// One sharp, explicit title carries the ask - no competing subtitle. The
// supporting details (payout, status, "just for love") sit in a calm top/bottom
// frame around it so the card stays easy to scan at a glance.
export const GivebackActionCard = ({
Expand Down Expand Up @@ -206,7 +166,7 @@ export const GivebackActionCard = ({
: 'shadow-1 bg-white text-black group-hover:scale-105',
)}
>
<PlatformLogo
<GivebackPlatformLogo
logoUrl={logoUrl}
Icon={Icon}
forceDark={forceDark}
Expand Down Expand Up @@ -282,7 +242,7 @@ export const GivebackActionCard = ({
: 'bg-surface-float hover:bg-surface-hover',
)}
>
{/* Glossy sheen that sweeps across on hover a small reward flourish. */}
{/* Glossy sheen that sweeps across on hover - a small reward flourish. */}
<span
aria-hidden
className="via-white/10 pointer-events-none absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent to-transparent transition-transform duration-700 ease-out group-hover:translate-x-full motion-reduce:hidden"
Expand All @@ -297,7 +257,7 @@ export const GivebackActionCard = ({
// read as temporary rather than finished.
return (
<FlexCol
aria-label={`${action.title} ${statusMeta?.label ?? ''}`}
aria-label={`${action.title}, ${statusMeta?.label ?? ''}`}
className={classNames(
'h-full w-full gap-3 rounded-16 p-4',
isDone
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ export const GivebackActionCatalog = ({
type={TypographyType.Footnote}
color={TypographyColor.Tertiary}
>
We can&apos;t pay for these, but we&apos;d genuinely appreciate
them.
No donation rides on these. They just help us out. We&apos;d love
you for it.
</Typography>
</FlexCol>
<ActionGrid actions={loveActions} onSubmit={setSubmissionAction} />
Expand Down
Loading
Loading