fix(tasks): preserve board header stack while scrolling
This commit is contained in:
parent
0f8ae2095d
commit
ba5dc52d10
@ -995,3 +995,55 @@ html[data-bs-theme="dark"] .shadow-xl {
|
||||
.tasks-column-scroll::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--accent-primary);
|
||||
}
|
||||
|
||||
@media (min-width: 80rem) {
|
||||
.tasks-board-column-group {
|
||||
--tasks-board-stack-gap: 0.5rem;
|
||||
--tasks-board-column-header-height: 4rem;
|
||||
--tasks-board-subcolumn-header-height: 5.125rem;
|
||||
}
|
||||
|
||||
.tasks-board-column-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 30;
|
||||
min-height: var(--tasks-board-column-header-height, 4rem);
|
||||
background: var(--surface-elevated);
|
||||
box-shadow: 0 var(--tasks-board-stack-gap, 0.5rem) 0 var(--background);
|
||||
}
|
||||
|
||||
.tasks-board-subcolumn-header-row {
|
||||
position: sticky;
|
||||
top: calc(
|
||||
var(--tasks-board-column-header-height, 4rem)
|
||||
+ var(--tasks-board-stack-gap, 0.5rem)
|
||||
);
|
||||
z-index: 20;
|
||||
min-height: var(--tasks-board-subcolumn-header-height, 5.125rem);
|
||||
background: var(--surface-secondary);
|
||||
box-shadow: 0 var(--tasks-board-stack-gap, 0.5rem) 0 var(--background);
|
||||
}
|
||||
|
||||
.tasks-board-lane-header {
|
||||
position: sticky;
|
||||
top: calc(
|
||||
var(--tasks-board-column-header-height, 4rem)
|
||||
+ var(--tasks-board-subcolumn-header-height, 5.125rem)
|
||||
+ var(--tasks-board-stack-gap, 0.5rem)
|
||||
+ var(--tasks-board-stack-gap, 0.5rem)
|
||||
);
|
||||
z-index: 15;
|
||||
background: var(--surface-secondary);
|
||||
box-shadow: 0 var(--tasks-board-stack-gap, 0.5rem) 0 var(--surface-secondary);
|
||||
}
|
||||
|
||||
.tasks-board-content-section-continuous {
|
||||
margin-bottom: -3.9375rem;
|
||||
}
|
||||
|
||||
.tasks-board-content-section-continuous::after {
|
||||
display: block;
|
||||
height: 3.9375rem;
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1010,7 +1010,7 @@ function BoardColumn({
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`flex items-center justify-between gap-3 rounded-xl border bg-[var(--surface-primary)] px-3 py-3 shadow-sm transition xl:sticky xl:top-0 xl:z-10 ${columnBorderClass} ${
|
||||
className={`tasks-board-column-header app-surface flex min-h-16 items-center justify-between gap-3 rounded-xl px-3 py-3 transition ${columnBorderClass} ${
|
||||
isDragging ? "shadow-xl" : ""
|
||||
}`}
|
||||
>
|
||||
@ -1406,9 +1406,9 @@ function BoardColumnGroup({
|
||||
transition,
|
||||
zIndex: isDragging ? 20 : undefined,
|
||||
}}
|
||||
className={`${hideOnMobile ? "hidden xl:flex" : "flex"} min-w-0 flex-col ${isDragging ? "opacity-70" : ""}`}
|
||||
className={`${hideOnMobile ? "hidden xl:flex" : "flex"} tasks-board-column-group min-w-0 flex-col ${isDragging ? "opacity-70" : ""}`}
|
||||
>
|
||||
<div className="app-surface xl:sticky xl:top-0 xl:z-30 flex items-center justify-between gap-3 rounded-xl border border-[var(--border-subtle)] px-3 py-3 shadow-sm">
|
||||
<div className="tasks-board-column-header app-surface flex min-h-16 items-center justify-between gap-3 rounded-xl px-3 py-3">
|
||||
<div
|
||||
ref={setActivatorNodeRef}
|
||||
className="min-w-0 flex-1 cursor-grab touch-none active:cursor-grabbing"
|
||||
@ -1534,6 +1534,7 @@ function BoardColumnRowView({
|
||||
onDelete,
|
||||
expanded,
|
||||
onToggle,
|
||||
hasFollowingSection,
|
||||
}: {
|
||||
row: TaskColumnRow;
|
||||
children: ReactNode;
|
||||
@ -1543,10 +1544,13 @@ function BoardColumnRowView({
|
||||
onDelete: () => void;
|
||||
expanded: boolean;
|
||||
onToggle: () => void;
|
||||
hasFollowingSection: boolean;
|
||||
}) {
|
||||
return (
|
||||
<section className="min-w-0 rounded-xl border border-[var(--border-subtle)] bg-[var(--surface-muted)] p-2">
|
||||
<div className={`flex items-center justify-between gap-3 px-1 ${expanded ? "mb-2" : ""}`}>
|
||||
<section className={`tasks-board-content-section min-w-0 rounded-xl border border-[var(--border-subtle)] bg-[var(--surface-secondary)] p-2 ${
|
||||
hasFollowingSection ? "tasks-board-content-section-continuous" : ""
|
||||
}`}>
|
||||
<div className={`tasks-board-lane-header flex items-center justify-between gap-3 px-1 ${expanded ? "mb-2" : ""}`}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onToggle}
|
||||
@ -1616,7 +1620,7 @@ function BoardBaseColumnsView({
|
||||
gridTemplateColumns,
|
||||
expanded,
|
||||
onToggle,
|
||||
attachedToHeaders = false,
|
||||
hasFollowingSection,
|
||||
}: {
|
||||
collapsible: boolean;
|
||||
tasksCount: number;
|
||||
@ -1625,14 +1629,12 @@ function BoardBaseColumnsView({
|
||||
gridTemplateColumns: string;
|
||||
expanded: boolean;
|
||||
onToggle: () => void;
|
||||
attachedToHeaders?: boolean;
|
||||
hasFollowingSection: boolean;
|
||||
}) {
|
||||
return (
|
||||
<section
|
||||
className={`min-w-0 border border-[var(--border-subtle)] bg-[var(--surface-muted)] p-2 ${
|
||||
attachedToHeaders ? "-mt-px rounded-b-xl border-t-0 pt-2" : "rounded-xl"
|
||||
}`}
|
||||
>
|
||||
<section className={`tasks-board-content-section min-w-0 rounded-xl border border-[var(--border-subtle)] bg-[var(--surface-secondary)] p-2 ${
|
||||
hasFollowingSection ? "tasks-board-content-section-continuous" : ""
|
||||
}`}>
|
||||
{headers ? (
|
||||
<div
|
||||
className="flex min-w-0 flex-col gap-2 xl:grid xl:w-max"
|
||||
@ -1645,7 +1647,7 @@ function BoardBaseColumnsView({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onToggle}
|
||||
className={`flex w-full items-center gap-2 rounded-lg px-1 py-1 text-left ${headers ? "mt-2" : ""} ${expanded ? "mb-2" : ""}`}
|
||||
className={`tasks-board-lane-header flex w-full items-center gap-2 rounded-lg px-1 py-1 text-left ${headers ? "mt-2" : ""} ${expanded ? "mb-2" : ""}`}
|
||||
aria-expanded={expanded}
|
||||
>
|
||||
<ChevronRight
|
||||
@ -7048,7 +7050,7 @@ function TasksPageContent() {
|
||||
gridTemplateColumns={gridTemplateColumns}
|
||||
expanded={!boardViewState.collapsed_base_column_ids.includes(column.id)}
|
||||
onToggle={() => toggleBoardViewState("base", column.id)}
|
||||
attachedToHeaders
|
||||
hasFollowingSection={columnRows.length > 0}
|
||||
>
|
||||
{previewCellColumns.map((item) => (
|
||||
renderTaskCell(item, null)
|
||||
@ -7066,16 +7068,16 @@ function TasksPageContent() {
|
||||
) : renderSubcolumnHeader(column, false);
|
||||
|
||||
return (
|
||||
<div className="flex min-w-0 flex-col xl:w-max">
|
||||
<div className="flex min-w-0 flex-col gap-2 xl:w-max">
|
||||
<div
|
||||
className="z-20 flex min-w-0 flex-col gap-2 rounded-t-xl border border-b-0 border-[var(--border-subtle)] bg-[var(--surface-muted)] p-2 pb-0 xl:sticky xl:top-[4.75rem] xl:grid xl:w-max"
|
||||
className="tasks-board-subcolumn-header-row flex min-w-0 flex-col gap-2 rounded-xl border border-[var(--border-subtle)] bg-[var(--surface-secondary)] p-2 xl:grid xl:w-max"
|
||||
style={{ gridTemplateColumns }}
|
||||
>
|
||||
{subcolumnHeaders}
|
||||
</div>
|
||||
{baseColumns}
|
||||
<div className="mt-2 flex min-w-0 flex-col gap-2">
|
||||
{columnRows.map((row) => {
|
||||
<div className="flex min-w-0 flex-col gap-2">
|
||||
{columnRows.map((row, rowIndex) => {
|
||||
const rowTasksCount = filteredTasks.filter((task) => task.row === row.id).length;
|
||||
return (
|
||||
<BoardColumnRowView
|
||||
@ -7089,6 +7091,7 @@ function TasksPageContent() {
|
||||
onDelete={() => void deleteColumnRow(row)}
|
||||
expanded={!boardViewState.collapsed_row_ids.includes(row.id)}
|
||||
onToggle={() => toggleBoardViewState("row", row.id)}
|
||||
hasFollowingSection={rowIndex < columnRows.length - 1}
|
||||
>
|
||||
{previewCellColumns.map((item) => renderTaskCell(item, row.id))}
|
||||
</BoardColumnRowView>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user