Skip to content

feat: enhance accessibility in ChatInput and StellarFiatModal#247

Open
JohnOluB wants to merge 869 commits into
leojay-net:mainfrom
JohnOluB:feature/accessibility-modal-focus
Open

feat: enhance accessibility in ChatInput and StellarFiatModal#247
JohnOluB wants to merge 869 commits into
leojay-net:mainfrom
JohnOluB:feature/accessibility-modal-focus

Conversation

@JohnOluB

Copy link
Copy Markdown
Contributor

Title: feat: enhance accessibility for ChatInput and StellarFiatModal

Description:
This PR improves accessibility in the Stellar-Dex-Chat app:

✅ Ensures keyboard navigation and focus visibility for all controls
✅ Traps focus inside open modals and restores focus on close
✅ Adds aria-labels for icon-only buttons

Screenshots/logs attached showing focus behavior and accessibility checks.

Closes #64

@drips-wave

drips-wave Bot commented Mar 27, 2026

Copy link
Copy Markdown

@JohnOluB Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@leojay-net

Copy link
Copy Markdown
Owner

fix issues @JohnOluB

leojay-net and others added 13 commits March 30, 2026 10:29
I've kept the implementation simple: it uses a local isLoading state that triggers whenever the drawer is opened, simulating a 1-second delay to represent fetching data from the Stellar network. During this time, the drawer is marked with aria-busy="true" for accessibility, and a stack of three skeletons is shown to match the expected receipt layout.

closes: leojay-net#365
fixed the replace deprecated stroopsToXlm export in stroops
…2-463

