Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
f0782f2
feat(game-center): level-focused arcade HUD for the progress snapshot
tomeredlich Aug 13, 2026
9ac2857
feat(game-center): trophy case award grid ordered by rarity
tomeredlich Aug 23, 2026
9104409
feat(game-center): milestone quests redesign mockup
tomeredlich Aug 23, 2026
c85cd65
feat(game-center): redesign achievement shelf as netflix-style slab c…
tomeredlich Aug 23, 2026
65a234b
feat(game-center): add shared LevelHud component (dark cabbage banner…
tomeredlich Aug 23, 2026
1efd7d4
feat(game-center): ship the milestone quests and badge case redesigns
tomeredlich Aug 23, 2026
80c17fc
fix(game-center): make the redesigned sections render in both themes
tomeredlich Aug 23, 2026
95c4552
feat(game-center): vertical milestone cards in a scroller, frameless …
tomeredlich Aug 23, 2026
550a9c6
fix(game-center): tighten the trophy grid and use real achievement art
tomeredlich Aug 23, 2026
c129a79
feat(game-center): drop the card frame around the progress snapshot
tomeredlich Aug 23, 2026
66de2af
fix(game-center): match the achievement shelf to the slab spec
tomeredlich Aug 23, 2026
aa5ca87
fix(game-center): spell out the achievement unlock date as "Aug 2"
tomeredlich Aug 23, 2026
c04cdf0
fix(game-center): let the achievement art fill the slab
tomeredlich Aug 23, 2026
322afb2
feat(game-center): sticky holographic hero card beside the page content
tomeredlich Aug 23, 2026
fbf0ce7
Revert "feat(game-center): sticky holographic hero card beside the pa…
tomeredlich Aug 23, 2026
e38c73d
feat(game-center): put each section's headline stat on its header row
tomeredlich Aug 23, 2026
32b978b
feat(game-center): rebuild community pulse as an ambient band
tomeredlich Aug 23, 2026
52332a8
feat(game-center): double the size of the achievement shelf cards
tomeredlich Aug 23, 2026
59aa44c
Revert "feat(game-center): double the size of the achievement shelf c…
tomeredlich Aug 23, 2026
5ac86e8
feat(game-center): drop section subtext, floor type at 14px, polish b…
tomeredlich Aug 23, 2026
5badde3
revert(game-center): drop the badge case sheen animation
tomeredlich Aug 23, 2026
25e5ad2
feat(game-center): move total XP into the level HUD stat row
tomeredlich Aug 24, 2026
dd4c904
feat(game-center): bare level number, x/x XP, unfilled non-claimable …
tomeredlich Aug 24, 2026
89b56dc
feat(game-center): move the XP readout under the progress bar
tomeredlich Aug 24, 2026
0add3f3
feat(game-center): continuous XP bar, larger achievement cards
tomeredlich Aug 24, 2026
26b2642
feat(game-center): add a section spine under the progress snapshot
tomeredlich Aug 24, 2026
fcb8dbe
Revert "feat(game-center): add a section spine under the progress sna…
tomeredlich Aug 24, 2026
9aca908
feat(game-center): split the progress snapshot into two boxes
tomeredlich Aug 24, 2026
fa4939a
feat(game-center): merge the snapshot halves into one box
tomeredlich Aug 24, 2026
c2f7a20
feat(game-center): drop the snapshot borders
tomeredlich Aug 24, 2026
b0afe29
feat(game-center): outline the snapshot and split it from tablet up
tomeredlich Aug 24, 2026
0c1d7af
feat(game-center): round the snapshot cells
tomeredlich Aug 24, 2026
4f88c6c
feat(game-center): enlarge the level badge and pattern its panel
tomeredlich Aug 24, 2026
7861ae3
feat(game-center): square level badge, unframed sections, trophy holder
tomeredlich Aug 24, 2026
d4be214
feat(game-center): shelf see-all card, community pulse last
tomeredlich Aug 24, 2026
2ff0897
chore: cherry-pick streak milestone offers (#6487)
tomeredlich Aug 24, 2026
a028c9c
feat(game-center): claim streak offers from the milestone rail
tomeredlich Aug 24, 2026
91a2e8f
feat(storybook): three Badges & Trophies combined-section designs
tomeredlich Aug 24, 2026
7425bed
feat(game-center): merge the badge and trophy cases into one section
tomeredlich Aug 24, 2026
a154392
feat(game-center): lead each case pane with its count
tomeredlich Aug 24, 2026
0dca983
feat(game-center): style the case panes like the progress snapshot
tomeredlich Aug 24, 2026
11bdb54
feat(game-center): badge artwork, wider awards, offer subtitles
tomeredlich Aug 24, 2026
8f4a76e
feat(game-center): white level badge, bigger achievement cards
tomeredlich Aug 24, 2026
e8f6eea
feat(game-center): one icon colour, framed case section
tomeredlich Aug 24, 2026
9b2fb12
feat(game-center): give the offers their own Claimable gifts strip
tomeredlich Aug 24, 2026
194ece2
feat(game-center): lay the milestones out as a grid
tomeredlich Aug 24, 2026
c8c6940
feat(game-center): split the case section evenly
tomeredlich Aug 24, 2026
03d9d93
feat(storybook): real topic logos on the badge rows
tomeredlich Aug 24, 2026
86afde2
feat(game-center): rebuild community pulse as two races
tomeredlich Aug 24, 2026
1543b0e
feat(game-center): drop the stat icons, frost the level badge
tomeredlich Aug 24, 2026
03b9246
feat(game-center): quieter milestones, glass topic rows, real award art
tomeredlich Aug 24, 2026
842b018
Revert "frosted glass on the topic rows"
tomeredlich Aug 24, 2026
dac1648
feat(game-center): use the daily.dev hero art behind the level
tomeredlich Aug 24, 2026
874cbaf
feat(storybook): three full-bleed progress hero designs
tomeredlich Aug 25, 2026
12f3099
feat(game-center): make the snapshot a full-bleed HUD bar
tomeredlich Aug 25, 2026
e26a863
fix(game-center): keep the HUD stacked at every width
tomeredlich Aug 25, 2026
7db411f
feat(game-center): lead the HUD with the greeting
tomeredlich Aug 25, 2026
1dfe6f9
feat(game-center): give the HUD room to breathe
tomeredlich Aug 25, 2026
ea28b6c
feat(game-center): drop every scroller, split badges from achievements
tomeredlich Aug 25, 2026
636f68d
feat(game-center): portrait achievement cards, medal on the badge chip
tomeredlich Aug 25, 2026
38ac93a
feat(game-center): badge paging, award value, and assorted polish
tomeredlich Aug 25, 2026
0480a77
feat(game-center): one progress bar everywhere, pager pinned low
tomeredlich Aug 25, 2026
8b91dfa
feat(game-center): drop the rarity rings, order awards by count
tomeredlich Aug 25, 2026
6f74298
feat(game-center): full achievement shelf, badges leaderboard
tomeredlich Aug 25, 2026
cd6b847
feat(storybook): real catalogue and leaderboard data in the page mock
tomeredlich Aug 25, 2026
3815891
feat(game-center): hover-only track, gold sub-1% chips, steady pager
tomeredlich Aug 25, 2026
526ca3a
feat(game-center): third community column, faded claimed quests
tomeredlich Aug 25, 2026
df5f380
Merge remote-tracking branch 'origin/main' into game-center-redesign
tomeredlich Aug 25, 2026
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
5 changes: 4 additions & 1 deletion packages/shared/src/components/DataTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface DataTileProps {
valueClassName?: string;
className?: {
container?: string;
label?: string;
};
}

Expand All @@ -36,7 +37,9 @@ export const DataTile: React.FC<DataTileProps> = ({
)}
>
<span className="flex flex-row items-center gap-1">
<Typography type={TypographyType.Footnote}>{label}</Typography>
<Typography type={TypographyType.Footnote} className={className?.label}>
{label}
</Typography>
<Tooltip content={info} enableMobileClick>
<span className="text-text-disabled">
<InfoIcon size={IconSize.Size16} />
Expand Down
51 changes: 51 additions & 0 deletions packages/shared/src/components/badges/TopReaderBadgeCompact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { ReactElement } from 'react';
import React from 'react';
import { DevCardTheme, themeToLinearGradient } from '../profile/devcard';
import type { TopReader } from './TopReaderBadge';
import {
Typography,
TypographyColor,
TypographyTag,
TypographyType,
} from '../typography/Typography';
import { formatDate, TimeFormatType } from '../../lib/dateFormat';

export const TopReaderBadgeCompact = ({
issuedAt,
keyword,
}: Pick<TopReader, 'issuedAt' | 'keyword'>): ReactElement => {
const formattedDate = formatDate({
value: issuedAt,
type: TimeFormatType.TopReaderBadge,
});

return (
<div className="flex w-max min-w-36 flex-col items-center gap-2 rounded-16 border border-border-subtlest-tertiary bg-surface-float p-4 text-center">
<Typography type={TypographyType.Callout} bold>
Top reader
</Typography>

<Typography
tag={TypographyTag.Time}
type={TypographyType.Subhead}
color={TypographyColor.Tertiary}
dateTime={new Date(issuedAt).toISOString()}
>
{formattedDate}
</Typography>

<div
className="mt-1 rounded-8 px-3 py-1"
style={{ backgroundImage: themeToLinearGradient[DevCardTheme.Gold] }}
>
<Typography
type={TypographyType.Subhead}
bold
className="whitespace-nowrap text-black"
>
{keyword.flags?.title || keyword.value}
</Typography>
</div>
</div>
);
};
162 changes: 162 additions & 0 deletions packages/shared/src/components/quest/LevelHud.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import type { ReactElement } from 'react';
import React from 'react';
import {
Typography,
TypographyTag,
TypographyType,
} from '../typography/Typography';
import { ProgressBar } from '../fields/ProgressBar';
import { gameCenterLevelBackground } from '../../lib/image';

type HudStatProps = {
label: string;
value: string;
};

const HudStat = ({ label, value }: HudStatProps): ReactElement => (
<div className="flex items-baseline gap-1.5">
<Typography type={TypographyType.Subhead} className="text-white opacity-64">
{label}
</Typography>
<Typography type={TypographyType.Callout} bold className="text-white">
{value}
</Typography>
</div>
);

// Off-token purples, so these stay inline rather than fighting the
// no-custom-color rule with arbitrary classes.
const levelPanelStyle = {
backgroundColor: '#2A0B3D',
backgroundImage: [
// A dark wash over the art, so the level, bar and readout keep their
// contrast wherever the artwork happens to be bright.
'linear-gradient(100deg, rgba(42,11,61,0.94) 0%, rgba(42,11,61,0.70) 42%, rgba(42,11,61,0.42) 100%)',
`url("${gameCenterLevelBackground}")`,
].join(', '),
backgroundSize: 'auto, cover',
backgroundPosition: 'center, 46% 50%',
};

// Frosted glass over the patterned panel: a translucent white wash, a
// lit top edge and a soft border, so the panel's pattern shows through.
const levelBadgeStyle = {
background:
'linear-gradient(145deg, rgba(255,255,255,0.42), rgba(255,255,255,0.10))',
border: '1px solid rgba(255,255,255,0.45)',
};

export interface LevelHudProps {
name: string;
level: number;
levelProgress: number;
totalXp: number;
xpInLevel: number;
xpToNextLevel: number;
currentStreak: number;
longestStreak: number;
badges?: number;
achievements?: { unlocked: number; total: number };
isPending: boolean;
}

export const LevelHud = ({
name,
level,
levelProgress,
totalXp,
xpInLevel,
xpToNextLevel,
currentStreak,
longestStreak,
badges,
achievements,
isPending,
}: LevelHudProps): ReactElement => {
const streakValue = isPending ? '...' : `${currentStreak.toLocaleString()}d`;
const longestValue = isPending ? '...' : `${longestStreak.toLocaleString()}d`;

const stats: HudStatProps[] = [
{
label: 'Streak',
value: streakValue,
},
{
label: 'Longest',
value: longestValue,
},
...(badges === undefined
? []
: [{ label: 'Badges', value: badges.toLocaleString() }]),
...(achievements
? [
{
label: 'Achievements',
value: `${achievements.unlocked}/${achievements.total}`,
},
]
: []),
{
label: 'Total XP',
value: isPending ? '...' : totalXp.toLocaleString(),
},
];

return (
<div
className="flex flex-col gap-4 px-4 py-8 tablet:px-8 tablet:py-10"
style={levelPanelStyle}
>
<div className="flex items-center gap-3">
<div
className="level-badge-glass flex size-14 shrink-0 items-center justify-center rounded-16 text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.55),inset_0_-1px_0_rgba(255,255,255,0.12),0_8px_24px_-8px_rgba(0,0,0,0.65)] backdrop-blur-[6px]"
style={levelBadgeStyle}
aria-label={`Level ${level}`}
>
<Typography
type={TypographyType.Title2}
className="w-full text-center !font-black tabular-nums !leading-none"
>
{level}
</Typography>
</div>
<Typography
tag={TypographyTag.H1}
type={TypographyType.Title1}
bold
className="min-w-0 truncate text-white"
>
{name}, here&apos;s how you&apos;re doing.
</Typography>
</div>

<div className="flex min-w-0 flex-1 flex-col gap-1.5">
<ProgressBar
percentage={levelProgress}
shouldShowBg
className={{
wrapper: 'h-2 rounded-max !bg-[#5A1E75]',
bar: 'h-full rounded-max',
barColor: 'bg-[#E669FB]',
}}
/>
<div className="flex items-baseline justify-between gap-3">
<Typography
type={TypographyType.Subhead}
bold
className="tabular-nums text-white"
>
{xpInLevel.toLocaleString()} /{' '}
{(xpInLevel + xpToNextLevel).toLocaleString()}
</Typography>
</div>
</div>

<div className="flex flex-wrap items-center gap-x-6 gap-y-2">
{stats.map((stat) => (
<HudStat key={stat.label} {...stat} />
))}
</div>
</div>
);
};
Loading
Loading