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
38 changes: 9 additions & 29 deletions src/components/DocsLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -599,10 +599,7 @@ export function DocsLayout({

const [isFullWidth, setIsFullWidth] = useLocalStorage('docsFullWidth', false)

const activePartners = partners.filter(
(d) =>
d.status === 'active' && d.name !== 'Nozzle.io' && d.id !== 'fireship',
)
const activePartners = partners.filter((d) => d.status === 'active')

const groupInitialOpenState = React.useMemo(() => {
return menuConfig.reduce<Record<string, boolean>>((acc, group, index) => {
Expand Down Expand Up @@ -937,31 +934,14 @@ export function DocsLayout({
</div>
{!isLandingPage && (
<RightRail breakpoint="md" className="md:w-[280px]">
<div className="relative">
<PartnersRail
analyticsPlacement="docs_right_rail"
analyticsProperties={{
framework: currentFramework.framework,
library_id: libraryId,
}}
partners={activePartners}
/>
<a
href="https://docs.google.com/document/d/1Hg2MzY2TU6U3hFEZ3MLe2oEOM3JS4-eByti3kdJU3I8"
target="_blank"
rel="noopener noreferrer"
className="absolute right-3 top-2 font-medium opacity-60 hover:opacity-100 text-xs hover:underline"
onClick={() => {
trackEvent('become_partner_clicked', {
framework: currentFramework.framework,
library_id: libraryId,
placement: 'docs_right_rail',
})
}}
>
Become a Partner
</a>
</div>
<PartnersRail
analyticsPlacement="docs_right_rail"
analyticsProperties={{
framework: currentFramework.framework,
library_id: libraryId,
}}
partners={activePartners}
/>
<div className="hidden md:block border border-gray-500/20 rounded-l-lg overflow-hidden w-full">
<RecentPostsWidget />
</div>
Expand Down
5 changes: 4 additions & 1 deletion src/components/Gam.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ export function GamVrec1({
return (
<div
{...props}
className={twMerge('w-[300px] flex flex-col gap-3', props.className)}
className={twMerge(
'w-full max-w-[300px] flex flex-col gap-3',
props.className,
)}
>
{promos.map((promo) => (
<Link
Expand Down
124 changes: 103 additions & 21 deletions src/components/PartnersGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import * as React from 'react'
import { partners as allPartners, PartnerImage } from '~/utils/partners'
import {
partners as allPartners,
PartnerImage,
partnerTierFlares,
partnerTierLabels,
partnerTierOrder,
type PartnerTier,
} from '~/utils/partners'
import { Card } from '~/components/Card'
import { trackEvent, useTrackedImpression } from '~/utils/analytics'

Expand All @@ -11,6 +18,39 @@ type PartnersGridProps = {
partnersList?: PartnerItem[]
}

const tierLayout: Record<
PartnerTier,
{
flexBasis: string
minHeight: string
logoMaxWidth: string
logoMaxHeight: string
padding: string
}
> = {
gold: {
flexBasis: 'basis-full sm:basis-1/2',
minHeight: 'min-h-[220px]',
logoMaxWidth: 'max-w-[400px]',
logoMaxHeight: 'max-h-[120px]',
padding: 'p-12',
},
silver: {
flexBasis: 'basis-full sm:basis-1/3 lg:basis-1/4',
minHeight: 'min-h-[130px]',
logoMaxWidth: 'max-w-[180px]',
logoMaxHeight: 'max-h-[56px]',
padding: 'p-6',
},
bronze: {
flexBasis: 'basis-1/2 sm:basis-1/4 lg:basis-1/5 xl:basis-1/6',
minHeight: 'min-h-[100px]',
logoMaxWidth: 'max-w-[110px]',
logoMaxHeight: 'max-h-[36px]',
padding: 'p-4',
},
}

function PartnerGridItem({
analyticsPlacement,
analyticsProperties,
Expand All @@ -33,18 +73,18 @@ function PartnerGridItem({
},
})

const width = Math.max(Math.round(120 + 280 * partner.score), 150)
const layout = tierLayout[partner.tier ?? 'bronze']

return (
<a
ref={ref}
href={partner.href}
target="_blank"
rel="noreferrer"
className="flex items-center justify-center p-6
className={`flex items-center justify-center
border-r border-b border-gray-200 dark:border-gray-800
hover:bg-gray-50 dark:hover:bg-gray-900/50 transition-colors duration-150 ease-out"
style={{ width, flexGrow: partner.score }}
hover:bg-gray-50 dark:hover:bg-gray-900/50 transition-colors duration-150 ease-out
${layout.flexBasis} ${layout.minHeight} ${layout.padding}`}
onClick={() => {
trackEvent('partner_card_clicked', {
partner_id: partner.id,
Expand All @@ -56,7 +96,15 @@ function PartnerGridItem({
})
}}
>
<PartnerImage config={partner.image} alt={partner.name} />
<div
className={`w-full flex items-center justify-center ${layout.logoMaxWidth}`}
>
<PartnerImage
className={`w-full object-contain ${layout.logoMaxHeight}`}
config={partner.image}
alt={partner.name}
/>
</div>
</a>
)
}
Expand All @@ -70,22 +118,56 @@ export function PartnersGrid({
(partner) => partner.status === 'active',
)

// Sort by score descending so larger partners come first
const sortedItems = [...items].sort((a, b) => b.score - a.score)
const tiers: Array<PartnerTier> = ['gold', 'silver', 'bronze']

const tiersWithPartners = tiers
.map((tier) => ({
tier,
partners: items
.filter((partner) => (partner.tier ?? 'bronze') === tier)
.sort((a, b) => b.score - a.score),
}))
.filter((row) => row.partners.length > 0)
.sort((a, b) => partnerTierOrder[a.tier] - partnerTierOrder[b.tier])

let slotIndex = 0

return (
<Card className="overflow-hidden">
<div className="flex flex-wrap justify-center items-stretch -mr-px -mb-px">
{sortedItems.map((partner, index) => (
<PartnerGridItem
key={partner.id}
analyticsPlacement={analyticsPlacement}
analyticsProperties={analyticsProperties}
index={index}
partner={partner}
/>
))}
</div>
</Card>
<div className="flex flex-col gap-3">
{tiersWithPartners.map((row) => {
const flare = partnerTierFlares[row.tier]
return (
<Card
key={row.tier}
className={`overflow-hidden rounded-none rounded-l-sm rounded-r-2xl bg-gradient-to-b ${flare.gradientStops}`}
>
<div className="ml-1.5 bg-white dark:bg-gray-900">
<div className="px-4 pt-3 pb-2 border-b border-gray-200 dark:border-gray-800 flex items-center gap-2">
<span className={flare.iconColor}>{flare.icon}</span>
<span
className={`text-[10px] uppercase tracking-[0.18em] font-semibold ${flare.labelColor}`}
>
{partnerTierLabels[row.tier]}
</span>
</div>
<div className="flex flex-wrap items-stretch -mr-px -mb-px">
{row.partners.map((partner) => {
const index = slotIndex++
return (
<PartnerGridItem
key={partner.id}
analyticsPlacement={analyticsPlacement}
analyticsProperties={analyticsProperties}
index={index}
partner={partner}
/>
)
})}
</div>
</div>
</Card>
)
})}
</div>
)
}
Loading
Loading