fix: admin type safety, refactor, and styling guidelines (closes leojay-net#460
…-integration-with-network-queue

add-toastprovider
@JohnOluB
JohnOluB force-pushed the feature/accessibility-modal-focus branch from 1c58f6c to 1e0145b Compare March 30, 2026 21:49
@JohnOluB
JohnOluB force-pushed the feature/accessibility-modal-focus branch from 1e0145b to 0018d07 Compare March 31, 2026 18:45
Depo-dev and others added 29 commits May 30, 2026 19:34
Closes leojay-net#492 - Add paused-state guard and explicit NotOperator error on
inactive-operator deactivation to set_operator, preventing silent
no-ops that can corrupt batch operation state.

Closes leojay-net#499 - Protect receipt-counter increment and daily-deposit
accumulator with checked arithmetic; emit DepositBalanceUpdatedEvent
so indexers can confirm balance updates without re-reading storage.

Closes leojay-net#452 - Replace hardcoded hex chart colors in the admin
dashboard with CSS custom properties (--color-chart-*) defined in
globals.css, enabling proper light/dark theme switching.

Closes leojay-net#490 - Add smooth scroll-to-top in AdminGuard when admin access
is granted, with unit tests covering granted, denied, and error paths.
…-ui-security-batch-492-499-452-490

feat: fix contract validation, deposit safety and admin UI improvements
…oundary

Closes leojay-net#590 — fix(frontend): race condition in chatStateMachine.ts
- Clone initial context in StateMachine constructor so action callbacks
  never mutate the shared module-level INITIAL_CONTEXT object, preventing
  cross-instance context pollution under concurrent usage / React StrictMode.
- Introduce getInitialContext() factory in chatStateMachine.ts so every
  machine instance starts from a fresh, timestamp-stamped context object.
- Add regression suite (chatStateMachine race condition regression leojay-net#590)
  verifying two independent machines never share or corrupt each other's state.

Closes leojay-net#663 — fix(frontend): memory leak in useChat.ts
- Track the onTransactionReady setTimeout in transactionReadyTimerRef and
  clear it in the useEffect cleanup, preventing post-unmount callback invocation.
- Replace Date.now()+1 ID in appendCancelledMessage with crypto.randomUUID()
  to eliminate ID collision risk under rapid cancellation.
- Add regression suite (useChat memory leak regression leojay-net#663) that unmounts
  the component before the 1-second timer fires and asserts the callback is
  never called.

Closes leojay-net#631 — feat(frontend): skeleton loading state in AuditTable.tsx
- Render an animated 5-row skeleton table (aria-busy="true") while the
  audit API fetch is in-flight, replacing the blank/empty state.
- Add unit test verifying skeleton rows appear during load and are replaced
  by real data once the fetch resolves.

Closes leojay-net#633 — feat(frontend): error boundary for ChatHistorySidebar.tsx
- Wrap the ChatHistorySidebar render tree with the existing ErrorBoundary
  component, surfacing a "Sidebar unavailable" fallback with a "Reload sidebar"
  button instead of a blank panel or React crash on unexpected errors.
- Add unit tests verifying the error boundary catches child throws and
  renders the custom title/retry label.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-663-multi-issue

fix/feat: resolve race condition, memory leak, add skeleton loading & error boundary
…elock role check

- Add comprehensive doc comments to enforce_daily_deposit_limit function
- Add doc block to set_daily_deposit_limit with description of per-token per-user scope
- Add doc comments to UserDailyDeposit, UserDailyWithdrawal, GlobalDailyWithdrawn structs
- Add clarifying comment on legacy DataKey::DailyWithdrawLimit variant
- Fix set_operator Errors section to include Error::NotOperator and Error::ContractPaused
- Add full doc block to queue_renounce_admin explaining timelock pattern and pause requirement
- Add full doc block to execute_renounce_admin with boundary check explanation
- All doc comments include Purpose, Arguments, Behavior, and Error sections as appropriate

Closes leojay-net#678 and leojay-net#693 (inline code documentation improvements)
- Fix error 303 (DailyLimitExceeded): correct description from 'daily withdrawal limit' to 'user's per-token daily deposit accumulator'
- Expand error 602 (ActionNotReady) description: add second trigger condition for queue_admin_action delay validation

Improves clarity for developers integrating the contract API.
- Fix DailyLimitExceeded error entry: correct description and mark as returned by deposit
- Add set_daily_deposit_limit to public functions table
- Add set_operator, queue_renounce_admin, execute_renounce_admin to public functions table

Ensures API reference is complete and accurate for all governance and rate-limit functions.
…lock

- Add 'Admin Action Timelock' section explaining queue_admin_action/execute_admin_action pattern
- Add details on admin renounce flow and pause requirement
- Add 'Daily Deposit Limit' section explaining per-user per-token rate limiting
- Include storage schema and relationship to other rate-limit mechanisms
- Include function signatures and enforcement behavior

Provides comprehensive architectural guidance for developers working with governance and rate-limiting features.
…documentation

Docs/678 693 improve documentation
…and leojay-net#840 in one release

Add mobile ChatInput layout, split-view dark mode fallback, optimistic
transaction amount display, and fee-vault reconciliation for withdraw_fees.

Co-authored-by: Cursor <cursoragent@cursor.com>
…-net#834)

Add copy-to-clipboard buttons to the admin dashboard audit log table for
the timestamp, admin address and parameters columns, reusing the existing
CopyButton component (which already provides a navigator.clipboard path
with an execCommand fallback). Extend CopyButton with an optional
ariaLabel prop so each button is individually labelled for accessibility.

Adds unit tests covering button presence and clipboard writes for all
three columns. No existing UI behaviour is changed.
…ChatInput (leojay-net#607)

The submit-shortcut label was derived from navigator.platform during
render. On the server navigator is undefined (label 'Ctrl+Enter') while
an Apple client computes 'Cmd+Enter', so the button title/aria-label/
aria-keyshortcuts and the sr-only hint differed between the server markup
and the first client render, triggering a React hydration mismatch.

Default isApplePlatform to the SSR-safe false and detect the platform in
a post-mount useEffect, so the initial client render matches the server
and the Apple label is applied only after hydration.

Adds a regression test asserting renderToString yields 'Ctrl+Enter' even
on an Apple platform, and that the label upgrades to 'Cmd+Enter' after
mount on Apple (and stays 'Ctrl+Enter' elsewhere).
…Input (leojay-net#632)

The chat textarea relied on the .theme-input class alone for its border
colour while also carrying Tailwind's `border` utility. The intended
themed border-color could be left to the utility cascade and render an
incorrect colour, and the input gave no visual error feedback when the
wallet was disconnected.

Drive the border colour from explicit theme-token classes
(.theme-input-border / .theme-input-border-invalid) whose specificity
beats Tailwind's preflight border-color reset, switching to the warning
token when walletWarning is set, and add aria-invalid for accessibility.

Adds a vitest regression test covering the default and
wallet-disconnected border states.
…ge event (leojay-net#697)

Strengthen enforce_withdrawal_quota (the withdrawal-quota daily-limit
validation):

- Use checked_add for the per-user daily accumulator, returning
  Error::Overflow, mirroring the deposit-side enforce_daily_deposit_limit
  hardening (leojay-net#499). This resolves the function's own documented TODO and
  prevents a crafted large withdrawal from wrapping the i128 accumulator
  and bypassing the quota check.
- Emit WithdrawalQuotaConsumedEvent on the success path so off-chain
  indexers can track per-user daily usage in real time. (Events on the
  rejection path are intentionally omitted since Soroban rolls back state
  on Err.)

Adds integration tests covering within-quota success + event emission,
accumulation up to the exact quota boundary, over-quota rejection, and
the 24-hour rolling-window reset emitting QuotaResetEvent.
…oard-copy-admin-page

feat(frontend): add clipboard copy button to admin/page.tsx (leojay-net#834)
…-limit-validation

feat(contract): implement daily limit validation for validate_withdrawal_quota (leojay-net#697)
…put-border-colour

fix(frontend): resolve incorrect border colour in ChatInput.tsx (leojay-net#632)
…put-hydration

fix(frontend): resolve hydration mismatch in ChatInput.tsx (leojay-net#607)
…theme-color-tokens

Fix/landing page theme color tokens
Enhance developer experience by adding comprehensive inline documentation:

Inline Code Documentation (lib.rs):
- Added detailed JSDoc comments for reconcile_fee_vault explaining purpose,
  parameters, returns, side effects, and reconciliation logic
- Enhanced deduct_fee_vault_ledger documentation with parameter descriptions,
  error cases, preconditions, and critical notes about reconciliation
- Documented accrue_fee with purpose, access control, side effects, and usage examples
- Improved get_accrued_fees documentation with notes about reconciliation
- Enhanced get_fee_withdrawal_nonce documentation explaining nonce semantics and replay protection
- Extensively documented withdraw_fees with comprehensive error handling, security
  considerations, reconciliation flow, and audit event details
- Documented withdraw_fees_batch with usage patterns, batch sweep semantics, and
  differences from single-token withdrawal

Architectural Guide (FEE_ACCRUAL_ARCHITECTURE.md):
- Created comprehensive 400+ line architectural guide covering:
  - Overview and key concepts (fee vault, accrual, withdrawal)
  - Detailed storage structure with DataKey mapping and guarantees
  - Complete operation walkthrough for all 7 core functions
  - Security considerations covering replay attacks, ledger consistency,
    admin authorization, and integer overflow/underflow
  - Full event schema documentation with FeeAccruedEvent,
    FeeVaultReconciledEvent, and FeeWithdrawnEvent
  - Complete error code mapping and recovery strategies
  - Usage patterns with real-world examples
  - Testing strategy coverage
  - Integration checklist
  - FAQ addressing common developer questions
  - Related issue cross-references

Closes leojay-net#580

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…limit

Fix missing boundary check in set_max_operators function that could allow
setting a maximum operator count below the current active operator count,
violating the cap invariant.

Changes:
- Added validation in set_max_operators to ensure new max >= current operator count
- Returns Error::ExceedsLimit if attempting to reduce max below current count
- Added comprehensive documentation explaining the validation logic
- Prevents edge case where cap becomes invalid due to admin misconfiguration

Tests Added:
- test_set_max_operators_boundary_check_rejects_reduction_below_current_count:
  Validates that reducing max below current count is rejected
- test_set_max_operators_allows_increase_above_current_count:
  Confirms increasing max is allowed
- test_set_max_operators_allows_exact_match_with_current_count:
  Validates edge case of max exactly matching current count
- test_set_max_operators_zero_remains_unlimited:
  Ensures max=0 (unlimited) is always valid

Closes leojay-net#827

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The cast from usize to u32 is necessary for the comparison, so suppress
the clippy::unnecessary_cast warning.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…crual-vault-docs

Docs/580 improve fee accrual vault docs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wave Feature: keyboard accessibility for chat and modals