@carrier-dpx/air-react-library 0.6.0 → 0.7.0

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.
Files changed (69) hide show
  1. package/package.json +1 -1
  2. package/src/components/BottomNavigation/BottomNavigation.figma.tsx +54 -0
  3. package/src/components/BottomNavigation/BottomNavigation.tsx +45 -0
  4. package/src/components/BottomNavigation/BottomNavigationAction.figma.tsx +87 -0
  5. package/src/components/BottomNavigation/BottomNavigationAction.tsx +110 -0
  6. package/src/components/BottomNavigation/index.ts +7 -0
  7. package/src/components/Icon/ArrowLeftIcon.figma.tsx +18 -17
  8. package/src/components/Icon/ArrowRightIcon.figma.tsx +18 -17
  9. package/src/components/Icon/CheckIcon.figma.tsx +18 -17
  10. package/src/components/Icon/CloseIcon.figma.tsx +18 -17
  11. package/src/components/Icon/HomeIcon.figma.tsx +18 -17
  12. package/src/components/Icon/Icon.figma.tsx +68 -0
  13. package/src/components/Icon/InfoIcon.figma.tsx +18 -17
  14. package/src/components/Icon/MenuIcon.figma.tsx +18 -17
  15. package/src/components/Icon/SearchIcon.figma.tsx +18 -17
  16. package/src/components/Icon/SettingsIcon.figma.tsx +2 -2
  17. package/src/components/Icon/UserIcon.figma.tsx +18 -17
  18. package/src/components/Icon/icons/demo/AlertIcon.figma.tsx +28 -0
  19. package/src/components/Icon/icons/demo/AlertIcon.tsx +19 -0
  20. package/src/components/Icon/icons/demo/DEMO_USAGE.md +113 -0
  21. package/src/components/Icon/icons/demo/DeviceManagerIcon.figma.tsx +38 -0
  22. package/src/components/Icon/icons/demo/DeviceManagerIcon.tsx +16 -0
  23. package/src/components/Icon/icons/demo/HomeIcon.figma.tsx +28 -0
  24. package/src/components/Icon/icons/demo/HomeIcon.tsx +13 -0
  25. package/src/components/Icon/icons/demo/README.md +57 -0
  26. package/src/components/Icon/icons/demo/SiteIcon.figma.tsx +28 -0
  27. package/src/components/Icon/icons/demo/SiteIcon.tsx +13 -0
  28. package/src/components/Icon/icons/demo/SvgIcon.tsx +39 -0
  29. package/src/components/Icon/icons/demo/WarningIcon.figma.tsx +28 -0
  30. package/src/components/Icon/icons/demo/WarningIcon.tsx +15 -0
  31. package/src/components/Icon/icons/demo/devicemanager_outlined.svg +6 -0
  32. package/src/components/Icon/icons/demo/home_outlined.svg +3 -0
  33. package/src/components/Icon/icons/demo/iconRegistry.ts +97 -0
  34. package/src/components/Icon/icons/demo/index.ts +23 -0
  35. package/src/components/Icon/icons/demo/site_outlined.svg +3 -0
  36. package/src/components/Icon/icons/demo/warning_outlined.svg +5 -0
  37. package/src/components/Navbar/ExtraNavigation/ExtraNavigation.tsx +86 -0
  38. package/src/components/Navbar/ExtraNavigation/index.ts +2 -0
  39. package/src/components/Navbar/ExtraNavigation/styles.tsx +10 -0
  40. package/src/components/Navbar/ExtraNavigation/types.ts +43 -0
  41. package/src/components/Navbar/Navbar.figma.tsx +118 -0
  42. package/src/components/Navbar/Navbar.tsx +110 -0
  43. package/src/components/Navbar/NavbarButtons/Item.figma.tsx +117 -0
  44. package/src/components/Navbar/NavbarButtons/NavbarFooterButton.tsx +57 -0
  45. package/src/components/Navbar/NavbarButtons/NavbarTooltip.tsx +56 -0
  46. package/src/components/Navbar/NavbarButtons/NavigationButton.tsx +98 -0
  47. package/src/components/Navbar/NavbarButtons/index.ts +3 -0
  48. package/src/components/Navbar/NavbarButtons/styles.tsx +112 -0
  49. package/src/components/Navbar/NavbarButtons/types.ts +8 -0
  50. package/src/components/Navbar/NavbarFooter/NavbarFooter.tsx +40 -0
  51. package/src/components/Navbar/NavbarFooter/index.ts +2 -0
  52. package/src/components/Navbar/NavbarFooter/styles.tsx +14 -0
  53. package/src/components/Navbar/NavbarFooter/types.ts +15 -0
  54. package/src/components/Navbar/NavbarLogo/NavbarLogo.tsx +45 -0
  55. package/src/components/Navbar/NavbarLogo/index.ts +2 -0
  56. package/src/components/Navbar/NavbarLogo/styles.ts +18 -0
  57. package/src/components/Navbar/NavbarLogo/types.ts +18 -0
  58. package/src/components/Navbar/NavbarProvider.tsx +15 -0
  59. package/src/components/Navbar/Navigation/Navigation.tsx +113 -0
  60. package/src/components/Navbar/Navigation/helpers.ts +9 -0
  61. package/src/components/Navbar/Navigation/index.ts +2 -0
  62. package/src/components/Navbar/Navigation/styles.tsx +10 -0
  63. package/src/components/Navbar/Navigation/types.ts +68 -0
  64. package/src/components/Navbar/constants.ts +45 -0
  65. package/src/components/Navbar/hooks/useNavbarContext.tsx +12 -0
  66. package/src/components/Navbar/index.tsx +7 -0
  67. package/src/components/Navbar/styles.tsx +44 -0
  68. package/src/components/Navbar/types.ts +67 -0
  69. package/src/index.ts +6 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Icon Registry
