feat(ui): phone layout up to 768 px

Phones in landscape and small tablets (iPad mini upright) got the
desktop layout from 640 px. The sm breakpoint is now 768 px; the media
queries in index.css and the width checks in code (isPhoneWidth) follow
it. The desktop header grid applies from sm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-11-02 12:37:52 +01:00
1 parent 8891dc046d
commit 117cf3445e
8 files changed
+39 -20

No files matched your search

@@ -18,6 +18,7 @@ import { AvatarStack, AvatarPerson } from '../../components/AvatarStack';
import { CountBadge } from '../../components/CountBadge';
import { ListSwitcher } from '../../components/ListSwitcher';
import { LivePill } from '../../components/LivePill';
import { isPhoneWidth } from '../../lib/breakpoints';
import { OriginBadge } from '../../components/OriginBadge';
import { VoiceInputButton } from '../../components/VoiceInputButton';
import { FormSheet } from '../../components/FormSheet';
@@ -126,10 +127,10 @@ export const SharedListsView: React.FC<SharedListsViewProps> = ({ onRefreshGloba
const inputRef = useRef<HTMLInputElement | null>(null);
// Phones: the add form lives in a sheet opened by "+" instead of taking room above the list
const [isPhone, setIsPhone] = useState(() => typeof window !== 'undefined' && window.innerWidth < 640);
const [isPhone, setIsPhone] = useState(isPhoneWidth);
const [showAddSheet, setShowAddSheet] = useState(false);
useEffect(() => {
const onResize = () => setIsPhone(window.innerWidth < 640);
const onResize = () => setIsPhone(isPhoneWidth());
window.addEventListener('resize', onResize);
return () => window.removeEventListener('resize', onResize);
}, []);
@@ -838,7 +839,7 @@ export const SharedListsView: React.FC<SharedListsViewProps> = ({ onRefreshGloba
}, [openItems]);
const focusNewItemInput = () => {
if (window.innerWidth < 640) {
if (isPhoneWidth()) {
setShowAddSheet(true);
return;
}
@@ -4,6 +4,7 @@ import { X, Trash2, Loader2 } from 'lucide-react';
import type { EmojiClickData } from 'emoji-picker-react';
import { Categories, EmojiStyle, Theme, SuggestionMode } from 'emoji-picker-react';
import { useKeyboardInset } from '../../lib/useKeyboardInset';
import { isPhoneWidth } from '../../lib/breakpoints';
// Lazy-load emoji-picker-react so the main bundle size stays small
const EmojiPicker = React.lazy(() => import('emoji-picker-react'));
@@ -38,7 +39,7 @@ export const EmojiPickerModal: React.FC<EmojiPickerModalProps> = ({
anchor,
}) => {
const { inset, visibleHeight } = useKeyboardInset();
const isPhone = typeof window !== 'undefined' && window.innerWidth < 640;
const isPhone = isPhoneWidth();
// On phones the picker shrinks with the keyboard so search field and results stay visible
const pickerHeight = isPhone ? Math.max(200, Math.min(350, visibleHeight - 110)) : 300;
const [isDark, setIsDark] = useState<boolean>(() =>
@@ -105,14 +106,14 @@ export const EmojiPickerModal: React.FC<EmojiPickerModalProps> = ({
const picker = (
<>
{/* Mobile Backdrop (< 640px) */}
{/* Mobile Backdrop (below sm) */}
<div
className={`fixed inset-0 bg-black/60 sm:hidden backdrop-blur-xs ${anchor ? 'z-[60]' : 'z-40'}`}
onClick={onClose}
aria-hidden="true"
/>
{/* Main Container: Mobile Bottom-Sheet (<640px) & Desktop Popover (>=640px) */}
{/* Main Container: Mobile Bottom-Sheet (below sm) & Desktop Popover (from sm) */}
<div
ref={containerRef}
className={`
@@ -60,6 +60,7 @@ import { CountBadge } from '../../components/CountBadge';
import { EmojiIconButton } from '../../components/EmojiIconButton';
import { LazyMount } from '../../components/LazyMount';
import { extractHashtags } from '../../lib/hashtags';
import { isPhoneWidth } from '../../lib/breakpoints';
interface WorkspaceViewProps {
currentUser?: User | null;
@@ -624,7 +625,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
const [newNoteIcon, setNewNoteIcon] = useState('🗒️');
const openNewNote = useCallback(
(folderPath = '') => {
if (window.innerWidth >= 640) {
if (!isPhoneWidth()) {
void handleCreateDocument(folderPath);
return;
}