All files / src/components/layout ActionBar.tsx

100% Statements 1/1
100% Branches 0/0
100% Functions 1/1
100% Lines 1/1

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29                                    46x                    
import React from "react";
 
interface ActionBarProps {
  /** Accessible name of the region, e.g. "Next step". */
  label: string;
  children: React.ReactNode;
}
 
// The page's one primary action (spec §5). From `md` up it is an inline row where
// the page places it; below `md` (phones) it is fixed to the bottom on glass-strong,
// AA from its own ≥0.85 opacity, never from what scrolls behind it. On a short
// viewport (browser zoom) it stays static — never a second fixed band. One DOM node
// for both, so the action is never duplicated. Pages that use it set AppLayout's
// reserveActionBar (9rem: the bar plus a two-line error) so the last row and the
// footer never sit behind it; data-action-bar drives the matching scroll padding
// (globals.css) so a focused bottom-row card scrolls clear of it. No safe-area
// padding: the root viewport is not viewportFit "cover", so the inset is always 0.
export function ActionBar({ label, children }: ActionBarProps) {
  return (
    <section
      aria-label={label}
      data-action-bar
      className="fixed inset-x-0 bottom-0 z-30 max-md:[@media(min-height:501px)]:mb-0 flex items-end gap-3 border-t border-hairline bg-glass-strong px-4 py-3 shadow-lift backdrop-blur-md [&>*:first-child]:flex-1 [@media(max-height:500px)]:static md:static md:z-auto md:items-center md:border-0 md:bg-transparent md:p-0 md:shadow-none md:backdrop-blur-none md:[&>*:first-child]:flex-none"
    >
      {children}
    </section>
  );
}