3
+ *
4
+ * Maps icon names to their SVG content.
5
+ * This allows us to render icons without creating individual React components.
6
+ *
7
+ * For 700 icons, you would generate this file programmatically from your SVG folder.
8
+ */
9
+
10
+ import { FC } from "react";
11
+
12
+ // Import SVG content as strings or React components
13
+ // Note: Your build system needs to support SVG imports
14
+ // If not, you can inline the SVG content here or use a loader
15
+
16
+ // For now, we'll create simple components inline
17
+ // In production, you'd generate these from SVG files
18
+
19
+ const DeviceManagerSvg: FC<React.SVGProps<SVGSVGElement>> = (props) => (
20
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
21
+ <path d="M2.49805 18.041C3.75805 18.2505 4.74948 19.2419 4.95898 20.502C5.00427 20.7744 4.77614 21 4.5 21H3C2.44772 21 2 20.5523 2 20V18.5C2 18.2239 2.22564 17.9957 2.49805 18.041Z" fill="currentColor"/>
22
+ <path d="M2.5 14.0176C5.97085 14.2618 8.73818 17.0292 8.98242 20.5C9.00176 20.7754 8.77612 21 8.5 21H7.5C7.22396 21 7.003 20.7756 6.97559 20.501C6.7411 18.1393 4.86065 16.2589 2.49902 16.0244C2.22437 15.997 2 15.776 2 15.5V14.5C2 14.2239 2.22457 13.9982 2.5 14.0176Z" fill="currentColor"/>
23
+ <path d="M2.5 10.0107C8.17278 10.2648 12.7351 14.8187 12.9893 20.5C13.0015 20.7758 12.7761 21 12.5 21H11.5C11.2239 21 11.0014 20.7757 10.9863 20.5C10.7359 15.928 7.07198 12.2641 2.5 12.0137C2.22427 11.9986 2 11.7761 2 11.5V10.5C2 10.2239 2.22424 9.99852 2.5 10.0107Z" fill="currentColor"/>
24
+ <path d="M9.09863 3.00488C9.32763 3.02757 9.54289 3.12883 9.70703 3.29297L11.4141 5H19C20.6569 5 22 6.34315 22 8V19.5C22 20.3284 21.3284 21 20.5 21H16C15.4477 21 15 20.5523 15 20C15 19.4477 15.4477 19 16 19H20V8C20 7.44772 19.5523 7 19 7H11C10.7348 7 10.4805 6.89457 10.293 6.70703L8.58594 5H4V7C4 7.55228 3.55228 8 3 8C2.44772 8 2 7.55228 2 7V4.5C2 3.67157 2.67157 3 3.5 3H9L9.09863 3.00488Z" fill="currentColor"/>
25
+ </svg>
26
+ );
27
+
28
+ const HomeSvg: FC<React.SVGProps<SVGSVGElement>> = (props) => (
29
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
30
+ <path fillRule="evenodd" clipRule="evenodd" d="M11.4775 2.33597C11.7769 2.25498 12.0907 2.24493 12.3936 2.3057L12.5225 2.33597L12.6826 2.38871C13.0467 2.52881 13.3532 2.7853 13.5967 2.97464L20.3789 8.25003C20.7873 8.56768 21.1481 8.83746 21.4121 9.19437C21.6289 9.48753 21.7903 9.81791 21.8887 10.169C21.9784 10.4897 21.9967 10.8234 22 11.1885V17.7998C22 18.3431 22.001 18.8108 21.9697 19.1944C21.9374 19.5896 21.8655 19.9831 21.6729 20.3614C21.3853 20.9257 20.9266 21.3853 20.3623 21.6729C19.9841 21.8656 19.5905 21.9365 19.1953 21.9688C18.8117 22.0001 18.3432 22 17.7998 22H6.2002C5.65675 22 5.18831 22.0001 4.80469 21.9688C4.40952 21.9365 4.01591 21.8656 3.6377 21.6729C3.07338 21.3853 2.61471 20.9257 2.32715 20.3614C2.1345 19.9831 2.06257 19.5896 2.03027 19.1944C2.01464 19.0028 2.00763 18.7901 2.00391 18.5577L2 17.7998V11.1885C2.00325 10.8234 2.02155 10.4897 2.11133 10.169C2.20966 9.81791 2.37114 9.48752 2.58789 9.19437C2.8519 8.83747 3.21269 8.56768 3.62109 8.25003L10.4033 2.97464C10.6816 2.75819 11.0423 2.45384 11.4775 2.33597ZM11.9932 4.28128C11.9181 4.33146 11.8184 4.40766 11.6318 4.55277L4.84961 9.82816C4.35264 10.2147 4.25877 10.2985 4.19629 10.3828C4.12408 10.4805 4.0699 10.5911 4.03711 10.708C4.0088 10.8092 4 10.934 4 11.5645V17.7998L4.00293 18.5254C4.00602 18.7261 4.01284 18.8905 4.02441 19.0323C4.0466 19.3034 4.0842 19.4047 4.10938 19.4541C4.20522 19.642 4.35802 19.7949 4.5459 19.8907C4.59536 19.9158 4.69642 19.9534 4.96777 19.9756C5.25108 19.9988 5.62379 20 6.2002 20H8V14.5996C8 14.3362 7.99889 14.0782 8.0166 13.8614C8.03529 13.6329 8.0796 13.3631 8.21777 13.0918C8.40947 12.7157 8.71564 12.4095 9.0918 12.2178C9.36296 12.0797 9.63289 12.0353 9.86133 12.0166C10.0781 11.9989 10.3363 12 10.5996 12H13.4004C13.6637 12 13.9219 11.9989 14.1387 12.0166C14.3671 12.0353 14.637 12.0797 14.9082 12.2178C15.2374 12.3856 15.513 12.6409 15.7051 12.9541L15.7822 13.0918L15.8691 13.294C15.9408 13.4951 15.9694 13.6899 15.9834 13.8614C16.0011 14.0782 16 14.3362 16 14.5996V20H17.7998C18.3762 20 18.7489 19.9988 19.0322 19.9756C19.3036 19.9534 19.4046 19.9158 19.4541 19.8907C19.642 19.7949 19.7948 19.642 19.8906 19.4541C19.9158 19.4047 19.9534 19.3034 19.9756 19.0323C19.9987 18.749 20 18.3762 20 17.7998V11.5645C20 10.934 19.9912 10.8092 19.9629 10.708C19.9301 10.5911 19.8759 10.4805 19.8037 10.3828C19.7412 10.2985 19.6474 10.2147 19.1504 9.82816L12.3682 4.55277C12.1816 4.40765 12.0819 4.33146 12.0068 4.28128C12.0045 4.27969 12.0022 4.27783 12 4.2764C11.9978 4.27783 11.9955 4.2797 11.9932 4.28128ZM10.5996 14C10.3035 14 10.1409 14.0003 10.0244 14.0098C10.0201 14.0102 10.0156 14.0104 10.0117 14.0108C10.0113 14.015 10.0111 14.0197 10.0107 14.0244C10.0012 14.141 10 14.3033 10 14.5996V20H14V14.5996C14 14.3033 13.9988 14.141 13.9893 14.0244C13.9889 14.0197 13.9877 14.015 13.9873 14.0108C13.9837 14.0104 13.9796 14.0101 13.9756 14.0098C13.8591 14.0003 13.6965 14 13.4004 14H10.5996Z" fill="currentColor"/>
31
+ </svg>
32
+ );
33
+
34
+ const SiteSvg: FC<React.SVGProps<SVGSVGElement>> = (props) => (
35
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
36
+ <path fillRule="evenodd" clipRule="evenodd" d="M15.7559 3.97363C16.3079 3.97385 16.7558 4.42155 16.7559 4.97363V6.60352H21.0391C21.5911 6.60367 22.0389 7.05143 22.0391 7.60352V15.3965H22.3721C22.9242 15.3966 23.372 15.8444 23.3721 16.3965C23.3719 16.9485 22.9241 17.3964 22.3721 17.3965H16.7559V19.0264H17.3379C17.89 19.0265 18.3378 19.4742 18.3379 20.0264C18.3377 20.5784 17.89 21.0262 17.3379 21.0264H6.66211C6.11002 21.0263 5.66227 20.5784 5.66211 20.0264C5.66219 19.4742 6.10996 19.0265 6.66211 19.0264H7.24512V17.3965H1.62793C1.07577 17.3965 0.628127 16.9486 0.62793 16.3965C0.628012 15.8443 1.0757 15.3965 1.62793 15.3965H1.96191V7.60352C1.96203 7.05133 2.4097 6.60352 2.96191 6.60352H7.24512V4.97363C7.2452 4.42142 7.69288 3.97363 8.24512 3.97363H15.7559ZM9.24512 19.0225H14.7559V5.97363H9.24512V19.0225ZM3.96191 15.3877H7.16211V8.60352H3.96191V15.3877ZM16.8379 15.3877H20.0391V8.60352H16.8379V15.3877Z" fill="currentColor"/>
37
+ </svg>
38
+ );
39
+
40
+ const WarningSvg: FC<React.SVGProps<SVGSVGElement>> = (props) => (
41
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
42
+ <path d="M12 16C12.2833 16 12.5212 16.0954 12.7129 16.2871C12.9046 16.4788 13 16.7167 13 17C13 17.2833 12.9046 17.5212 12.7129 17.7129C12.5212 17.9046 12.2833 18 12 18C11.7167 18 11.4788 17.9045 11.2871 17.7129C11.0955 17.5212 11 17.2833 11 17C11 16.7167 11.0955 16.4788 11.2871 16.2871C11.4788 16.0955 11.7167 16 12 16Z" fill="currentColor"/>
43
+ <path d="M12 10C12.2833 10 12.5212 10.0954 12.7129 10.2871C12.9046 10.4788 13 10.7167 13 11V14C13 14.2833 12.9046 14.5212 12.7129 14.7129C12.5212 14.9046 12.2833 15 12 15C11.7167 15 11.4788 14.9045 11.2871 14.7129C11.0955 14.5212 11 14.2833 11 14V11C11 10.7167 11.0955 10.4788 11.2871 10.2871C11.4788 10.0955 11.7167 10 12 10Z" fill="currentColor"/>
44
+ <path fillRule="evenodd" clipRule="evenodd" d="M12 3C12.1666 3 12.329 3.04172 12.4873 3.125C12.6456 3.20833 12.775 3.33334 12.875 3.5L22.125 19.5C22.225 19.6667 22.271 19.8377 22.2627 20.0127C22.2544 20.1876 22.2083 20.3501 22.125 20.5C22.0417 20.6499 21.9252 20.7707 21.7754 20.8623C21.6255 20.9539 21.4586 20.9999 21.2754 21H2.72462C2.54144 20.9999 2.37452 20.9539 2.22462 20.8623C2.0748 20.7707 1.95828 20.6499 1.87501 20.5C1.79171 20.3501 1.74567 20.1876 1.73732 20.0127C1.72898 19.8377 1.77501 19.6667 1.87501 19.5L11.125 3.5C11.225 3.33334 11.3544 3.20833 11.5127 3.125C11.671 3.04173 11.8334 3 12 3ZM4.45021 19H19.5498L12 6L4.45021 19Z" fill="currentColor"/>
45
+ </svg>
46
+ );
47
+
48
+ // AlertIcon uses the same SVG as WarningIcon
49
+ const AlertSvg = WarningSvg;
50
+
51
+ export interface IconInfo {
52
+ name: string;
53
+ component: FC<React.SVGProps<SVGSVGElement>>;
54
+ variant?: "outlined" | "filled";
55
+ }
56
+
57
+ export const iconRegistry: Record<string, IconInfo> = {
58
+ devicemanager: {
59
+ name: "devicemanager",
60
+ component: DeviceManagerSvg,
61
+ variant: "outlined",
62
+ },
63
+ home: {
64
+ name: "home",
65
+ component: HomeSvg,
66
+ variant: "outlined",
67
+ },
68
+ site: {
69
+ name: "site",
70
+ component: SiteSvg,
71
+ variant: "outlined",
72
+ },
73
+ warning: {
74
+ name: "warning",
75
+ component: WarningSvg,
76
+ variant: "outlined",
77
+ },
78
+ alert: {
79
+ name: "alert",
80
+ component: AlertSvg,
81
+ variant: "outlined",
82
+ },
83
+ };
84
+
85
+ /**
86
+ * Get an icon component by name
87
+ */
88
+ export const getIcon = (name: string): IconInfo | undefined => {
89
+ return iconRegistry[name.toLowerCase()];
90
+ };
91
+
92
+ /**
93
+ * Get all available icon names
94
+ */
95
+ export const getIconNames = (): string[] => {
96
+ return Object.keys(iconRegistry);
97
+ };
@@ -0,0 +1,23 @@
1
+ // Generic SvgIcon component - use this for dynamic icon loading
2
+ export { SvgIcon } from "./SvgIcon";
3
+ export type { SvgIconProps } from "./SvgIcon";
4
+
5
+ // Icon registry for programmatic access
6
+ export { iconRegistry, getIcon, getIconNames } from "./iconRegistry";
7
+ export type { IconInfo } from "./iconRegistry";
8
+
9
+ // Individual icon components (for Figma Code Connect or direct usage)
10
+ export { DeviceManagerIcon } from "./DeviceManagerIcon";
11
+ export type { DeviceManagerIconProps } from "./DeviceManagerIcon";
12
+
13
+ export { HomeIcon } from "./HomeIcon";
14
+ export type { HomeIconProps } from "./HomeIcon";
15
+
16
+ export { SiteIcon } from "./SiteIcon";
17
+ export type { SiteIconProps } from "./SiteIcon";
18
+
19
+ export { WarningIcon } from "./WarningIcon";
20
+ export type { WarningIconProps } from "./WarningIcon";
21
+
22
+ export { AlertIcon } from "./AlertIcon";
23
+ export type { AlertIconProps } from "./AlertIcon";
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M15.7559 3.97363C16.3079 3.97385 16.7558 4.42155 16.7559 4.97363V6.60352H21.0391C21.5911 6.60367 22.0389 7.05143 22.0391 7.60352V15.3965H22.3721C22.9242 15.3966 23.372 15.8444 23.3721 16.3965C23.3719 16.9485 22.9241 17.3964 22.3721 17.3965H16.7559V19.0264H17.3379C17.89 19.0265 18.3378 19.4742 18.3379 20.0264C18.3377 20.5784 17.89 21.0262 17.3379 21.0264H6.66211C6.11002 21.0263 5.66227 20.5784 5.66211 20.0264C5.66219 19.4742 6.10996 19.0265 6.66211 19.0264H7.24512V17.3965H1.62793C1.07577 17.3965 0.628127 16.9486 0.62793 16.3965C0.628012 15.8443 1.0757 15.3965 1.62793 15.3965H1.96191V7.60352C1.96203 7.05133 2.4097 6.60352 2.96191 6.60352H7.24512V4.97363C7.2452 4.42142 7.69288 3.97363 8.24512 3.97363H15.7559ZM9.24512 19.0225H14.7559V5.97363H9.24512V19.0225ZM3.96191 15.3877H7.16211V8.60352H3.96191V15.3877ZM16.8379 15.3877H20.0391V8.60352H16.8379V15.3877Z" fill="black"/>
3
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12 16C12.2833 16 12.5212 16.0954 12.7129 16.2871C12.9046 16.4788 13 16.7167 13 17C13 17.2833 12.9046 17.5212 12.7129 17.7129C12.5212 17.9046 12.2833 18 12 18C11.7167 18 11.4788 17.9045 11.2871 17.7129C11.0955 17.5212 11 17.2833 11 17C11 16.7167 11.0955 16.4788 11.2871 16.2871C11.4788 16.0955 11.7167 16 12 16Z" fill="black"/>
3
+ <path d="M12 10C12.2833 10 12.5212 10.0954 12.7129 10.2871C12.9046 10.4788 13 10.7167 13 11V14C13 14.2833 12.9046 14.5212 12.7129 14.7129C12.5212 14.9046 12.2833 15 12 15C11.7167 15 11.4788 14.9045 11.2871 14.7129C11.0955 14.5212 11 14.2833 11 14V11C11 10.7167 11.0955 10.4788 11.2871 10.2871C11.4788 10.0955 11.7167 10 12 10Z" fill="black"/>
4
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M12 3C12.1666 3 12.329 3.04172 12.4873 3.125C12.6456 3.20833 12.775 3.33334 12.875 3.5L22.125 19.5C22.225 19.6667 22.271 19.8377 22.2627 20.0127C22.2544 20.1876 22.2083 20.3501 22.125 20.5C22.0417 20.6499 21.9252 20.7707 21.7754 20.8623C21.6255 20.9539 21.4586 20.9999 21.2754 21H2.72462C2.54144 20.9999 2.37452 20.9539 2.22462 20.8623C2.0748 20.7707 1.95828 20.6499 1.87501 20.5C1.79171 20.3501 1.74567 20.1876 1.73732 20.0127C1.72898 19.8377 1.77501 19.6667 1.87501 19.5L11.125 3.5C11.225 3.33334 11.3544 3.20833 11.5127 3.125C11.671 3.04173 11.8334 3 12 3ZM4.45021 19H19.5498L12 6L4.45021 19Z" fill="black"/>
5
+ </svg>
@@ -0,0 +1,86 @@
1
+ import { FC } from "react";
2
+ import { styled } from "@mui/material/styles";
3
+ import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
4
+ import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
5
+ import { useNavbarContext } from "../hooks/useNavbarContext";
6
+ import btnStyles from "../NavbarButtons/styles";
7
+ import extraNavigationStyles from "./styles";
8
+ import { ExtraNavigationProps } from "./types";
9
+ import Button from "../../Button";
10
+ import Box from "../../Box";
11
+ import { NavigationButton } from "../NavbarButtons";
12
+ import { NavbarButtonClasses } from "../NavbarButtons/types";
13
+ import Divider from "../../Divider";
14
+ import { NavigationItemType } from "../Navigation";
15
+
16
+ /**
17
+ * The ExtraNavigation component allows adding extra navigation buttons.
18
+ *
19
+ * //Named Import
20
+ * `import { ExtraNavigation } from '@carrier-io/air-react'`
21
+ */
22
+
23
+ const ButtonStyled = styled(Button)(btnStyles[NavbarButtonClasses.NavbarBtn]);
24
+ const ContainerStyled = styled(Box)(extraNavigationStyles.container);
25
+
26
+ export const ExtraNavigation: FC<ExtraNavigationProps> = ({
27
+ items,
28
+ disableTooltip = false,
29
+ expanded = false,
30
+ onClickExpanded,
31
+ disableRipple = false,
32
+ disableTouchRipple = false,
33
+ ...rest
34
+ }) => {
35
+ const { openedDrawer } = useNavbarContext();
36
+
37
+ return (
38
+ <ContainerStyled {...rest}>
39
+ {items?.length > 0 && (
40
+ <>
41
+ <ButtonStyled
42
+ variant="text"
43
+ onClick={() => onClickExpanded?.()}
44
+ disableRipple={disableRipple}
45
+ disableTouchRipple={disableTouchRipple}
46
+ >
47
+ {expanded ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
48
+ &nbsp; External Apps
49
+ </ButtonStyled>
50
+ {expanded &&
51
+ items?.map((item, idx) => {
52
+ if (item.type === "DIVIDER") {
53
+ return (
54
+ <Divider
55
+ key={`divider_${idx.toString()}`}
56
+ sx={{ margin: "9px 0" }}
57
+ >
58
+ {item.children}
59
+ </Divider>
60
+ );
61
+ }
62
+
63
+ const { id, icon, label } = item as NavigationItemType;
64
+
65
+ return (
66
+ <NavigationButton
67
+ key={id}
68
+ data={{
69
+ id,
70
+ label,
71
+ }}
72
+ onClick={() => item.onClick?.()}
73
+ disableTooltip={disableTooltip}
74
+ disableRipple={disableRipple}
75
+ disableTouchRipple={disableTouchRipple}
76
+ withOffset={openedDrawer}
77
+ >
78
+ {icon}
79
+ </NavigationButton>
80
+ );
81
+ })}
82
+ </>
83
+ )}
84
+ </ContainerStyled>
85
+ );
86
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./ExtraNavigation";
2
+ export * from "./types";
@@ -0,0 +1,10 @@
1
+ import { CSSObject } from "@mui/material";
2
+
3
+ export default {
4
+ container: {
5
+ display: "flex",
6
+ flexDirection: "column",
7
+ },
8
+ } as {
9
+ [key in "container"]: CSSObject;
10
+ };
@@ -0,0 +1,43 @@
1
+ import { NavigationDividerType, NavigationItemType } from "../Navigation";
2
+ import { BoxProps } from "../../Box";
3
+
4
+ export interface ExtraNavigationProps
5
+ extends Pick<BoxProps, "children" | "sx"> {
6
+ /**
7
+ * Extra navigation elements.
8
+ */
9
+ items: ExtraNavigationItem[];
10
+ /**
11
+ * Show all items.
12
+ * @default false
13
+ */
14
+ expanded?: boolean;
15
+ /**
16
+ * Callback fired when expand button is clicked.
17
+ */
18
+ onClickExpanded?: () => void;
19
+ /**
20
+ * Allow show tooltip.
21
+ * @default false
22
+ */
23
+ disableTooltip?: boolean;
24
+ /**
25
+ * Allow ripple effect.
26
+ * @default false
27
+ */
28
+ disableRipple?: boolean;
29
+ /**
30
+ * Allow ripple touch effect.
31
+ * @default false
32
+ */
33
+ disableTouchRipple?: boolean;
34
+ }
35
+
36
+ export interface ExtraNavigationItemType
37
+ extends Omit<NavigationItemType, "path"> {
38
+ onClick?: () => void;
39
+ }
40
+
41
+ export type ExtraNavigationItem =
42
+ | ExtraNavigationItemType
43
+ | NavigationDividerType;
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Navbar Component
3
+ *
4
+ * This connects Figma's Navbar component to the React Navbar component.
5
+ *
6
+ * Figma URL: https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=37601-412630
7
+ *
8
+ * Figma Properties:
9
+ * - expanded (true, false) - Controls drawer expanded state → disableHoverListener (inverted)
10
+ * When expanded=false, drawer is locked (disableHoverListener=true)
11
+ * When expanded=true, drawer can expand on hover (disableHoverListener=false)
12
+ * - activeButtonType (basic, indicator) - Active button style type → Navigation.activeButtonType
13
+ * - background (true, false) - Show/hide background layer → transparentBackground (inverted)
14
+ * - logo (true, false) - Show/hide logo layer → controls Navbar.Logo visibility
15
+ * - carrierLogo (true, false) - Show/hide carrierLogo layer → NavbarFooter.showCarrierLogo
16
+ * - helpButton (true, false) - Show/hide helpButton layer → controls help button visibility
17
+ * - border (true, false) - Show/hide border → border
18
+ *
19
+ * Note: Navigation items are nested "Item" component instances that map to Navigation.items array
20
+ */
21
+
22
+ import figma from "@figma/code-connect";
23
+ import { Navbar } from "./Navbar";
24
+ import { Navigation } from "./Navigation";
25
+ import { NavbarFooter } from "./NavbarFooter";
26
+ import { NavbarLogo } from "./NavbarLogo";
27
+
28
+ figma.connect(
29
+ Navbar,
30
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=37601-412630",
31
+ {
32
+ props: {
33
+ /**
34
+ * EXPANDED STATE → DISABLE HOVER LISTENER
35
+ * Maps Figma's "expanded" property to React's disableHoverListener prop (inverted)
36
+ * Figma: expanded=false means drawer is collapsed/locked
37
+ * React: disableHoverListener=true means drawer cannot expand on hover
38
+ * So we invert: expanded=false → disableHoverListener=true
39
+ */
40
+ expanded: figma.boolean("expanded"),
41
+
42
+ /**
43
+ * BACKGROUND VISIBILITY
44
+ * Maps Figma's "background" boolean to React's transparentBackground prop
45
+ * Figma: background=true means background is visible (not transparent)
46
+ * React: transparentBackground=true means background is transparent
47
+ * So we invert: background=false → transparentBackground=true
48
+ */
49
+ background: figma.boolean("background"),
50
+
51
+ /**
52
+ * BORDER
53
+ * Maps Figma's "border" boolean to React's border prop
54
+ */
55
+ border: figma.boolean("border"),
56
+
57
+ /**
58
+ * ACTIVE BUTTON TYPE
59
+ * Maps Figma's "activeButtonType" property - passed to Navigation component
60
+ */
61
+ activeButtonType: figma.enum("activeButtonType", {
62
+ basic: "basic",
63
+ indicator: "indicator",
64
+ }),
65
+
66
+ /**
67
+ * LOGO VISIBILITY
68
+ * Maps Figma's "logo" boolean - controls NavbarLogo visibility
69
+ */
70
+ logo: figma.boolean("logo"),
71
+
72
+ /**
73
+ * CARRIER LOGO VISIBILITY
74
+ * Maps Figma's "carrierLogo" boolean - passed to NavbarFooter.showCarrierLogo
75
+ */
76
+ carrierLogo: figma.boolean("carrierLogo"),
77
+
78
+ /**
79
+ * HELP BUTTON VISIBILITY
80
+ * Maps Figma's "helpButton" boolean - controls help button visibility
81
+ */
82
+ helpButton: figma.boolean("helpButton"),
83
+ },
84
+ /**
85
+ * EXAMPLE CODE TEMPLATE
86
+ * Shows how the Navbar component should be used in React code
87
+ * Composes Navbar.Logo, Navbar.Navigation, and Navbar.Footer as children
88
+ */
89
+ example: ({ expanded, activeButtonType, background, border, logo, carrierLogo }) => {
90
+ // Invert expanded: Figma expanded=false → React disableHoverListener=true
91
+ const disableHoverListener = !expanded;
92
+
93
+ // Invert background: Figma background=true → React transparentBackground=false
94
+ const transparentBackground = !background;
95
+
96
+ return (
97
+ <Navbar
98
+ disableHoverListener={disableHoverListener}
99
+ transparentBackground={transparentBackground}
100
+ border={border}
101
+ >
102
+ <NavbarLogo label="Logo">
103
+ {/* Logo content - conditionally rendered based on logo prop */}
104
+ </NavbarLogo>
105
+ <Navigation
106
+ activeButtonType={activeButtonType}
107
+ currentPathname="/"
108
+ items={[]}
109
+ onClick={() => {}}
110
+ />
111
+ <NavbarFooter showCarrierLogo={carrierLogo}>
112
+ {/* Footer content */}
113
+ </NavbarFooter>
114
+ </Navbar>
115
+ );
116
+ },
117
+ }
118
+ );
@@ -0,0 +1,110 @@
1
+ import { useState, useEffect } from "react";
2
+ import clsx from "clsx";
3
+ import { styled } from "@mui/material/styles";
4
+ import { NavbarProps } from "./types";
5
+ import styles from "./styles";
6
+ import Box from "../Box";
7
+ import { NavbarProvider } from "./NavbarProvider";
8
+ import { NavbarLogo } from "./NavbarLogo";
9
+ import { Navigation } from "./Navigation";
10
+ import { ExtraNavigation } from "./ExtraNavigation";
11
+ import { NavbarFooter } from "./NavbarFooter";
12
+ import { NavbarFooterButton, NavigationButton } from "./NavbarButtons";
13
+ import {
14
+ navSetWideMode,
15
+ navSetMaxWidthPx,
16
+ navSetChildHeightPx,
17
+ navSetBackgroundTransparent,
18
+ navSetChildMarginPx,
19
+ navSetBorder,
20
+ } from "./constants";
21
+ import { CSSObject } from "@mui/material";
22
+ import { getSxStyles } from "../utils/styles";
23
+
24
+ const NavbarContainerStyled = styled(Box)(styles.container);
25
+
26
+ /** The NavBar pattern is a collapsible surface containing supplementary content or actions that is anchored to the edge of the screen.
27
+ * //Named Import
28
+ * `import { Navbar } from '@carrier-io/air-react'`
29
+ */
30
+ export const Navbar = ({
31
+ disableHoverListener = true,
32
+ onDrawerSizeChanged,
33
+ children,
34
+ heightOffset = 0,
35
+ tooltipProps,
36
+ wideMode,
37
+ transparentBackground,
38
+ childMargin,
39
+ childHeight,
40
+ maxOpenWidth,
41
+ border = true,
42
+ sx,
43
+ ...rest
44
+ }: NavbarProps) => {
45
+ const [openedDrawer, setOpenedDrawer] = useState<boolean>(false);
46
+ const [update, setUpdate] = useState<boolean>(false);
47
+
48
+ const handleOpenDrawer = (): void => {
49
+ if (!disableHoverListener) {
50
+ setOpenedDrawer(!openedDrawer);
51
+ if (onDrawerSizeChanged) {
52
+ onDrawerSizeChanged(!openedDrawer);
53
+ }
54
+ }
55
+ };
56
+
57
+ //This sets the override flag for getting the correct values out of nav constants
58
+ useEffect(() => {
59
+ navSetWideMode(wideMode ?? false);
60
+ setUpdate(!update);
61
+ }, [wideMode]);
62
+ useEffect(() => {
63
+ navSetBackgroundTransparent(!!transparentBackground);
64
+ setUpdate(!update);
65
+ }, [transparentBackground]);
66
+ useEffect(() => {
67
+ if (!!childMargin) navSetChildMarginPx(childMargin);
68
+ setUpdate(!update);
69
+ }, [childMargin]);
70
+ useEffect(() => {
71
+ if (!!childHeight) navSetChildHeightPx(childHeight);
72
+ setUpdate(!update);
73
+ }, [childHeight]);
74
+ useEffect(() => {
75
+ if (!!maxOpenWidth) navSetMaxWidthPx(maxOpenWidth);
76
+ setUpdate(!update);
77
+ }, [maxOpenWidth]);
78
+ useEffect(() => {
79
+ navSetBorder(!!border);
80
+ setUpdate(!update);
81
+ }, [border]);
82
+
83
+ return (
84
+ <NavbarProvider value={{ openedDrawer, tooltipProps }}>
85
+ <NavbarContainerStyled
86
+ {...rest}
87
+ className={clsx({
88
+ opened: openedDrawer,
89
+ })}
90
+ sx={(theme) =>
91
+ ({
92
+ ...getSxStyles(theme, sx),
93
+ height: "calc(100% - " + heightOffset + "px)",
94
+ } as CSSObject)
95
+ }
96
+ onMouseEnter={() => !openedDrawer && handleOpenDrawer()}
97
+ onMouseLeave={() => openedDrawer && handleOpenDrawer()}
98
+ >
99
+ {children && <Box sx={{ width: "100%" }}>{children}</Box>}
100
+ </NavbarContainerStyled>
101
+ </NavbarProvider>
102
+ );
103
+ };
104
+
105
+ Navbar.Logo = NavbarLogo;
106
+ Navbar.Navigation = Navigation;
107
+ Navbar.ExtraNavigation = ExtraNavigation;
108
+ Navbar.Footer = NavbarFooter;
109
+ Navbar.NavButton = NavigationButton;
110
+ Navbar.NavFooterButton = NavbarFooterButton;
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Navbar Item Component
3
+ *
4
+ * This connects Figma's "Item" component to the React NavigationButton component.
5
+ * Items are used within the Navbar Navigation component.
6
+ *
7
+ * Figma URL: https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=37601-412122
8
+ *
9
+ * Figma Properties:
10
+ * - activeButtonType (basic, indicator) → NavigationButton.activeButtonType
11
+ * - expanded (true, false) → Visual state (Navbar expands on hover by default)
12
+ * - selected (true, false) → NavigationButton.active
13
+ * - disabled (true, false) → NavigationButton.disabled
14
+ * - state (enabled, hover, focus) → Visual state (not a prop)
15
+ * - invertIndicator (true, false) → May affect styling
16
+ * - tooltip (true, false) → NavigationButton.disableTooltip (inverted)
17
+ * - divider (true, false) → If true, renders Divider component below Item
18
+ *
19
+ * Structure:
20
+ * - Label layer: Contains the text label
21
+ * - Icon: Nested within UnstyledButton component, swapped via Icon component instance
22
+ */
23
+
24
+ import figma from "@figma/code-connect";
25
+ import { NavigationButton } from "./NavigationButton";
26
+ import Divider from "../../Divider";
27
+
28
+ figma.connect(
29
+ NavigationButton,
30
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=37601-412122",
31
+ {
32
+ props: {
33
+ /**
34
+ * ACTIVE BUTTON TYPE
35
+ * Maps Figma's "activeButtonType" property to NavigationButton.activeButtonType
36
+ */
37
+ activeButtonType: figma.enum("activeButtonType", {
38
+ basic: "basic",
39
+ indicator: "indicator",
40
+ }),
41
+
42
+ /**
43
+ * SELECTED STATE
44
+ * Maps Figma's "selected" boolean to NavigationButton.active prop
45
+ */
46
+ active: figma.boolean("selected"),
47
+
48
+ /**
49
+ * DISABLED STATE
50
+ * Maps Figma's "disabled" boolean to NavigationButton.disabled prop
51
+ */
52
+ disabled: figma.boolean("disabled"),
53
+
54
+ /**
55
+ * TOOLTIP VISIBILITY
56
+ * Maps Figma's "tooltip" boolean to NavigationButton.disableTooltip (inverted)
57
+ * Figma: tooltip=true means tooltip is visible
58
+ * React: disableTooltip=true means tooltip is disabled
59
+ */
60
+ tooltip: figma.boolean("tooltip"),
61
+
62
+ /**
63
+ * DIVIDER FLAG
64
+ * Maps Figma's "divider" boolean - if true, renders Divider below
65
+ */
66
+ divider: figma.boolean("divider"),
67
+
68
+ /**
69
+ * LABEL TEXT
70
+ * Maps text property "✏️ Label" from Item component
71
+ */
72
+ label: figma.string("✏️ Label"),
73
+
74
+ /**
75
+ * ITEM ID
76
+ * Maps text property "🆔 ID" from Item component
77
+ */
78
+ id: figma.string("🆔 ID"),
79
+
80
+ /**
81
+ * ICON
82
+ * Maps Icon component instance from Item component
83
+ * Since Icon component properties are surfaced to Item, the instance swap property
84
+ * should be named after the component ("Icon"), not the layer name ("Start Icon")
85
+ */
86
+ children: figma.instance("Icon"),
87
+ },
88
+ /**
89
+ * EXAMPLE CODE TEMPLATE
90
+ * Shows how NavigationButton should be used
91
+ * If divider=true, renders Divider component below the NavigationButton
92
+ *
93
+ * NOTE: Instance name for id mapping may need iteration after testing in Figma Make.
94
+ * Currently generating id from label as fallback.
95
+ */
96
+ example: ({ activeButtonType, active, disabled, tooltip, divider, label, id, children }) => {
97
+ const disableTooltip = !tooltip;
98
+
99
+ if (divider) {
100
+ return <Divider sx={{ margin: "9px 0" }} />;
101
+ }
102
+
103
+ return (
104
+ <NavigationButton
105
+ data={{ id: id, label: label }}
106
+ activeButtonType={activeButtonType}
107
+ active={active}
108
+ disabled={disabled}
109
+ disableTooltip={disableTooltip}
110
+ onClick={() => {}}
111
+ >
112
+ {children}
113
+ </NavigationButton>
114
+ );
115
+ },
116
+ }
117
+ );