Spaces:
Running
Running
i AM SO DONE I HAVE TO STUDY FOR EXAMS
Browse files- app/components/Desktop.tsx +13 -13
- app/components/Dock.tsx +2 -2
- app/components/TopBar.tsx +17 -13
- app/components/Window.tsx +39 -19
- app/globals.css +78 -22
app/components/Desktop.tsx
CHANGED
|
@@ -644,9 +644,9 @@ export function Desktop() {
|
|
| 644 |
/>
|
| 645 |
|
| 646 |
<div className="flex-1 z-10 relative pointer-events-auto">
|
| 647 |
-
{/* Desktop Icons -
|
| 648 |
-
<div className="absolute top-16 left-
|
| 649 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 650 |
<DraggableDesktopIcon
|
| 651 |
id="files"
|
| 652 |
label="Files"
|
|
@@ -657,7 +657,7 @@ export function Desktop() {
|
|
| 657 |
/>
|
| 658 |
</div>
|
| 659 |
|
| 660 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 661 |
<DraggableDesktopIcon
|
| 662 |
id="messages"
|
| 663 |
label="Messages"
|
|
@@ -668,7 +668,7 @@ export function Desktop() {
|
|
| 668 |
/>
|
| 669 |
</div>
|
| 670 |
|
| 671 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 672 |
<DraggableDesktopIcon
|
| 673 |
id="gemini"
|
| 674 |
label="Gemini"
|
|
@@ -678,7 +678,7 @@ export function Desktop() {
|
|
| 678 |
onDoubleClick={openGeminiChat}
|
| 679 |
/>
|
| 680 |
</div>
|
| 681 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 682 |
<DraggableDesktopIcon
|
| 683 |
id="clock"
|
| 684 |
label="Clock"
|
|
@@ -689,7 +689,7 @@ export function Desktop() {
|
|
| 689 |
/>
|
| 690 |
</div>
|
| 691 |
|
| 692 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 693 |
<DraggableDesktopIcon
|
| 694 |
id="calendar"
|
| 695 |
label="Calendar"
|
|
@@ -700,7 +700,7 @@ export function Desktop() {
|
|
| 700 |
/>
|
| 701 |
</div>
|
| 702 |
|
| 703 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 704 |
<DraggableDesktopIcon
|
| 705 |
id="harddrive"
|
| 706 |
label="System"
|
|
@@ -711,7 +711,7 @@ export function Desktop() {
|
|
| 711 |
/>
|
| 712 |
</div>
|
| 713 |
|
| 714 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 715 |
<DraggableDesktopIcon
|
| 716 |
id="flutter-editor"
|
| 717 |
label="Flutter IDE"
|
|
@@ -722,7 +722,7 @@ export function Desktop() {
|
|
| 722 |
/>
|
| 723 |
</div>
|
| 724 |
|
| 725 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 726 |
<DraggableDesktopIcon
|
| 727 |
id="quiz"
|
| 728 |
label="Quiz Master"
|
|
@@ -733,7 +733,7 @@ export function Desktop() {
|
|
| 733 |
/>
|
| 734 |
</div>
|
| 735 |
|
| 736 |
-
<div className="pointer-events-auto w-24 h-24">
|
| 737 |
<DraggableDesktopIcon
|
| 738 |
id="voice-app"
|
| 739 |
label="Voice Studio"
|
|
@@ -745,8 +745,8 @@ export function Desktop() {
|
|
| 745 |
</div>
|
| 746 |
</div>
|
| 747 |
|
| 748 |
-
{/* Windows Container */}
|
| 749 |
-
<div className="fixed inset-0
|
| 750 |
<AnimatePresence>
|
| 751 |
{fileManagerOpen && (
|
| 752 |
<motion.div
|
|
|
|
| 644 |
/>
|
| 645 |
|
| 646 |
<div className="flex-1 z-10 relative pointer-events-auto">
|
| 647 |
+
{/* Desktop Icons - Responsive grid layout, visible on all screen sizes */}
|
| 648 |
+
<div className="absolute top-16 left-2 right-2 sm:left-4 sm:right-4 bottom-24 grid grid-cols-3 xs:grid-cols-4 sm:grid-cols-4 md:grid-cols-5 lg:grid-flow-col lg:grid-cols-none lg:grid-rows-[repeat(auto-fill,100px)] gap-2 sm:gap-4 pointer-events-none overflow-y-auto lg:overflow-visible z-0">
|
| 649 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 650 |
<DraggableDesktopIcon
|
| 651 |
id="files"
|
| 652 |
label="Files"
|
|
|
|
| 657 |
/>
|
| 658 |
</div>
|
| 659 |
|
| 660 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 661 |
<DraggableDesktopIcon
|
| 662 |
id="messages"
|
| 663 |
label="Messages"
|
|
|
|
| 668 |
/>
|
| 669 |
</div>
|
| 670 |
|
| 671 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 672 |
<DraggableDesktopIcon
|
| 673 |
id="gemini"
|
| 674 |
label="Gemini"
|
|
|
|
| 678 |
onDoubleClick={openGeminiChat}
|
| 679 |
/>
|
| 680 |
</div>
|
| 681 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 682 |
<DraggableDesktopIcon
|
| 683 |
id="clock"
|
| 684 |
label="Clock"
|
|
|
|
| 689 |
/>
|
| 690 |
</div>
|
| 691 |
|
| 692 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 693 |
<DraggableDesktopIcon
|
| 694 |
id="calendar"
|
| 695 |
label="Calendar"
|
|
|
|
| 700 |
/>
|
| 701 |
</div>
|
| 702 |
|
| 703 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 704 |
<DraggableDesktopIcon
|
| 705 |
id="harddrive"
|
| 706 |
label="System"
|
|
|
|
| 711 |
/>
|
| 712 |
</div>
|
| 713 |
|
| 714 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 715 |
<DraggableDesktopIcon
|
| 716 |
id="flutter-editor"
|
| 717 |
label="Flutter IDE"
|
|
|
|
| 722 |
/>
|
| 723 |
</div>
|
| 724 |
|
| 725 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 726 |
<DraggableDesktopIcon
|
| 727 |
id="quiz"
|
| 728 |
label="Quiz Master"
|
|
|
|
| 733 |
/>
|
| 734 |
</div>
|
| 735 |
|
| 736 |
+
<div className="pointer-events-auto w-20 h-20 sm:w-24 sm:h-24">
|
| 737 |
<DraggableDesktopIcon
|
| 738 |
id="voice-app"
|
| 739 |
label="Voice Studio"
|
|
|
|
| 745 |
</div>
|
| 746 |
</div>
|
| 747 |
|
| 748 |
+
{/* Windows Container - adjusted for mobile topbar height */}
|
| 749 |
+
<div className="fixed inset-0 pointer-events-none" style={{ position: 'fixed', top: '40px', left: 0, right: 0, bottom: 0 }}>
|
| 750 |
<AnimatePresence>
|
| 751 |
{fileManagerOpen && (
|
| 752 |
<motion.div
|
app/components/Dock.tsx
CHANGED
|
@@ -64,7 +64,7 @@ const DockItem: React.FC<DockItemProps> = ({ icon, label, onClick, isActive = fa
|
|
| 64 |
onMouseEnter={() => setIsHovered(true)}
|
| 65 |
onMouseLeave={() => setIsHovered(false)}
|
| 66 |
onClick={handleClick}
|
| 67 |
-
className={`app-icon w-10 h-10 md:w-12 md:h-12 rounded-xl shadow-lg flex items-center justify-center cursor-pointer border transition-all ${className}`}
|
| 68 |
title={label}
|
| 69 |
>
|
| 70 |
{icon}
|
|
@@ -152,7 +152,7 @@ export function Dock({
|
|
| 152 |
return (
|
| 153 |
<div className="dock-container">
|
| 154 |
<div
|
| 155 |
-
className="dock-glass px-2 pb-1.5 pt-2 md:px-3 md:pb-2 md:pt-3 rounded-t-2xl md:rounded-2xl flex items-end gap-2 md:gap-3 shadow-2xl border border-white/20 transition-all duration-300"
|
| 156 |
onMouseMove={(e) => mouseX.current = e.pageX}
|
| 157 |
onMouseLeave={() => mouseX.current = null}
|
| 158 |
>
|
|
|
|
| 64 |
onMouseEnter={() => setIsHovered(true)}
|
| 65 |
onMouseLeave={() => setIsHovered(false)}
|
| 66 |
onClick={handleClick}
|
| 67 |
+
className={`app-icon w-10 h-10 sm:w-11 sm:h-11 md:w-12 md:h-12 rounded-xl shadow-lg flex items-center justify-center cursor-pointer border transition-all ${className}`}
|
| 68 |
title={label}
|
| 69 |
>
|
| 70 |
{icon}
|
|
|
|
| 152 |
return (
|
| 153 |
<div className="dock-container">
|
| 154 |
<div
|
| 155 |
+
className="dock-glass px-1 pb-1 pt-1.5 sm:px-2 sm:pb-1.5 sm:pt-2 md:px-3 md:pb-2 md:pt-3 rounded-t-2xl md:rounded-2xl flex items-end gap-1 sm:gap-2 md:gap-3 shadow-2xl border border-white/20 transition-all duration-300 overflow-x-auto max-w-full"
|
| 156 |
onMouseMove={(e) => mouseX.current = e.pageX}
|
| 157 |
onMouseLeave={() => mouseX.current = null}
|
| 158 |
>
|
app/components/TopBar.tsx
CHANGED
|
@@ -24,7 +24,8 @@ interface TopBarProps {
|
|
| 24 |
|
| 25 |
export function TopBar({ activeAppName = 'Finder', onAboutClick, onSleep, onRestart, onShutdown }: TopBarProps) {
|
| 26 |
const [activeMenu, setActiveMenu] = useState<'apple' | 'battery' | 'wifi' | 'clock' | null>(null)
|
| 27 |
-
const [
|
|
|
|
| 28 |
const menuRef = useRef<HTMLDivElement>(null)
|
| 29 |
|
| 30 |
useEffect(() => {
|
|
@@ -39,7 +40,9 @@ export function TopBar({ activeAppName = 'Finder', onAboutClick, onSleep, onRest
|
|
| 39 |
hour12: true
|
| 40 |
})
|
| 41 |
const dateString = `${days[now.getDay()]} ${now.getDate()} ${months[now.getMonth()]}`
|
| 42 |
-
|
|
|
|
|
|
|
| 43 |
}
|
| 44 |
|
| 45 |
updateTime()
|
|
@@ -63,8 +66,8 @@ export function TopBar({ activeAppName = 'Finder', onAboutClick, onSleep, onRest
|
|
| 63 |
}
|
| 64 |
|
| 65 |
return (
|
| 66 |
-
<div className="fixed top-0 left-0 right-0 h-8 glass flex items-center justify-between px-4 text-sm z-50 shadow-sm backdrop-blur-xl bg-white/40 border-b border-white/20 select-none">
|
| 67 |
-
<div className="flex items-center space-x-4" ref={menuRef}>
|
| 68 |
<div className="relative">
|
| 69 |
<button
|
| 70 |
onClick={() => toggleMenu('apple')}
|
|
@@ -136,14 +139,14 @@ export function TopBar({ activeAppName = 'Finder', onAboutClick, onSleep, onRest
|
|
| 136 |
</AnimatePresence>
|
| 137 |
</div>
|
| 138 |
|
| 139 |
-
<span className="font-bold text-gray-800">Reuben OS</span>
|
| 140 |
-
<span className="text-gray-600 text-xs ml-2 font-medium">{activeAppName}</span>
|
| 141 |
</div>
|
| 142 |
|
| 143 |
-
<div className="flex items-center space-x-4" ref={menuRef}>
|
| 144 |
-
<div className="flex items-center space-x-3 text-gray-700">
|
| 145 |
{/* Battery */}
|
| 146 |
-
<div className="relative">
|
| 147 |
<button
|
| 148 |
onClick={() => toggleMenu('battery')}
|
| 149 |
className={`hover:bg-black/5 rounded px-1 py-0.5 transition-colors ${activeMenu === 'battery' ? 'bg-black/10' : ''}`}
|
|
@@ -179,7 +182,7 @@ export function TopBar({ activeAppName = 'Finder', onAboutClick, onSleep, onRest
|
|
| 179 |
</div>
|
| 180 |
|
| 181 |
{/* WiFi */}
|
| 182 |
-
<div className="relative">
|
| 183 |
<button
|
| 184 |
onClick={() => toggleMenu('wifi')}
|
| 185 |
className={`hover:bg-black/5 rounded px-1 py-0.5 transition-colors ${activeMenu === 'wifi' ? 'bg-black/10' : ''}`}
|
|
@@ -235,16 +238,17 @@ export function TopBar({ activeAppName = 'Finder', onAboutClick, onSleep, onRest
|
|
| 235 |
</AnimatePresence>
|
| 236 |
</div>
|
| 237 |
|
| 238 |
-
<MagnifyingGlass size={18} weight="bold" />
|
| 239 |
</div>
|
| 240 |
|
| 241 |
{/* Clock */}
|
| 242 |
<div className="relative">
|
| 243 |
<button
|
| 244 |
onClick={() => toggleMenu('clock')}
|
| 245 |
-
className={`font-medium text-gray-800 min-w-[140px] text-right hover:bg-black/5 rounded px-2 py-0.5 transition-colors ${activeMenu === 'clock' ? 'bg-black/10' : ''}`}
|
| 246 |
>
|
| 247 |
-
{
|
|
|
|
| 248 |
</button>
|
| 249 |
<AnimatePresence>
|
| 250 |
{activeMenu === 'clock' && (
|
|
|
|
| 24 |
|
| 25 |
export function TopBar({ activeAppName = 'Finder', onAboutClick, onSleep, onRestart, onShutdown }: TopBarProps) {
|
| 26 |
const [activeMenu, setActiveMenu] = useState<'apple' | 'battery' | 'wifi' | 'clock' | null>(null)
|
| 27 |
+
const [dateDisplay, setDateDisplay] = useState('')
|
| 28 |
+
const [timeDisplay, setTimeDisplay] = useState('')
|
| 29 |
const menuRef = useRef<HTMLDivElement>(null)
|
| 30 |
|
| 31 |
useEffect(() => {
|
|
|
|
| 40 |
hour12: true
|
| 41 |
})
|
| 42 |
const dateString = `${days[now.getDay()]} ${now.getDate()} ${months[now.getMonth()]}`
|
| 43 |
+
|
| 44 |
+
setDateDisplay(dateString)
|
| 45 |
+
setTimeDisplay(timeString)
|
| 46 |
}
|
| 47 |
|
| 48 |
updateTime()
|
|
|
|
| 66 |
}
|
| 67 |
|
| 68 |
return (
|
| 69 |
+
<div className="fixed top-0 left-0 right-0 h-10 sm:h-8 glass flex items-center justify-between px-2 sm:px-4 text-xs sm:text-sm z-50 shadow-sm backdrop-blur-xl bg-white/40 border-b border-white/20 select-none">
|
| 70 |
+
<div className="flex items-center space-x-2 sm:space-x-4" ref={menuRef}>
|
| 71 |
<div className="relative">
|
| 72 |
<button
|
| 73 |
onClick={() => toggleMenu('apple')}
|
|
|
|
| 139 |
</AnimatePresence>
|
| 140 |
</div>
|
| 141 |
|
| 142 |
+
<span className="font-bold text-gray-800 hidden sm:inline text-xs sm:text-sm">Reuben OS</span>
|
| 143 |
+
<span className="text-gray-600 text-[10px] sm:text-xs ml-1 sm:ml-2 font-medium hidden xs:inline">{activeAppName}</span>
|
| 144 |
</div>
|
| 145 |
|
| 146 |
+
<div className="flex items-center space-x-2 md:space-x-4" ref={menuRef}>
|
| 147 |
+
<div className="flex items-center space-x-1 md:space-x-3 text-gray-700">
|
| 148 |
{/* Battery */}
|
| 149 |
+
<div className="relative hidden sm:block">
|
| 150 |
<button
|
| 151 |
onClick={() => toggleMenu('battery')}
|
| 152 |
className={`hover:bg-black/5 rounded px-1 py-0.5 transition-colors ${activeMenu === 'battery' ? 'bg-black/10' : ''}`}
|
|
|
|
| 182 |
</div>
|
| 183 |
|
| 184 |
{/* WiFi */}
|
| 185 |
+
<div className="relative hidden sm:block">
|
| 186 |
<button
|
| 187 |
onClick={() => toggleMenu('wifi')}
|
| 188 |
className={`hover:bg-black/5 rounded px-1 py-0.5 transition-colors ${activeMenu === 'wifi' ? 'bg-black/10' : ''}`}
|
|
|
|
| 238 |
</AnimatePresence>
|
| 239 |
</div>
|
| 240 |
|
| 241 |
+
<MagnifyingGlass size={18} weight="bold" className="hidden sm:block" />
|
| 242 |
</div>
|
| 243 |
|
| 244 |
{/* Clock */}
|
| 245 |
<div className="relative">
|
| 246 |
<button
|
| 247 |
onClick={() => toggleMenu('clock')}
|
| 248 |
+
className={`font-medium text-gray-800 min-w-[50px] sm:min-w-[60px] md:min-w-[140px] text-right hover:bg-black/5 rounded px-1 sm:px-2 py-0.5 transition-colors text-[11px] sm:text-xs ${activeMenu === 'clock' ? 'bg-black/10' : ''}`}
|
| 249 |
>
|
| 250 |
+
<span className="hidden md:inline mr-2">{dateDisplay}</span>
|
| 251 |
+
<span>{timeDisplay}</span>
|
| 252 |
</button>
|
| 253 |
<AnimatePresence>
|
| 254 |
{activeMenu === 'clock' && (
|
app/components/Window.tsx
CHANGED
|
@@ -53,10 +53,10 @@ const Window: React.FC<WindowProps> = ({
|
|
| 53 |
const currentPositionRef = React.useRef({ x, y: Math.max(y, 32) });
|
| 54 |
const currentSizeRef = React.useRef({ width, height });
|
| 55 |
|
| 56 |
-
// Detect mobile device
|
| 57 |
useEffect(() => {
|
| 58 |
const checkMobile = () => {
|
| 59 |
-
setIsMobile(window.innerWidth <=
|
| 60 |
};
|
| 61 |
checkMobile();
|
| 62 |
window.addEventListener('resize', checkMobile);
|
|
@@ -69,22 +69,50 @@ const Window: React.FC<WindowProps> = ({
|
|
| 69 |
const windowClass = darkMode ? 'bg-gray-900 border-gray-700' : 'bg-[#f5f5f5] border-gray-300/50';
|
| 70 |
const headerClass = darkMode ? 'bg-gray-800 border-gray-700' : 'macos-window-header';
|
| 71 |
|
| 72 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
if (isMobile) {
|
| 74 |
return (
|
| 75 |
<div
|
| 76 |
-
className={`fixed
|
| 77 |
-
style={{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
>
|
| 79 |
<div
|
| 80 |
-
className={`h-
|
| 81 |
>
|
| 82 |
-
<div className="flex space-x-2 group">
|
| 83 |
-
<
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
</div>
|
| 87 |
-
<span className="font-semibold text-gray-700 flex-1 text-center
|
| 88 |
</div>
|
| 89 |
<div className="flex-1 overflow-auto">{children}</div>
|
| 90 |
</div>
|
|
@@ -106,14 +134,6 @@ const Window: React.FC<WindowProps> = ({
|
|
| 106 |
if (onMaximize) onMaximize();
|
| 107 |
};
|
| 108 |
|
| 109 |
-
// Bring window to front
|
| 110 |
-
const bringToFront = () => {
|
| 111 |
-
// Call onFocus to bring window to front
|
| 112 |
-
if (onFocus) {
|
| 113 |
-
onFocus();
|
| 114 |
-
}
|
| 115 |
-
};
|
| 116 |
-
|
| 117 |
// Calculate Rnd props based on state
|
| 118 |
const rndProps = isMaximized ? {
|
| 119 |
position: { x: 0, y: 4 }, // 32px for TopBar offset (h-8 = 32px)
|
|
|
|
| 53 |
const currentPositionRef = React.useRef({ x, y: Math.max(y, 32) });
|
| 54 |
const currentSizeRef = React.useRef({ width, height });
|
| 55 |
|
| 56 |
+
// Detect mobile device - update threshold to better match small screens
|
| 57 |
useEffect(() => {
|
| 58 |
const checkMobile = () => {
|
| 59 |
+
setIsMobile(window.innerWidth <= 768);
|
| 60 |
};
|
| 61 |
checkMobile();
|
| 62 |
window.addEventListener('resize', checkMobile);
|
|
|
|
| 69 |
const windowClass = darkMode ? 'bg-gray-900 border-gray-700' : 'bg-[#f5f5f5] border-gray-300/50';
|
| 70 |
const headerClass = darkMode ? 'bg-gray-800 border-gray-700' : 'macos-window-header';
|
| 71 |
|
| 72 |
+
// Bring window to front function - define it early
|
| 73 |
+
const bringToFront = () => {
|
| 74 |
+
if (onFocus) {
|
| 75 |
+
onFocus();
|
| 76 |
+
}
|
| 77 |
+
};
|
| 78 |
+
|
| 79 |
+
// On mobile, render with reduced size instead of full screen
|
| 80 |
if (isMobile) {
|
| 81 |
return (
|
| 82 |
<div
|
| 83 |
+
className={`fixed flex flex-col overflow-hidden ${windowClass} ${className} rounded-lg shadow-2xl`}
|
| 84 |
+
style={{
|
| 85 |
+
top: '60px',
|
| 86 |
+
left: '10px',
|
| 87 |
+
right: '10px',
|
| 88 |
+
bottom: '80px',
|
| 89 |
+
zIndex: zIndex || 1000,
|
| 90 |
+
maxHeight: 'calc(100vh - 140px)'
|
| 91 |
+
}}
|
| 92 |
+
onMouseDown={bringToFront}
|
| 93 |
+
onTouchStart={bringToFront}
|
| 94 |
>
|
| 95 |
<div
|
| 96 |
+
className={`h-12 flex items-center px-3 space-x-2 border-b ${headerClass} ${headerClassName}`}
|
| 97 |
>
|
| 98 |
+
<div className="flex space-x-2 group relative z-10">
|
| 99 |
+
<button
|
| 100 |
+
className="traffic-light traffic-close w-6 h-6 sm:w-4 sm:h-4"
|
| 101 |
+
onClick={onClose}
|
| 102 |
+
aria-label="Close"
|
| 103 |
+
/>
|
| 104 |
+
<button
|
| 105 |
+
className="traffic-light traffic-min w-6 h-6 sm:w-4 sm:h-4"
|
| 106 |
+
onClick={onMinimize}
|
| 107 |
+
aria-label="Minimize"
|
| 108 |
+
/>
|
| 109 |
+
<button
|
| 110 |
+
className="traffic-light traffic-max w-6 h-6 sm:w-4 sm:h-4"
|
| 111 |
+
onClick={onMaximize}
|
| 112 |
+
aria-label="Maximize"
|
| 113 |
+
/>
|
| 114 |
</div>
|
| 115 |
+
<span className="font-semibold text-gray-700 flex-1 text-center text-sm truncate px-2">{title}</span>
|
| 116 |
</div>
|
| 117 |
<div className="flex-1 overflow-auto">{children}</div>
|
| 118 |
</div>
|
|
|
|
| 134 |
if (onMaximize) onMaximize();
|
| 135 |
};
|
| 136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
// Calculate Rnd props based on state
|
| 138 |
const rndProps = isMaximized ? {
|
| 139 |
position: { x: 0, y: 4 }, // 32px for TopBar offset (h-8 = 32px)
|
app/globals.css
CHANGED
|
@@ -225,6 +225,8 @@
|
|
| 225 |
position: relative;
|
| 226 |
cursor: pointer;
|
| 227 |
transition: all 0.2s ease;
|
|
|
|
|
|
|
| 228 |
}
|
| 229 |
|
| 230 |
.traffic-close {
|
|
@@ -368,9 +370,10 @@
|
|
| 368 |
user-select: auto;
|
| 369 |
}
|
| 370 |
|
| 371 |
-
/*
|
| 372 |
.macos-window {
|
| 373 |
-
@apply rounded-
|
|
|
|
| 374 |
}
|
| 375 |
|
| 376 |
/* Adjust dock for mobile */
|
|
@@ -380,42 +383,69 @@
|
|
| 380 |
|
| 381 |
.dock-glass {
|
| 382 |
@apply rounded-t-2xl rounded-b-none;
|
| 383 |
-
padding: 0.5rem
|
|
|
|
| 384 |
}
|
| 385 |
|
| 386 |
-
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 387 |
.desktop-icon {
|
| 388 |
-
display:
|
|
|
|
| 389 |
}
|
| 390 |
|
| 391 |
-
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 392 |
.traffic-light {
|
| 393 |
-
width:
|
| 394 |
-
height:
|
| 395 |
-
margin-right:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
}
|
| 397 |
}
|
| 398 |
|
| 399 |
/* Landscape mobile optimization */
|
| 400 |
@media (max-width: 1024px) and (orientation: landscape) {
|
|
|
|
| 401 |
/* Top bar more compact */
|
| 402 |
.macos-window-header {
|
| 403 |
-
@apply h-
|
| 404 |
}
|
| 405 |
|
|
|
|
| 406 |
.traffic-light {
|
| 407 |
-
width:
|
| 408 |
-
height:
|
| 409 |
-
margin-right:
|
| 410 |
}
|
| 411 |
|
| 412 |
-
/* Dock
|
| 413 |
.dock-container {
|
| 414 |
@apply bottom-0;
|
| 415 |
}
|
| 416 |
|
| 417 |
.dock-glass {
|
| 418 |
padding: 0.25rem 0.75rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 419 |
}
|
| 420 |
|
| 421 |
/* Scrollbars thinner on mobile */
|
|
@@ -427,6 +457,7 @@
|
|
| 427 |
|
| 428 |
/* Portrait mobile optimization */
|
| 429 |
@media (max-width: 768px) and (orientation: portrait) {
|
|
|
|
| 430 |
/* Stack dock items more compactly */
|
| 431 |
.dock-item {
|
| 432 |
@apply gap-0;
|
|
@@ -440,11 +471,31 @@
|
|
| 440 |
|
| 441 |
/* Touch-friendly improvements */
|
| 442 |
@media (hover: none) and (pointer: coarse) {
|
| 443 |
-
|
|
|
|
| 444 |
.traffic-light {
|
| 445 |
-
width:
|
| 446 |
-
height:
|
| 447 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 448 |
}
|
| 449 |
|
| 450 |
/* Better tap feedback */
|
|
@@ -465,6 +516,11 @@
|
|
| 465 |
background-color: transparent;
|
| 466 |
box-shadow: none;
|
| 467 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
}
|
| 469 |
|
| 470 |
/* Markdown Content Styles */
|
|
@@ -472,11 +528,11 @@
|
|
| 472 |
@apply text-sm leading-relaxed;
|
| 473 |
}
|
| 474 |
|
| 475 |
-
.markdown-content
|
| 476 |
@apply mb-3;
|
| 477 |
}
|
| 478 |
|
| 479 |
-
.markdown-content
|
| 480 |
@apply mb-0;
|
| 481 |
}
|
| 482 |
|
|
@@ -517,8 +573,8 @@
|
|
| 517 |
@apply ml-2;
|
| 518 |
}
|
| 519 |
|
| 520 |
-
.markdown-content li
|
| 521 |
-
.markdown-content li
|
| 522 |
@apply ml-4 mt-1;
|
| 523 |
}
|
| 524 |
|
|
|
|
| 225 |
position: relative;
|
| 226 |
cursor: pointer;
|
| 227 |
transition: all 0.2s ease;
|
| 228 |
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
| 229 |
+
z-index: 10;
|
| 230 |
}
|
| 231 |
|
| 232 |
.traffic-close {
|
|
|
|
| 370 |
user-select: auto;
|
| 371 |
}
|
| 372 |
|
| 373 |
+
/* Don't force windows to be full screen - keep them contained */
|
| 374 |
.macos-window {
|
| 375 |
+
@apply rounded-lg shadow-xl;
|
| 376 |
+
max-height: calc(100vh - 140px) !important;
|
| 377 |
}
|
| 378 |
|
| 379 |
/* Adjust dock for mobile */
|
|
|
|
| 383 |
|
| 384 |
.dock-glass {
|
| 385 |
@apply rounded-t-2xl rounded-b-none;
|
| 386 |
+
padding: 0.5rem 0.75rem;
|
| 387 |
+
max-height: 70px;
|
| 388 |
}
|
| 389 |
|
| 390 |
+
/* Dock icons smaller on mobile */
|
| 391 |
+
.dock-item {
|
| 392 |
+
@apply w-10 h-10 sm:w-12 sm:h-12;
|
| 393 |
+
}
|
| 394 |
+
|
| 395 |
+
/* Desktop icons visible on mobile now */
|
| 396 |
.desktop-icon {
|
| 397 |
+
display: flex !important;
|
| 398 |
+
@apply w-16 h-16 sm:w-20 sm:h-20;
|
| 399 |
}
|
| 400 |
|
| 401 |
+
/* Desktop icon labels smaller on mobile */
|
| 402 |
+
.desktop-icon-label {
|
| 403 |
+
@apply text-[9px] sm:text-[10px];
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
/* Adjust traffic lights for touch - make them clickable */
|
| 407 |
.traffic-light {
|
| 408 |
+
width: 24px;
|
| 409 |
+
height: 24px;
|
| 410 |
+
margin-right: 8px;
|
| 411 |
+
@apply cursor-pointer;
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
/* Ensure traffic lights are always on top and show symbols */
|
| 415 |
+
.traffic-light::after {
|
| 416 |
+
font-size: 14px;
|
| 417 |
+
opacity: 1;
|
| 418 |
}
|
| 419 |
}
|
| 420 |
|
| 421 |
/* Landscape mobile optimization */
|
| 422 |
@media (max-width: 1024px) and (orientation: landscape) {
|
| 423 |
+
|
| 424 |
/* Top bar more compact */
|
| 425 |
.macos-window-header {
|
| 426 |
+
@apply h-10 px-3;
|
| 427 |
}
|
| 428 |
|
| 429 |
+
/* Keep traffic lights larger for touch in landscape */
|
| 430 |
.traffic-light {
|
| 431 |
+
width: 20px;
|
| 432 |
+
height: 20px;
|
| 433 |
+
margin-right: 8px;
|
| 434 |
}
|
| 435 |
|
| 436 |
+
/* Dock compact in landscape */
|
| 437 |
.dock-container {
|
| 438 |
@apply bottom-0;
|
| 439 |
}
|
| 440 |
|
| 441 |
.dock-glass {
|
| 442 |
padding: 0.25rem 0.75rem;
|
| 443 |
+
max-height: 60px;
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
/* Windows should leave space for dock and topbar in landscape */
|
| 447 |
+
.macos-window {
|
| 448 |
+
max-height: calc(100vh - 100px) !important;
|
| 449 |
}
|
| 450 |
|
| 451 |
/* Scrollbars thinner on mobile */
|
|
|
|
| 457 |
|
| 458 |
/* Portrait mobile optimization */
|
| 459 |
@media (max-width: 768px) and (orientation: portrait) {
|
| 460 |
+
|
| 461 |
/* Stack dock items more compactly */
|
| 462 |
.dock-item {
|
| 463 |
@apply gap-0;
|
|
|
|
| 471 |
|
| 472 |
/* Touch-friendly improvements */
|
| 473 |
@media (hover: none) and (pointer: coarse) {
|
| 474 |
+
|
| 475 |
+
/* Larger touch targets - 44px is Apple's recommended minimum */
|
| 476 |
.traffic-light {
|
| 477 |
+
min-width: 32px;
|
| 478 |
+
min-height: 32px;
|
| 479 |
+
width: 32px;
|
| 480 |
+
height: 32px;
|
| 481 |
+
margin-right: 10px;
|
| 482 |
+
touch-action: manipulation;
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
/* Always show traffic light symbols on touch devices */
|
| 486 |
+
.traffic-close::after {
|
| 487 |
+
content: '×' !important;
|
| 488 |
+
opacity: 0.7;
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
.traffic-min::after {
|
| 492 |
+
content: '−' !important;
|
| 493 |
+
opacity: 0.7;
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
.traffic-max::after {
|
| 497 |
+
content: '+' !important;
|
| 498 |
+
opacity: 0.7;
|
| 499 |
}
|
| 500 |
|
| 501 |
/* Better tap feedback */
|
|
|
|
| 516 |
background-color: transparent;
|
| 517 |
box-shadow: none;
|
| 518 |
}
|
| 519 |
+
|
| 520 |
+
/* Ensure windows are touch-scrollable */
|
| 521 |
+
.macos-window {
|
| 522 |
+
-webkit-overflow-scrolling: touch;
|
| 523 |
+
}
|
| 524 |
}
|
| 525 |
|
| 526 |
/* Markdown Content Styles */
|
|
|
|
| 528 |
@apply text-sm leading-relaxed;
|
| 529 |
}
|
| 530 |
|
| 531 |
+
.markdown-content>* {
|
| 532 |
@apply mb-3;
|
| 533 |
}
|
| 534 |
|
| 535 |
+
.markdown-content>*:last-child {
|
| 536 |
@apply mb-0;
|
| 537 |
}
|
| 538 |
|
|
|
|
| 573 |
@apply ml-2;
|
| 574 |
}
|
| 575 |
|
| 576 |
+
.markdown-content li>ul,
|
| 577 |
+
.markdown-content li>ol {
|
| 578 |
@apply ml-4 mt-1;
|
| 579 |
}
|
| 580 |
|