@carrier-dpx/air-react-library 0.4.0 → 0.6.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 (33) hide show
  1. package/README.md +3 -0
  2. package/package.json +10 -7
  3. package/src/components/Copyright/Copyright.figma.tsx +19 -0
  4. package/src/components/Copyright/Copyright.tsx +36 -0
  5. package/src/components/Copyright/index.ts +3 -0
  6. package/src/components/Copyright/styles.ts +8 -0
  7. package/src/components/Copyright/types.ts +8 -0
  8. package/src/components/Divider/Divider.horizontal.figma.tsx +50 -0
  9. package/src/components/Divider/Divider.tsx +57 -0
  10. package/src/components/Divider/Divider.vertical.figma.tsx +54 -0
  11. package/src/components/Divider/index.ts +3 -0
  12. package/src/components/Icon/ArrowLeftIcon.figma.tsx +32 -0
  13. package/src/components/Icon/ArrowRightIcon.figma.tsx +32 -0
  14. package/src/components/Icon/CheckIcon.figma.tsx +32 -0
  15. package/src/components/Icon/CloseIcon.figma.tsx +32 -0
  16. package/src/components/Icon/HomeIcon.figma.tsx +32 -0
  17. package/src/components/Icon/Icon.tsx +24 -0
  18. package/src/components/Icon/InfoIcon.figma.tsx +32 -0
  19. package/src/components/Icon/MenuIcon.figma.tsx +32 -0
  20. package/src/components/Icon/README.md +207 -0
  21. package/src/components/Icon/SearchIcon.figma.tsx +32 -0
  22. package/src/components/Icon/SettingsIcon.figma.tsx +61 -0
  23. package/src/components/Icon/UserIcon.figma.tsx +32 -0
  24. package/src/components/Icon/index.ts +3 -0
  25. package/src/components/Link/Link.figma.tsx +70 -0
  26. package/src/components/Link/Link.tsx +69 -0
  27. package/src/components/Link/index.ts +3 -0
  28. package/src/components/theme/FleetThemeProvider.tsx +50 -50
  29. package/src/components/theme/constants/fleetComponents.ts +873 -873
  30. package/src/components/theme/constants/styleTokens.ts +37 -1
  31. package/src/components/types/common.ts +5 -0
  32. package/src/components/types/props.ts +6 -0
  33. package/src/index.ts +8 -0
