From 36311e529356f54bd7cb00d5e2e75d3d99fe0db0 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 11 Dec 2025 10:43:25 -0800 Subject: [PATCH] refactor: remove disabled tooltip from PaginationNavButton (#21199) for #19974 The MUI tooltip inside `PaginationNavButton` was a controlled component. This + the stateful logic inside `PaginationNavButtonCore` meant that `showDisabledMessage` would never be set to true. I.e., the "You are already on the first page" tooltip if on the first page and the "You are already on the last page" tooltip if on the last page would never show up. The `PaginationNavButton`s gets disabled if we're at either the first/last page, and disabled buttons can't receive focus, so there's no way to open the MUI tooltips with keyboard navigation. Removing the MUI tooltip + related props from `PaginationNavButton` has no effect on my screen reader UX with macOS VoiceOver; it's entirely unchanged --- .../PaginationWidget/PaginationNavButton.tsx | 74 ++----------------- .../PaginationWidget/PaginationWidgetBase.tsx | 2 - 2 files changed, 8 insertions(+), 68 deletions(-) diff --git a/site/src/components/PaginationWidget/PaginationNavButton.tsx b/site/src/components/PaginationWidget/PaginationNavButton.tsx index b5c8a1f9d5..3e6d905384 100644 --- a/site/src/components/PaginationWidget/PaginationNavButton.tsx +++ b/site/src/components/PaginationWidget/PaginationNavButton.tsx @@ -1,86 +1,28 @@ -import Tooltip from "@mui/material/Tooltip"; import { Button } from "components/Button/Button"; -import { - type ButtonHTMLAttributes, - type ReactNode, - useEffect, - useState, -} from "react"; +import type { ButtonHTMLAttributes, ReactNode } from "react"; type PaginationNavButtonProps = Omit< ButtonHTMLAttributes, - | "aria-disabled" - // Need to omit color for MUI compatibility - | "color" + "aria-disabled" > & { // Required/narrowed versions of default props children: ReactNode; disabled: boolean; onClick: () => void; "aria-label": string; - - // Bespoke props - disabledMessage: ReactNode; - disabledMessageTimeout?: number; }; -function PaginationNavButtonCore({ +export function PaginationNavButton({ onClick, disabled, - disabledMessage, - disabledMessageTimeout = 3000, - ...delegatedProps -}: PaginationNavButtonProps) { - const [showDisabledMessage, setShowDisabledMessage] = useState(false); - - // Inline state sync - this is safe/recommended by the React team in this case - if (!disabled && showDisabledMessage) { - setShowDisabledMessage(false); - } - - useEffect(() => { - if (!showDisabledMessage) { - return; - } - - const timeoutId = setTimeout( - () => setShowDisabledMessage(false), - disabledMessageTimeout, - ); - - return () => clearTimeout(timeoutId); - }, [showDisabledMessage, disabledMessageTimeout]); - - return ( - - {/* - * Going more out of the way to avoid attaching the disabled prop directly - * to avoid unwanted side effects of using the prop: - * - Not being focusable/keyboard-navigable - * - Not being able to call functions in response to invalid actions - * (mostly for giving direct UI feedback to those actions) - */} -