← Back to blog

Accessibility in Trading UIs: Why It Matters More Than You Think

WCAG compliance, keyboard navigation for power users, and screen reader considerations for financial data - practical guidance for making trading interfaces accessible.

By Oliver Benns


Accessibility in trading applications tends to get dismissed as a compliance checkbox. That is a mistake. Many of the features that make an interface accessible - keyboard navigation, clear focus indicators, high contrast text - are the same features that power users depend on for speed.

Keyboard navigation is not optional

Professional traders already expect full keyboard control. They want to place orders, switch instruments, and navigate between panels without touching a mouse. Building for accessibility means building for your most demanding users.

A solid keyboard navigation system covers:

  • Tab order - Logical flow through panels, forms, and interactive elements
  • Focus trapping - Modals and dropdowns trap focus until dismissed
  • Skip links - Jump directly to the order form or order book from anywhere
  • Arrow key navigation - Move through price levels in the order book or rows in a blotter
function useArrowNavigation(items: HTMLElement[]) { const [activeIndex, setActiveIndex] = useState(0); const handleKeyDown = useCallback((e: KeyboardEvent) => { switch (e.key) { case "ArrowDown": e.preventDefault(); setActiveIndex((i) => Math.min(i + 1, items.length - 1)); break; case "ArrowUp": e.preventDefault(); setActiveIndex((i) => Math.max(i - 1, 0)); break; case "Enter": items[activeIndex]?.click(); break; } }, [items, activeIndex]); useEffect(() => { items[activeIndex]?.focus(); }, [activeIndex, items]); return { activeIndex, handleKeyDown }; }

Screen readers and live data

Trading UIs update constantly. If every price tick gets announced by a screen reader, the experience becomes unusable. The key is being selective about what gets announced.

Use ARIA live regions with aria-live="polite" for important state changes, and avoid marking rapidly updating data as live:

// Don't do this - screen reader will announce every tick <span aria-live="polite">{currentPrice}</span> // Do this - only announce meaningful events <div aria-live="polite" role="status"> {orderStatus === "filled" && ( <span>Order filled: {filledQuantity} at {avgPrice}</span> )} </div>

For the order book and price displays, use aria-label to provide context without live announcements:

<td aria-label={`Bid price ${formatPrice(price)}, quantity ${formatQuantity(qty)}`}> {formatPrice(price)} </td>

Colour is not enough

Trading interfaces rely heavily on colour to communicate state. Green for profit, red for loss, blue for bids, orange for asks. Every one of these needs a secondary indicator for colour-blind users.

Common approaches:

  • Icons alongside colour - An up arrow for profit, down arrow for loss
  • Text labels - Explicitly label "Buy" and "Sell" rather than relying on column colour
  • Patterns - Use solid fills for bids and hatched fills for asks on depth charts
function PnlDisplay({ value }: { value: number }) { const isPositive = value >= 0; return ( <span className={isPositive ? "text-green-400" : "text-red-400"}> {isPositive ? "▲" : "▼"} {formatCurrency(value)} </span> ); }

Test your interface with a colour blindness simulator. Roughly 8% of men have some form of colour vision deficiency, and in a professional trading environment that is a significant portion of your users.

Focus management in dynamic interfaces

Trading UIs have panels that resize, tabs that switch, and modals that open and close. Each of these transitions needs explicit focus management.

When a modal closes, focus should return to the element that opened it. When a panel is minimised, focus should move to the next logical panel. When an order is submitted and the form resets, focus should return to the first input.

function useReturnFocus() { const triggerRef = useRef<HTMLElement | null>(null); const saveTrigger = useCallback(() => { triggerRef.current = document.activeElement as HTMLElement; }, []); const restoreFocus = useCallback(() => { triggerRef.current?.focus(); }, []); return { saveTrigger, restoreFocus }; }

Without explicit focus management, keyboard users lose their place every time the UI changes, which in a trading application is constantly.

Contrast and readability

WCAG 2.1 requires a minimum contrast ratio of 4.5:1 for normal text and 3:1 for large text. Dark-themed trading UIs frequently fail this, especially with muted text on dark backgrounds.

Check these common problem areas:

ElementCommon issue
Secondary text (timestamps, labels)Grey on dark grey, often below 3:1
Disabled buttonsToo similar to the background
Chart grid linesSo faint they are invisible to low-vision users
Input placeholder textLight grey on dark, fails contrast

Use a tool like the Chrome DevTools contrast checker or axe-core to audit your interface systematically.

Accessible tables and blotters

Order blotters and position tables need proper semantic markup. This means using <table>, <thead>, <th>, and <td> rather than divs styled to look like tables.

<table role="grid" aria-label="Open orders"> <thead> <tr> <th scope="col">Instrument</th> <th scope="col">Side</th> <th scope="col">Price</th> <th scope="col">Quantity</th> <th scope="col">Status</th> </tr> </thead> <tbody> {orders.map((order) => ( <tr key={order.id} aria-selected={selectedId === order.id}> <td>{order.instrument}</td> <td>{order.side}</td> <td>{formatPrice(order.price, order.instrument)}</td> <td>{formatQuantity(order.quantity, order.instrument)}</td> <td>{order.status}</td> </tr> ))} </tbody> </table>

For virtualised lists (which most trading blotters use for performance), ensure that aria-rowcount and aria-rowindex are set so screen readers understand the full extent of the data.

Reduced motion

Some users are sensitive to animation. Respect the prefers-reduced-motion media query:

@media (prefers-reduced-motion: reduce) { .price-flash { animation: none; } .panel-transition { transition: none; } }

Price flash animations, panel slide transitions, and chart animations should all be suppressible. This is a one-line CSS change per animation, but it makes a real difference for users with vestibular disorders.

The business case

Beyond doing the right thing, accessibility has practical benefits for trading applications:

  • Regulatory requirements - Financial services in many jurisdictions require accessible interfaces
  • Power user satisfaction - Keyboard navigation and clear focus states benefit every trader, not just those with disabilities
  • Reduced support burden - Clear labelling and logical navigation reduce user confusion
  • Broader market - Accessibility opens your platform to users who would otherwise be excluded

Treating accessibility as an afterthought means retrofitting it across hundreds of components. Building it in from the start is dramatically cheaper and produces a better interface for everyone.

Kickstart Your Trading Application

Hedge UI is a React starter kit with production-ready trading components, real-time data handling, and customisable layouts — so you can ship faster.

Get Hedge UI