mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-24 14:45:36 +00:00
## Summary Unified preview branch combining three feature PRs for the website product pages. > **Constituent PRs:** #11247, #11270, #11266 ## Changes - **Cloud page** (#11247): Add Cloud product page sections (Hero, Reason, FAQ, AI Models, Audience, Pricing, ProductCards). Extract `FAQSection` to `common/` and `ReasonSection` to `product/shared/` for reuse across product pages. Add cloud-related i18n translations. - **API & Enterprise pages** (#11270): Add API page (Hero, Steps, Automation, Reason) and Enterprise page (Hero, Team, DataOwnership, BYOKey, Orchestration, Reason). Add shared `CardGridSection`, `FeatureShowcaseSection`, `CloudBannerSection`. Add all API/enterprise i18n translations. - **Use case images** (#11266): Replace placeholder divs with real images in `UseCaseSection`. Add SVG blob clip-paths (`objectBoundingBox`) and crossfade transitions on category switch. Use `useId()` for unique clip-path IDs. ## Review Focus - Shared component API design (`ReasonSection` slot/prop surface) - Component placement: `common/` vs `product/shared/` - Clip-path coordinate accuracy and crossfade transition smoothness --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: DrJKL <DrJKL0424@gmail.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> Co-authored-by: pythongosssss <125205205+pythongosssss@users.noreply.github.com> Co-authored-by: AustinMroz <austin@comfy.org>
110 lines
2.9 KiB
Vue
110 lines
2.9 KiB
Vue
<script setup lang="ts">
|
||
import { cn } from '@comfyorg/tailwind-utils'
|
||
import { computed, reactive } from 'vue'
|
||
|
||
import type { Locale, TranslationKey } from '../../i18n/translations'
|
||
|
||
import { t } from '../../i18n/translations'
|
||
|
||
const {
|
||
locale = 'en',
|
||
headingKey,
|
||
faqPrefix,
|
||
faqCount
|
||
} = defineProps<{
|
||
locale?: Locale
|
||
headingKey: TranslationKey
|
||
faqPrefix: string
|
||
faqCount: number
|
||
}>()
|
||
|
||
const faqKeys: Array<{ q: TranslationKey; a: TranslationKey }> = Array.from(
|
||
{ length: faqCount },
|
||
(_, i) => ({
|
||
q: `${faqPrefix}.${i + 1}.q` as TranslationKey,
|
||
a: `${faqPrefix}.${i + 1}.a` as TranslationKey
|
||
})
|
||
)
|
||
|
||
const faqs = computed(() =>
|
||
faqKeys.map(({ q, a }) => ({
|
||
question: t(q, locale),
|
||
answer: t(a, locale)
|
||
}))
|
||
)
|
||
|
||
const expanded = reactive(faqKeys.map(() => false))
|
||
|
||
function toggle(index: number) {
|
||
expanded[index] = !expanded[index]
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<section class="px-4 py-24 md:px-20 md:py-40">
|
||
<div class="flex flex-col gap-6 md:flex-row md:gap-16">
|
||
<!-- Left heading -->
|
||
<div
|
||
class="bg-primary-comfy-ink sticky top-20 z-10 w-full shrink-0 self-start py-4 md:top-28 md:w-80 md:py-0"
|
||
>
|
||
<h2 class="text-primary-comfy-canvas text-4xl font-light md:text-5xl">
|
||
{{ t(headingKey, locale) }}
|
||
</h2>
|
||
</div>
|
||
|
||
<!-- Right FAQ list -->
|
||
<div class="flex-1">
|
||
<div
|
||
v-for="(faq, index) in faqs"
|
||
:key="index"
|
||
class="border-primary-comfy-canvas/20 border-b"
|
||
>
|
||
<button
|
||
:id="`faq-trigger-${index}`"
|
||
type="button"
|
||
:aria-expanded="expanded[index]"
|
||
:aria-controls="`faq-panel-${index}`"
|
||
:class="
|
||
cn(
|
||
'flex w-full cursor-pointer items-center justify-between text-left',
|
||
index === 0 ? 'pb-6' : 'py-6'
|
||
)
|
||
"
|
||
@click="toggle(index)"
|
||
>
|
||
<span
|
||
:class="
|
||
cn(
|
||
'text-lg font-light md:text-xl',
|
||
expanded[index]
|
||
? 'text-primary-comfy-yellow'
|
||
: 'text-primary-comfy-canvas'
|
||
)
|
||
"
|
||
>
|
||
{{ faq.question }}
|
||
</span>
|
||
<span
|
||
class="text-primary-comfy-yellow ml-4 shrink-0 text-2xl"
|
||
aria-hidden="true"
|
||
>
|
||
{{ expanded[index] ? '−' : '+' }}
|
||
</span>
|
||
</button>
|
||
<section
|
||
v-show="expanded[index]"
|
||
:id="`faq-panel-${index}`"
|
||
role="region"
|
||
:aria-labelledby="`faq-trigger-${index}`"
|
||
class="pb-6"
|
||
>
|
||
<p class="text-primary-comfy-canvas/70 text-sm whitespace-pre-line">
|
||
{{ faq.answer }}
|
||
</p>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</template>
|