diff --git a/README.md b/README.md index dd15d82..4267238 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ The app runs at http://localhost:5173 by default. completed, failed), search/status/date-range filters synced to the URL, plus loading, error and empty states. - **Mock wallet** — connect a demo Stellar wallet (no network calls). +- **Keyboard navigation** — skip link, header, page content, and footer follow a + logical tab order; navigation actions use a single focus stop each. ## Tech Stack @@ -62,8 +64,9 @@ cp .env.example .env ## Testing Integration tests cover send-money validation, successful transfer submission, -pending button behavior, duplicate-submission prevention, and Transfers page -filter sync (search, status, and date-range presets such as last 7/30/90 days). +pending button behavior, duplicate-submission prevention, Transfers page filter +sync (search, status, and date-range presets), and keyboard tab order across +the main pages. ## Accessibility diff --git a/src/App.css b/src/App.css index 0c52f97..66820da 100644 --- a/src/App.css +++ b/src/App.css @@ -1,5 +1,6 @@ .app { display: flex; + flex-direction: column; min-height: 100vh; } diff --git a/src/components/Button.css b/src/components/Button.css index d9b5fb8..0ab4bf5 100644 --- a/src/components/Button.css +++ b/src/components/Button.css @@ -13,9 +13,11 @@ min-height: 44px; } -.btn:disabled { +.btn:disabled, +.btn[aria-disabled='true'] { opacity: 0.5; cursor: not-allowed; + pointer-events: none; } .btn-primary { diff --git a/src/components/Button.jsx b/src/components/Button.jsx index 53c5ce4..0ea8fb4 100644 --- a/src/components/Button.jsx +++ b/src/components/Button.jsx @@ -1,3 +1,4 @@ +import { Link } from 'react-router-dom' import './Button.css' /** @@ -7,18 +8,38 @@ import './Button.css' * @param {boolean} [props.disabled] * @param {Function} [props.onClick] * @param {'button'|'submit'} [props.type] + * @param {string} [props.to] - when set, renders as a router link styled as a button */ export default function Button({ children, variant = 'primary', disabled = false, type = 'button', - onClick + onClick, + to }) { + const className = `btn btn-${variant}` + + if (to) { + if (disabled) { + return ( + + {children} + + ) + } + + return ( + + {children} + + ) + } + return (
The page you are looking for does not exist or has moved.
- - - + ) } diff --git a/src/pages/Transfers.jsx b/src/pages/Transfers.jsx index 5cd18a2..c320f88 100644 --- a/src/pages/Transfers.jsx +++ b/src/pages/Transfers.jsx @@ -1,5 +1,5 @@ import { useCallback, useMemo } from 'react' -import { Link, useSearchParams } from 'react-router-dom' +import { useSearchParams } from 'react-router-dom' import Chart from '../components/Chart.jsx' import TransferRow from '../components/TransferRow.jsx' import Skeleton from '../components/Skeleton.jsx' @@ -82,9 +82,7 @@ export default function Transfers() {