1
0
mirror of synced 2025-12-19 18:10:59 -05:00

make journey track cards clickable with hover effect (#58544)

This commit is contained in:
Robert Sese
2025-11-24 15:28:31 -06:00
committed by GitHub
parent c77a233961
commit 0fcf4b6ced
2 changed files with 80 additions and 75 deletions

View File

@@ -1,11 +1,12 @@
.learningTracks {
.journeyTracks {
margin-bottom: 1rem;
margin-left: 1rem;
}
.trackCard {
border: 1px solid
var(--borderColor-default, var(--color-border-default, #d1d9e0));
border-radius: 12px;
padding: 1.5rem;
padding-bottom: 0.75rem;
margin-bottom: 1rem;
margin-left: 1rem;
box-shadow:
0px 1px 3px 0px rgba(31, 35, 40, 0.08),
0px 1px 0px 0px rgba(31, 35, 40, 0.06);
@@ -15,6 +16,24 @@
--bgColor-default,
var(--color-canvas-default, #ffffff)
);
transition: all 0.2s ease-in-out;
// journey card hover effect only when the card is not expanded
&:not([open]):hover {
box-shadow:
0 0.25rem 0.5rem 0 rgba(31, 35, 40, 0.12),
0 0.125rem 0.25rem 0 rgba(31, 35, 40, 0.08);
transform: translateY(-2px);
background-color: var(--bgColor-muted, var(--color-canvas-subtle));
}
}
.trackSummary {
list-style: none;
cursor: pointer;
display: block;
position: relative;
padding: 1.5rem 1.5rem 1.75rem 1.5rem;
}
.trackHeader {
@@ -26,25 +45,25 @@
gap: 0.5rem;
}
.anchorLink {
color: var(--fgColor-default, var(--color-fg-default, #1f2328));
text-decoration: none;
}
.trackDescription {
margin: 0 0 1rem 0;
margin: 0;
padding-right: 2rem;
p {
margin: 0;
color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
}
}
.expandButton {
top: 0;
right: 0;
top: 1.5rem;
right: 1.5rem;
}
.trackGuides {
margin-top: 1rem;
margin-bottom: 1rem;
padding-left: 0;
margin-top: 0;
margin-bottom: 0;
padding: 0 1.5rem 0.75rem 1.5rem;
list-style: none;
counter-reset: guide-counter;
}
@@ -76,11 +95,6 @@
line-height: 1;
}
.guideLink {
color: var(--fgColor-accent, var(--color-accent-fg, #0969da));
text-decoration: none;
}
/* Hide only the timeline line that extends below the last badge, preserve everything else */
.timelineContainer :global(.Timeline-Item:last-child::before) {
background: linear-gradient(
@@ -189,21 +203,20 @@
}
.mobileItem .mobileTile {
border: 1px solid
var(--borderColor-default, var(--color-border-default, #d1d9e0));
border-radius: 12px;
padding: 1rem;
margin-top: 0.5rem;
text-align: left;
box-shadow:
0px 1px 3px 0px rgba(31, 35, 40, 0.08),
0px 1px 0px 0px rgba(31, 35, 40, 0.06);
position: relative;
.trackCard {
z-index: 3;
background-color: var(
--bgColor-default,
var(--color-canvas-default, #ffffff)
);
}
.trackSummary {
padding: 1rem 1rem 1.75rem 1rem;
}
.trackGuides {
padding: 0 1rem 0.75rem 1rem;
}
}
/* Desktop: show Timeline component */

View File

@@ -1,6 +1,6 @@
/* filepath: /workspaces/docs-internal/src/landings/components/journey/JourneyLearningTracks.tsx */
import { ChevronDownIcon, ChevronUpIcon } from '@primer/octicons-react'
import { Button, Details, Timeline, Token, useDetails } from '@primer/react'
import { Details, Timeline, Token, useDetails } from '@primer/react'
import { Link } from '@/frame/components/Link'
import { JourneyTrack } from '@/journeys/lib/journey-path-resolver'
import styles from './JourneyLearningTracks.module.scss'
@@ -14,40 +14,38 @@ export const JourneyLearningTracks = ({ tracks }: JourneyLearningTracksProps) =>
return null
}
const renderTrackContent = (track: JourneyTrack, trackIndex: number) => {
const renderTrackContent = (track: JourneyTrack) => {
const { getDetailsProps, open } = useDetails({})
return (
<>
<Details
{...getDetailsProps()}
id={`track-${track.id}`}
className={styles.trackCard}
data-testid="journey-track"
>
<summary className={styles.trackSummary}>
<div className={styles.trackHeader}>
<h3 className="h4 text-bold">{track.title}</h3>
<Token text={`${track.guides?.length || 0} articles`} />
</div>
<p className={styles.trackDescription}>{track.description}</p>
<Details {...getDetailsProps()}>
<Button
as="summary"
variant="invisible"
className={`position-absolute ${styles.expandButton}`}
aria-label={
open
? `Collapse article list ${trackIndex + 1}`
: `Expand article list ${trackIndex + 1}`
}
>
<div className={styles.trackDescription}>
<p>{track.description}</p>
</div>
<div className={`position-absolute ${styles.expandButton}`}>
{open ? <ChevronUpIcon /> : <ChevronDownIcon />}
</Button>
</div>
</summary>
<ol className={styles.trackGuides} data-testid="journey-articles">
{(track.guides || []).map((article: { href: string; title: string }) => (
<li key={article.title}>
<Link href={article.href} className={`text-semibold ${styles.guideLink}`}>
<Link href={article.href} className="text-semibold">
{article.title}
</Link>
</li>
))}
</ol>
</Details>
</>
)
}
@@ -60,10 +58,8 @@ export const JourneyLearningTracks = ({ tracks }: JourneyLearningTracksProps) =>
return (
<Timeline.Item key={track.id}>
<Timeline.Badge className={styles.timelineBadge}>{trackIndex + 1}</Timeline.Badge>
<Timeline.Body className={styles.learningTracks}>
<div className="position-relative" data-testid="journey-track">
{renderTrackContent(track, trackIndex)}
</div>
<Timeline.Body className={styles.journeyTracks}>
{renderTrackContent(track)}
</Timeline.Body>
</Timeline.Item>
)
@@ -76,11 +72,7 @@ export const JourneyLearningTracks = ({ tracks }: JourneyLearningTracksProps) =>
{tracks.map((track, trackIndex) => (
<div key={track.id} className={styles.mobileItem}>
<div className={styles.mobileBadge}>{trackIndex + 1}</div>
<div className={styles.mobileTile}>
<div className="position-relative" data-testid="journey-track">
{renderTrackContent(track, trackIndex)}
</div>
</div>
<div className={styles.mobileTile}>{renderTrackContent(track)}</div>
{trackIndex < tracks.length - 1 && <div className={styles.mobileConnector} />}
</div>
))}