@carrier-dpx/air-react-library 0.1.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.
- package/README.md +72 -0
- package/package.json +50 -0
- package/src/components/Button/Button.figma.tsx +142 -0
- package/src/components/Button/Button.tsx +104 -0
- package/src/components/Button/index.ts +3 -0
- package/src/components/theme/constants/styleTokens.ts +6 -0
- package/src/components/utils/styles.ts +8 -0
- package/src/index.ts +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Air React Library
|
|
2
|
+
|
|
3
|
+
Air web React component library for Figma Make integration.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @carrier-dpx/air-react-library
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Peer Dependencies
|
|
12
|
+
|
|
13
|
+
This library requires the following peer dependencies:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install react react-dom @mui/material @emotion/react @emotion/styled
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Button Component
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { Button } from '@carrier-dpx/air-react-library';
|
|
25
|
+
|
|
26
|
+
function App() {
|
|
27
|
+
return (
|
|
28
|
+
<Button
|
|
29
|
+
variant="contained"
|
|
30
|
+
color="primary"
|
|
31
|
+
size="large"
|
|
32
|
+
onClick={() => console.log('clicked')}
|
|
33
|
+
>
|
|
34
|
+
Get Started
|
|
35
|
+
</Button>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Available Props
|
|
41
|
+
|
|
42
|
+
#### Button
|
|
43
|
+
|
|
44
|
+
- `variant`: `"contained"` | `"outlined"` | `"text"` (default: `"contained"`)
|
|
45
|
+
- `color`: `"base"` | `"primary"` | `"secondary"` | `"error"` | `"warning"` | `"success"` | `"info"` (default: `"primary"`)
|
|
46
|
+
- `size`: `"xlarge"` | `"large"` | `"medium"` | `"small"` | `"xsmall"`
|
|
47
|
+
- `shape`: `"rounded"` | `"circular"` (default: `"rounded"`)
|
|
48
|
+
- `disabled`: `boolean`
|
|
49
|
+
- `startIcon`: `ReactNode` - Icon to display before the button text
|
|
50
|
+
- `endIcon`: `ReactNode` - Icon to display after the button text
|
|
51
|
+
- `onClick`: `() => void` - Click handler
|
|
52
|
+
- All standard Material-UI Button props
|
|
53
|
+
|
|
54
|
+
## Figma Integration
|
|
55
|
+
|
|
56
|
+
This library is integrated with Figma Code Connect. When using Figma Make, components from this library will be automatically suggested and used in generated code.
|
|
57
|
+
|
|
58
|
+
## Components
|
|
59
|
+
|
|
60
|
+
Currently available components:
|
|
61
|
+
|
|
62
|
+
- **Button** - Material-UI based button component with Carrier DPX design system styling
|
|
63
|
+
|
|
64
|
+
More components coming soon!
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT
|
|
69
|
+
|
|
70
|
+
## Repository
|
|
71
|
+
|
|
72
|
+
[https://github.com/Carrier-DPX/air-react-library](https://github.com/Carrier-DPX/air-react-library)
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@carrier-dpx/air-react-library",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Air web React component library for Figma Make",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"types": "src/index.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"src",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/Carrier-DPX/air-react-library.git"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"figma:connect": "figma connect",
|
|
20
|
+
"figma:publish": "figma connect publish"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"react",
|
|
24
|
+
"components",
|
|
25
|
+
"figma",
|
|
26
|
+
"code-connect",
|
|
27
|
+
"carrier",
|
|
28
|
+
"design-system",
|
|
29
|
+
"ui",
|
|
30
|
+
"material-ui"
|
|
31
|
+
],
|
|
32
|
+
"author": "Carrier DPX",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react": "^18.0.0",
|
|
36
|
+
"react-dom": "^18.0.0",
|
|
37
|
+
"@mui/material": "^5.0.0",
|
|
38
|
+
"@emotion/react": "^11.0.0",
|
|
39
|
+
"@emotion/styled": "^11.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@figma/code-connect": "^1.0.0",
|
|
43
|
+
"@mui/material": "^5.15.0",
|
|
44
|
+
"@emotion/react": "^11.11.0",
|
|
45
|
+
"@emotion/styled": "^11.11.0",
|
|
46
|
+
"@types/react": "^18.0.0",
|
|
47
|
+
"@types/react-dom": "^18.0.0",
|
|
48
|
+
"typescript": "^5.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Figma Code Connect Configuration for Button Component
|
|
3
|
+
*
|
|
4
|
+
* This file creates the bridge between your Figma Button component
|
|
5
|
+
* and your React Button component. It tells Figma Make:
|
|
6
|
+
* 1. Which React component corresponds to which Figma component
|
|
7
|
+
* 2. How Figma properties/variants map to React props
|
|
8
|
+
* 3. How to generate code examples
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import figma from "@figma/code-connect";
|
|
12
|
+
import Button from "./Button";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* figma.connect() creates the connection between Figma and React
|
|
16
|
+
*
|
|
17
|
+
* Parameters:
|
|
18
|
+
* 1. Button - Your React component
|
|
19
|
+
* 2. Figma URL - Points to your specific component in Figma
|
|
20
|
+
* 3. Configuration object - Defines the prop mappings
|
|
21
|
+
*/
|
|
22
|
+
figma.connect(
|
|
23
|
+
Button,
|
|
24
|
+
"https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=20456-152342",
|
|
25
|
+
{
|
|
26
|
+
/**
|
|
27
|
+
* PROPS MAPPING
|
|
28
|
+
*
|
|
29
|
+
* This section maps Figma properties to React props.
|
|
30
|
+
*
|
|
31
|
+
* Format options:
|
|
32
|
+
* - figma.enum("PropertyName", { ... }) - for variant/dropdown properties
|
|
33
|
+
* - figma.boolean("PropertyName") - for boolean properties
|
|
34
|
+
* - figma.string("PropertyName") - for text properties
|
|
35
|
+
* - figma.children("LayerName") - for nested content/children
|
|
36
|
+
* - figma.instance("LayerName") - for nested component instances
|
|
37
|
+
*/
|
|
38
|
+
props: {
|
|
39
|
+
/**
|
|
40
|
+
* VARIANT MAPPING
|
|
41
|
+
* Maps Figma's "variant" property to React's "variant" prop
|
|
42
|
+
*
|
|
43
|
+
* Figma: filled, outlined, text
|
|
44
|
+
* React: contained, outlined, text
|
|
45
|
+
*
|
|
46
|
+
* Note: "filled" in Figma maps to "contained" in Material-UI
|
|
47
|
+
*/
|
|
48
|
+
variant: figma.enum("variant", {
|
|
49
|
+
filled: "contained",
|
|
50
|
+
outlined: "outlined",
|
|
51
|
+
text: "text",
|
|
52
|
+
}),
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* SIZE MAPPING
|
|
56
|
+
* Maps Figma's "size" property to React's "size" prop
|
|
57
|
+
*
|
|
58
|
+
* Figma size names include pixel values (e.g., "xlarge-56px")
|
|
59
|
+
* React expects just the size name (e.g., "xlarge")
|
|
60
|
+
*/
|
|
61
|
+
size: figma.enum("size", {
|
|
62
|
+
"xlarge-56px": "xlarge",
|
|
63
|
+
"large-48px": "large",
|
|
64
|
+
"medium-40px": "medium",
|
|
65
|
+
"small-32px": "small",
|
|
66
|
+
"xsmall-24px": "xsmall",
|
|
67
|
+
}),
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* COLOR MAPPING
|
|
71
|
+
* Maps Figma's "color" property to React's "color" prop
|
|
72
|
+
*
|
|
73
|
+
* Note: "base" is a custom color in the Carrier DPX theme palette
|
|
74
|
+
* It's an extension of the standard Material-UI colors and provides
|
|
75
|
+
* the foundation colors for the design system
|
|
76
|
+
*/
|
|
77
|
+
color: figma.enum("color", {
|
|
78
|
+
base: "base",
|
|
79
|
+
primary: "primary",
|
|
80
|
+
secondary: "secondary",
|
|
81
|
+
error: "error",
|
|
82
|
+
warning: "warning",
|
|
83
|
+
success: "success",
|
|
84
|
+
info: "info",
|
|
85
|
+
}),
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* DISABLED STATE
|
|
89
|
+
* Maps Figma's "disabled" boolean property to React's "disabled" prop
|
|
90
|
+
*/
|
|
91
|
+
disabled: figma.boolean("disabled"),
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* BUTTON TEXT/CHILDREN
|
|
95
|
+
* Maps the text content from the "Button Label" layer
|
|
96
|
+
* Uses figma.children() to capture nested text content
|
|
97
|
+
*/
|
|
98
|
+
children: figma.children("Button Label"),
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* START ICON
|
|
102
|
+
* Maps Figma's "startIcon" layer (when visible) to React's startIcon prop
|
|
103
|
+
*
|
|
104
|
+
* figma.instance() connects to nested component instances in Figma
|
|
105
|
+
* The "startIcon" boolean property controls visibility in Figma
|
|
106
|
+
*/
|
|
107
|
+
startIcon: figma.instance("startIcon"),
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* END ICON
|
|
111
|
+
* Maps Figma's "endIcon" layer (when visible) to React's endIcon prop
|
|
112
|
+
*/
|
|
113
|
+
endIcon: figma.instance("endIcon"),
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* EXAMPLE CODE TEMPLATE
|
|
118
|
+
*
|
|
119
|
+
* This defines how the component should appear in generated code.
|
|
120
|
+
* The template uses the props mapped above.
|
|
121
|
+
*
|
|
122
|
+
* When Figma Make generates code, it will substitute the actual
|
|
123
|
+
* values based on the component instance properties.
|
|
124
|
+
*
|
|
125
|
+
* Note: We're ignoring the "state" and "label" properties because:
|
|
126
|
+
* - "state" (enabled/hover/focus) is a visual state in Figma, not a prop
|
|
127
|
+
* - "label" is just a boolean to show/hide the text layer
|
|
128
|
+
*/
|
|
129
|
+
example: ({ variant, color, size, disabled, startIcon, endIcon, children }) => (
|
|
130
|
+
<Button
|
|
131
|
+
variant={variant}
|
|
132
|
+
color={color}
|
|
133
|
+
size={size}
|
|
134
|
+
disabled={disabled}
|
|
135
|
+
startIcon={startIcon}
|
|
136
|
+
endIcon={endIcon}
|
|
137
|
+
>
|
|
138
|
+
{children}
|
|
139
|
+
</Button>
|
|
140
|
+
),
|
|
141
|
+
}
|
|
142
|
+
);
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { ElementType, forwardRef, Ref } from "react";
|
|
2
|
+
|
|
3
|
+
import MuiButton, { ButtonProps as MuiButtonProps } from "@mui/material/Button";
|
|
4
|
+
import { TouchRippleActions } from "@mui/material/ButtonBase/TouchRipple";
|
|
5
|
+
import { CSSObject, Theme } from "@mui/material/styles";
|
|
6
|
+
|
|
7
|
+
import { getSxStyles } from "../utils/styles";
|
|
8
|
+
import { styleTokens } from "../theme/constants/styleTokens";
|
|
9
|
+
|
|
10
|
+
declare module "@mui/material/Button" {
|
|
11
|
+
interface ButtonPropsSizeOverrides {
|
|
12
|
+
xlarge: true;
|
|
13
|
+
xsmall: true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ButtonProps extends MuiButtonProps {
|
|
18
|
+
/**
|
|
19
|
+
* A ref that points to the TouchRipple element.
|
|
20
|
+
*/
|
|
21
|
+
touchRippleRef?: Ref<TouchRippleActions>;
|
|
22
|
+
/**
|
|
23
|
+
* The component used for the root node. Either a string to use a HTML element or a component.
|
|
24
|
+
*/
|
|
25
|
+
component?: ElementType;
|
|
26
|
+
/**
|
|
27
|
+
* The border radius of the button.
|
|
28
|
+
* @default "rounded"
|
|
29
|
+
*/
|
|
30
|
+
shape?: "rounded" | "circular";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const getHoverOverrides = (theme: Theme): CSSObject => ({
|
|
34
|
+
"&.MuiButton-containedPrimary:hover": {
|
|
35
|
+
backgroundColor: theme.palette.primary?.containedHoverBackground,
|
|
36
|
+
},
|
|
37
|
+
"&.MuiButton-containedSecondary:hover": {
|
|
38
|
+
backgroundColor: theme.palette.secondary?.containedHoverBackground,
|
|
39
|
+
},
|
|
40
|
+
"&.MuiButton-containedError:hover": {
|
|
41
|
+
backgroundColor: theme.palette.error?.containedHoverBackground,
|
|
42
|
+
},
|
|
43
|
+
"&.MuiButton-containedWarning:hover": {
|
|
44
|
+
backgroundColor: theme.palette.warning?.containedHoverBackground,
|
|
45
|
+
},
|
|
46
|
+
"&.MuiButton-containedSuccess:hover": {
|
|
47
|
+
backgroundColor: theme.palette.success?.containedHoverBackground,
|
|
48
|
+
},
|
|
49
|
+
"&.MuiButton-containedInfo:hover": {
|
|
50
|
+
backgroundColor: theme.palette.info?.containedHoverBackground,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
/** The Button component allows users to take action which is communicated through a text label and optional icons.
|
|
55
|
+
*
|
|
56
|
+
* // Default import
|
|
57
|
+
* import Button from '@carrier-io/air-react/Button'
|
|
58
|
+
*
|
|
59
|
+
* // Named import
|
|
60
|
+
* import { Button } from '@carrier-io/air-react'
|
|
61
|
+
*/
|
|
62
|
+
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
63
|
+
(
|
|
64
|
+
{
|
|
65
|
+
color = "primary",
|
|
66
|
+
size,
|
|
67
|
+
variant = "contained",
|
|
68
|
+
disableElevation = true,
|
|
69
|
+
shape = "rounded",
|
|
70
|
+
sx,
|
|
71
|
+
...rest
|
|
72
|
+
},
|
|
73
|
+
ref
|
|
74
|
+
) => {
|
|
75
|
+
return (
|
|
76
|
+
<MuiButton
|
|
77
|
+
ref={ref}
|
|
78
|
+
color={color}
|
|
79
|
+
size={size}
|
|
80
|
+
variant={variant}
|
|
81
|
+
disableElevation={disableElevation}
|
|
82
|
+
sx={(theme) =>
|
|
83
|
+
({
|
|
84
|
+
borderRadius:
|
|
85
|
+
shape === "rounded"
|
|
86
|
+
? styleTokens.borderRadius.large
|
|
87
|
+
: styleTokens.borderRadius.circular,
|
|
88
|
+
...getHoverOverrides(theme),
|
|
89
|
+
...getSxStyles(theme, sx),
|
|
90
|
+
} as CSSObject)
|
|
91
|
+
}
|
|
92
|
+
style={{
|
|
93
|
+
textTransform: "unset",
|
|
94
|
+
border: variant === "text" ? "none" : "",
|
|
95
|
+
}}
|
|
96
|
+
{...rest}
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
Button.displayName = "Button";
|
|
103
|
+
|
|
104
|
+
export default Button;
|
package/src/index.ts
ADDED