@appforgeapps/uiforge 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1652,6 +1652,19 @@ function App() {
1652
1652
  }
1653
1653
  ```
1654
1654
 
1655
+ ## Mobile Header Best Practices
1656
+
1657
+ For building mobile headers with `MobileHeaderLayout`, `IconButton`, `SafeAreaContainer`, and `OverflowMenu`, see [MOBILE_HEADER_BEST_PRACTICES.md](./MOBILE_HEADER_BEST_PRACTICES.md) for:
1658
+
1659
+ - Touch target guidelines (44×44px minimum)
1660
+ - ARIA label requirements for accessibility
1661
+ - Recommended header height (56px)
1662
+ - Safe area usage for notched devices
1663
+ - When to use overflow menus vs primary actions
1664
+ - Layout vs behavior separation rationale
1665
+
1666
+ See `examples/CourseForgeMobileHeaderExample.tsx` for a complete composition example demonstrating these patterns.
1667
+
1655
1668
  ## Development
1656
1669
 
1657
1670
  ### Prerequisites
package/dist/index.d.ts CHANGED
@@ -487,6 +487,71 @@ export declare interface HamburgerButtonProps extends Omit<default_2.ButtonHTMLA
487
487
 
488
488
  export declare const HeartRateIcon: default_2.FC<IconProps>;
489
489
 
490
+ /**
491
+ * IconButton - An accessible icon-only button with touch-friendly targets
492
+ *
493
+ * Features:
494
+ * - 44x44px minimum touch target for all sizes (WCAG 2.1 compliant)
495
+ * - Keyboard accessible (Enter/Space triggers click)
496
+ * - Visible focus styles
497
+ * - Optional badge support for notifications
498
+ * - Dark mode support
499
+ * - Reduced motion support
500
+ *
501
+ * @example
502
+ * ```tsx
503
+ * import { IconButton, CloseIcon } from '@appforgeapps/uiforge'
504
+ *
505
+ * <IconButton
506
+ * icon={<CloseIcon />}
507
+ * ariaLabel="Close dialog"
508
+ * onClick={handleClose}
509
+ * />
510
+ * ```
511
+ *
512
+ * @example With badge
513
+ * ```tsx
514
+ * <IconButton
515
+ * icon={<NotificationIcon />}
516
+ * ariaLabel="Notifications"
517
+ * badge={5}
518
+ * onClick={handleNotifications}
519
+ * />
520
+ * ```
521
+ */
522
+ export declare const IconButton: default_2.FC<IconButtonProps>;
523
+
524
+ /**
525
+ * Props for the IconButton component
526
+ */
527
+ export declare interface IconButtonProps extends Omit<default_2.ButtonHTMLAttributes<HTMLButtonElement>, 'aria-label'> {
528
+ /**
529
+ * The icon element to display. Should be an SVG icon or icon component.
530
+ */
531
+ icon: default_2.ReactNode;
532
+ /**
533
+ * Size variant of the button.
534
+ * All sizes maintain a minimum 44x44px touch target for accessibility.
535
+ * @default 'medium'
536
+ */
537
+ size?: 'small' | 'medium' | 'large';
538
+ /**
539
+ * Accessible label for the button.
540
+ * Required for icon-only buttons to ensure screen reader accessibility.
541
+ * @important Always provide a descriptive label for icon-only buttons.
542
+ */
543
+ ariaLabel: string;
544
+ /**
545
+ * Optional badge content to display (e.g., notification count).
546
+ * Can be a string or number. Will be visually displayed as a small badge on the button.
547
+ */
548
+ badge?: string | number;
549
+ /**
550
+ * Additional CSS class names for styling overrides.
551
+ */
552
+ className?: string;
553
+ }
554
+
490
555
  /**
491
556
  * UIForge Icon Library
492
557
  * A collection of monochrome SVG icons for use across UIForge components
@@ -512,6 +577,206 @@ export declare const MeetingIcon: default_2.FC<IconProps>;
512
577
 
513
578
  export declare const MergeIcon: default_2.FC<IconProps>;
514
579
 
580
+ /**
581
+ * MobileHeaderLayout - A 3-slot mobile header layout primitive
582
+ *
583
+ * This component provides a standardized mobile header with left, center, and right slots.
584
+ * It uses SafeAreaContainer internally to respect device safe areas (iOS notch, status bar).
585
+ *
586
+ * Features:
587
+ * - 3-slot layout: left / center (title) / right
588
+ * - Safe area handling via SafeAreaContainer
589
+ * - Left and right slots have fixed min-width (≥44px) for touch targets
590
+ * - Center slot is flexible with text-overflow: ellipsis for long titles
591
+ * - Optional hide-on-desktop behavior (configurable via CSS variable)
592
+ * - CSS variables for height (default 56px) and padding
593
+ * - Dark mode support
594
+ *
595
+ * @example Basic usage
596
+ * ```tsx
597
+ * import { MobileHeaderLayout, IconButton, ArrowLeftIcon } from '@appforgeapps/uiforge'
598
+ *
599
+ * <MobileHeaderLayout
600
+ * left={<IconButton icon={<ArrowLeftIcon />} ariaLabel="Go back" onClick={handleBack} />}
601
+ * title="Page Title"
602
+ * right={<IconButton icon={<MenuIcon />} ariaLabel="Menu" onClick={handleMenu} />}
603
+ * />
604
+ * ```
605
+ *
606
+ * @example With React node as title
607
+ * ```tsx
608
+ * <MobileHeaderLayout
609
+ * left={<BackButton />}
610
+ * title={<Logo />}
611
+ * hideOnDesktop
612
+ * />
613
+ * ```
614
+ *
615
+ * @example Long title with ellipsis
616
+ * ```tsx
617
+ * <MobileHeaderLayout
618
+ * title="This is a very long title that will be truncated with ellipsis"
619
+ * right={<OverflowMenuButton />}
620
+ * />
621
+ * ```
622
+ */
623
+ export declare const MobileHeaderLayout: default_2.FC<MobileHeaderLayoutProps>;
624
+
625
+ /**
626
+ * Props for the MobileHeaderLayout component
627
+ */
628
+ export declare interface MobileHeaderLayoutProps extends Omit<default_2.HTMLAttributes<HTMLDivElement>, 'title'> {
629
+ /**
630
+ * Content to render in the left slot (typically a back button or hamburger menu).
631
+ * Slot has a fixed min-width of 44px for touch target consistency.
632
+ */
633
+ left?: default_2.ReactNode;
634
+ /**
635
+ * Content to render in the center slot.
636
+ * Can be a string (which will be rendered with ellipsis on overflow) or a React node.
637
+ */
638
+ title?: default_2.ReactNode;
639
+ /**
640
+ * Content to render in the right slot (typically action buttons or overflow menu).
641
+ * Slot has a fixed min-width of 44px for touch target consistency.
642
+ */
643
+ right?: default_2.ReactNode;
644
+ /**
645
+ * When true, the header is hidden at desktop breakpoints (min-width: 600px by default).
646
+ * Override the breakpoint in your own CSS by targeting .uiforge-mobile-header-layout--hide-on-desktop.
647
+ * @default false
648
+ */
649
+ hideOnDesktop?: boolean;
650
+ /**
651
+ * Additional CSS class names for styling overrides.
652
+ */
653
+ className?: string;
654
+ }
655
+
656
+ /**
657
+ * OverflowMenu - An accessible popover menu for secondary actions
658
+ *
659
+ * Features:
660
+ * - Keyboard accessible (Arrow keys, Enter, Escape)
661
+ * - ARIA attributes for screen readers
662
+ * - Click outside to close
663
+ * - Focus management (returns focus to trigger on close)
664
+ * - Optional custom trigger element
665
+ * - Menu item icons and disabled states
666
+ * - Dark mode support
667
+ * - Reduced motion support
668
+ *
669
+ * @example Basic usage
670
+ * ```tsx
671
+ * import { OverflowMenu } from '@appforgeapps/uiforge'
672
+ *
673
+ * <OverflowMenu
674
+ * items={[
675
+ * { id: 'edit', label: 'Edit' },
676
+ * { id: 'delete', label: 'Delete' },
677
+ * ]}
678
+ * onSelect={(item) => console.log('Selected:', item.id)}
679
+ * />
680
+ * ```
681
+ *
682
+ * @example With icons and disabled items
683
+ * ```tsx
684
+ * <OverflowMenu
685
+ * items={[
686
+ * { id: 'edit', label: 'Edit', icon: <EditIcon /> },
687
+ * { id: 'archive', label: 'Archive', icon: <ArchiveIcon />, disabled: true },
688
+ * { id: 'delete', label: 'Delete', icon: <DeleteIcon /> },
689
+ * ]}
690
+ * ariaLabel="Post actions"
691
+ * onSelect={handleAction}
692
+ * />
693
+ * ```
694
+ *
695
+ * @example With custom trigger
696
+ * ```tsx
697
+ * <OverflowMenu
698
+ * trigger={<IconButton icon={<MoreIcon />} ariaLabel="More options" />}
699
+ * items={menuItems}
700
+ * onSelect={handleSelect}
701
+ * />
702
+ * ```
703
+ */
704
+ export declare const OverflowMenu: default_2.FC<OverflowMenuProps>;
705
+
706
+ /**
707
+ * Represents a single item in the overflow menu
708
+ */
709
+ export declare interface OverflowMenuItem {
710
+ /**
711
+ * Unique identifier for this menu item
712
+ */
713
+ id: string;
714
+ /**
715
+ * Display label for this menu item
716
+ */
717
+ label: string;
718
+ /**
719
+ * Optional icon to display (can be a React node like an SVG icon)
720
+ */
721
+ icon?: default_2.ReactNode;
722
+ /**
723
+ * Whether this menu item is disabled
724
+ * @default false
725
+ */
726
+ disabled?: boolean;
727
+ /**
728
+ * Optional callback when this item is clicked.
729
+ * If not provided, the parent onSelect callback will be used.
730
+ */
731
+ onClick?: () => void;
732
+ }
733
+
734
+ /**
735
+ * Props for the OverflowMenu component
736
+ */
737
+ export declare interface OverflowMenuProps {
738
+ /**
739
+ * Array of menu items to display
740
+ */
741
+ items: OverflowMenuItem[];
742
+ /**
743
+ * Callback when a menu item is selected
744
+ */
745
+ onSelect?: (item: OverflowMenuItem) => void;
746
+ /**
747
+ * Accessible label for the trigger button
748
+ * @default 'More actions'
749
+ */
750
+ ariaLabel?: string;
751
+ /**
752
+ * Custom trigger element. If not provided, a default "..." button is rendered.
753
+ */
754
+ trigger?: default_2.ReactNode;
755
+ /**
756
+ * Alignment of the menu relative to the trigger button
757
+ * @default 'right'
758
+ */
759
+ align?: 'left' | 'right';
760
+ /**
761
+ * Whether the menu is disabled
762
+ * @default false
763
+ */
764
+ disabled?: boolean;
765
+ /**
766
+ * Size variant of the trigger button (when using default trigger)
767
+ * @default 'medium'
768
+ */
769
+ size?: 'small' | 'medium' | 'large';
770
+ /**
771
+ * Additional CSS class names for styling overrides
772
+ */
773
+ className?: string;
774
+ /**
775
+ * Test ID for the component
776
+ */
777
+ 'data-testid'?: string;
778
+ }
779
+
515
780
  export declare const PlanetIcon: default_2.FC<IconProps>;
516
781
 
517
782
  /**
@@ -531,6 +796,80 @@ export declare const RocketIcon: default_2.FC<IconProps>;
531
796
 
532
797
  export declare const RunningIcon: default_2.FC<IconProps>;
533
798
 
799
+ /**
800
+ * SafeAreaContainer - A container component that applies device safe area insets as padding.
801
+ *
802
+ * This component wraps content and automatically applies `env(safe-area-inset-*)` CSS values
803
+ * as padding to respect device safe areas such as iOS notches, status bars, and home indicators.
804
+ *
805
+ * Features:
806
+ * - Automatically applies safe area insets on all supported devices (iOS, Android)
807
+ * - Falls back gracefully to 0px on browsers that don't support `env()` function
808
+ * - Allows selective disabling of individual insets via props
809
+ * - Minimal CSS footprint with no JavaScript dependencies
810
+ * - Dark mode compatible
811
+ *
812
+ * @example Basic usage for a mobile header
813
+ * ```tsx
814
+ * import { SafeAreaContainer } from '@appforgeapps/uiforge'
815
+ *
816
+ * <SafeAreaContainer disableBottom>
817
+ * <header>My App Header</header>
818
+ * </SafeAreaContainer>
819
+ * ```
820
+ *
821
+ * @example Full-screen container with all safe areas
822
+ * ```tsx
823
+ * <SafeAreaContainer className="my-app-layout">
824
+ * <main>Content here is protected from notches and home indicators</main>
825
+ * </SafeAreaContainer>
826
+ * ```
827
+ *
828
+ * @example Header with only top inset
829
+ * ```tsx
830
+ * <SafeAreaContainer disableBottom disableLeft disableRight>
831
+ * <nav>Navigation bar</nav>
832
+ * </SafeAreaContainer>
833
+ * ```
834
+ */
835
+ export declare const SafeAreaContainer: default_2.FC<SafeAreaContainerProps>;
836
+
837
+ /**
838
+ * Props for the SafeAreaContainer component
839
+ */
840
+ export declare interface SafeAreaContainerProps extends default_2.HTMLAttributes<HTMLDivElement> {
841
+ /**
842
+ * The content to be wrapped with safe area insets.
843
+ */
844
+ children: default_2.ReactNode;
845
+ /**
846
+ * Disable the top safe area inset padding.
847
+ * Useful when a parent element already handles the top inset.
848
+ * @default false
849
+ */
850
+ disableTop?: boolean;
851
+ /**
852
+ * Disable the bottom safe area inset padding.
853
+ * Useful when you only need top inset for headers.
854
+ * @default false
855
+ */
856
+ disableBottom?: boolean;
857
+ /**
858
+ * Disable the left safe area inset padding.
859
+ * @default false
860
+ */
861
+ disableLeft?: boolean;
862
+ /**
863
+ * Disable the right safe area inset padding.
864
+ * @default false
865
+ */
866
+ disableRight?: boolean;
867
+ /**
868
+ * Additional CSS class names for styling overrides.
869
+ */
870
+ className?: string;
871
+ }
872
+
534
873
  export declare const SatelliteIcon: default_2.FC<IconProps>;
535
874
 
536
875
  export declare const ServerIcon: default_2.FC<IconProps>;