Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions frontend/src/components/Drawer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ describe("Drawer", () => {
it("closes on backdrop click", async () => {
renderDrawer(true);

const backdrop = screen.getByRole("dialog");
fireEvent.click(backdrop);
const backdrop = screen.getByText("Drawer Title").closest(".drawer-backdrop");
expect(backdrop).toBeInTheDocument();
fireEvent.click(backdrop!);

await waitFor(() => {
expect(onClose).toHaveBeenCalledTimes(1);
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ export const Drawer: React.FC<DrawerProps> = ({
<div
className="drawer-backdrop"
onClick={handleBackdropClick}
role="dialog"
aria-modal="true"
aria-labelledby={drawerId}
aria-describedby={descId}
>
<div
ref={panelRef}
tabIndex={-1}
role="dialog"
aria-modal="true"
aria-labelledby={drawerId}
aria-describedby={descId}
className="drawer-panel glass-panel"
onClick={(e) => e.stopPropagation()}
>
Expand Down
21 changes: 15 additions & 6 deletions frontend/src/components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,17 @@ export const Modal: React.FC<ModalProps> = ({
document.addEventListener('keydown', handleKeyDown);
document.body.style.overflow = 'hidden';

// Focus the modal itself or the first focusable element
// Focus the first focusable element inside the modal, or fallback to the modal container
if (modalRef.current) {
modalRef.current.focus();
const focusableElements = modalRef.current.querySelectorAll<HTMLElement>(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);

if (focusableElements.length > 0) {
focusableElements[0].focus();
} else {
modalRef.current.focus();
}
}
} else {
document.removeEventListener('keydown', handleKeyDown);
Expand Down Expand Up @@ -132,14 +140,15 @@ export const Modal: React.FC<ModalProps> = ({
padding: '1rem',
}}
onClick={handleBackdropClick}
role="dialog"
aria-modal="true"
aria-labelledby={modalId}
aria-describedby={descId}
onClick={handleBackdropClick}
>
<div
ref={modalRef}
tabIndex={-1}
role="dialog"
aria-modal="true"
aria-labelledby={modalId}
aria-describedby={descId}
className="glass-panel"
style={{
background: 'var(--bg-surface)',
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/TransactionFilterPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ export const TransactionFilterPanel: React.FC<TransactionFilterPanelProps> = ({

useEffect(() => {
if (localSearch === filters.search) return;
if (localSearch === "" && filters.search !== "") {
onSearchChange("");
return;
}
const id = window.setTimeout(() => onSearchChange(localSearch), DEBOUNCE_MS);
return () => window.clearTimeout(id);
}, [localSearch, filters.search, onSearchChange]);
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/pages/TransactionHistory.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,8 @@ describe("TransactionHistory", () => {

fireEvent.change(searchInput, { target: { value: "" } });

await waitFor(() =>
expect(within(table).getByText("USDC")).toBeInTheDocument(),
);
expect(within(table).getByText("EURC")).toBeInTheDocument();
expect(await screen.findByText("USDC")).toBeInTheDocument();
expect(await screen.findByText("EURC")).toBeInTheDocument();
expect(mockGetTransactions).toHaveBeenCalledTimes(1);
});

Expand Down
4 changes: 4 additions & 0 deletions frontend/src/pages/VaultComparison.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ describe("VaultComparison", () => {

expect(screen.getByRole("heading", { name: /Compare Vault Strategies/i })).toBeInTheDocument();
expect(screen.getByText(/Side-by-side comparison/i)).toBeInTheDocument();
const franklinMatches = screen.getAllByText(/Franklin BENJI Connector/i);
expect(franklinMatches.length).toBeGreaterThan(0);
const tokenizedMatches = screen.getAllByText(/Tokenized Treasury Ladder/i);
expect(tokenizedMatches.length).toBeGreaterThan(0);
expect(screen.getByRole("button", { name: /Franklin BENJI Connector/i })).toBeInTheDocument();
expect(screen.getByRole("button", { name: /Tokenized Treasury Ladder/i })).toBeInTheDocument();
it("renders the default two-strategy comparison", () => {
Expand Down
Loading