diff --git a/apps/frontend/package.json b/apps/frontend/package.json index da142482783e4..2edecb7266ccc 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -26,7 +26,6 @@ "react": "^19.2.7", "react-dom": "^19.2.7", "react-icons": "^5.7.0", - "react-loading-skeleton": "^3.5.0", "react-redux": "^9.3.0", "react-spinners": "^0.17.0", "react-toastify": "^11.1.0", diff --git a/apps/frontend/src/index.css b/apps/frontend/src/index.css index 14ae121a249c8..bc1f86d95e18c 100644 --- a/apps/frontend/src/index.css +++ b/apps/frontend/src/index.css @@ -104,11 +104,18 @@ Override background color in dark mode with GitHub's dark mode background color. background-color: color-mix(in oklab, var(--color-error), #f00 40%); } - /* Unscoped, this strips the focus ring from the site's search box. */ - input:focus, - select:focus { - outline: 0; - border: var(--color-primary) solid 1px; + /* daisyUI's disabled border matches its own background and its text sits at 2.5:1. */ + .input:is(:disabled, [disabled]) { + border-color: color-mix( + in oklab, + var(--color-base-content) 20%, + transparent + ); + + &:is(input), + & :is(input) { + color: color-mix(in oklab, var(--color-base-content) 65%, transparent); + } } } diff --git a/apps/frontend/src/wizard/Home/stages/Customize.tsx b/apps/frontend/src/wizard/Home/stages/Customize.tsx index 9ab3c858cb8f6..a8191e32d896d 100644 --- a/apps/frontend/src/wizard/Home/stages/Customize.tsx +++ b/apps/frontend/src/wizard/Home/stages/Customize.tsx @@ -414,7 +414,7 @@ export function CustomizeStage({
-
+
diff --git a/apps/frontend/src/wizard/Home/stages/Display.tsx b/apps/frontend/src/wizard/Home/stages/Display.tsx index 89ea760175991..df6e4d1155cec 100644 --- a/apps/frontend/src/wizard/Home/stages/Display.tsx +++ b/apps/frontend/src/wizard/Home/stages/Display.tsx @@ -101,7 +101,7 @@ export function DisplayStage({
, - action: () => void, -) { - useEffect(() => { - /** - * Alert if clicked on outside of element - */ - function handleClickOutside(event: MouseEvent) { - if (ref.current && !ref.current.contains(event.target as Node)) { - action(); - } - } - - // Bind the event listener - document.addEventListener("mousedown", handleClickOutside); - - return () => { - // Unbind the event listener on clean up - document.removeEventListener("mousedown", handleClickOutside); - }; - }, [action, ref]); -} - interface LoginAccountDeleteModalProps { onClose: () => void; onConfirm: () => void; @@ -38,36 +13,44 @@ export function LoginAccountDeleteModal( ): JSX.Element { const { onConfirm, onClose } = props; - const wrapperRef = useRef(null); - useOutsideAlerter(wrapperRef, onClose); - - return createPortal( - // `wizard` because this mounts on `body`, outside the element the app's styles are scoped to. -
-
-
-

Delete Account

-
-
-

- Are you sure you want to delete your account from GitHub Stats - Extended? -

-
-
- - -
+ const titleId = useId(); + + return ( + { + if (node !== null && !node.open) { + node.showModal(); + } + }} + className="modal" + aria-labelledby={titleId} + onClose={onClose} + > +
+

+ Delete Account +

+
+
+

+ Are you sure you want to delete your account from GitHub Stats + Extended? +

+
+
+ +
-
, - document.body, + {/* daisyUI's backdrop: submitting it closes the dialog, so a click outside dismisses. */} +
+ +
+ ); } diff --git a/apps/frontend/src/wizard/Home/stages/Login/LoginAccountManagement.tsx b/apps/frontend/src/wizard/Home/stages/Login/LoginAccountManagement.tsx index d5792a6b578e8..4120c24e9a98e 100644 --- a/apps/frontend/src/wizard/Home/stages/Login/LoginAccountManagement.tsx +++ b/apps/frontend/src/wizard/Home/stages/Login/LoginAccountManagement.tsx @@ -49,7 +49,7 @@ export function LoginAccountManagement(): JSX.Element { }; return ( - +
{privateAccess ? (
diff --git a/apps/frontend/src/wizard/Home/stages/Login/LoginBox.tsx b/apps/frontend/src/wizard/Home/stages/Login/LoginBox.tsx index c69bfb82a6c5b..b853eb9de97ab 100644 --- a/apps/frontend/src/wizard/Home/stages/Login/LoginBox.tsx +++ b/apps/frontend/src/wizard/Home/stages/Login/LoginBox.tsx @@ -1,20 +1,17 @@ -import { clsx } from "clsx"; import type { JSX, ReactNode } from "react"; import { LoginBoxDemoCards } from "./LoginBoxDemoCards"; interface LoginBoxProps { children: ReactNode; - - isOpaque?: boolean; } export function LoginBox(props: LoginBoxProps): JSX.Element { - const { children, isOpaque = false } = props; + const { children } = props; return (
-
+
{children} diff --git a/apps/frontend/src/wizard/components/Card/SvgInline.tsx b/apps/frontend/src/wizard/components/Card/SvgInline.tsx index c5cd9b47307a0..3c767ab32c806 100644 --- a/apps/frontend/src/wizard/components/Card/SvgInline.tsx +++ b/apps/frontend/src/wizard/components/Card/SvgInline.tsx @@ -4,8 +4,6 @@ import { loadConfigFromEnv } from "@stats-organization/github-readme-stats-core" import axios from "axios"; import { useEffect, useRef, useState } from "react"; import type { JSX } from "react"; -import Skeleton from "react-loading-skeleton"; -import "react-loading-skeleton/dist/skeleton.css"; import { setShouldMock } from "../../../axios-override.js"; import { @@ -117,13 +115,17 @@ export function SvgInline(props: SvgInlineProps): JSX.Element { if (forceLoading || !loaded) { if (compact) { return ( - +
); } // maximum dimensions of cards in SelectCard stage return ( -
- +
+
); } diff --git a/apps/frontend/src/wizard/components/Generic/Select.tsx b/apps/frontend/src/wizard/components/Generic/Select.tsx index c7a17bc2cb5bf..8acb92bfaaf8f 100644 --- a/apps/frontend/src/wizard/components/Generic/Select.tsx +++ b/apps/frontend/src/wizard/components/Generic/Select.tsx @@ -12,6 +12,8 @@ interface SelectProps { options: Array; selectedOption: SelectOption; + "aria-labelledby"?: string; + className?: string; disabled?: boolean; @@ -24,9 +26,11 @@ export function Select({ onOptionChange, disabled, className, + "aria-labelledby": ariaLabelledBy, }: SelectProps): JSX.Element { return ( +

{description}

{ setInputValue(e.target.value); @@ -49,6 +52,10 @@ export function NumericSection({ disabled={disabled} placeholder={placeholder} /> + {/* Hidden until the field is `:user-invalid`, then shown in the error colour. */} +

+ Enter a number between {min} and {max}. +

); } diff --git a/apps/frontend/src/wizard/components/Home/Progress.tsx b/apps/frontend/src/wizard/components/Home/Progress.tsx index 6e9b9def16cbe..55a07332bf2f6 100644 --- a/apps/frontend/src/wizard/components/Home/Progress.tsx +++ b/apps/frontend/src/wizard/components/Home/Progress.tsx @@ -1,4 +1,5 @@ import { clsx } from "clsx"; +import { useEffect, useRef } from "react"; import type { JSX, MouseEventHandler } from "react"; import { FaArrowLeft as LeftArrowIcon, @@ -60,9 +61,38 @@ export function ProgressBar({ const leftDisabled = currItemIndex === 0; const rightDisabled = currItemIndex === items.length - 1; + const barRef = useRef(null); + + /* + * The bar resizes because the step labels wrap, so a panel stacking under it cannot use a fixed offset. + * Publish the measured height instead; `Customize` and `Display` pin their card against it. + */ + useEffect(() => { + const bar = barRef.current; + if (bar === null) { + return undefined; + } + + const observer = new ResizeObserver(() => { + document.documentElement.style.setProperty( + "--wizard-progress-height", + `${bar.getBoundingClientRect().height}px`, + ); + }); + observer.observe(bar); + + return () => { + observer.disconnect(); + document.documentElement.style.removeProperty("--wizard-progress-height"); + }; + }, []); + return ( // The site header is fixed, so the bar parks directly under it rather than at the viewport top. -
+