Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 12 additions & 3 deletions frontend/src/components/panels/LibrarySpaceView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,14 @@ export function LibrarySpaceView({ project, dark, onClose, embedded }: Props) {
)}
</div>

<div className="flex-1 overflow-x-auto overflow-y-hidden p-4">
<div className="flex gap-3 h-full min-w-max mx-auto justify-center">
{/* Desktop: columns are full-height and scroll internally, so the
board itself must not scroll vertically. Mobile: a column is
taller than the screen, and overflow-y-hidden made everything
below the fold unreachable — you could scroll sideways but not
down. Below md the board scrolls vertically and the columns
size to their content instead of fighting for a bounded height. */}
<div className="flex-1 overflow-x-auto overflow-y-auto md:overflow-y-hidden p-4">
<div className="flex gap-3 h-auto md:h-full min-w-max mx-auto justify-center items-start md:items-stretch">
{columns.map((col: LibraryTaskColumn) => {
const isDropTarget = dragOverColumn === col.id;
return (
Expand Down Expand Up @@ -513,7 +519,10 @@ export function LibrarySpaceView({ project, dark, onClose, embedded }: Props) {
)}
</div>

<div className="flex-1 overflow-y-auto p-2 space-y-2">
{/* On mobile the board scrolls, so a column must grow to
its content; an inner overflow-y-auto here would create
a second, nested scroll region that traps the gesture. */}
<div className="flex-1 md:overflow-y-auto p-2 space-y-2">
{(tasksByColumn[col.id] ?? []).map((task) => (
<TaskCard
key={task.id}
Expand Down
26 changes: 18 additions & 8 deletions frontend/src/components/panels/SpacePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -637,15 +637,25 @@ export function SpacePage({ spaceSlug, onBack }: Props) {
)}
{showingSpaceChat && (
<div className={clsx(
'w-full md:w-[var(--chat-w)] flex flex-col shrink-0 min-h-0',
'border-t md:border-t-0 md:border-l',
'flex flex-col min-h-0',
// MOBILE: an overlay sheet, not a flex sibling. As a sibling it
// competed with the tab content for height, so on a tall board it
// was pushed below the fold and simply never appeared. Fixed to
// the bottom above everything, it always shows when toggled.
// z-40 clears the mobile tab bar (z-30), and the sheet sits ON
// TOP of it rather than behind: 'over content' is the whole point.
// pb-mobile-nav gives the bar its 3.5rem back, and the CSS rule
// zeroes that padding the moment the keyboard opens and the bar
// hides — otherwise a dead strip sits under the composer.
'fixed inset-x-0 bottom-0 z-40 h-[60svh] min-h-[12rem] border-t shadow-2xl',
'pb-mobile-nav pb-[calc(3.5rem+env(safe-area-inset-bottom,0px))] md:pb-0',
// DESKTOP: back to the resizable in-flow column it was.
'md:static md:inset-auto md:z-auto md:h-auto md:min-h-0 md:shadow-none',
'md:w-[var(--chat-w)] md:shrink-0 md:border-t-0 md:border-l',
// svh, not vh: on iOS `vh` is the LARGE viewport — the height as
// if the browser chrome were hidden — so a 40vh pane is taller than
// 40% of what you can actually see, and with shrink-0 it can be
// pushed past the bottom edge. `svh` is the small viewport, which
// is the one that is always really there. A floor keeps it usable
// rather than a sliver on a short screen.
'h-[45svh] min-h-[10rem] md:h-auto md:min-h-0',
// if the browser chrome were hidden — so a 60vh pane is taller than
// 60% of what you can actually see and runs past the bottom edge.
// `svh` is the small viewport, the one that is always really there.
)}
style={{
borderColor: 'var(--space-accent-border)',
Expand Down
Loading