@@ -216,30 +216,79 @@ export function ProfileConnectionGoals(props: {profile: Profile}) {
216216
217217 const { seekingText, relationshipText, romanticStyles} = goals
218218
219- const status = [ relationshipText , ...( romanticStyles ?? [ ] ) ] . filter ( Boolean ) . join ( ' · ' )
219+ const status = [ relationshipText , ...( romanticStyles ?? [ ] ) ] . filter ( Boolean ) . join ( DOT_SEPARATOR )
220220
221221 return (
222222 < div
223223 className = "border-canvas-300 mt-2 flex max-w-2xl flex-wrap gap-x-16 gap-y-6 border-t pt-6"
224224 data-testid = "profile-connection-goals"
225225 >
226- < HeroFact label = { t ( 'profile.looking_for' , 'Looking for' ) } > { seekingText } </ HeroFact >
227- { status && < HeroFact label = { t ( 'profile.status' , 'Status' ) } > { status } </ HeroFact > }
226+ { /* Split back apart at render: `seekingText` is still consumed as one plain string by
227+ `SeekingAndRelationship`, so the builders keep returning strings. */ }
228+ < HeroFact label = { t ( 'profile.looking_for' , 'Looking for' ) } >
229+ < DottedList items = { seekingText . split ( DOT_SEPARATOR ) } />
230+ </ HeroFact >
231+ { status && (
232+ < HeroFact label = { t ( 'profile.status' , 'Status' ) } >
233+ < DottedList items = { status . split ( DOT_SEPARATOR ) } />
234+ </ HeroFact >
235+ ) }
228236 </ div >
229237 )
230238}
231239
240+ export const DOT_SEPARATOR = ' · '
241+
242+ /**
243+ * A run of fragments joined by middots, with the middots stepped back from the words.
244+ *
245+ * The separator is punctuation, not content, so it should not sit at the same weight as the text it
246+ * divides — the eyebrow over the name has always dimmed its own slashes, and these now match.
247+ *
248+ * Carries no colour or size of its own: every caller has a different register (a hero fact, a tag
249+ * run, a qualifier under a rail value) and the run should inherit whichever it lands in.
250+ */
251+ function DottedList ( props : { items : string [ ] } ) {
252+ const { items} = props
253+ return (
254+ < >
255+ { items . map ( ( item , i ) => (
256+ < React . Fragment key = { i } >
257+ { /* The spaces around the middot are load-bearing, not decoration: they are the only
258+ soft-wrap opportunities in the run. Spacing the separator with padding instead leaves the
259+ whole list one unbreakable inline chain, which overflows any container narrower than the
260+ full run — the Interests block pushed the grid wide enough to scroll the page sideways. */ }
261+ { i > 0 && (
262+ < >
263+ { ' ' }
264+ < span aria-hidden className = "text-ink-500/50 select-none" >
265+ ·
266+ </ span > { ' ' }
267+ </ >
268+ ) }
269+ { item }
270+ </ React . Fragment >
271+ ) ) }
272+ </ >
273+ )
274+ }
275+
276+ /**
277+ * Label over value, for the two facts that close the hero.
278+ *
279+ * Both lines stepped down from where they were. The label was `ink-400`, the one neutral grey in a
280+ * warm ramp, at 10px — 2.15:1 in light and 3.0:1 in dark, under AA either way for text that small.
281+ * The value was `ink-900`, which in dark (#F7F4EF) is within a percent of the name's white, so a
282+ * third-tier fact was rendering at the brightest value on the page. Only the name keeps that now.
283+ */
232284function HeroFact ( props : { label : string ; children : ReactNode } ) {
233285 const { label, children} = props
234286 return (
235287 < div className = "min-w-0" >
236- < div
237- className = "text-ink-400 font-dm-sans uppercase"
238- style = { { fontSize : '10px' , letterSpacing : '0.18em' , marginBottom : '7px' } }
239- >
288+ < div className = "text-ink-500 font-microcaps" style = { { marginBottom : '7px' } } >
240289 { label }
241290 </ div >
242- < div className = "text-ink-900 " style = { { fontSize : '15.5px' } } >
291+ < div className = "text-ink-700 font-dm-sans " style = { { fontSize : '15.5px' } } >
243292 { children }
244293 </ div >
245294 </ div >
@@ -361,7 +410,7 @@ export function getCompactSeekingText(profile: Profile, t: any) {
361410 ? t ( 'profile.age_max_compact' , 'under {max}' , { max} )
362411 : t ( 'profile.age_range_compact' , '{min}-{max}' , { min, max} )
363412
364- return [ connection , genderText , ageText ] . filter ( Boolean ) . join ( ' · ' )
413+ return [ connection , genderText , ageText ] . filter ( Boolean ) . join ( DOT_SEPARATOR )
365414}
366415
367416function capitalizeFirst ( s : string ) {
@@ -610,16 +659,19 @@ function Cannabis(props: {profile: Profile}) {
610659 const prefText = formatPartnerPreferences ( profile . cannabis_pref , t )
611660
612661 return (
613- < AboutRow title = { t ( 'profile.cannabis' , 'Cannabis' ) } text = { parts } >
614- { showIntentions && (
615- < div className = "flex flex-wrap gap-2 mt-2" >
616- { profile . cannabis_intention ! . map ( ( i ) => (
617- < Chip key = { i } >
618- { t ( `profile.substance_intention.${ i } ` , INVERTED_SUBSTANCE_INTENTION_CHOICES [ i ] ) }
619- </ Chip >
620- ) ) }
621- </ div >
622- ) }
662+ < AboutRow
663+ title = { t ( 'profile.cannabis' , 'Cannabis' ) }
664+ text = { parts }
665+ details = {
666+ showIntentions && (
667+ < DottedList
668+ items = { profile . cannabis_intention ! . map ( ( i ) =>
669+ t ( `profile.substance_intention.${ i } ` , INVERTED_SUBSTANCE_INTENTION_CHOICES [ i ] ) ,
670+ ) }
671+ />
672+ )
673+ }
674+ >
623675 { prefText && (
624676 < div className = { 'text-ink-500 mt-2' } style = { { fontSize : '12.5px' } } >
625677 { prefText }
@@ -645,16 +697,19 @@ function Psychedelics(props: {profile: Profile}) {
645697 const prefText = formatPartnerPreferences ( profile . psychedelics_pref , t )
646698
647699 return (
648- < AboutRow title = { t ( 'profile.psychedelics' , 'Psychedelics' ) } text = { parts } >
649- { showIntentions && (
650- < div className = "flex flex-wrap gap-2 mt-2" >
651- { profile . psychedelics_intention ! . map ( ( i ) => (
652- < Chip key = { i } >
653- { t ( `profile.substance_intention.${ i } ` , INVERTED_SUBSTANCE_INTENTION_CHOICES [ i ] ) }
654- </ Chip >
655- ) ) }
656- </ div >
657- ) }
700+ < AboutRow
701+ title = { t ( 'profile.psychedelics' , 'Psychedelics' ) }
702+ text = { parts }
703+ details = {
704+ showIntentions && (
705+ < DottedList
706+ items = { profile . psychedelics_intention ! . map ( ( i ) =>
707+ t ( `profile.substance_intention.${ i } ` , INVERTED_SUBSTANCE_INTENTION_CHOICES [ i ] ) ,
708+ ) }
709+ />
710+ )
711+ }
712+ >
658713 { prefText && (
659714 < div className = { 'text-ink-500 mt-2' } style = { { fontSize : '12.5px' } } >
660715 { prefText }
@@ -834,16 +889,7 @@ function TagList(props: {items: string[]}) {
834889 const { items} = props
835890 return (
836891 < div className = "text-primary-900" style = { { fontSize : '15px' , lineHeight : '1.65' } } >
837- { items . map ( ( item , i ) => (
838- < React . Fragment key = { item } >
839- { i > 0 && (
840- < span aria-hidden className = "text-ink-400 select-none" >
841- { ' · ' }
842- </ span >
843- ) }
844- { item }
845- </ React . Fragment >
846- ) ) }
892+ < DottedList items = { items } />
847893 </ div >
848894 )
849895}
0 commit comments