Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
cc66489
fix(profile): stop the Activity gallery moving the reader, and unstac…
jwalkingjew Sep 19, 2026
af98219
feat(profile): report what the Activity gallery is doing on the devic…
jwalkingjew Sep 19, 2026
016123e
refactor: move the autoplay work out of this PR (GEO-2974)
jwalkingjew Sep 19, 2026
3ddd7e2
Revert the Activity gallery's height floor (GEO-2974)
jwalkingjew Sep 19, 2026
f2b735f
fix(profile): preserve mobile activity scroll position
jwalkingjew Sep 19, 2026
94c4ac8
fix(profile): show the mobile activity reserve on mobile (GEO-2974)
jwalkingjew Sep 19, 2026
4876473
fix(profile): widen the activity claim card so its pills sit side by …
jwalkingjew Sep 19, 2026
2f0ed06
feat(profile): stop nesting the mobile activity gallery inside a card…
jwalkingjew Sep 19, 2026
612ed04
fix(profile): stop the activity reserve dragging the reader back up (…
jwalkingjew Sep 19, 2026
0a74302
feat(profile): land See all on the tab bar rather than the page top (…
jwalkingjew Sep 20, 2026
1613abb
refactor(profile): tighten the activity tests and the comments around…
jwalkingjew Sep 20, 2026
ee27426
fix(profile): keep the tab anchor off the client boundary, and let th…
jwalkingjew Sep 20, 2026
cb31e9b
revert(debates): leave the gated autoplay thresholds alone
jwalkingjew Sep 20, 2026
c8e6e6c
docs(profile): say what the anchor fix did and did not fix
jwalkingjew Sep 20, 2026
f0f4749
fix(profile): watch every input the height reserve depends on
jwalkingjew Sep 20, 2026
1f8c05f
docs(profile): name the browser the viewport fix is for
jwalkingjew Sep 20, 2026
f814017
fix(profile): a viewport that shrinks and grows back must not end the…
jwalkingjew Sep 20, 2026
a89d7db
fix(profile): put the reader back when a growing viewport clamps them
jwalkingjew Sep 20, 2026
c546fe6
test: move the server/client boundary guard to its own PR
jwalkingjew Sep 20, 2026
34f7f5d
Merge branch 'master' into preston/activity-mobile
jwalkingjew Sep 21, 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
34 changes: 23 additions & 11 deletions apps/web/app/space/[id]/(space)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { SpaceMembers } from '~/partials/space-page/space-members';
import { SpacePageMetadataHeader } from '~/partials/space-page/space-metadata-header';
import { SpaceTabs } from '~/partials/space-page/space-tabs';
import type { PersonRecordCounts } from '~/partials/space-page/space-tabs';
import { SPACE_TABS_ANCHOR } from '~/partials/space-page/space-tabs-anchor';

import { cachedFetchEntitiesBatch, cachedFetchEntityPage } from '../../(entity)/[id]/[entityId]/cached-fetch-entity';
import { cachedFetchSpace } from '../cached-fetch-space';
Expand Down Expand Up @@ -209,17 +210,28 @@ export default async function Layout(props0: LayoutProps) {
</>
) : null}
<TypeSchemaInline entityId={props.id} spaceId={spaceId} />
<React.Suspense fallback={null}>
<SpaceTabs
spaceId={spaceId}
entityId={props.id}
initialTabRelations={props.tabRelations ?? []}
tabEntities={props.tabEntities}
typeIds={typeIds}
isProfile={isProfile}
personRecordCounts={personRecordCounts}
/>
</React.Suspense>
{/*
* The tab bar is a link target, so a link can send the reader to the tabs rather than
* to the top of the page — see `withSpaceTabsAnchor`.
*
* The margin clears the navbar, which is `sticky top-0 h-11` and would otherwise cover
* the row the link exists to show — the same 44px the hub panel and the side rail sit
* below as `top-11`. `scroll-mt-14` is that plus 12px, so the tabs land under the
* navbar rather than welded to it.
*/}
<div id={SPACE_TABS_ANCHOR} className="scroll-mt-14">
<React.Suspense fallback={null}>
<SpaceTabs
spaceId={spaceId}
entityId={props.id}
initialTabRelations={props.tabRelations ?? []}
tabEntities={props.tabEntities}
typeIds={typeIds}
isProfile={isProfile}
personRecordCounts={personRecordCounts}
/>
</React.Suspense>
</div>
</div>
</SpaceHeaderContentGate>
<Spacer height={20} />
Expand Down
68 changes: 41 additions & 27 deletions apps/web/core/debates/browse/debate-feed-player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -392,35 +392,49 @@ function DebaterVideo({
</div>
)}

{/* Debater identity: avatar + name + position, opens their personal space in the side panel. */}
<button
type="button"
onClick={openProfile}
className="absolute bottom-3 left-4 z-10 flex items-center gap-2 text-left"
>
<span className="block size-5 shrink-0 overflow-hidden rounded-full bg-white">
<Avatar avatarUrl={participant?.avatar_cid} value={participant?.profile_space_id} size={20} />
</span>
<span className="truncate text-[1rem] font-medium text-white [text-shadow:0_1px_2px_rgba(0,0,0,0.55)]">
{name}
</span>
{/*
* The tile's bottom line: who is speaking on the left, the winner vote on
* the right.
*
* One row rather than two absolutely-positioned corners. They used to be
* `left-4` and `right-4` independently, which is fine at the width a feed
* card gives a tile and not at the width a 312px gallery card does — the
* name and its Agree/Disagree chip simply ran on underneath the button,
* which reads as "Ag…" and "Disagr…" with a pill on top. A flex row cannot
* overlap: the identity takes what is left after the vote, and the name
* truncates into it.
*/}
<div className="pointer-events-none absolute inset-x-0 bottom-3 z-10 flex items-end justify-between gap-2 px-4">
{/* Debater identity: avatar + name + position, opens their personal space in the side panel. */}
<button
type="button"
onClick={openProfile}
className="pointer-events-auto flex min-w-0 items-center gap-2 text-left"
>
<span className="block size-5 shrink-0 overflow-hidden rounded-full bg-white">
<Avatar avatarUrl={participant?.avatar_cid} value={participant?.profile_space_id} size={20} />
</span>
<span className="truncate text-[1rem] font-medium text-white [text-shadow:0_1px_2px_rgba(0,0,0,0.55)]">
{name}
</span>
{participant && (
<DebateTileChip className={cx('shrink-0 text-text', tileChipSurface)}>
{participant.position_label}
</DebateTileChip>
)}
</button>

{participant && (
<DebateTileChip className={cx('shrink-0 text-text', tileChipSurface)}>
{participant.position_label}
</DebateTileChip>
<WinnerVoteButton
className="pointer-events-auto shrink-0"
debaterName={name}
sharePercent={votes.sharePercentFor(participant)}
isMyPick={votes.isMyPick(participant)}
disabled={votes.isVoting}
onVote={() => votes.castVote(participant)}
/>
)}
</button>

{participant && (
<WinnerVoteButton
className="absolute right-4 bottom-3 z-10"
debaterName={name}
sharePercent={votes.sharePercentFor(participant)}
isMyPick={votes.isMyPick(participant)}
disabled={votes.isVoting}
onVote={() => votes.castVote(participant)}
/>
)}
</div>

{scrubber && <div className="absolute inset-x-0 bottom-0 z-10">{scrubber}</div>}
</div>
Expand Down
Loading
Loading