Skip to content

Commit bde18d8

Browse files
authored
Landing page fixes 2 (#13751)
1 parent 87918f9 commit bde18d8

12 files changed

Lines changed: 356 additions & 167 deletions

packages/web/src/public-site/pages/landing-2026/components/CreateFutureCTA.module.css

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@
8080
background: transparent;
8181
cursor: pointer;
8282
text-decoration: none;
83-
transition: box-shadow 0.25s ease;
83+
transition:
84+
box-shadow 0.25s ease,
85+
background 0.2s ease,
86+
border-color 0.2s ease;
8487
box-sizing: border-box;
8588
}
8689

@@ -92,6 +95,17 @@
9295
inset -4px 0px 4px 0px rgba(175, 72, 255, 0.25);
9396
}
9497

98+
/* Figma 2738-4495: press state */
99+
.ctaButton:active {
100+
background: rgba(53, 20, 75, 0.85);
101+
border-color: rgba(175, 72, 255, 0.9);
102+
box-shadow: none;
103+
}
104+
105+
.ctaButton:active .ctaLabel {
106+
color: #e7c7ff;
107+
}
108+
95109
.ctaLabel {
96110
font-family: 'Urbanist', sans-serif;
97111
font-weight: 700;
@@ -100,12 +114,12 @@
100114
color: #fff;
101115
text-transform: capitalize;
102116
white-space: nowrap;
117+
transition: color 0.2s ease;
103118
}
104119

