submenu.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. import { Platform } from 'react-native';
  2. import { NeoButton, NeoButtonLink, useNeoButtonExpoUI } from 'app/design/controls';
  3. import { sanitazeUrl } from 'app/lib/util';
  4. const isWeb = Platform.OS === 'web';
  5. export default function MenuItemSubmenu({ icon, title, pressed, disabled, addon, onPress, href }) {
  6. const controlSize = 'small';
  7. const borderShape = 'capsule';
  8. // Glass on every platform: native draws Expo UI glass (tinted when
  9. // selected), web the styled JS glass with its `pressedToggle` accent fill.
  10. // Do not branch on useIsDesktop() — SSR is forced desktop, then the first
  11. // layout effect flips it on narrow viewports and React 19 hydration
  12. // recovery can stack-overflow (see measure.js).
  13. const style = 'glass';
  14. const native = useNeoButtonExpoUI({ style, controlSize, borderShape });
  15. const useNativeGlass = !isWeb && !!native;
  16. const commonProps = {
  17. label: title,
  18. image: icon,
  19. style,
  20. selected: pressed,
  21. selectedState: 'pressedToggle',
  22. controlSize,
  23. borderShape,
  24. disabled,
  25. // Glass NeoButton keeps Expo UI for selected + addon counters.
  26. addon,
  27. haptics: 'Medium',
  28. onPress,
  29. };
  30. const finalHref = sanitazeUrl(href);
  31. // Custom onPress (conductor tabs) owns navigation — a Link wrapper
  32. // nests role=button inside <a> and double-fires router.push + pushState.
  33. if (finalHref && !useNativeGlass && !onPress) {
  34. return <NeoButtonLink {...commonProps} href={finalHref} />;
  35. }
  36. return <NeoButton {...commonProps} interactive />;
  37. }