fix(base): pin selection bar to viewport with Confluence-style dark pill

This commit is contained in:
Philipinho
2026-04-18 16:54:49 +01:00
parent b6b6e1809a
commit 3f52e54207
2 changed files with 80 additions and 24 deletions
@@ -1,5 +1,5 @@
import { memo } from "react"; import { memo } from "react";
import { ActionIcon, Button, Transition } from "@mantine/core"; import { Transition } from "@mantine/core";
import { IconTrash, IconX } from "@tabler/icons-react"; import { IconTrash, IconX } from "@tabler/icons-react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useRowSelection } from "@/features/base/hooks/use-row-selection"; import { useRowSelection } from "@/features/base/hooks/use-row-selection";
@@ -23,28 +23,27 @@ export const SelectionActionBar = memo(function SelectionActionBar({
<Transition mounted={isOpen} transition="slide-up" duration={150}> <Transition mounted={isOpen} transition="slide-up" duration={150}>
{(styles) => ( {(styles) => (
<div className={classes.selectionActionBarWrapper} style={styles}> <div className={classes.selectionActionBarWrapper} style={styles}>
<div className={classes.selectionActionBar}> <div className={classes.selectionActionBar} role="toolbar">
<span className={classes.selectionActionBarCount}> <span className={classes.selectionActionBarCount}>
{t("{{count}} selected", { count: selectionCount })} {t("{{count}} selected", { count: selectionCount })}
</span> </span>
<Button <button
size="xs" type="button"
color="red" className={classes.selectionActionBarDelete}
variant="light" disabled={isPending}
leftSection={<IconTrash size={14} />}
loading={isPending}
onClick={() => void deleteSelected()} onClick={() => void deleteSelected()}
> >
<IconTrash size={14} />
{t("Delete")} {t("Delete")}
</Button> </button>
<ActionIcon <button
size="sm" type="button"
variant="subtle" className={classes.selectionActionBarClose}
onClick={clear} onClick={clear}
aria-label={t("Clear selection")} aria-label={t("Clear selection")}
> >
<IconX size={14} /> <IconX size={14} />
</ActionIcon> </button>
</div> </div>
</div> </div>
)} )}
@@ -376,28 +376,85 @@
} }
.selectionActionBarWrapper { .selectionActionBarWrapper {
position: sticky; position: fixed;
bottom: 16px; left: 50%;
bottom: 24px;
transform: translateX(-50%);
display: flex; display: flex;
justify-content: center; justify-content: center;
pointer-events: none; pointer-events: none;
z-index: 5; z-index: 200;
grid-column: 1 / -1;
} }
.selectionActionBar { .selectionActionBar {
pointer-events: auto; pointer-events: auto;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 8px; gap: 4px;
padding: 6px 10px; padding: 6px 6px 6px 14px;
border-radius: var(--mantine-radius-md); border-radius: 999px;
box-shadow: var(--mantine-shadow-lg); box-shadow:
background: light-dark(var(--mantine-color-white), var(--mantine-color-dark-6)); 0 10px 30px rgba(0, 0, 0, 0.25),
border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); 0 2px 8px rgba(0, 0, 0, 0.18);
background: light-dark(
var(--mantine-color-dark-8),
var(--mantine-color-dark-5)
);
color: var(--mantine-color-white);
border: 1px solid light-dark(
var(--mantine-color-dark-9),
var(--mantine-color-dark-4)
);
} }
.selectionActionBarCount { .selectionActionBarCount {
font-size: var(--mantine-font-size-sm); font-size: var(--mantine-font-size-sm);
color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); font-weight: 500;
color: var(--mantine-color-white);
padding-right: 10px;
margin-right: 2px;
border-right: 1px solid rgba(255, 255, 255, 0.15);
}
.selectionActionBarDelete {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
border: none;
background: transparent;
color: var(--mantine-color-red-4);
font-size: var(--mantine-font-size-sm);
font-weight: 500;
border-radius: 999px;
cursor: pointer;
transition: background 120ms ease;
}
.selectionActionBarDelete:hover:not(:disabled) {
background: rgba(255, 255, 255, 0.08);
}
.selectionActionBarDelete:disabled {
opacity: 0.6;
cursor: default;
}
.selectionActionBarClose {
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
border: none;
background: transparent;
color: var(--mantine-color-gray-3);
border-radius: 999px;
cursor: pointer;
transition: background 120ms ease, color 120ms ease;
}
.selectionActionBarClose:hover {
background: rgba(255, 255, 255, 0.08);
color: var(--mantine-color-white);
} }