diff --git a/packages/shared/src/components/archive/ArchiveIndexPage.tsx b/packages/shared/src/components/archive/ArchiveIndexPage.tsx index 46ab41643b3..f1e6f77dce0 100644 --- a/packages/shared/src/components/archive/ArchiveIndexPage.tsx +++ b/packages/shared/src/components/archive/ArchiveIndexPage.tsx @@ -2,6 +2,7 @@ import type { ReactElement } from 'react'; import React from 'react'; import classNames from 'classnames'; import type { Archive } from '../../graphql/archive'; +import { ArchiveScopeType } from '../../graphql/archive'; import type { ArchiveScopeInfo, ArchivesByYear } from '../../lib/archive'; import { getArchiveUrlFromArchive, @@ -13,6 +14,9 @@ import Link from '../utilities/Link'; import { ArrowIcon } from '../icons'; import { IconSize } from '../Icon'; import { ElementPlaceholder } from '../ElementPlaceholder'; +import { CopyLinkButton } from '../share/CopyLinkButton'; +import { LogEvent } from '../../lib/log'; +import { ReferralCampaignKey } from '../../lib/referral'; interface ArchiveIndexPageProps { scopeType: ArchiveScopeInfo['scopeType']; @@ -159,13 +163,31 @@ export function ArchiveIndexPage({ className, }: ArchiveIndexPageProps): ReactElement { const groups = groupArchivesByYear(archives); + const isTagScope = scopeType === ArchiveScopeType.Tag; + const shareCampaign = isTagScope + ? ReferralCampaignKey.ShareTag + : ReferralCampaignKey.ShareSource; + const shareEvent = isTagScope ? LogEvent.ShareTag : LogEvent.ShareSource; return (
{/* Header */} -

- Best of {scopeName} — Archive -

+
+

+ Best of {scopeName} — Archive +

+ ({ + event_name: shareEvent, + target_id: scopeId, + }), + }} + /> +
{/* Archive grid by year */} + {/* Hover-revealed only where hover exists; always there on touch. */} + ({ + event_name: LogEvent.ShareSource, + target_id: item.id, + }), + }} + /> ))} diff --git a/packages/shared/src/components/cards/entity/SquadEntityCard.tsx b/packages/shared/src/components/cards/entity/SquadEntityCard.tsx index 383b85ece75..a386218abcf 100644 --- a/packages/shared/src/components/cards/entity/SquadEntityCard.tsx +++ b/packages/shared/src/components/cards/entity/SquadEntityCard.tsx @@ -7,13 +7,16 @@ import { TypographyType, } from '../../typography/Typography'; import type { Origin } from '../../../lib/log'; +import { LogEvent } from '../../../lib/log'; import { largeNumberFormat } from '../../../lib'; import { SquadActionButton } from '../../squads/SquadActionButton'; import { SourceIcon } from '../../icons'; import { IconSize } from '../../Icon'; import { useSquad } from '../../../hooks'; -import { ButtonSize } from '../../buttons/Button'; +import { ButtonSize, ButtonVariant } from '../../buttons/Button'; import SquadHeaderMenu from '../../squads/SquadHeaderMenu'; +import { CopyLinkButton } from '../../share/CopyLinkButton'; +import { ReferralCampaignKey } from '../../../lib/referral'; import { Separator } from '../common/common'; import EntityDescription from './EntityDescription'; import EntityCard from './EntityCard'; @@ -59,6 +62,18 @@ const SquadEntityCard = ({ actionButtons={ !isLoading && ( <> + ({ + event_name: LogEvent.ShareSource, + target_id: squad.id, + }), + }} + /> { + const [, onShareOrCopyLink] = useShareOrCopyLink(shareProps); + + return ( + + )} + push( @@ -469,15 +481,7 @@ export const TagTopicPage = ({ feedId, }) } - shareProps={{ - text: `Check out the ${tag} tag on daily.dev`, - link: globalThis?.location?.href, - cid: ReferralCampaignKey.ShareTag, - logObject: () => ({ - event_name: LogEvent.ShareTag, - target_id: tag, - }), - }} + shareProps={shareProps} />
{/* SEO crawl paths preserved from the legacy tag page. */} diff --git a/packages/storybook/stories/features/snapshot/surfaceChrome.tsx b/packages/storybook/stories/features/snapshot/surfaceChrome.tsx new file mode 100644 index 00000000000..d4654bca9ff --- /dev/null +++ b/packages/storybook/stories/features/snapshot/surfaceChrome.tsx @@ -0,0 +1,162 @@ +import React from 'react'; +import { + Button, + ButtonSize, + ButtonVariant, +} from '@dailydotdev/shared/src/components/buttons/Button'; +import { LinkIcon } from '@dailydotdev/shared/src/components/icons'; + +export const AVATAR = + 'https://res.cloudinary.com/daily-now/image/upload/s--O0TOmw4y--/f_auto/v1715772965/public/noProfile'; + + +/* ------------------------------------------------------------------ prose */ + +export const H1 = ({ children }: { children: React.ReactNode }) => ( +

{children}

+); + +export const P = ({ children }: { children: React.ReactNode }) => ( +

{children}

+); + +export const Note = ({ children }: { children: React.ReactNode }) => ( +

+ {children} +

+); + +/* ---------------------------------------------------------------- controls */ + +/** + * Inert on purpose: this page compares where a control sits inside a real + * screen. The working buttons and live capture are on Button placements. + */ +export const Control = () => ( + + + + + + + +); + +/* ---------------------------------------------------------------- sources */ + +/** The source page is left-aligned, and its actions sit below the title. */ +const SourceScreen = ({ device }: { device: DeviceName }) => ( + +
+ + Sources / XDA Developers + + +
+ +

+ XDA Developers +

+
+ +
+ +
+ +

+ News and reviews for developers, by developers. +

+ +
+ {['#android', '#hardware', '#reviews'].map((tag) => ( + + {tag} + + ))} +
+
+
+); + +/* ----------------------------------------------------------------- squads */ + +/** SquadEntityCard: w-80, image and actions on one row, body under it. */ +const SquadCard = () => ( +
+
+ +
+ + + {/* SquadHeaderMenu — `invisible group-hover/menu:visible`. */} + +
+
+
+ + Frontend Fans + +

+ Everything CSS, React and the browser. Ship it and show it. +

+ + 2.4K Members + · + 12K Upvotes + +
+
+); + +const SquadScreen = ({ device }: { device: DeviceName }) => ( + +
+

Squads

+
+ + {device === 'Desktop' && } +
+
+
+); + +/* ---------------------------------------------------------------- archive */ + +/** ArchiveIndexPage: a month grid, no posts and no feed controls. */ +const ArchiveScreen = ({ device }: { device: DeviceName }) => ( + +
+ + Sources / XDA Developers / Best of + +
+

+ Best of XDA Developers — Archive +

+ +
+ +
+ {['2026', '2025'].map((year) => ( +
+

+ {year} +

+
+ {['January', 'February', 'March', 'April'].map((month) => ( + + + {month} + + + 24 posts + + + ))} +
+
+ ))} +
+
+
+); + +/* -------------------------------------------------------------------- page */ + +const Rails = ({ + Screen, +}: { + Screen: React.ComponentType<{ device: DeviceName }>; +}) => ( + + + + + +); + +const Directories = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + +); + +const meta: Meta = { + title: 'Features/Snapshot/Surfaces/Topic & directory pages', + component: Directories, + parameters: { layout: 'fullscreen' }, +}; + +export default meta; + +export const Variations: StoryObj = {}; diff --git a/packages/webapp/pages/sources/[source].tsx b/packages/webapp/pages/sources/[source].tsx index baab4eadec0..4a48fc4e6f5 100644 --- a/packages/webapp/pages/sources/[source].tsx +++ b/packages/webapp/pages/sources/[source].tsx @@ -301,7 +301,7 @@ const SourcePage = ({

{source.name}

- +
{source?.description && (

{source?.description}