feat(landing): add Share chip to integration and model pages (#5582)

- add a Share chip (copy link / X / LinkedIn) to integration and
  model detail pages, matching the bordered secondary-pill chip
  already used for View docs / All {provider} models
- rework ShareButton to render as a Chip everywhere (blog, library,
  integrations, models) instead of a bespoke muted-text trigger, and
  switch its copy-link state to the shared useCopyToClipboard hook
This commit is contained in:
Waleed
2026-07-10 17:21:16 -07:00
committed by GitHub
parent 7962236719
commit 8525ba5a2b
3 changed files with 19 additions and 22 deletions
@@ -1,7 +1,14 @@
'use client'
import { useState } from 'react'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@sim/emcn'
import {
Chip,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
TRIGGER_BORDER_CLASS,
useCopyToClipboard,
} from '@sim/emcn'
import { Duplicate } from '@sim/emcn/icons'
import { Share2 } from 'lucide-react'
import { LinkedInIcon, xIcon as XIcon } from '@/components/icons'
@@ -11,18 +18,9 @@ interface ShareButtonProps {
title: string
}
/** Bordered `Chip` trigger with a copy-link / X / LinkedIn share menu — the one Share control used across blog, library, integration, and model pages. */
export function ShareButton({ url, title }: ShareButtonProps) {
const [copied, setCopied] = useState(false)
const handleCopyLink = async () => {
try {
await navigator.clipboard.writeText(url)
setCopied(true)
setTimeout(() => setCopied(false), 1500)
} catch {
/* clipboard unavailable */
}
}
const { copied, copy } = useCopyToClipboard({ resetMs: 1500 })
const handleShareTwitter = () => {
const tweetUrl = `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`
@@ -37,17 +35,12 @@ export function ShareButton({ url, title }: ShareButtonProps) {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button
type='button'
className='flex items-center gap-1.5 text-[var(--text-muted)] text-sm hover:text-[var(--text-primary)]'
aria-label='Share this post'
>
<Share2 className='size-4' />
<span>Share</span>
</button>
<Chip leftIcon={Share2} className={TRIGGER_BORDER_CLASS} aria-label='Share this page'>
Share
</Chip>
</DropdownMenuTrigger>
<DropdownMenuContent align='end'>
<DropdownMenuItem onSelect={handleCopyLink}>
<DropdownMenuItem onSelect={() => copy(url)}>
<Duplicate className='size-4' />
{copied ? 'Copied!' : 'Copy link'}
</DropdownMenuItem>
@@ -17,6 +17,7 @@ import {
import { BackLink } from '@/app/(landing)/components'
import { JsonLd } from '@/app/(landing)/components/json-ld'
import { LandingFAQ } from '@/app/(landing)/components/landing-faq'
import { ShareButton } from '@/app/(landing)/components/share-button'
import { IntegrationCtaButton } from '@/app/(landing)/integrations/(shell)/[slug]/components/integration-cta-button'
import { TemplateCardButton } from '@/app/(landing)/integrations/(shell)/[slug]/components/template-card-button'
import { IntegrationIcon } from '@/app/(landing)/integrations/components/integration-icon'
@@ -494,6 +495,7 @@ export default async function IntegrationPage({ params }: { params: Promise<{ sl
>
View docs
</ChipLink>
<ShareButton url={`${baseUrl}/integrations/${slug}`} title={`${name} Integration`} />
</div>
<p className='mt-5 text-[var(--text-muted)] text-xs'>
@@ -5,6 +5,7 @@ import { SITE_URL } from '@/lib/core/utils/urls'
import { BackLink } from '@/app/(landing)/components'
import { JsonLd } from '@/app/(landing)/components/json-ld'
import { LandingFAQ } from '@/app/(landing)/components/landing-faq'
import { ShareButton } from '@/app/(landing)/components/share-button'
import { FeaturedModelCard, ProviderIcon } from '@/app/(landing)/models/components/model-primitives'
import {
ALL_CATALOG_MODELS,
@@ -181,6 +182,7 @@ export default async function ModelPage({
<ChipLink href={provider.href} className='border border-[var(--border-1)]'>
All {provider.name} models
</ChipLink>
<ShareButton url={`${baseUrl}${model.href}`} title={model.displayName} />
</div>
</div>