- Add comprehensive database migrations (001-024) for schema evolution - Enhance API schema with expanded type definitions and resolvers - Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth - Implement new services: AI optimization, billing, blockchain, compliance, marketplace - Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage) - Update Crossplane provider with enhanced VM management capabilities - Add comprehensive test suite for API endpoints and services - Update frontend components with improved GraphQL subscriptions and real-time updates - Enhance security configurations and headers (CSP, CORS, etc.) - Update documentation and configuration files - Add new CI/CD workflows and validation scripts - Implement design system improvements and UI enhancements
54 lines
1.4 KiB
TypeScript
54 lines
1.4 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect } from 'react'
|
|
|
|
export function SkipLink() {
|
|
return (
|
|
<a
|
|
href="#main-content"
|
|
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-phoenix-fire focus:text-white focus:rounded-md"
|
|
>
|
|
Skip to main content
|
|
</a>
|
|
)
|
|
}
|
|
|
|
export function useKeyboardNavigation() {
|
|
useEffect(() => {
|
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
// Tab navigation enhancement
|
|
if (e.key === 'Tab') {
|
|
document.body.classList.add('keyboard-navigation')
|
|
}
|
|
}
|
|
|
|
const handleMouseDown = () => {
|
|
document.body.classList.remove('keyboard-navigation')
|
|
}
|
|
|
|
window.addEventListener('keydown', handleKeyDown)
|
|
window.addEventListener('mousedown', handleMouseDown)
|
|
|
|
return () => {
|
|
window.removeEventListener('keydown', handleKeyDown)
|
|
window.removeEventListener('mousedown', handleMouseDown)
|
|
}
|
|
}, [])
|
|
}
|
|
|
|
// Add focus indicators for keyboard navigation
|
|
export function FocusIndicator() {
|
|
useEffect(() => {
|
|
const style = document.createElement('style')
|
|
style.textContent = `
|
|
.keyboard-navigation *:focus {
|
|
outline: 2px solid #f59e0b !important;
|
|
outline-offset: 2px !important;
|
|
}
|
|
`
|
|
document.head.appendChild(style)
|
|
return () => document.head.removeChild(style)
|
|
}, [])
|
|
}
|
|
|