mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 11:04:27 +08:00
fix(web): match standalone marketplace mobile banners and collections
Show recommend as icon-only on mobile, keep event/ad posters uncropped, and hide collection carousel dots under 879px.
This commit is contained in:
parent
0da1c88de7
commit
6e5cd92eec
@ -12,18 +12,18 @@ import type { MarketplaceBannerPage } from './banners'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useTranslation } from '#i18n'
|
||||
import { trackEvent } from '@/app/components/base/amplitude'
|
||||
import {
|
||||
rememberMarketplaceSiteReferrer,
|
||||
trackMarketplaceSiteEvent,
|
||||
} from '@/utils/marketplace-site-track'
|
||||
import { buildMarketplaceBannerClickProperties } from './home-trending-track'
|
||||
import Partner from '@/app/components/plugins/base/badges/partner'
|
||||
import Verified from '@/app/components/plugins/base/badges/verified'
|
||||
import { MARKETPLACE_API_PREFIX } from '@/config'
|
||||
import Link from '@/next/link'
|
||||
import {
|
||||
rememberMarketplaceSiteReferrer,
|
||||
trackMarketplaceSiteEvent,
|
||||
} from '@/utils/marketplace-site-track'
|
||||
import { getPluginLinkInMarketplace } from '../utils'
|
||||
import background from './assets/background.webp'
|
||||
import difyUpdatesArt from './assets/dify-updates-art.png'
|
||||
import { buildMarketplaceBannerClickProperties } from './home-trending-track'
|
||||
import styles from './home-trending.module.css'
|
||||
|
||||
const getMarketplaceAssetURL = (path?: string) => {
|
||||
@ -120,7 +120,12 @@ function TrendingCopy({
|
||||
<h2 className="shrink-0 text-xl leading-6 font-semibold tracking-[-0.4px] text-text-primary">
|
||||
{heading}
|
||||
</h2>
|
||||
<p className="w-full text-[13px] leading-5 font-normal tracking-[-0.065px] text-text-tertiary">
|
||||
<p
|
||||
className={cn(
|
||||
styles.copyDescription,
|
||||
'w-full text-[13px] leading-5 font-normal tracking-[-0.065px] text-text-tertiary',
|
||||
)}
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
@ -175,7 +180,10 @@ function TrendingCard({
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-[10px] border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge"
|
||||
className={cn(
|
||||
styles.cardIcon,
|
||||
'flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-[10px] border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge',
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: !iconURL ? card.icon_background : undefined,
|
||||
}}
|
||||
@ -196,7 +204,7 @@ function TrendingCard({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex w-full items-end gap-1">
|
||||
<div className={cn(styles.cardMeta, 'flex w-full items-end gap-1')}>
|
||||
<div className="flex min-w-0 flex-1 flex-col items-start gap-[3px]">
|
||||
<div className="flex w-full min-w-0 items-center gap-[3px]">
|
||||
<h3 className="min-w-0 truncate text-sm leading-[normal] font-medium text-text-primary">
|
||||
@ -257,9 +265,18 @@ function TrendingRecommendationSlide({
|
||||
height={900}
|
||||
alt=""
|
||||
aria-hidden
|
||||
className="absolute top-[-173px] left-[-990px] h-[1201px] w-[2135px] max-w-none opacity-80"
|
||||
className={cn(
|
||||
styles.recommendBackdrop,
|
||||
'absolute top-[-173px] left-[-990px] h-[1201px] w-[2135px] max-w-none opacity-80',
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
aria-hidden
|
||||
className={cn(
|
||||
styles.recommendBackdrop,
|
||||
'absolute inset-0 bg-text-accent mix-blend-color',
|
||||
)}
|
||||
/>
|
||||
<div aria-hidden className="absolute inset-0 bg-text-accent mix-blend-color" />
|
||||
|
||||
<div className={cn(styles.recommendCards, 'relative z-10 h-full items-center')}>
|
||||
{banner.content.cards.map((card) => (
|
||||
@ -440,20 +457,12 @@ export function HomeBannerSlide({
|
||||
}) {
|
||||
if (banner.style_type === 'blog')
|
||||
return (
|
||||
<BlogBannerSlide
|
||||
banner={banner}
|
||||
isMarketplacePlatform={isMarketplacePlatform}
|
||||
page={page}
|
||||
/>
|
||||
<BlogBannerSlide banner={banner} isMarketplacePlatform={isMarketplacePlatform} page={page} />
|
||||
)
|
||||
|
||||
if (banner.style_type === 'event' || banner.style_type === 'ad')
|
||||
return (
|
||||
<ImageBannerSlide
|
||||
banner={banner}
|
||||
isMarketplacePlatform={isMarketplacePlatform}
|
||||
page={page}
|
||||
/>
|
||||
<ImageBannerSlide banner={banner} isMarketplacePlatform={isMarketplacePlatform} page={page} />
|
||||
)
|
||||
|
||||
return (
|
||||
|
||||
@ -116,8 +116,60 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Recommend mobile: 96px app icons (Figma 1026:24938), not desktop cards. */
|
||||
:global([data-marketplace-standalone]) .recommendBackdrop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .recommendCards {
|
||||
padding: 16px 20px;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
overflow: hidden;
|
||||
padding: 36px 12px;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .recommendCards > .card {
|
||||
display: flex;
|
||||
flex: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 96px;
|
||||
min-width: 96px;
|
||||
max-width: 96px;
|
||||
height: 96px;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
background: transparent;
|
||||
border-radius: 20px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .recommendCards > .card:nth-child(-n + 3) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .recommendCards > .card:nth-child(n + 4) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .cardIcon {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
border-color: var(--color-effects-icon-border);
|
||||
border-radius: 20px;
|
||||
box-shadow:
|
||||
0 0.5px 5px 0 var(--color-shadow-shadow-4),
|
||||
0 0.5px 2px -0.5px var(--color-shadow-shadow-4);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .cardMeta {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .copyDescription {
|
||||
font-size: 15px;
|
||||
letter-spacing: -0.075px;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .updatesArt {
|
||||
@ -167,6 +219,11 @@
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .recommendVisual {
|
||||
border-radius: 12px;
|
||||
background-color: var(--color-text-accent);
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .stackedCopy {
|
||||
flex: none;
|
||||
height: 160px;
|
||||
@ -178,10 +235,18 @@
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* Event/ad mobile art is a 393×357 frame (Figma 1026:28881), matching
|
||||
the stacked blog/recommend card height of 197 + 160. */
|
||||
/* Event/ad mobile: show the full poster instead of cropping it into a
|
||||
357px cover box. Height follows the selected image's aspect ratio. */
|
||||
:global([data-marketplace-standalone]) .imageSlide {
|
||||
height: 357px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .imageSlide :is(picture, img) {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: auto;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
:global([data-marketplace-standalone]) .readMoreDesktop {
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
@media (max-width: 879px) {
|
||||
:global([data-marketplace-standalone]) .pagination {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ import useEmblaCarousel from 'embla-carousel-react'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from '#i18n'
|
||||
import { MARKETPLACE_CONTAINER_ID } from '../constants'
|
||||
import styles from './carousel.module.css'
|
||||
import { CAROUSEL_PAGE_CLASS } from './collection-constants'
|
||||
|
||||
export type CarouselPage = {
|
||||
@ -76,7 +77,7 @@ const CarouselControls = ({
|
||||
return (
|
||||
<div className="absolute -top-10 right-0 flex items-center gap-3">
|
||||
{showPagination && (
|
||||
<div className="flex items-center gap-1">
|
||||
<div className={cn(styles.pagination, 'flex items-center gap-1')}>
|
||||
{paginationItems.map((item, index) => (
|
||||
<button
|
||||
key={item.id}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user