963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
4.5 KiB
4.5 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| Use Native Menus for Dropdowns and Context Menus | HIGH | native accessibility, platform-consistent UX | user-interface, menus, context-menus, zeego, accessibility |
Use Native Menus for Dropdowns and Context Menus
Use native platform menus instead of custom JS implementations. Native menus provide built-in accessibility, consistent platform UX, and better performance. Use zeego for cross-platform native menus.
Incorrect (custom JS menu):
import { useState } from 'react';
import { View, Pressable, Text } from 'react-native';
function MyMenu() {
const [open, setOpen] = useState(false);
return (
<View>
<Pressable onPress={() => setOpen(!open)}>
<Text>Open Menu</Text>
</Pressable>
{open && (
<View style={{ position: 'absolute', top: 40 }}>
<Pressable onPress={() => console.log('edit')}>
<Text>Edit</Text>
</Pressable>
<Pressable onPress={() => console.log('delete')}>
<Text>Delete</Text>
</Pressable>
</View>
)}
</View>
);
}
Correct (native menu with zeego):
import * as DropdownMenu from 'zeego/dropdown-menu';
function MyMenu() {
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Pressable>
<Text>Open Menu</Text>
</Pressable>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item key="edit" onSelect={() => console.log('edit')}>
<DropdownMenu.ItemTitle>Edit</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
<DropdownMenu.Item key="delete" destructive onSelect={() => console.log('delete')}>
<DropdownMenu.ItemTitle>Delete</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
);
}
Context menu (long-press):
import * as ContextMenu from 'zeego/context-menu';
function MyContextMenu() {
return (
<ContextMenu.Root>
<ContextMenu.Trigger>
<View style={{ padding: 20 }}>
<Text>Long press me</Text>
</View>
</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Item key="copy" onSelect={() => console.log('copy')}>
<ContextMenu.ItemTitle>Copy</ContextMenu.ItemTitle>
</ContextMenu.Item>
<ContextMenu.Item key="paste" onSelect={() => console.log('paste')}>
<ContextMenu.ItemTitle>Paste</ContextMenu.ItemTitle>
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
);
}
Checkbox items:
import * as DropdownMenu from 'zeego/dropdown-menu';
function SettingsMenu() {
const [notifications, setNotifications] = useState(true);
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Pressable>
<Text>Settings</Text>
</Pressable>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.CheckboxItem
key="notifications"
value={notifications}
onValueChange={() => setNotifications((prev) => !prev)}
>
<DropdownMenu.ItemIndicator />
<DropdownMenu.ItemTitle>Notifications</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
</DropdownMenu.Content>
</DropdownMenu.Root>
);
}
Submenus:
import * as DropdownMenu from 'zeego/dropdown-menu';
function MenuWithSubmenu() {
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Pressable>
<Text>Options</Text>
</Pressable>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item key="home" onSelect={() => console.log('home')}>
<DropdownMenu.ItemTitle>Home</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger key="more">
<DropdownMenu.ItemTitle>More Options</DropdownMenu.ItemTitle>
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Item key="settings">
<DropdownMenu.ItemTitle>Settings</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
<DropdownMenu.Item key="help">
<DropdownMenu.ItemTitle>Help</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
</DropdownMenu.Content>
</DropdownMenu.Root>
);
}
Reference: Zeego Documentation