fix(board): make container headers fully clickable (#7006)
This commit is contained in:
1 parent
6f93be1227
commit
b40f000dd5
2 files changed
+27
-9
No files matched your search
@@ -50,7 +50,8 @@ was introduced; widen the affected Container before moving widgets into its righ
|
||||
### Containers and rails
|
||||
|
||||
A **Container** groups apps, widgets, and nested Containers. It can have a label, collapse control, app-opening action,
|
||||
border color, and CSS classes.
|
||||
border color, and CSS classes. Click anywhere on a collapsible Container’s header to collapse or expand it.
|
||||
The header also supports Enter and Space; its app-opening action and edit controls work independently.
|
||||
|
||||
Items can occupy the outermost rows and columns of a Container. The drop preview shows the position where the item
|
||||
will remain when released.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createContext, useContext } from "react";
|
||||
import { createContext, useContext, useRef } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { ActionIcon, Badge, Box, Button, Card } from "@mantine/core";
|
||||
import { IconChevronDown, IconChevronUp, IconExternalLink } from "@tabler/icons-react";
|
||||
@@ -33,6 +33,7 @@ interface Props {
|
||||
|
||||
export const BoardContainerSection = ({ section }: Props) => {
|
||||
const board = useRequiredBoard();
|
||||
const togglePointer = useRef<{ x: number; y: number; moved: boolean } | null>(null);
|
||||
const containerDepth = useContext(ContainerDepthContext);
|
||||
// Stagger nested controls inward and downward without wrapping back over ancestors.
|
||||
const menuRightOffset = 4 + containerDepth * 32;
|
||||
@@ -73,15 +74,15 @@ export const BoardContainerSection = ({ section }: Props) => {
|
||||
labelMaxWidth = `calc(100% - ${labelLeft}px - ${reservedMenuWidth})`;
|
||||
collapsedLabelPaddingRight = reservedMenuWidth;
|
||||
}
|
||||
// Expanded controls sit on the border without reserving a header row.
|
||||
// The native toggle spans the header; sibling actions stay above it.
|
||||
const toggleLayout = isVisuallyCollapsed
|
||||
? { top: 0, left: 0, w: "100%", h: "100%", maw: "100%" }
|
||||
: {
|
||||
top: labelTop,
|
||||
left: labelLeft,
|
||||
w: "auto",
|
||||
left: 0,
|
||||
w: "100%",
|
||||
h: 20,
|
||||
maw: labelMaxWidth,
|
||||
maw: "100%",
|
||||
};
|
||||
const toggleIcon = isVisuallyCollapsed ? (
|
||||
<IconChevronDown size="var(--mantine-font-size-md)" />
|
||||
@@ -125,13 +126,29 @@ export const BoardContainerSection = ({ section }: Props) => {
|
||||
pos="absolute"
|
||||
{...toggleLayout}
|
||||
px={6}
|
||||
ps={isVisuallyCollapsed ? labelLeft : 6}
|
||||
pe={isVisuallyCollapsed ? collapsedLabelPaddingRight : 6}
|
||||
ps={labelLeft}
|
||||
pe={collapsedLabelPaddingRight}
|
||||
radius="sm"
|
||||
variant="default"
|
||||
justify={options.showLabel ? "flex-start" : "center"}
|
||||
leftSection={options.showLabel && toggleIcon}
|
||||
onClick={toggle}
|
||||
onPointerDown={(event) => {
|
||||
togglePointer.current = { x: event.clientX, y: event.clientY, moved: false };
|
||||
}}
|
||||
onPointerMove={(event) => {
|
||||
const pointer = togglePointer.current;
|
||||
if (!pointer || event.buttons === 0) return;
|
||||
if (Math.hypot(event.clientX - pointer.x, event.clientY - pointer.y) > 5) {
|
||||
pointer.moved = true;
|
||||
}
|
||||
}}
|
||||
onPointerCancel={() => {
|
||||
togglePointer.current = null;
|
||||
}}
|
||||
onClick={(event) => {
|
||||
if (event.detail > 0 && togglePointer.current?.moved) return;
|
||||
toggle();
|
||||
}}
|
||||
aria-expanded={!isVisuallyCollapsed}
|
||||
aria-controls={contentId}
|
||||
aria-label={`${t(isVisuallyCollapsed ? "action.expand" : "action.collapse")}: ${label}`}
|
||||
|
||||
Reference in new issue
Block a user