105120
@media (max-width: 800px) {
106121
.section {
107122
padding: 32px 16px;
108-
box-shadow: 0 10px 50px rgba(53, 5, 152, 0.25);
109123
}
110124

111125
.content {

packages/web/src/public-site/pages/landing-2026/components/FAQ2026.module.css

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,16 @@
7272
text-shadow 0.2s ease;
7373
}
7474

75-
.faqItem[aria-expanded='true'] .faqQuestion,
76-
.faqItem:hover .faqQuestion,
77-
.faqItem:active .faqQuestion,
75+
/* Purple hover when whole FAQ row is hovered; carets match text color */
76+
.faqItem:hover .faqQuestion {
77+
color: #e7c7ff;
78+
text-shadow:
79+
-4px 0px 4px rgba(175, 72, 255, 0.25),
80+
4px 0px 4px rgba(175, 72, 255, 0.25),
81+
0px -4px 4px rgba(175, 72, 255, 0.25),
82+
0px 4px 4px rgba(175, 72, 255, 0.25);
83+
}
84+
7885
.faqItem:focus-visible .faqQuestion {
7986
color: #e7c7ff;
8087
text-shadow:
@@ -84,28 +91,39 @@
8491
0px 4px 4px rgba(175, 72, 255, 0.25);
8592
}
8693

94+
/* Press state: same purple as hover (Figma 2777-2986) */
95+
.faqItem:active .faqQuestion {
96+
color: #e7c7ff;
97+
text-shadow:
98+
-4px 0px 4px rgba(175, 72, 255, 0.25),
99+
4px 0px 4px rgba(175, 72, 255, 0.25),
100+
0px -4px 4px rgba(175, 72, 255, 0.25),
101+
0px 4px 4px rgba(175, 72, 255, 0.25);
102+
}
103+
87104
.chevron {
88105
width: 16px;
89106
height: 16px;
90107
flex-shrink: 0;
91-
transition: transform 0.3s ease;
108+
display: inline-flex;
109+
align-items: center;
110+
justify-content: center;
111+
color: #fff;
112+
transition:
113+
transform 0.3s ease,
114+
color 0.2s ease;
92115
}
93116

94-
.chevron svg,
95-
.chevron svg path {
96-
fill: #fff !important;
97-
transition: fill 0.2s ease;
117+
.chevron svg {
118+
width: 100%;
119+
height: 100%;
98120
}
99121

100-
.faqItem[aria-expanded='true'] .chevron svg,
101-
.faqItem[aria-expanded='true'] .chevron svg path,
102-
.faqItem:hover .chevron svg,
103-
.faqItem:hover .chevron svg path,
104-
.faqItem:active .chevron svg,
105-
.faqItem:active .chevron svg path,
106-
.faqItem:focus-visible .chevron svg,
107-
.faqItem:focus-visible .chevron svg path {
108-
fill: #e7c7ff !important;
122+
/* Purple when whole row hover/focus/active, same as question */
123+
.faqItem:hover .chevron,
124+
.faqItem:focus-visible .chevron,
125+
.faqItem:active .chevron {
126+
color: #e7c7ff;
109127
}
110128

111129
.faqItem[aria-expanded='true'] .chevron {

packages/web/src/public-site/pages/landing-2026/components/FAQ2026.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
11
import { useState } from 'react'
22

3-
import { IconCaretDown } from '@audius/harmony'
4-
53
import styles from './FAQ2026.module.css'
64

5+
/** Inline chevron so we control color (white default, purple on hover) without Harmony theme override */
6+
function ChevronDown({ className }: { className?: string }) {
7+
return (
8+
<span className={className} aria-hidden>
9+
<svg
10+
width='16'
11+
height='16'
12+
viewBox='0 0 16 16'
13+
fill='none'
14+
xmlns='http://www.w3.org/2000/svg'
15+
>
16+
<path
17+
d='M4 6L8 10L12 6'
18+
stroke='currentColor'
19+
strokeWidth='2'
20+
strokeLinecap='round'
21+
strokeLinejoin='round'
22+
/>
23+
</svg>
24+
</span>
25+
)
26+
}
27+
728
const faqItems = [
829
{
930
question: 'Who is Audius made for?',
@@ -62,11 +83,7 @@ export const FAQ2026 = (_props: FAQ2026Props) => {
6283
>
6384
<div className={styles.faqHeader}>
6485
<p className={styles.faqQuestion}>{item.question}</p>
65-
<IconCaretDown
66-
size='s'
67-
color='default'
68-
className={styles.chevron}
69-
/>
86+
<ChevronDown className={styles.chevron} />
7087
</div>
7188
{isOpen ? (
7289
<div className={styles.faqContent}>

packages/web/src/public-site/pages/landing-2026/components/FeaturedContests2026.module.css

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,30 @@
111111
overflow: hidden;
112112
}
113113

114+
.artworkSkeletonInner {
115+
position: absolute;
116+
inset: 0;
117+
background: rgba(255, 255, 255, 0.06);
118+
}
119+
120+
.artworkWrapLoaded .artworkSkeletonInner {
121+
opacity: 0;
122+
pointer-events: none;
123+
transition: opacity 0.25s ease;
124+
}
125+
114126
.artwork {
115127
position: absolute;
116128
inset: 0;
117129
width: 100%;
118130
height: 100%;
119131
object-fit: cover;
132+
opacity: 0;
133+
transition: opacity 0.35s ease;
134+
}
135+
136+
.artworkWrapLoaded .artwork {
137+
opacity: 1;
120138
}
121139

122140
.bwOverlay {

packages/web/src/public-site/pages/landing-2026/components/FeaturedContests2026.tsx

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
import { MouseEvent } from 'react'
1+
import { MouseEvent, useState } from 'react'
22

33
import {
44
useExploreContent,
55
useRemixContest,
66
useTrack,
77
useUser
88
} from '@audius/common/api'
9-
import { ID } from '@audius/common/models'
9+
import { imageBlank } from '@audius/common/assets'
10+
import { useImageSize } from '@audius/common/hooks'
11+
import { ID, SquareSizes } from '@audius/common/models'
1012
import { useLinkClickHandler } from 'react-router'
1113

14+
import { preload } from 'utils/image'
15+
1216
import featuredLines from '../assets/featured-lines.svg?url'
1317

1418
import styles from './FeaturedContests2026.module.css'
@@ -30,10 +34,19 @@ function ContestCard({
3034
id: ID
3135
setRenderPublicSite: (v: boolean) => void
3236
}) {
37+
const [imageLoaded, setImageLoaded] = useState(false)
3338
const { data: contest, isPending: contestPending } = useRemixContest(id)
3439
const { data: track, isPending: trackPending } = useTrack(contest?.entityId)
3540
const { data: user, isPending: userPending } = useUser(track?.owner_id)
3641

42+
const artwork = track?.artwork
43+
const { imageUrl, onError } = useImageSize({
44+
artwork,
45+
targetSize: SquareSizes.SIZE_480_BY_480,
46+
defaultImage: imageBlank as string,
47+
preloadImageFn: preload
48+
})
49+
3750
const isPending = contestPending || trackPending || userPending || !track
3851
const permalink = track?.permalink ?? ''
3952
const handleNavigate = useLinkClickHandler(permalink)
@@ -43,6 +56,8 @@ function ContestCard({
4356
handleNavigate(e as MouseEvent<HTMLAnchorElement>)
4457
}
4558

59+
const showImage = imageUrl != null && imageUrl !== (imageBlank as string)
60+
4661
if (isPending) {
4762
return (
4863
<div className={styles.card}>
@@ -52,28 +67,27 @@ function ContestCard({
5267
)
5368
}
5469

55-
const artworkUrl =
56-
(track?.artwork && (track.artwork as Record<string, string>)['480x480']) ??
57-
null
58-
5970
return (
6071
<button
6172
type='button'
6273
className={styles.card}
6374
onClick={onClick}
6475
aria-label={`Contest: ${track?.title} by ${user?.name}`}
6576
>
66-
<div className={styles.artworkWrap}>
67-
{artworkUrl ? (
77+
<div
78+
className={`${styles.artworkWrap} ${imageLoaded ? styles.artworkWrapLoaded : ''}`}
79+
>
80+
<div className={styles.artworkSkeletonInner} aria-hidden='true' />
81+
{showImage ? (
6882
<img
69-
src={artworkUrl}
83+
src={imageUrl}
7084
alt=''
7185
className={styles.artwork}
7286
loading='lazy'
87+
onLoad={() => setImageLoaded(true)}
88+
onError={() => onError(imageUrl!)}
7389
/>
74-
) : (
75-
<div className={styles.artworkPlaceholder} />
76-
)}
90+
) : null}
7791
<div className={styles.bwOverlay} aria-hidden='true' />
7892
</div>
7993
<span className={styles.title}>{track?.title}</span>

packages/web/src/public-site/pages/landing-2026/components/Footer2026.tsx

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { MouseEvent } from 'react'
2-
31
import { route } from '@audius/common/utils'
42
import {
53
IconAudiusLogoHorizontal,
@@ -9,14 +7,18 @@ import {
97
IconX
108
} from '@audius/harmony'
119
import type { IconComponent } from '@audius/harmony'
12-
import { useNavigate } from 'react-router'
13-
14-
import { handleClickRoute } from 'public-site/components/handleClickRoute'
1510

1611
import styles from './Footer2026.module.css'
1712

1813
const { PRIVACY_POLICY, TERMS_OF_SERVICE } = route
1914

15+
const getLegalUrl = (path: string) => {
16+
if (typeof window !== 'undefined' && window.location?.origin) {
17+
return `${window.location.origin}${path}`
18+
}
19+
return `https://audius.co${path}`
20+
}
21+
2022
type Footer2026Props = {
2123
isMobile: boolean
2224
setRenderPublicSite: (shouldRender: boolean) => void
@@ -32,7 +34,7 @@ const siteLinks = [
3234
const socialLinks: { label: string; href: string; Icon: IconComponent }[] = [
3335
{
3436
label: 'Instagram',
35-
href: 'https://instagram.com/audiusmusic',
37+
href: 'https://instagram.com/audius',
3638
Icon: IconInstagram
3739
},
3840
{
@@ -47,18 +49,12 @@ const socialLinks: { label: string; href: string; Icon: IconComponent }[] = [
4749
},
4850
{
4951
label: 'X (Twitter)',
50-
href: 'https://twitter.com/audiusproject',
52+
href: 'https://twitter.com/audius',
5153
Icon: IconX
5254
}
5355
]
5456

5557
export const Footer2026 = (props: Footer2026Props) => {
56-
const navigate = useNavigate()
57-
58-
const onLegalClick = (legalRoute: string) => (e: MouseEvent) => {
59-
handleClickRoute(legalRoute, props.setRenderPublicSite, navigate)(e)
60-
}
61-
6258
return (
6359
<footer className={styles.footer}>
6460
<div className={styles.inner}>
@@ -117,20 +113,22 @@ export const Footer2026 = (props: Footer2026Props) => {
117113
&copy; 2025 Audius Music. All rights reserved.
118114
</p>
119115
<div className={styles.legalLinks}>
120-
<button
121-
type='button'
116+
<a
117+
href={getLegalUrl(TERMS_OF_SERVICE)}
122118
className={styles.legalLink}
123-
onClick={onLegalClick(TERMS_OF_SERVICE)}
119+
target='_blank'
120+
rel='noopener noreferrer'
124121
>
125122
Terms of Service
126-
</button>
127-
<button
128-
type='button'
123+
</a>
124+
<a
125+
href={getLegalUrl(PRIVACY_POLICY)}
129126
className={styles.legalLink}
130-
onClick={onLegalClick(PRIVACY_POLICY)}
127+
target='_blank'
128+
rel='noopener noreferrer'
131129
>
132130
Privacy Policy
133-
</button>
131+
</a>
134132
</div>
135133
</div>
136134
</div>

packages/web/src/public-site/pages/landing-2026/components/GrowthStartsHere.module.css

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,12 @@
7777
}
7878

7979
.visualWrap {
80-
width: 612px;
81-
flex-shrink: 0;
80+
max-width: 612px;
81+
width: 100%;
82+
flex: 0 1 612px;
83+
min-width: 0;
8284
align-self: stretch;
85+
max-height: min(480px, 55vh);
8386
overflow: hidden;
8487
}
8588

0 commit comments

Comments
 (0)