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
1 change: 1 addition & 0 deletions src/components/home-comps/showcase/capcut-logo-black.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/components/home-comps/showcase/capcut-logo-white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
81 changes: 69 additions & 12 deletions src/components/home-comps/showcase/index.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -47,49 +47,81 @@
.section-title {
color: var(--home-title-color);
text-align: center;
font-size: 56px;
font-size: 64px;
font-style: normal;
font-weight: 500;
line-height: 61px;
line-height: 1.15;
margin-bottom: 16px;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}

.title-line {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
transform: translateX(-0.12em);
}

.title-line-sub {
font-size: 0.5em;
font-weight: 500;
letter-spacing: 0.02em;
opacity: 0.5;
}

.tiktok-logo {
height: 2em;
height: 2.11em;
width: auto;
// The SVG has ~25% built-in padding; pull it in with negative margins
margin: -0.51em -0.2em -0.51em -0.35em;
margin: -0.51em -0.25em -0.51em -0.25em;
vertical-align: middle;
position: relative;
top: -0.04em;
animation: tiktok-glitch 4s ease-in-out infinite;
}

.tiktok-logo-light {
.capcut-logo {
height: 0.78em;
width: auto;
position: relative;
top: 0.06em;
margin-left: 0.2em;
animation: capcut-glow 5s ease-in-out infinite;
animation-delay: 2s;
}

.logo-and {
font-size: 0.6em;
font-weight: 400;
opacity: 0.5;
margin: 0 0.15em;
}

.logo-light {
display: inline-block;
}

.tiktok-logo-dark {
.logo-dark {
display: none;
}

.section-subtitle {
color: var(--home-features-item-desc-color);
text-align: center;
font-size: 18px;
font-size: 16px;
font-weight: 400;
line-height: 1.6;
margin: 0 0 48px;
margin: 0 0 16px;
}

// ── Act 2: Invitation ──

.try-section {
margin-top: 64px;
margin-top: 24px;
margin-bottom: 48px;
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -283,11 +315,11 @@
}
}

:global(.dark) .show-case-frame .tiktok-logo-light {
:global(.dark) .show-case-frame .logo-light {
display: none;
}

:global(.dark) .show-case-frame .tiktok-logo-dark {
:global(.dark) .show-case-frame .logo-dark {
display: inline-block;
}

Expand Down Expand Up @@ -324,5 +356,30 @@
}
}


// CapCut cyan glow pulse + subtle shake
@keyframes capcut-glow {
0%, 75%, 100% {
transform: translate(0, 0);
filter: drop-shadow(0 0 0 transparent);
}
82% {
transform: translate(-1px, 0.5px);
filter: drop-shadow(0 0 12px rgba(1, 224, 248, 0.6))
drop-shadow(0 0 24px rgba(1, 224, 248, 0.25));
}
86% {
transform: translate(1px, -0.5px);
filter: drop-shadow(0 0 10px rgba(1, 224, 248, 0.5))
drop-shadow(0 0 20px rgba(1, 224, 248, 0.2));
}
90% {
transform: translate(-0.5px, 0);
filter: drop-shadow(0 0 6px rgba(1, 224, 248, 0.3))
drop-shadow(0 0 12px rgba(1, 224, 248, 0.1));
}
93% {
transform: translate(0, 0);
filter: drop-shadow(0 0 0 transparent);
}
}

60 changes: 45 additions & 15 deletions src/components/home-comps/showcase/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { MobileShow } from './mobile-show';
import { TrustedBy } from '../trusted-by';
import tiktokLogoBlack from './tiktok-logo-black.svg';
import tiktokLogoWhite from './tiktok-logo-white.svg';
import capcutLogoBlack from './capcut-logo-black.svg';
import capcutLogoWhite from './capcut-logo-white.svg';

const showCaseList = [
{
Expand Down Expand Up @@ -52,31 +54,59 @@ const tryTitle = {

const trySubtitle = {
en: 'Build in minutes with our hands-on tutorials.',
zh: '跟随教程,几分钟上手',
zh: '跟随教程,几分钟上手',
} as const;

export const ShowCase: React.FC = () => {
export const ShowCase: React.FC<{ showMarquee?: boolean }> = ({
showMarquee = false,
}) => {
const lang = useLang() as 'en' | 'zh';

return (
<div className={styles['show-case-frame']}>
{/* Act 1: Credibility */}
<div className={styles['section-title']}>
{lang === 'zh' ? '' : 'Trusted by'}
<img
src={tiktokLogoBlack}
alt="TikTok"
className={`${styles['tiktok-logo']} ${styles['tiktok-logo-light']}`}
/>
<img
src={tiktokLogoWhite}
alt="TikTok"
className={`${styles['tiktok-logo']} ${styles['tiktok-logo-dark']}`}
/>
{lang === 'zh' ? '同款' : ''}
<span className={`${styles['title-line']} ${styles['title-line-sub']}`}>
{lang === 'zh' ? '信赖之选' : 'Trusted by'}
</span>
<span className={styles['title-line']}>
<a
href="https://www.tiktok.com"
target="_blank"
rel="noopener noreferrer"
>
<img
src={tiktokLogoBlack}
alt="TikTok"
className={`${styles['tiktok-logo']} ${styles['logo-light']}`}
/>
<img
src={tiktokLogoWhite}
alt="TikTok"
className={`${styles['tiktok-logo']} ${styles['logo-dark']}`}
/>
</a>

<a
href="https://www.capcut.com"
target="_blank"
rel="noopener noreferrer"
>
<img
src={capcutLogoBlack}
alt="CapCut"
className={`${styles['capcut-logo']} ${styles['logo-light']}`}
/>
<img
src={capcutLogoWhite}
alt="CapCut"
className={`${styles['capcut-logo']} ${styles['logo-dark']}`}
/>
</a>
</span>
</div>
<p className={styles['section-subtitle']}>{sectionSubtitle[lang]}</p>
<TrustedBy />
{showMarquee && <TrustedBy />}

{/* Act 2: Invitation */}
<div className={styles['try-section']}>
Expand Down
1 change: 1 addition & 0 deletions src/components/home-comps/trusted-by/index.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
flex-direction: column;
align-items: center;
width: 100%;
padding: 32px 0 40px;
}

// Wide outer container for commanding presence
Expand Down
28 changes: 15 additions & 13 deletions src/components/home-comps/trusted-by/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import React from 'react';
import styles from './index.module.less';

const apps = [
export interface AppIcon {
name: string;
icon: string;
}

const defaultApps: AppIcon[] = [
{
name: 'TikTok',
icon: 'https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/f4/95/3c/f4953cfb-b350-6763-a0b4-ceed8cef74ed/TikTok_AppIcon26-0-0-1x_U007epad-0-1-0-0-85-220.png/128x128bb.jpg',
Expand All @@ -18,21 +23,16 @@ const apps = [
name: 'Lemon8',
icon: 'https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/5f/d0/24/5fd02457-e750-4dd4-5da7-82a20ebbdfd6/AppIconOriginal-0-0-1x_U007emarketing-0-8-0-85-220.png/128x128bb.jpg',
},
{
name: 'Doubao',
icon: 'https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/e7/e3/51/e7e351d5-afa0-66a1-7081-22f15531aa91/AppIcon-0-0-1x_U007epad-0-8-0-sRGB-85-220.png/128x128bb.jpg',
},
{
name: 'Gauth',
icon: 'https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/62/98/8b/62988bc5-694a-7105-3c75-9de354dc9169/AppIcon-0-0-1x_U007emarketing-0-8-0-85-220.png/128x128bb.jpg',
},
{
name: 'Tokopedia',
icon: 'https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/8d/6e/be/8d6ebe18-1679-96ee-17b0-790800f5ef34/MainAppIcon-0-0-1x_U007epad-0-1-0-0-85-220.png/128x128bb.jpg',
},
];

const IconList: React.FC<{ offset?: number }> = ({ offset = 0 }) => (
const IconList: React.FC<{ apps: AppIcon[]; offset?: number }> = ({
apps,
offset = 0,
}) => (
<div className={styles['icon-group']}>
{apps.map((app) => (
<div key={`${app.name}-${offset}`} className={styles['icon-item']}>
Expand All @@ -48,14 +48,16 @@ const IconList: React.FC<{ offset?: number }> = ({ offset = 0 }) => (
</div>
);

export const TrustedBy: React.FC = () => {
export const TrustedBy: React.FC<{ apps?: AppIcon[] }> = ({
apps = defaultApps,
}) => {
return (
<div className={styles['trusted-by']}>
<div className={styles['marquee-outer']}>
<div className={styles['marquee-wrapper']}>
<div className={styles['marquee-track']}>
<IconList offset={0} />
<IconList offset={1} />
<IconList apps={apps} offset={0} />
<IconList apps={apps} offset={1} />
</div>
</div>
</div>
Expand Down
Loading