jac-client 0.2.0__py3-none-any.whl → 0.2.3__py3-none-any.whl
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.
- jac_client/docs/README.md +50 -20
- jac_client/docs/advanced-state.md +13 -14
- jac_client/docs/asset-serving/intro.md +209 -0
- jac_client/docs/assets/pipe_line-v2.svg +32 -0
- jac_client/docs/file-system/app.jac.md +121 -0
- jac_client/docs/file-system/backend-frontend.md +217 -0
- jac_client/docs/file-system/intro.md +72 -0
- jac_client/docs/file-system/nested-imports.md +348 -0
- jac_client/docs/guide-example/intro.md +11 -13
- jac_client/docs/guide-example/step-01-setup.md +30 -20
- jac_client/docs/guide-example/step-02-components.md +24 -24
- jac_client/docs/guide-example/step-03-styling.md +24 -24
- jac_client/docs/guide-example/step-04-todo-ui.md +17 -17
- jac_client/docs/guide-example/step-05-local-state.md +23 -23
- jac_client/docs/guide-example/step-06-events.md +23 -24
- jac_client/docs/guide-example/step-07-effects.md +27 -28
- jac_client/docs/guide-example/step-08-walkers.md +23 -23
- jac_client/docs/guide-example/step-09-authentication.md +18 -18
- jac_client/docs/guide-example/step-10-routing.md +20 -21
- jac_client/docs/guide-example/step-11-final.md +34 -35
- jac_client/docs/imports.md +4 -5
- jac_client/docs/lifecycle-hooks.md +12 -13
- jac_client/docs/routing.md +21 -22
- jac_client/docs/styling/intro.md +249 -0
- jac_client/docs/styling/js-styling.md +367 -0
- jac_client/docs/styling/material-ui.md +341 -0
- jac_client/docs/styling/pure-css.md +299 -0
- jac_client/docs/styling/sass.md +403 -0
- jac_client/docs/styling/styled-components.md +395 -0
- jac_client/docs/styling/tailwind.md +298 -0
- jac_client/examples/all-in-one/.babelrc +9 -0
- jac_client/examples/all-in-one/README.md +16 -0
- jac_client/examples/all-in-one/app.jac +426 -0
- jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client/examples/all-in-one/button.jac +7 -0
- jac_client/examples/all-in-one/components/button.jac +7 -0
- jac_client/examples/all-in-one/package.json +29 -0
- jac_client/examples/all-in-one/styles.css +26 -0
- jac_client/examples/all-in-one/vite.config.js +28 -0
- jac_client/examples/asset-serving/css-with-image/.babelrc +9 -0
- jac_client/examples/asset-serving/css-with-image/README.md +91 -0
- jac_client/examples/asset-serving/css-with-image/app.jac +88 -0
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +28 -0
- jac_client/examples/asset-serving/css-with-image/styles.css +26 -0
- jac_client/examples/asset-serving/css-with-image/vite.config.js +28 -0
- jac_client/examples/asset-serving/image-asset/.babelrc +9 -0
- jac_client/examples/asset-serving/image-asset/README.md +119 -0
- jac_client/examples/asset-serving/image-asset/app.jac +55 -0
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +28 -0
- jac_client/examples/asset-serving/image-asset/styles.css +26 -0
- jac_client/examples/asset-serving/image-asset/vite.config.js +28 -0
- jac_client/examples/asset-serving/import-alias/.babelrc +9 -0
- jac_client/examples/asset-serving/import-alias/README.md +83 -0
- jac_client/examples/asset-serving/import-alias/app.jac +111 -0
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +28 -0
- jac_client/examples/asset-serving/import-alias/vite.config.js +28 -0
- jac_client/examples/basic/app.jac +14 -9
- jac_client/examples/basic/package.json +1 -1
- jac_client/examples/basic/vite.config.js +0 -1
- jac_client/examples/basic-auth/package.json +1 -1
- jac_client/examples/basic-auth/vite.config.js +0 -1
- jac_client/examples/basic-auth-with-router/package.json +1 -1
- jac_client/examples/basic-auth-with-router/vite.config.js +0 -1
- jac_client/examples/basic-full-stack/package.json +1 -1
- jac_client/examples/basic-full-stack/vite.config.js +0 -1
- jac_client/examples/css-styling/js-styling/.babelrc +9 -0
- jac_client/examples/css-styling/js-styling/README.md +183 -0
- jac_client/examples/css-styling/js-styling/app.jac +84 -0
- jac_client/examples/css-styling/js-styling/package.json +28 -0
- jac_client/examples/css-styling/js-styling/styles.js +100 -0
- jac_client/examples/css-styling/js-styling/vite.config.js +27 -0
- jac_client/examples/css-styling/material-ui/.babelrc +9 -0
- jac_client/examples/css-styling/material-ui/README.md +16 -0
- jac_client/examples/css-styling/material-ui/app.jac +122 -0
- jac_client/examples/css-styling/material-ui/package.json +32 -0
- jac_client/examples/css-styling/material-ui/vite.config.js +27 -0
- jac_client/examples/css-styling/pure-css/.babelrc +9 -0
- jac_client/examples/css-styling/pure-css/README.md +16 -0
- jac_client/examples/css-styling/pure-css/app.jac +64 -0
- jac_client/examples/css-styling/pure-css/package.json +28 -0
- jac_client/examples/css-styling/pure-css/styles.css +111 -0
- jac_client/examples/css-styling/pure-css/vite.config.js +27 -0
- jac_client/examples/css-styling/sass-example/.babelrc +9 -0
- jac_client/examples/css-styling/sass-example/README.md +16 -0
- jac_client/examples/css-styling/sass-example/app.jac +64 -0
- jac_client/examples/css-styling/sass-example/package.json +29 -0
- jac_client/examples/css-styling/sass-example/styles.scss +153 -0
- jac_client/examples/css-styling/sass-example/vite.config.js +27 -0
- jac_client/examples/css-styling/styled-components/.babelrc +9 -0
- jac_client/examples/css-styling/styled-components/README.md +16 -0
- jac_client/examples/css-styling/styled-components/app.jac +71 -0
- jac_client/examples/css-styling/styled-components/package.json +29 -0
- jac_client/examples/css-styling/styled-components/styled.js +90 -0
- jac_client/examples/css-styling/styled-components/vite.config.js +27 -0
- jac_client/examples/css-styling/tailwind-example/.babelrc +9 -0
- jac_client/examples/css-styling/tailwind-example/README.md +16 -0
- jac_client/examples/css-styling/tailwind-example/app.jac +63 -0
- jac_client/examples/css-styling/tailwind-example/global.css +1 -0
- jac_client/examples/css-styling/tailwind-example/package.json +30 -0
- jac_client/examples/css-styling/tailwind-example/vite.config.js +29 -0
- jac_client/examples/full-stack-with-auth/app.jac +20 -33
- jac_client/examples/full-stack-with-auth/package.json +1 -1
- jac_client/examples/full-stack-with-auth/vite.config.js +0 -1
- jac_client/examples/little-x/app.jac +327 -218
- jac_client/examples/little-x/submit-button.jac +1 -1
- jac_client/examples/nested-folders/nested-advance/.babelrc +9 -0
- jac_client/examples/nested-folders/nested-advance/ButtonRoot.jac +11 -0
- jac_client/examples/nested-folders/nested-advance/README.md +77 -0
- jac_client/examples/nested-folders/nested-advance/app.jac +35 -0
- jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +19 -0
- jac_client/examples/nested-folders/nested-advance/level1/Card.jac +43 -0
- jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +25 -0
- jac_client/examples/nested-folders/nested-advance/package.json +29 -0
- jac_client/examples/nested-folders/nested-advance/vite.config.js +28 -0
- jac_client/examples/nested-folders/nested-basic/.babelrc +9 -0
- jac_client/examples/nested-folders/nested-basic/README.md +183 -0
- jac_client/examples/nested-folders/nested-basic/app.jac +13 -0
- jac_client/examples/nested-folders/nested-basic/app.js +7 -0
- jac_client/examples/nested-folders/nested-basic/button.jac +7 -0
- jac_client/examples/nested-folders/nested-basic/components/button.jac +7 -0
- jac_client/examples/nested-folders/nested-basic/package.json +28 -0
- jac_client/examples/nested-folders/nested-basic/vite.config.js +27 -0
- jac_client/examples/with-router/app.jac +1 -1
- jac_client/examples/with-router/package.json +1 -1
- jac_client/examples/with-router/vite.config.js +0 -1
- jac_client/plugin/cli.py +7 -2
- jac_client/plugin/client.py +68 -5
- jac_client/plugin/client_runtime.jac +1 -1
- jac_client/plugin/vite_client_bundle.py +162 -14
- jac_client/tests/__init__.py +0 -1
- jac_client/tests/fixtures/basic-app/app.jac +7 -2
- jac_client/tests/fixtures/cl_file/app.cl.jac +48 -0
- jac_client/tests/fixtures/cl_file/app.jac +15 -0
- jac_client/tests/fixtures/client_app_with_antd/app.jac +14 -8
- jac_client/tests/fixtures/js_import/app.jac +19 -15
- jac_client/tests/fixtures/js_import/utils.js +0 -1
- jac_client/tests/fixtures/package.json +1 -1
- jac_client/tests/fixtures/relative_import/app.jac +4 -6
- jac_client/tests/fixtures/relative_import/button.jac +7 -6
- jac_client/tests/fixtures/spawn_test/app.jac +1 -5
- jac_client/tests/fixtures/test_fragments_spread/app.jac +24 -10
- jac_client/tests/test_asset_examples.py +322 -0
- jac_client/tests/test_cl.py +480 -426
- jac_client/tests/test_create_jac_app.py +125 -133
- jac_client/tests/test_it.py +329 -0
- jac_client/tests/test_nested_file.py +374 -0
- {jac_client-0.2.0.dist-info → jac_client-0.2.3.dist-info}/METADATA +11 -3
- jac_client-0.2.3.dist-info/RECORD +171 -0
- jac_client-0.2.0.dist-info/RECORD +0 -72
- {jac_client-0.2.0.dist-info → jac_client-0.2.3.dist-info}/WHEEL +0 -0
- {jac_client-0.2.0.dist-info → jac_client-0.2.3.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# JavaScript Styling
|
|
2
|
+
|
|
3
|
+
Inline styles using JavaScript objects for dynamic styling in Jac applications.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
JavaScript styling uses JavaScript objects to define styles, which are then applied via the `style` prop. This approach is perfect for:
|
|
8
|
+
- Dynamic styling based on state
|
|
9
|
+
- Programmatic style generation
|
|
10
|
+
- Component-scoped styles without CSS files
|
|
11
|
+
- React-style inline styling
|
|
12
|
+
|
|
13
|
+
## Example
|
|
14
|
+
|
|
15
|
+
See the complete working example: [`examples/css-styling/js-styling/`](../../examples/css-styling/js-styling/)
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### 1. Define Style Objects
|
|
20
|
+
|
|
21
|
+
Create `styles.js`:
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
const countDisplay = {
|
|
25
|
+
fontSize: "3.75rem",
|
|
26
|
+
fontWeight: "bold",
|
|
27
|
+
transition: "color 0.3s ease"
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default {
|
|
31
|
+
container: {
|
|
32
|
+
minHeight: "100vh",
|
|
33
|
+
background: "linear-gradient(to bottom right, #dbeafe, #e0e7ff)",
|
|
34
|
+
display: "flex",
|
|
35
|
+
alignItems: "center",
|
|
36
|
+
justifyContent: "center",
|
|
37
|
+
padding: "1rem"
|
|
38
|
+
},
|
|
39
|
+
card: {
|
|
40
|
+
backgroundColor: "#ffffff",
|
|
41
|
+
borderRadius: "1rem",
|
|
42
|
+
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
43
|
+
padding: "2rem",
|
|
44
|
+
maxWidth: "28rem",
|
|
45
|
+
width: "100%"
|
|
46
|
+
},
|
|
47
|
+
countDisplayZero: {
|
|
48
|
+
...countDisplay,
|
|
49
|
+
color: "#1f2937"
|
|
50
|
+
},
|
|
51
|
+
countDisplayPositive: {
|
|
52
|
+
...countDisplay,
|
|
53
|
+
color: "#16a34a"
|
|
54
|
+
},
|
|
55
|
+
countDisplayNegative: {
|
|
56
|
+
...countDisplay,
|
|
57
|
+
color: "#dc2626"
|
|
58
|
+
},
|
|
59
|
+
button: {
|
|
60
|
+
color: "#ffffff",
|
|
61
|
+
fontWeight: "bold",
|
|
62
|
+
padding: "0.75rem 1.5rem",
|
|
63
|
+
borderRadius: "0.5rem",
|
|
64
|
+
border: "none",
|
|
65
|
+
cursor: "pointer"
|
|
66
|
+
},
|
|
67
|
+
buttonDecrement: {
|
|
68
|
+
backgroundColor: "#ef4444"
|
|
69
|
+
},
|
|
70
|
+
buttonReset: {
|
|
71
|
+
backgroundColor: "#6b7280"
|
|
72
|
+
},
|
|
73
|
+
buttonIncrement: {
|
|
74
|
+
backgroundColor: "#22c55e"
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 2. Import Styles
|
|
80
|
+
|
|
81
|
+
```jac
|
|
82
|
+
# Pages
|
|
83
|
+
cl import from react {useState, useEffect}
|
|
84
|
+
cl import from .styles { default as styles }
|
|
85
|
+
|
|
86
|
+
cl {
|
|
87
|
+
def app() -> any {
|
|
88
|
+
return <div style={styles.container}>
|
|
89
|
+
<div style={styles.card}>
|
|
90
|
+
<h1 style={styles.title}>Counter Application</h1>
|
|
91
|
+
</div>
|
|
92
|
+
</div>;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. Apply Styles
|
|
98
|
+
|
|
99
|
+
Use the `style` prop with style objects:
|
|
100
|
+
|
|
101
|
+
```jac
|
|
102
|
+
return <div style={styles.container}>
|
|
103
|
+
<div style={styles.card}>
|
|
104
|
+
<h1 style={styles.title}>Counter Application</h1>
|
|
105
|
+
</div>
|
|
106
|
+
</div>;
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 4. Dynamic Styles
|
|
110
|
+
|
|
111
|
+
Select styles based on state:
|
|
112
|
+
|
|
113
|
+
```jac
|
|
114
|
+
let countStyle = styles.countDisplayZero if count == 0 else (styles.countDisplayPositive if count > 0 else styles.countDisplayNegative);
|
|
115
|
+
|
|
116
|
+
return <div style={countStyle}>{count}</div>;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Style Object Format
|
|
120
|
+
|
|
121
|
+
JavaScript style objects use camelCase property names (React convention):
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
{
|
|
125
|
+
backgroundColor: "#ffffff", // not background-color
|
|
126
|
+
fontSize: "1.5rem", // not font-size
|
|
127
|
+
marginTop: "10px", // not margin-top
|
|
128
|
+
zIndex: 1, // not z-index
|
|
129
|
+
borderTopLeftRadius: "4px" // not border-top-left-radius
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Best Practices
|
|
134
|
+
|
|
135
|
+
### 1. Use Object Spread
|
|
136
|
+
|
|
137
|
+
Share common styles with spread operator:
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
const baseButton = {
|
|
141
|
+
padding: "0.75rem 1.5rem",
|
|
142
|
+
borderRadius: "0.5rem",
|
|
143
|
+
border: "none",
|
|
144
|
+
cursor: "pointer"
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export default {
|
|
148
|
+
primaryButton: {
|
|
149
|
+
...baseButton,
|
|
150
|
+
backgroundColor: "#007bff",
|
|
151
|
+
color: "#ffffff"
|
|
152
|
+
},
|
|
153
|
+
secondaryButton: {
|
|
154
|
+
...baseButton,
|
|
155
|
+
backgroundColor: "#6c757d",
|
|
156
|
+
color: "#ffffff"
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 2. Organize by Component
|
|
162
|
+
|
|
163
|
+
Group related styles together:
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
export default {
|
|
167
|
+
// Container styles
|
|
168
|
+
container: { ... },
|
|
169
|
+
card: { ... },
|
|
170
|
+
|
|
171
|
+
// Button styles
|
|
172
|
+
button: { ... },
|
|
173
|
+
buttonPrimary: { ... },
|
|
174
|
+
buttonSecondary: { ... },
|
|
175
|
+
|
|
176
|
+
// Text styles
|
|
177
|
+
title: { ... },
|
|
178
|
+
subtitle: { ... }
|
|
179
|
+
};
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### 3. Use Constants
|
|
183
|
+
|
|
184
|
+
Define reusable values at the top:
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
const COLORS = {
|
|
188
|
+
primary: "#007bff",
|
|
189
|
+
secondary: "#6c757d",
|
|
190
|
+
success: "#28a745",
|
|
191
|
+
danger: "#dc3545"
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const SPACING = {
|
|
195
|
+
sm: "0.5rem",
|
|
196
|
+
md: "1rem",
|
|
197
|
+
lg: "2rem"
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export default {
|
|
201
|
+
button: {
|
|
202
|
+
backgroundColor: COLORS.primary,
|
|
203
|
+
padding: SPACING.md
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 4. CamelCase Properties
|
|
209
|
+
|
|
210
|
+
Follow React naming convention:
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
// Good
|
|
214
|
+
{
|
|
215
|
+
backgroundColor: "#fff",
|
|
216
|
+
fontSize: "1rem",
|
|
217
|
+
marginTop: "10px"
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Avoid
|
|
221
|
+
{
|
|
222
|
+
"background-color": "#fff", // Wrong
|
|
223
|
+
"font-size": "1rem" // Wrong
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 5. Extract Complex Logic
|
|
228
|
+
|
|
229
|
+
Move style calculations to functions:
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
export const getButtonStyle = (variant, disabled) => {
|
|
233
|
+
const base = {
|
|
234
|
+
padding: "0.75rem 1.5rem",
|
|
235
|
+
borderRadius: "0.5rem",
|
|
236
|
+
border: "none",
|
|
237
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
238
|
+
opacity: disabled ? 0.5 : 1
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const variants = {
|
|
242
|
+
primary: { backgroundColor: "#007bff", color: "#ffffff" },
|
|
243
|
+
secondary: { backgroundColor: "#6c757d", color: "#ffffff" }
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
return { ...base, ...variants[variant] };
|
|
247
|
+
};
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Advanced Patterns
|
|
251
|
+
|
|
252
|
+
### Style Functions
|
|
253
|
+
|
|
254
|
+
Create functions that return styles:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
export const getButtonStyle = (variant) => ({
|
|
258
|
+
padding: "0.75rem 1.5rem",
|
|
259
|
+
borderRadius: "0.5rem",
|
|
260
|
+
backgroundColor: variant === 'primary' ? '#007bff' : '#6c757d',
|
|
261
|
+
color: '#ffffff'
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Use in Jac:
|
|
266
|
+
|
|
267
|
+
```jac
|
|
268
|
+
let buttonStyle = getButtonStyle("primary");
|
|
269
|
+
|
|
270
|
+
return <button style={buttonStyle}>Click Me</button>;
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Conditional Styles
|
|
274
|
+
|
|
275
|
+
Use ternary operators for conditional styles:
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
export default {
|
|
279
|
+
button: (isActive, isDisabled) => ({
|
|
280
|
+
backgroundColor: isActive ? '#007bff' : '#6c757d',
|
|
281
|
+
opacity: isDisabled ? 0.5 : 1,
|
|
282
|
+
cursor: isDisabled ? 'not-allowed' : 'pointer'
|
|
283
|
+
})
|
|
284
|
+
};
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Dynamic Values
|
|
288
|
+
|
|
289
|
+
Calculate styles based on props:
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
export const getContainerStyle = (width, height) => ({
|
|
293
|
+
width: `${width}px`,
|
|
294
|
+
height: `${height}px`,
|
|
295
|
+
display: "flex",
|
|
296
|
+
alignItems: "center",
|
|
297
|
+
justifyContent: "center"
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Advantages
|
|
302
|
+
|
|
303
|
+
- **Dynamic styling** based on props/state
|
|
304
|
+
- **No CSS file needed**
|
|
305
|
+
- **Type-safe** with TypeScript
|
|
306
|
+
- **Component-scoped** by default
|
|
307
|
+
- **Programmatic style generation**
|
|
308
|
+
- **Easy to debug** (JavaScript objects)
|
|
309
|
+
- **No build step** for styles
|
|
310
|
+
|
|
311
|
+
## Limitations
|
|
312
|
+
|
|
313
|
+
- **No pseudo-classes** (hover, focus, etc.)
|
|
314
|
+
- **No media queries**
|
|
315
|
+
- **No CSS animations** (use JavaScript)
|
|
316
|
+
- **Verbose** for complex styles
|
|
317
|
+
- **No CSS preprocessor features**
|
|
318
|
+
- **Performance** can be slower for many elements
|
|
319
|
+
|
|
320
|
+
## When to Use
|
|
321
|
+
|
|
322
|
+
Choose JavaScript Styling when:
|
|
323
|
+
|
|
324
|
+
- You need dynamic styles based on state
|
|
325
|
+
- You want programmatic style generation
|
|
326
|
+
- You prefer keeping styles in JavaScript
|
|
327
|
+
- You're building component libraries
|
|
328
|
+
- You need runtime style calculations
|
|
329
|
+
- You want type safety with TypeScript
|
|
330
|
+
|
|
331
|
+
## Import Syntax
|
|
332
|
+
|
|
333
|
+
Style objects are imported as JavaScript modules:
|
|
334
|
+
|
|
335
|
+
```jac
|
|
336
|
+
# Default export
|
|
337
|
+
cl import from .styles { default as styles }
|
|
338
|
+
|
|
339
|
+
# Named exports (if using named exports)
|
|
340
|
+
cl import from .styles { button, card, container }
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Combining Styles
|
|
344
|
+
|
|
345
|
+
You can combine multiple style objects:
|
|
346
|
+
|
|
347
|
+
```jac
|
|
348
|
+
let combinedStyle = {
|
|
349
|
+
...styles.base,
|
|
350
|
+
...styles.button,
|
|
351
|
+
...(isActive ? styles.active : {})
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
return <button style={combinedStyle}>Click Me</button>;
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Next Steps
|
|
358
|
+
|
|
359
|
+
- Explore [Styled Components](./styled-components.md) for CSS-in-JS with more features
|
|
360
|
+
- Check out [Emotion](./emotion.md) for similar CSS-in-JS approach (coming soon)
|
|
361
|
+
- Learn about [CSS Modules](./css-modules.md) for scoped CSS (coming soon)
|
|
362
|
+
- See [Pure CSS](./pure-css.md) for traditional CSS approach
|
|
363
|
+
|
|
364
|
+
## Resources
|
|
365
|
+
|
|
366
|
+
- [React Inline Styles](https://react.dev/learn/javascript-in-jsx-with-curly-braces#using-double-curlies-css-and-other-objects-in-jsx)
|
|
367
|
+
- [CSS-in-JS Comparison](https://github.com/MicheleBertoli/css-in-js)
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# Material-UI
|
|
2
|
+
|
|
3
|
+
Comprehensive React component library with Material Design for Jac applications.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Material-UI (MUI) provides pre-built, accessible React components following Material Design principles. This approach is perfect for:
|
|
8
|
+
- Rapid application development
|
|
9
|
+
- Consistent Material Design
|
|
10
|
+
- Accessible components out of the box
|
|
11
|
+
- Enterprise applications
|
|
12
|
+
|
|
13
|
+
## Example
|
|
14
|
+
|
|
15
|
+
See the complete working example: [`examples/css-styling/material-ui/`](../../examples/css-styling/material-ui/)
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### 1. Install Material-UI
|
|
20
|
+
|
|
21
|
+
Add to `package.json`:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@mui/material": "^5.15.0",
|
|
27
|
+
"@mui/icons-material": "^5.15.0"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Import Components
|
|
33
|
+
|
|
34
|
+
In your Jac file:
|
|
35
|
+
|
|
36
|
+
```jac
|
|
37
|
+
# Pages
|
|
38
|
+
cl import from react {useState, useEffect}
|
|
39
|
+
cl import from "@mui/material/Button" { default as Button }
|
|
40
|
+
cl import from "@mui/material/Card" { default as Card }
|
|
41
|
+
cl import from "@mui/material/CardContent" { default as CardContent }
|
|
42
|
+
cl import from "@mui/material/Box" { default as Box }
|
|
43
|
+
cl import from "@mui/icons-material/Add" { default as AddIcon }
|
|
44
|
+
cl import from "@mui/icons-material/Remove" { default as RemoveIcon }
|
|
45
|
+
|
|
46
|
+
cl {
|
|
47
|
+
def app() -> any {
|
|
48
|
+
return <Box sx={{"display": "flex", "justifyContent": "center"}}>
|
|
49
|
+
<Card>
|
|
50
|
+
<CardContent>
|
|
51
|
+
<Button variant="contained" onClick={handleIncrement}>
|
|
52
|
+
<AddIcon />
|
|
53
|
+
</Button>
|
|
54
|
+
</CardContent>
|
|
55
|
+
</Card>
|
|
56
|
+
</Box>;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Key Features
|
|
62
|
+
|
|
63
|
+
### Theming
|
|
64
|
+
|
|
65
|
+
Material-UI comes with a built-in theme system:
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
|
69
|
+
|
|
70
|
+
const theme = createTheme({
|
|
71
|
+
palette: {
|
|
72
|
+
primary: {
|
|
73
|
+
main: '#1976d2',
|
|
74
|
+
},
|
|
75
|
+
secondary: {
|
|
76
|
+
main: '#dc004e',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
typography: {
|
|
80
|
+
fontFamily: 'Roboto, Arial, sans-serif',
|
|
81
|
+
},
|
|
82
|
+
spacing: 8, // 8px base unit
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Wrap your app
|
|
86
|
+
<ThemeProvider theme={theme}>
|
|
87
|
+
<App />
|
|
88
|
+
</ThemeProvider>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### sx Prop
|
|
92
|
+
|
|
93
|
+
Use the `sx` prop for styling:
|
|
94
|
+
|
|
95
|
+
```jac
|
|
96
|
+
<Box sx={{
|
|
97
|
+
display: "flex",
|
|
98
|
+
justifyContent: "center",
|
|
99
|
+
alignItems: "center",
|
|
100
|
+
minHeight: "100vh",
|
|
101
|
+
backgroundColor: "background.default"
|
|
102
|
+
}}>
|
|
103
|
+
<Card sx={{
|
|
104
|
+
maxWidth: 400,
|
|
105
|
+
padding: 2
|
|
106
|
+
}}>
|
|
107
|
+
Content
|
|
108
|
+
</Card>
|
|
109
|
+
</Box>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Component Variants
|
|
113
|
+
|
|
114
|
+
Use built-in variants:
|
|
115
|
+
|
|
116
|
+
```jac
|
|
117
|
+
<Button variant="contained" color="primary">Contained</Button>
|
|
118
|
+
<Button variant="outlined" color="secondary">Outlined</Button>
|
|
119
|
+
<Button variant="text">Text</Button>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Common Components
|
|
123
|
+
|
|
124
|
+
### Layout Components
|
|
125
|
+
|
|
126
|
+
```jac
|
|
127
|
+
# Box - Container component
|
|
128
|
+
<Box sx={{"display": "flex", "gap": 2}}>
|
|
129
|
+
<Box>Item 1</Box>
|
|
130
|
+
<Box>Item 2</Box>
|
|
131
|
+
</Box>
|
|
132
|
+
|
|
133
|
+
# Grid - Responsive grid system
|
|
134
|
+
cl import from "@mui/material/Grid" { default as Grid }
|
|
135
|
+
<Grid container spacing={2}>
|
|
136
|
+
<Grid item xs={12} md={6}>Column 1</Grid>
|
|
137
|
+
<Grid item xs={12} md={6}>Column 2</Grid>
|
|
138
|
+
</Grid>
|
|
139
|
+
|
|
140
|
+
# Stack - Flexbox container
|
|
141
|
+
cl import from "@mui/material/Stack" { default as Stack }
|
|
142
|
+
<Stack direction="row" spacing={2}>
|
|
143
|
+
<Button>Button 1</Button>
|
|
144
|
+
<Button>Button 2</Button>
|
|
145
|
+
</Stack>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Input Components
|
|
149
|
+
|
|
150
|
+
```jac
|
|
151
|
+
# TextField
|
|
152
|
+
cl import from "@mui/material/TextField" { default as TextField }
|
|
153
|
+
<TextField label="Name" variant="outlined" />
|
|
154
|
+
|
|
155
|
+
# Button
|
|
156
|
+
<Button variant="contained" color="primary" onClick={handleClick}>
|
|
157
|
+
Click Me
|
|
158
|
+
</Button>
|
|
159
|
+
|
|
160
|
+
# Select
|
|
161
|
+
cl import from "@mui/material/Select" { default as Select }
|
|
162
|
+
cl import from "@mui/material/MenuItem" { default as MenuItem }
|
|
163
|
+
<Select value={value} onChange={handleChange}>
|
|
164
|
+
<MenuItem value="option1">Option 1</MenuItem>
|
|
165
|
+
<MenuItem value="option2">Option 2</MenuItem>
|
|
166
|
+
</Select>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Feedback Components
|
|
170
|
+
|
|
171
|
+
```jac
|
|
172
|
+
# Card
|
|
173
|
+
<Card>
|
|
174
|
+
<CardContent>
|
|
175
|
+
<Typography variant="h5">Card Title</Typography>
|
|
176
|
+
<Typography variant="body2">Card content</Typography>
|
|
177
|
+
</CardContent>
|
|
178
|
+
</Card>
|
|
179
|
+
|
|
180
|
+
# Dialog
|
|
181
|
+
cl import from "@mui/material/Dialog" { default as Dialog }
|
|
182
|
+
cl import from "@mui/material/DialogTitle" { default as DialogTitle }
|
|
183
|
+
<Dialog open={open} onClose={handleClose}>
|
|
184
|
+
<DialogTitle>Dialog Title</DialogTitle>
|
|
185
|
+
</Dialog>
|
|
186
|
+
|
|
187
|
+
# Snackbar
|
|
188
|
+
cl import from "@mui/material/Snackbar" { default as Snackbar }
|
|
189
|
+
cl import from "@mui/material/Alert" { default as Alert }
|
|
190
|
+
<Snackbar open={open} autoHideDuration={6000}>
|
|
191
|
+
<Alert severity="success">Success message!</Alert>
|
|
192
|
+
</Snackbar>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Best Practices
|
|
196
|
+
|
|
197
|
+
### 1. Use sx Prop
|
|
198
|
+
|
|
199
|
+
For component-specific styling:
|
|
200
|
+
|
|
201
|
+
```jac
|
|
202
|
+
<Box sx={{
|
|
203
|
+
display: "flex",
|
|
204
|
+
justifyContent: "center",
|
|
205
|
+
padding: 2,
|
|
206
|
+
backgroundColor: "primary.main"
|
|
207
|
+
}}>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 2. Leverage Variants
|
|
211
|
+
|
|
212
|
+
Use built-in variants when possible:
|
|
213
|
+
|
|
214
|
+
```jac
|
|
215
|
+
<Button variant="contained" color="primary">Primary</Button>
|
|
216
|
+
<Typography variant="h1">Heading</Typography>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 3. Theme Customization
|
|
220
|
+
|
|
221
|
+
Customize theme for brand colors:
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
const theme = createTheme({
|
|
225
|
+
palette: {
|
|
226
|
+
primary: {
|
|
227
|
+
main: '#your-brand-color',
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### 4. Accessibility
|
|
234
|
+
|
|
235
|
+
MUI components are accessible by default:
|
|
236
|
+
|
|
237
|
+
```jac
|
|
238
|
+
<Button aria-label="Add item">
|
|
239
|
+
<AddIcon />
|
|
240
|
+
</Button>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 5. Icons
|
|
244
|
+
|
|
245
|
+
Use @mui/icons-material for consistent icons:
|
|
246
|
+
|
|
247
|
+
```jac
|
|
248
|
+
cl import from "@mui/icons-material/Add" { default as AddIcon }
|
|
249
|
+
cl import from "@mui/icons-material/Delete" { default as DeleteIcon }
|
|
250
|
+
cl import from "@mui/icons-material/Edit" { default as EditIcon }
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Advantages
|
|
254
|
+
|
|
255
|
+
- **Pre-built, accessible components**
|
|
256
|
+
- **Consistent Material Design**
|
|
257
|
+
- **Comprehensive component library**
|
|
258
|
+
- **Built-in theming system**
|
|
259
|
+
- **TypeScript support**
|
|
260
|
+
- **Active community** and documentation
|
|
261
|
+
- **Production-ready** components
|
|
262
|
+
|
|
263
|
+
## Limitations
|
|
264
|
+
|
|
265
|
+
- **Larger bundle size**
|
|
266
|
+
- **Material Design aesthetic** (may not fit all brands)
|
|
267
|
+
- **Learning curve** for component API
|
|
268
|
+
- **Less flexibility** than custom CSS
|
|
269
|
+
- **Requires JavaScript** for styling
|
|
270
|
+
|
|
271
|
+
## When to Use
|
|
272
|
+
|
|
273
|
+
Choose Material-UI when:
|
|
274
|
+
|
|
275
|
+
- You want pre-built components
|
|
276
|
+
- You need accessible components
|
|
277
|
+
- You prefer Material Design
|
|
278
|
+
- You're building enterprise applications
|
|
279
|
+
- You want to focus on functionality over styling
|
|
280
|
+
- You need comprehensive component library
|
|
281
|
+
|
|
282
|
+
## Import Syntax
|
|
283
|
+
|
|
284
|
+
MUI components are imported from their specific packages:
|
|
285
|
+
|
|
286
|
+
```jac
|
|
287
|
+
# Material components
|
|
288
|
+
cl import from "@mui/material/Button" { default as Button }
|
|
289
|
+
cl import from "@mui/material/Card" { default as Card }
|
|
290
|
+
|
|
291
|
+
# Icons
|
|
292
|
+
cl import from "@mui/icons-material/Add" { default as AddIcon }
|
|
293
|
+
cl import from "@mui/icons-material/Delete" { default as DeleteIcon }
|
|
294
|
+
|
|
295
|
+
# Multiple imports
|
|
296
|
+
cl import from "@mui/material" {
|
|
297
|
+
Button,
|
|
298
|
+
Card,
|
|
299
|
+
CardContent,
|
|
300
|
+
Box
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Theming Example
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
// theme.js
|
|
308
|
+
import { createTheme } from '@mui/material/styles';
|
|
309
|
+
|
|
310
|
+
export const theme = createTheme({
|
|
311
|
+
palette: {
|
|
312
|
+
mode: 'light',
|
|
313
|
+
primary: {
|
|
314
|
+
main: '#1976d2',
|
|
315
|
+
},
|
|
316
|
+
secondary: {
|
|
317
|
+
main: '#dc004e',
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
typography: {
|
|
321
|
+
fontFamily: 'Roboto, Arial, sans-serif',
|
|
322
|
+
h1: {
|
|
323
|
+
fontSize: '2.5rem',
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
spacing: 8,
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Next Steps
|
|
331
|
+
|
|
332
|
+
- Explore [Material-UI Documentation](https://mui.com/)
|
|
333
|
+
- Check out [Chakra UI](./chakra-ui.md) for alternative component library (coming soon)
|
|
334
|
+
- Learn about [Ant Design](./ant-design.md) for enterprise components (coming soon)
|
|
335
|
+
- See [Styled Components](./styled-components.md) for CSS-in-JS approach
|
|
336
|
+
|
|
337
|
+
## Resources
|
|
338
|
+
|
|
339
|
+
- [Material-UI Documentation](https://mui.com/)
|
|
340
|
+
- [Material-UI Components](https://mui.com/material-ui/getting-started/)
|
|
341
|
+
- [Material Design Guidelines](https://m3.material.io/)
|