UI improvements: responsive layout, unified panels, credit legend
- Add responsive 2-panel layout (mobile single-col, tablet/desktop grid) - Unify specialization ranking with credit bars, status badges, and expandable allocation breakdowns (remove standalone ResultsDashboard) - Inline decision tree ceiling data on course buttons with spec counts - Add Clear All button to reset all course selections - Add collapsible CreditLegend explaining bars, badges, and limits - Extract ModeComparison and MutualExclusionWarnings to Notifications - Add useMediaQuery hook with matchMedia-based breakpoint detection
This commit is contained in:
34
app/src/hooks/useMediaQuery.ts
Normal file
34
app/src/hooks/useMediaQuery.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export type Breakpoint = 'mobile' | 'tablet' | 'desktop';
|
||||
|
||||
const mobileQuery = '(max-width: 639px)';
|
||||
const tabletQuery = '(min-width: 640px) and (max-width: 1024px)';
|
||||
|
||||
function getBreakpoint(): Breakpoint {
|
||||
if (window.matchMedia(mobileQuery).matches) return 'mobile';
|
||||
if (window.matchMedia(tabletQuery).matches) return 'tablet';
|
||||
return 'desktop';
|
||||
}
|
||||
|
||||
export function useMediaQuery(): Breakpoint {
|
||||
const [breakpoint, setBreakpoint] = useState<Breakpoint>(getBreakpoint);
|
||||
|
||||
useEffect(() => {
|
||||
const mobileMql = window.matchMedia(mobileQuery);
|
||||
const tabletMql = window.matchMedia(tabletQuery);
|
||||
|
||||
function onChange() {
|
||||
setBreakpoint(getBreakpoint());
|
||||
}
|
||||
|
||||
mobileMql.addEventListener('change', onChange);
|
||||
tabletMql.addEventListener('change', onChange);
|
||||
return () => {
|
||||
mobileMql.removeEventListener('change', onChange);
|
||||
tabletMql.removeEventListener('change', onChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return breakpoint;
|
||||
}
|
||||
Reference in New Issue
Block a user