@@ -0,0 +1,207 @@
1
+ # Icon Component with Figma Code Connect
2
+
3
+ This directory contains the Icon wrapper component and Figma Code Connect mappings for individual icon components.
4
+
5
+ ## Architecture
6
+
7
+ ### Icon Wrapper + Individual Icon Components
8
+
9
+ The Icon system uses:
10
+ - **One Icon wrapper component** (`Icon.tsx`) - Material-UI Icon wrapper that handles `fontSize` (xsmall, small, medium, large)
11
+ - **Individual icon components** - Separate components for each icon (SettingsIcon, HomeIcon, etc.) that handle `variant` (outlined, filled)
12
+ - **Individual Figma connections** - One `.figma.tsx` file per icon component
13
+
14
+ ## Component Usage
15
+
16
+ ```tsx
17
+ import { Icon } from '@carrier-dpx/air-react-library';
18
+ import { SettingsIcon, HomeIcon } from '@carrier-io/icons'; // Your icon library
19
+
20
+ // Basic usage
21
+ <Icon fontSize="medium">
22
+ <SettingsIcon variant="filled" />
23
+ </Icon>
24
+
25
+ // Different sizes
26
+ <Icon fontSize="xsmall">
27
+ <HomeIcon variant="outlined" />
28
+ </Icon>
29
+
30
+ <Icon fontSize="large">
31
+ <SettingsIcon variant="filled" />
32
+ </Icon>
33
+ ```
34
+
35
+ ## Figma Code Connect Pattern
36
+
37
+ Each icon has its own `.figma.tsx` file that:
38
+
39
+ 1. **Imports the icon component** (from your icon library)
40
+ 2. **Imports the Icon wrapper** (for fontSize)
41
+ 3. **Maps to a specific Figma icon component** (via Figma URL)
42
+ 4. **Maps variant and optionally fontSize** props
43
+
44
+ ### Example: SettingsIcon.figma.tsx
45
+
46
+ ```tsx
47
+ import figma from "@figma/code-connect";
48
+ import Icon from "./Icon";
49
+ import { SettingsIcon } from '@carrier-io/icons'; // Your icon library
50
+
51
+ figma.connect(
52
+ SettingsIcon, // The actual icon component
53
+ "https://www.figma.com/design/.../SettingsIcon",
54
+ {
55
+ props: {
56
+ // Variant is handled by the icon component
57
+ variant: figma.enum("variant", {
58
+ outlined: "outlined",
59
+ filled: "filled",
60
+ }),
61
+
62
+ // fontSize is optional - can be mapped from Figma or set manually
63
+ // fontSize: figma.enum("fontSize", {
64
+ // "xsmall-12px": "xsmall",
65
+ // "small-16px": "small",
66
+ // "medium-24px": "medium",
67
+ // "large-32px": "large",
68
+ // }),
69
+ },
70
+ example: ({ variant }) => (
71
+ <Icon fontSize="medium">
72
+ <SettingsIcon variant={variant} />
73
+ </Icon>
74
+ ),
75
+ }
76
+ );
77
+ ```
78
+
79
+ **Key Points**:
80
+ - The icon component (SettingsIcon) is what Figma connects to
81
+ - The Icon wrapper handles fontSize
82
+ - Each icon gets its own `.figma.tsx` file so Figma recognizes them separately
83
+
84
+ ## Icon Component Structure
85
+
86
+ Your icon components should follow this pattern:
87
+
88
+ ```tsx
89
+ // SettingsIcon.tsx (in your icon library)
90
+ export interface SettingsIconProps {
91
+ variant?: "outlined" | "filled";
92
+ // ... other props
93
+ }
94
+
95
+ export const SettingsIcon: FC<SettingsIconProps> = ({ variant = "outlined", ...props }) => {
96
+ // Render SVG based on variant
97
+ return <svg>...</svg>;
98
+ };
99
+ ```
100
+
101
+ ## Adding New Icons
102
+
103
+ To add a new icon to the Figma integration:
104
+
105
+ 1. **Ensure the icon component exists** in your icon library (Bitbucket repo)
106
+
107
+ 2. **Create a new `.figma.tsx` file** following the pattern:
108
+ ```tsx
109
+ // {IconName}Icon.figma.tsx
110
+ import figma from "@figma/code-connect";
111
+ import Icon from "./Icon";
112
+ import { YourIconName } from '@carrier-io/icons'; // Your icon library
113
+
114
+ figma.connect(
115
+ YourIconName,
116
+ "YOUR_FIGMA_ICON_URL_HERE",
117
+ {
118
+ props: {
119
+ variant: figma.enum("variant", {
120
+ outlined: "outlined",
121
+ filled: "filled",
122
+ }),
123
+ },
124
+ example: ({ variant }) => (
125
+ <Icon fontSize="medium">
126
+ <YourIconName variant={variant} />
127
+ </Icon>
128
+ ),
129
+ }
130
+ );
131
+ ```
132
+
133
+ 3. **Get the Figma URL** by:
134
+ - Opening the icon component in Figma
135
+ - Right-clicking → "Copy link to selection"
136
+ - Replacing the URL in the `figma.connect()` call
137
+
138
+ ## Scaling to 700 Icons
139
+
140
+ ### Option 1: Manual Creation
141
+ Create individual `.figma.tsx` files for each icon. This gives you full control.
142
+
143
+ ### Option 2: Code Generation Script
144
+ Create a script that generates `.figma.tsx` files from a list of icons:
145
+
146
+ ```typescript
147
+ // scripts/generateIconConnections.ts
148
+ const icons = [
149
+ { name: "SettingsIcon", figmaNodeId: "SETTINGS-ICON-NODE-ID" },
150
+ { name: "HomeIcon", figmaNodeId: "HOME-ICON-NODE-ID" },
151
+ // ... 698 more icons
152
+ ];
153
+
154
+ icons.forEach(({ name, figmaNodeId }) => {
155
+ const content = `
156
+ import figma from "@figma/code-connect";
157
+ import Icon from "./Icon";
158
+ import { ${name} } from '@carrier-io/icons';
159
+
160
+ figma.connect(
161
+ ${name},
162
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=${figmaNodeId}",
163
+ {
164
+ props: {
165
+ variant: figma.enum("variant", {
166
+ outlined: "outlined",
167
+ filled: "filled",
168
+ }),
169
+ },
170
+ example: ({ variant }) => (
171
+ <Icon fontSize="medium">
172
+ <${name} variant={variant} />
173
+ </Icon>
174
+ ),
175
+ }
176
+ );
177
+ `;
178
+ // Write to file: ${name}.figma.tsx
179
+ });
180
+ ```
181
+
182
+ ## Icon Library Integration
183
+
184
+ The icon components should be imported from your icon library package (Bitbucket repo). Update the imports in each `.figma.tsx` file to point to your actual icon library:
185
+
186
+ ```tsx
187
+ // Replace placeholder imports with actual icon library imports
188
+ import { SettingsIcon, HomeIcon, UserIcon } from '@carrier-io/icons';
189
+ ```
190
+
191
+ ## Testing
192
+
193
+ The current setup includes sample Figma connections for testing. To test:
194
+
195
+ 1. **Update imports** in `.figma.tsx` files to point to your actual icon library
196
+ 2. **Update Figma URLs** with real node IDs from your Figma file
197
+ 3. **Run** `npm run figma:connect` to publish connections
198
+ 4. **Open Figma** and check Dev Mode
199
+ 5. **Select an icon component** → verify it shows the correct React code
200
+
201
+ ## Notes
202
+
203
+ - Each icon needs its own Figma component with a "variant" property (outlined/filled)
204
+ - The Icon wrapper handles fontSize (xsmall, small, medium, large)
205
+ - Icon components handle variant (outlined, filled)
206
+ - Icon components are imported from your icon library (Bitbucket repo)
207
+ - The Figma URL must point to the specific icon component instance
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Search Icon
3
+ *
4
+ * NOTE: Import SearchIcon from your actual icon library package.
5
+ * Example: import { SearchIcon } from '@carrier-io/icons';
6
+ */
7
+
8
+ import figma from "@figma/code-connect";
9
+ import Icon from "./Icon";
10
+ // TODO: Import from your actual icon library
11
+ // import { SearchIcon } from '@carrier-io/icons';
12
+
13
+ // Placeholder - replace with actual SearchIcon import
14
+ const SearchIcon = ({ variant, ...props }: any) => <span {...props}>SearchIcon</span>;
15
+
16
+ figma.connect(
17
+ SearchIcon,
18
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=SEARCH-ICON-NODE-ID",
19
+ {
20
+ props: {
21
+ variant: figma.enum("variant", {
22
+ outlined: "outlined",
23
+ filled: "filled",
24
+ }),
25
+ },
26
+ example: ({ variant }) => (
27
+ <Icon fontSize="medium">
28
+ <SearchIcon variant={variant} />
29
+ </Icon>
30
+ ),
31
+ }
32
+ );
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Settings Icon
3
+ *
4
+ * This connects Figma's SettingsIcon component to the React SettingsIcon component.
5
+ * The icon component is wrapped in the Icon wrapper for fontSize control.
6
+ *
7
+ * Figma URL: https://www.figma.com/design/RT43n0bKuuIt7ylllD3DR0/Icon-Library?node-id=1401-6386
8
+ *
9
+ * NOTE: Import SettingsIcon from your actual icon library package.
10
+ * Example: import { SettingsIcon } from '@carrier-io/icons';
11
+ */
12
+
13
+ import figma from "@figma/code-connect";
14
+ import Icon from "./Icon";
15
+ // TODO: Import from your actual icon library
16
+ // import { SettingsIcon } from '@carrier-io/icons';
17
+
18
+ // Placeholder - replace with actual SettingsIcon import
19
+ const SettingsIcon = ({ variant, ...props }: any) => <span {...props}>SettingsIcon</span>;
20
+
21
+ figma.connect(
22
+ SettingsIcon,
23
+ "https://www.figma.com/design/RT43n0bKuuIt7ylllD3DR0/Icon-Library?node-id=1401-6386",
24
+ {
25
+ props: {
26
+ /**
27
+ * STYLE MAPPING
28
+ * Maps Figma's "Style" property to the icon component's "variant" prop
29
+ * Figma uses "Style" with values "Outlined" and "Filled"
30
+ * React icon component expects "variant" with values "outlined" and "filled"
31
+ */
32
+ variant: figma.enum("Style", {
33
+ Outlined: "outlined",
34
+ Filled: "filled",
35
+ }),
36
+
37
+ /**
38
+ * FONT SIZE MAPPING (optional)
39
+ * If your Figma icon component has a fontSize property, map it here
40
+ * Otherwise, fontSize is set on the Icon wrapper component
41
+ */
42
+ // fontSize: figma.enum("fontSize", {
43
+ // "xsmall-12px": "xsmall",
44
+ // "small-16px": "small",
45
+ // "medium-24px": "medium",
46
+ // "large-32px": "large",
47
+ // }),
48
+ },
49
+ /**
50
+ * EXAMPLE CODE TEMPLATE
51
+ * Shows the icon component wrapped in Icon for fontSize control.
52
+ * The Icon wrapper handles fontSize (xsmall, small, medium, large).
53
+ * The icon component handles variant (outlined, filled).
54
+ */
55
+ example: ({ variant }) => (
56
+ <Icon fontSize="medium">
57
+ <SettingsIcon variant={variant} />
58
+ </Icon>
59
+ ),
60
+ }
61
+ );
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Figma Code Connect Configuration for User Icon
3
+ *
4
+ * NOTE: Import UserIcon from your actual icon library package.
5
+ * Example: import { UserIcon } from '@carrier-io/icons';
6
+ */
7
+
8
+ import figma from "@figma/code-connect";
9
+ import Icon from "./Icon";
10
+ // TODO: Import from your actual icon library
11
+ // import { UserIcon } from '@carrier-io/icons';
12
+
13
+ // Placeholder - replace with actual UserIcon import
14
+ const UserIcon = ({ variant, ...props }: any) => <span {...props}>UserIcon</span>;
15
+
16
+ figma.connect(
17
+ UserIcon,
18
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=USER-ICON-NODE-ID",
19
+ {
20
+ props: {
21
+ variant: figma.enum("variant", {
22
+ outlined: "outlined",
23
+ filled: "filled",
24
+ }),
25
+ },
26
+ example: ({ variant }) => (
27
+ <Icon fontSize="medium">
28
+ <UserIcon variant={variant} />
29
+ </Icon>
30
+ ),
31
+ }
32
+ );
@@ -0,0 +1,3 @@
1
+ export { default } from "./Icon";
2
+ export * from "./Icon";
3
+ export type { IconProps } from "./Icon";
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Link Component
3
+ */
4
+
5
+ import figma from "@figma/code-connect";
6
+ import Link from "./Link";
7
+
8
+ figma.connect(
9
+ Link,
10
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=6574-50682",
11
+ {
12
+ props: {
13
+ /**
14
+ * VARIANT MAPPING
15
+ * Same variants as Typography component
16
+ */
17
+ variant: figma.enum("variant", {
18
+ body1: "body1",
19
+ "body1 semibold": "body1Semibold",
20
+ "body1 bold": "body1Bold",
21
+ body2: "body2",
22
+ "body2 semibold": "body2Semibold",
23
+ "body2 bold": "body2Bold",
24
+ body3: "body3",
25
+ "body3 semibold": "body3Semibold",
26
+ "body3 bold": "body3Bold",
27
+ h1: "h1",
28
+ h2: "h2",
29
+ h3: "h3",
30
+ h4: "h4",
31
+ h5: "h5",
32
+ h6: "h6",
33
+ caps1: "caps1",
34
+ "caps1 bold": "caps1Bold",
35
+ caps2: "caps2",
36
+ "caps2 bold": "caps2Bold",
37
+ caps3: "caps3",
38
+ "caps3 bold": "caps3Bold",
39
+ caps4: "caps4",
40
+ "caps4 bold": "caps4Bold",
41
+ }),
42
+
43
+ /**
44
+ * UNDERLINE MAPPING
45
+ * Maps Figma underline style to React underline prop
46
+ */
47
+ underline: figma.enum("underline", {
48
+ always: "always",
49
+ hover: "hover",
50
+ none: "none",
51
+ }),
52
+
53
+ /**
54
+ * TEXT CONTENT
55
+ * Maps the link text from "Label" layer
56
+ */
57
+ children: figma.children("Label"),
58
+ },
59
+
60
+ /**
61
+ * CODE EXAMPLE TEMPLATE
62
+ * Note: href is a runtime prop, not configured in static Figma component
63
+ */
64
+ example: ({ variant, underline, children }) => (
65
+ <Link variant={variant} underline={underline} href="#">
66
+ {children}
67
+ </Link>
68
+ ),
69
+ }
70
+ );
@@ -0,0 +1,69 @@
1
+ import { forwardRef } from "react";
2
+
3
+ import MuiLink, { LinkProps as MuiLinkProps } from "@mui/material/Link";
4
+ import { AllSystemCSSProperties, ResponsiveStyleValue } from "@mui/system";
5
+ import { useTheme } from "@mui/material";
6
+ import { TypographyProps } from "@mui/material/Typography";
7
+
8
+ // List of variants we want to exclude
9
+ type ExcludedVariants =
10
+ | "overline"
11
+ | "avatarLetter"
12
+ | "buttonLarge"
13
+ | "buttonMedium"
14
+ | "buttonSmall"
15
+ | "caption"
16
+ | "inputLabel"
17
+ | "inputText1"
18
+ | "inputText2"
19
+ | "helperText"
20
+ | "alertTitle"
21
+ | "tableHeader1"
22
+ | "tableHeader2"
23
+ | "badge"
24
+ | "chip"
25
+ | "tooltip";
26
+
27
+ // Get all valid variant options from MUI's Typography component
28
+ type MUIValidVariants = Exclude<TypographyProps["variant"], ExcludedVariants>;
29
+
30
+ export interface LinkProps extends Omit<MuiLinkProps, "variant"> {
31
+ /**
32
+ * Specifies how to capitalize an element's text
33
+ */
34
+ textTransform?: ResponsiveStyleValue<AllSystemCSSProperties["textTransform"]>;
35
+ /**
36
+ * The target attribute specifies where to open the linked document:
37
+ */
38
+ target?: string;
39
+ /**
40
+ * Applies the theme typography styles.
41
+ */
42
+ variant?: MUIValidVariants;
43
+ }
44
+
45
+ /** The Link component allows you to easily customize anchor elements with your theme colors and typography styles.
46
+ *
47
+ * `import Link from '@carrier-io/air-react/Link'`
48
+ */
49
+
50
+ const Link = forwardRef<HTMLAnchorElement, LinkProps>(
51
+ ({ color, variant = "body2", ...rest }, ref) => {
52
+ const theme = useTheme();
53
+ const resolvedColor = color ?? theme.palette.primary.main;
54
+
55
+ return (
56
+ <MuiLink
57
+ {...rest}
58
+ color={resolvedColor}
59
+ ref={ref}
60
+ variant={variant}
61
+ sx={{ cursor: "pointer", textUnderlineOffset: "4px" }}
62
+ />
63
+ );
64
+ }
65
+ );
66
+
67
+ Link.displayName = "Link";
68
+
69
+ export default Link;
@@ -0,0 +1,3 @@
1
+ export { default } from "./Link";
2
+ export * from "./Link";
3
+ export type { LinkProps } from "./Link";
@@ -1,50 +1,50 @@
1
- import React, { ReactNode, useEffect } from "react";
2
- import { Theme, ThemeProvider, createTheme } from "@mui/material/styles";
3
- import { airDarkThemeOptions, fleetThemeOptions } from "./fleetThemeOptions";
4
-
5
- // Define theme instances
6
- const ahpTheme: Theme = createTheme({ ...fleetThemeOptions });
7
-
8
- const airLightTheme: Theme = createTheme(fleetThemeOptions);
9
-
10
- const airDarkTheme: Theme = createTheme(airDarkThemeOptions);
11
-
12
- // Mapping from theme names to actual Theme instances
13
- export const ThemeMap = {
14
- AHP: ahpTheme,
15
- AirLight: airLightTheme,
16
- AirDark: airDarkTheme,
17
- } as const;
18
-
19
- // Define props for FleetThemeProvider
20
- export type ThemeProviderProps = {
21
- /** Content to render with the specified theme */
22
- children?: ReactNode;
23
-
24
- /** Custom Theme instance or predefined theme key */
25
- theme?: Theme | keyof typeof ThemeMap;
26
- };
27
-
28
- // FleetThemeProvider component
29
- const FleetThemeProvider: React.FC<ThemeProviderProps> = ({
30
- children,
31
- theme = airLightTheme, // Default to airLightTheme
32
- }) => {
33
- const resolvedTheme = typeof theme === "string" ? ThemeMap[theme] : theme;
34
-
35
- // Load Nunito Sans font
36
- useEffect(() => {
37
- // Check if font is already loaded
38
- if (!document.querySelector('link[href*="Nunito+Sans"]')) {
39
- const link = document.createElement('link');
40
- link.href = 'https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@200;300;400;600;700;800;900&display=swap';
41
- link.rel = 'stylesheet';
42
- document.head.appendChild(link);
43
- }
44
- }, []);
45
-
46
- return <ThemeProvider theme={resolvedTheme}>{children}</ThemeProvider>;
47
- };
48
-
49
- export default FleetThemeProvider;
50
- export { FleetThemeProvider };
1
+ import React, { ReactNode, useEffect } from "react";
2
+ import { Theme, ThemeProvider, createTheme } from "@mui/material/styles";
3
+ import { airDarkThemeOptions, fleetThemeOptions } from "./fleetThemeOptions";
4
+
5
+ // Define theme instances
6
+ const ahpTheme: Theme = createTheme({ ...fleetThemeOptions });
7
+
8
+ const airLightTheme: Theme = createTheme(fleetThemeOptions);
9
+
10
+ const airDarkTheme: Theme = createTheme(airDarkThemeOptions);
11
+
12
+ // Mapping from theme names to actual Theme instances
13
+ export const ThemeMap = {
14
+ AHP: ahpTheme,
15
+ AirLight: airLightTheme,
16
+ AirDark: airDarkTheme,
17
+ } as const;
18
+
19
+ // Define props for FleetThemeProvider
20
+ export type ThemeProviderProps = {
21
+ /** Content to render with the specified theme */
22
+ children?: ReactNode;
23
+
24
+ /** Custom Theme instance or predefined theme key */
25
+ theme?: Theme | keyof typeof ThemeMap;
26
+ };
27
+
28
+ // FleetThemeProvider component
29
+ const FleetThemeProvider: React.FC<ThemeProviderProps> = ({
30
+ children,
31
+ theme = airLightTheme, // Default to airLightTheme
32
+ }) => {
33
+ const resolvedTheme = typeof theme === "string" ? ThemeMap[theme] : theme;
34
+
35
+ // Load Nunito Sans font
36
+ useEffect(() => {
37
+ // Check if font is already loaded
38
+ if (!document.querySelector('link[href*="Nunito+Sans"]')) {
39
+ const link = document.createElement('link');
40
+ link.href = 'https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@200;300;400;600;700;800;900&display=swap';
41
+ link.rel = 'stylesheet';
42
+ document.head.appendChild(link);
43
+ }
44
+ }, []);
45
+
46
+ return <ThemeProvider theme={resolvedTheme}>{children}</ThemeProvider>;
47
+ };
48
+
49
+ export default FleetThemeProvider;
50
+ export { FleetThemeProvider };