create-aziz-app 2.0.3 ā 2.0.4
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/bin/create-aziz-app.js +209 -3
- package/package.json +1 -1
- package/template/README.md +8 -0
- package/template/app.html +3 -108
- package/template/docs/CSS-FRAMEWORKS.md +221 -0
- package/template/docs/STYLING.md +269 -0
- package/template/package.json +1 -1
- package/template/styles/globals.css +190 -0
- package/template/styles/tailwind.css +122 -0
package/bin/create-aziz-app.js
CHANGED
|
@@ -62,10 +62,22 @@ async function main() {
|
|
|
62
62
|
const includeApiExamples = await question(' Include example API routes? (Y/n): ');
|
|
63
63
|
const includeDocs = await question(' Include documentation? (Y/n): ');
|
|
64
64
|
|
|
65
|
+
// Ask for CSS framework
|
|
66
|
+
console.log('\nšØ CSS Framework:');
|
|
67
|
+
console.log(' 1. None (custom CSS)');
|
|
68
|
+
console.log(' 2. Bootstrap 5');
|
|
69
|
+
console.log(' 3. Tailwind CSS');
|
|
70
|
+
const cssChoice = await question(' Choose (1/2/3): ');
|
|
71
|
+
|
|
72
|
+
let cssFramework = 'none';
|
|
73
|
+
if (cssChoice === '2') cssFramework = 'bootstrap';
|
|
74
|
+
else if (cssChoice === '3') cssFramework = 'tailwind';
|
|
75
|
+
|
|
65
76
|
const features = {
|
|
66
77
|
examples: includeExamples.toLowerCase() !== 'n' && includeExamples.toLowerCase() !== 'no',
|
|
67
78
|
apiExamples: includeApiExamples.toLowerCase() !== 'n' && includeApiExamples.toLowerCase() !== 'no',
|
|
68
|
-
docs: includeDocs.toLowerCase() !== 'n' && includeDocs.toLowerCase() !== 'no'
|
|
79
|
+
docs: includeDocs.toLowerCase() !== 'n' && includeDocs.toLowerCase() !== 'no',
|
|
80
|
+
cssFramework: cssFramework
|
|
69
81
|
};
|
|
70
82
|
|
|
71
83
|
console.log(`\nā” Creating "${projectName}"...\n`);
|
|
@@ -81,6 +93,9 @@ async function main() {
|
|
|
81
93
|
// Update dev server port
|
|
82
94
|
updateDevServerPort(targetDir, port);
|
|
83
95
|
|
|
96
|
+
// Setup CSS framework
|
|
97
|
+
setupCSSFramework(targetDir, features.cssFramework);
|
|
98
|
+
|
|
84
99
|
console.log(`ā
Done! Your project is ready.\n`);
|
|
85
100
|
console.log(`š Welcome to Aziz App - A React-like Framework\n`);
|
|
86
101
|
console.log(`š Created project: ${projectName}\n`);
|
|
@@ -104,8 +119,13 @@ async function main() {
|
|
|
104
119
|
console.log(` ⢠File-based Routing - pages/About.jsx ā #/about`);
|
|
105
120
|
console.log(` ⢠API Routes - Next.js-like API system`);
|
|
106
121
|
console.log(` ⢠Auto-Import - No manual script tags!`);
|
|
107
|
-
console.log(` ⢠Live Reload - Instant browser refresh
|
|
108
|
-
|
|
122
|
+
console.log(` ⢠Live Reload - Instant browser refresh`);
|
|
123
|
+
if (features.cssFramework === 'bootstrap') {
|
|
124
|
+
console.log(` ⢠Bootstrap 5 - Responsive CSS framework`);
|
|
125
|
+
} else if (features.cssFramework === 'tailwind') {
|
|
126
|
+
console.log(` ⢠Tailwind CSS - Utility-first CSS framework`);
|
|
127
|
+
}
|
|
128
|
+
console.log(`\nš” Quick tips:\n`);
|
|
109
129
|
console.log(` ⢠Create pages/MyPage.jsx ā Auto-imported!`);
|
|
110
130
|
console.log(` ⢠Create api/todos.js ā Auto-imported!`);
|
|
111
131
|
console.log(` ⢠Just save and browser refreshes automatically`);
|
|
@@ -170,6 +190,192 @@ function updateDevServerPort(targetDir, port) {
|
|
|
170
190
|
}
|
|
171
191
|
}
|
|
172
192
|
|
|
193
|
+
// Setup CSS framework
|
|
194
|
+
function setupCSSFramework(targetDir, framework) {
|
|
195
|
+
const htmlPath = path.join(targetDir, 'app.html');
|
|
196
|
+
if (!fs.existsSync(htmlPath)) return;
|
|
197
|
+
|
|
198
|
+
let html = fs.readFileSync(htmlPath, 'utf8');
|
|
199
|
+
|
|
200
|
+
if (framework === 'bootstrap') {
|
|
201
|
+
// Replace globals.css with Bootstrap CDN
|
|
202
|
+
html = html.replace(
|
|
203
|
+
'<link rel="stylesheet" href="styles/globals.css">',
|
|
204
|
+
`<!-- Bootstrap 5 CSS -->
|
|
205
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
206
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">`
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
// Add Bootstrap JS before closing body tag
|
|
210
|
+
const bootstrapJS = `
|
|
211
|
+
<!-- Bootstrap 5 JS -->
|
|
212
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
213
|
+
|
|
214
|
+
`;
|
|
215
|
+
html = html.replace('</body>', bootstrapJS + '</body>');
|
|
216
|
+
|
|
217
|
+
// Update components
|
|
218
|
+
updateComponentsForBootstrap(targetDir);
|
|
219
|
+
|
|
220
|
+
} else if (framework === 'tailwind') {
|
|
221
|
+
// Replace globals.css with Tailwind CSS
|
|
222
|
+
html = html.replace(
|
|
223
|
+
'<link rel="stylesheet" href="styles/globals.css">',
|
|
224
|
+
`<!-- Tailwind CSS -->
|
|
225
|
+
<link rel="stylesheet" href="styles/tailwind.css">
|
|
226
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
227
|
+
<script>
|
|
228
|
+
tailwind.config = {
|
|
229
|
+
theme: {
|
|
230
|
+
extend: {
|
|
231
|
+
colors: {
|
|
232
|
+
primary: '#61dafb',
|
|
233
|
+
dark: '#282c34'
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
</script>`
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// Update components
|
|
242
|
+
updateComponentsForTailwind(targetDir);
|
|
243
|
+
}
|
|
244
|
+
// If 'none', keep globals.css as is
|
|
245
|
+
|
|
246
|
+
fs.writeFileSync(htmlPath, html);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Update components for Bootstrap
|
|
250
|
+
function updateComponentsForBootstrap(targetDir) {
|
|
251
|
+
// Update Navbar
|
|
252
|
+
const navbarPath = path.join(targetDir, 'components', 'Navbar.jsx');
|
|
253
|
+
if (fs.existsSync(navbarPath)) {
|
|
254
|
+
const navbarContent = `/** @jsx h */
|
|
255
|
+
|
|
256
|
+
function Navbar() {
|
|
257
|
+
const path = getCurrentPath();
|
|
258
|
+
|
|
259
|
+
return (
|
|
260
|
+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
|
261
|
+
<div class="container-fluid">
|
|
262
|
+
<span class="navbar-brand" onClick={() => navigate("home")} style={{ cursor: 'pointer' }}>
|
|
263
|
+
ā” AzizApp
|
|
264
|
+
</span>
|
|
265
|
+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
|
266
|
+
<span class="navbar-toggler-icon"></span>
|
|
267
|
+
</button>
|
|
268
|
+
<div class="collapse navbar-collapse" id="navbarNav">
|
|
269
|
+
<ul class="navbar-nav">
|
|
270
|
+
<li class="nav-item">
|
|
271
|
+
<a href="#/home" class={\`nav-link \${path === "home" ? "active" : ""}\`}>Home</a>
|
|
272
|
+
</li>
|
|
273
|
+
<li class="nav-item">
|
|
274
|
+
<a href="#/about" class={\`nav-link \${path === "about" ? "active" : ""}\`}>About</a>
|
|
275
|
+
</li>
|
|
276
|
+
<li class="nav-item">
|
|
277
|
+
<a href="#/contact" class={\`nav-link \${path === "contact" ? "active" : ""}\`}>Contact</a>
|
|
278
|
+
</li>
|
|
279
|
+
<li class="nav-item">
|
|
280
|
+
<a href="#/test" class={\`nav-link \${path === "test" ? "active" : ""}\`}>Test</a>
|
|
281
|
+
</li>
|
|
282
|
+
<li class="nav-item">
|
|
283
|
+
<a href="#/api-demo" class={\`nav-link \${path === "api-demo" ? "active" : ""}\`}>API Demo</a>
|
|
284
|
+
</li>
|
|
285
|
+
</ul>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
</nav>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
`;
|
|
292
|
+
fs.writeFileSync(navbarPath, navbarContent);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Update Footer
|
|
296
|
+
const footerPath = path.join(targetDir, 'components', 'Footer.jsx');
|
|
297
|
+
if (fs.existsSync(footerPath)) {
|
|
298
|
+
const footerContent = `/** @jsx h */
|
|
299
|
+
|
|
300
|
+
function Footer() {
|
|
301
|
+
return (
|
|
302
|
+
<footer class="bg-dark text-light text-center py-3 mt-auto">
|
|
303
|
+
<div class="container">
|
|
304
|
+
<p class="mb-0">Made with ā” AzizApp</p>
|
|
305
|
+
</div>
|
|
306
|
+
</footer>
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
`;
|
|
310
|
+
fs.writeFileSync(footerPath, footerContent);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Update components for Tailwind
|
|
315
|
+
function updateComponentsForTailwind(targetDir) {
|
|
316
|
+
// Update Navbar
|
|
317
|
+
const navbarPath = path.join(targetDir, 'components', 'Navbar.jsx');
|
|
318
|
+
if (fs.existsSync(navbarPath)) {
|
|
319
|
+
const navbarContent = `/** @jsx h */
|
|
320
|
+
|
|
321
|
+
function Navbar() {
|
|
322
|
+
const path = getCurrentPath();
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<nav class="bg-dark shadow-lg">
|
|
326
|
+
<div class="container mx-auto px-4">
|
|
327
|
+
<div class="flex items-center justify-between h-16">
|
|
328
|
+
<span
|
|
329
|
+
class="text-primary text-xl font-bold cursor-pointer hover:text-blue-300 transition"
|
|
330
|
+
onClick={() => navigate("home")}
|
|
331
|
+
>
|
|
332
|
+
ā” AzizApp
|
|
333
|
+
</span>
|
|
334
|
+
<div class="flex space-x-4">
|
|
335
|
+
<a href="#/home" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "home" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
336
|
+
Home
|
|
337
|
+
</a>
|
|
338
|
+
<a href="#/about" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "about" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
339
|
+
About
|
|
340
|
+
</a>
|
|
341
|
+
<a href="#/contact" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "contact" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
342
|
+
Contact
|
|
343
|
+
</a>
|
|
344
|
+
<a href="#/test" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "test" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
345
|
+
Test
|
|
346
|
+
</a>
|
|
347
|
+
<a href="#/api-demo" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "api-demo" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
348
|
+
API Demo
|
|
349
|
+
</a>
|
|
350
|
+
</div>
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
</nav>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
`;
|
|
357
|
+
fs.writeFileSync(navbarPath, navbarContent);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Update Footer
|
|
361
|
+
const footerPath = path.join(targetDir, 'components', 'Footer.jsx');
|
|
362
|
+
if (fs.existsSync(footerPath)) {
|
|
363
|
+
const footerContent = `/** @jsx h */
|
|
364
|
+
|
|
365
|
+
function Footer() {
|
|
366
|
+
return (
|
|
367
|
+
<footer class="bg-dark text-gray-400 text-center py-4 mt-auto">
|
|
368
|
+
<div class="container mx-auto">
|
|
369
|
+
<p>Made with ā” AzizApp</p>
|
|
370
|
+
</div>
|
|
371
|
+
</footer>
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
`;
|
|
375
|
+
fs.writeFileSync(footerPath, footerContent);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
173
379
|
// Run main function
|
|
174
380
|
main().catch(err => {
|
|
175
381
|
console.error('ā Error:', err);
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -122,6 +122,14 @@ const response = await fetchApi('/api/todos');
|
|
|
122
122
|
const data = await response.json();
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
+
### CSS Frameworks
|
|
126
|
+
Choose your preferred styling:
|
|
127
|
+
- **Custom CSS** - Built-in responsive styles
|
|
128
|
+
- **Bootstrap 5** - Popular component framework
|
|
129
|
+
- **Tailwind CSS** - Utility-first framework
|
|
130
|
+
|
|
131
|
+
The CLI will automatically set up your chosen framework!
|
|
132
|
+
|
|
125
133
|
### Auto-Import
|
|
126
134
|
- Create files in `pages/`, `components/`, or `api/`
|
|
127
135
|
- Dev server automatically detects them
|
package/template/app.html
CHANGED
|
@@ -5,116 +5,11 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>My Aziz App</title>
|
|
7
7
|
|
|
8
|
+
<!-- Global Styles -->
|
|
9
|
+
<link rel="stylesheet" href="styles/globals.css">
|
|
10
|
+
|
|
8
11
|
<!-- Babel compiles JSX in the browser -->
|
|
9
12
|
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
|
10
|
-
|
|
11
|
-
<style>
|
|
12
|
-
/* ---- Reset ---- */
|
|
13
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
14
|
-
|
|
15
|
-
body {
|
|
16
|
-
font-family: Arial, sans-serif;
|
|
17
|
-
background-color: #f5f5f5;
|
|
18
|
-
color: #333;
|
|
19
|
-
min-height: 100vh;
|
|
20
|
-
display: flex;
|
|
21
|
-
flex-direction: column;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* ---- Navbar ---- */
|
|
25
|
-
nav {
|
|
26
|
-
background-color: #282c34;
|
|
27
|
-
padding: 16px 32px;
|
|
28
|
-
display: flex;
|
|
29
|
-
align-items: center;
|
|
30
|
-
gap: 24px;
|
|
31
|
-
}
|
|
32
|
-
nav .brand {
|
|
33
|
-
color: #61dafb;
|
|
34
|
-
font-size: 20px;
|
|
35
|
-
font-weight: bold;
|
|
36
|
-
cursor: pointer;
|
|
37
|
-
}
|
|
38
|
-
nav a {
|
|
39
|
-
color: #ffffffcc;
|
|
40
|
-
text-decoration: none;
|
|
41
|
-
font-size: 15px;
|
|
42
|
-
transition: color 0.2s;
|
|
43
|
-
}
|
|
44
|
-
nav a:hover, nav a.active { color: #61dafb; }
|
|
45
|
-
|
|
46
|
-
/* ---- Page wrapper ---- */
|
|
47
|
-
#root {
|
|
48
|
-
flex: 1;
|
|
49
|
-
padding: 40px 32px;
|
|
50
|
-
max-width: 900px;
|
|
51
|
-
width: 100%;
|
|
52
|
-
margin: 0 auto;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/* ---- Footer ---- */
|
|
56
|
-
footer {
|
|
57
|
-
background-color: #282c34;
|
|
58
|
-
color: #888;
|
|
59
|
-
text-align: center;
|
|
60
|
-
padding: 16px;
|
|
61
|
-
font-size: 13px;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/* ---- Utility styles ---- */
|
|
65
|
-
h1 { margin-bottom: 16px; color: #282c34; }
|
|
66
|
-
h2 { margin-bottom: 12px; }
|
|
67
|
-
p { line-height: 1.6; margin-bottom: 12px; color: #555; }
|
|
68
|
-
|
|
69
|
-
.card {
|
|
70
|
-
background: white;
|
|
71
|
-
border-radius: 10px;
|
|
72
|
-
padding: 24px;
|
|
73
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
|
74
|
-
margin-bottom: 20px;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.btn {
|
|
78
|
-
display: inline-block;
|
|
79
|
-
padding: 10px 22px;
|
|
80
|
-
border: none;
|
|
81
|
-
border-radius: 8px;
|
|
82
|
-
cursor: pointer;
|
|
83
|
-
font-size: 15px;
|
|
84
|
-
transition: opacity 0.2s;
|
|
85
|
-
}
|
|
86
|
-
.btn:hover { opacity: 0.85; }
|
|
87
|
-
.btn-primary { background-color: #61dafb; color: #282c34; font-weight: bold; }
|
|
88
|
-
.btn-danger { background-color: #ff6b6b; color: white; }
|
|
89
|
-
.btn-grey { background-color: #ccc; color: #333; }
|
|
90
|
-
|
|
91
|
-
/* ---- Counter (on home page) ---- */
|
|
92
|
-
.count-display {
|
|
93
|
-
font-size: 64px;
|
|
94
|
-
font-weight: bold;
|
|
95
|
-
color: #282c34;
|
|
96
|
-
margin: 16px 0;
|
|
97
|
-
text-align: center;
|
|
98
|
-
}
|
|
99
|
-
.counter-actions { display: flex; gap: 12px; justify-content: center; margin-top: 8px; }
|
|
100
|
-
|
|
101
|
-
/* ---- Form ---- */
|
|
102
|
-
form { display: flex; flex-direction: column; gap: 12px; }
|
|
103
|
-
input, textarea {
|
|
104
|
-
padding: 10px 14px;
|
|
105
|
-
border: 1px solid #ddd;
|
|
106
|
-
border-radius: 8px;
|
|
107
|
-
font-size: 15px;
|
|
108
|
-
outline: none;
|
|
109
|
-
transition: border-color 0.2s;
|
|
110
|
-
}
|
|
111
|
-
input:focus, textarea:focus { border-color: #61dafb; }
|
|
112
|
-
textarea { resize: vertical; min-height: 100px; }
|
|
113
|
-
|
|
114
|
-
/* ---- 404 ---- */
|
|
115
|
-
.not-found { text-align: center; padding: 60px 0; }
|
|
116
|
-
.not-found h1 { font-size: 80px; color: #61dafb; }
|
|
117
|
-
</style>
|
|
118
13
|
</head>
|
|
119
14
|
<body>
|
|
120
15
|
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# CSS Frameworks Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Aziz App supports three CSS options:
|
|
6
|
+
1. **Custom CSS** - Built-in custom styles
|
|
7
|
+
2. **Bootstrap 5** - Popular component framework
|
|
8
|
+
3. **Tailwind CSS** - Utility-first framework
|
|
9
|
+
|
|
10
|
+
## Bootstrap 5
|
|
11
|
+
|
|
12
|
+
### What's Included
|
|
13
|
+
|
|
14
|
+
When you choose Bootstrap, the CLI automatically adds:
|
|
15
|
+
- Bootstrap 5.3.2 CSS (CDN)
|
|
16
|
+
- Bootstrap Icons
|
|
17
|
+
- Bootstrap 5 JS Bundle
|
|
18
|
+
- Updated Navbar with Bootstrap classes
|
|
19
|
+
- Updated Footer with Bootstrap classes
|
|
20
|
+
|
|
21
|
+
### Using Bootstrap
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
// Example: Bootstrap Button
|
|
25
|
+
<button class="btn btn-primary">Click Me</button>
|
|
26
|
+
|
|
27
|
+
// Example: Bootstrap Card
|
|
28
|
+
<div class="card">
|
|
29
|
+
<div class="card-body">
|
|
30
|
+
<h5 class="card-title">Card Title</h5>
|
|
31
|
+
<p class="card-text">Some content</p>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
// Example: Bootstrap Grid
|
|
36
|
+
<div class="container">
|
|
37
|
+
<div class="row">
|
|
38
|
+
<div class="col-md-6">Column 1</div>
|
|
39
|
+
<div class="col-md-6">Column 2</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Bootstrap Components
|
|
45
|
+
|
|
46
|
+
Available components:
|
|
47
|
+
- Buttons, Cards, Modals
|
|
48
|
+
- Forms, Inputs, Validation
|
|
49
|
+
- Navbar, Dropdowns, Tabs
|
|
50
|
+
- Alerts, Badges, Progress bars
|
|
51
|
+
- Grid system, Flexbox utilities
|
|
52
|
+
|
|
53
|
+
### Resources
|
|
54
|
+
|
|
55
|
+
- [Bootstrap Docs](https://getbootstrap.com/docs/5.3/)
|
|
56
|
+
- [Bootstrap Icons](https://icons.getbootstrap.com/)
|
|
57
|
+
- [Bootstrap Examples](https://getbootstrap.com/docs/5.3/examples/)
|
|
58
|
+
|
|
59
|
+
## Tailwind CSS
|
|
60
|
+
|
|
61
|
+
### What's Included
|
|
62
|
+
|
|
63
|
+
When you choose Tailwind, the CLI automatically adds:
|
|
64
|
+
- Tailwind CSS CDN (Play CDN)
|
|
65
|
+
- Custom color configuration
|
|
66
|
+
- Updated Navbar with Tailwind classes
|
|
67
|
+
- Updated Footer with Tailwind classes
|
|
68
|
+
|
|
69
|
+
### Using Tailwind
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
// Example: Tailwind Button
|
|
73
|
+
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
|
|
74
|
+
Click Me
|
|
75
|
+
</button>
|
|
76
|
+
|
|
77
|
+
// Example: Tailwind Card
|
|
78
|
+
<div class="bg-white shadow-lg rounded-lg p-6">
|
|
79
|
+
<h2 class="text-2xl font-bold mb-4">Card Title</h2>
|
|
80
|
+
<p class="text-gray-700">Some content</p>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
// Example: Tailwind Grid
|
|
84
|
+
<div class="container mx-auto">
|
|
85
|
+
<div class="grid grid-cols-2 gap-4">
|
|
86
|
+
<div>Column 1</div>
|
|
87
|
+
<div>Column 2</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Tailwind Utilities
|
|
93
|
+
|
|
94
|
+
Common utilities:
|
|
95
|
+
- Layout: `flex`, `grid`, `container`
|
|
96
|
+
- Spacing: `p-4`, `m-2`, `space-x-4`
|
|
97
|
+
- Colors: `bg-blue-500`, `text-red-600`
|
|
98
|
+
- Typography: `text-xl`, `font-bold`
|
|
99
|
+
- Effects: `shadow-lg`, `rounded-lg`
|
|
100
|
+
|
|
101
|
+
### Custom Colors
|
|
102
|
+
|
|
103
|
+
Pre-configured colors:
|
|
104
|
+
- `primary` - #61dafb (Aziz blue)
|
|
105
|
+
- `dark` - #282c34 (Dark background)
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
<div class="bg-primary text-dark">Custom colors!</div>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Resources
|
|
112
|
+
|
|
113
|
+
- [Tailwind Docs](https://tailwindcss.com/docs)
|
|
114
|
+
- [Tailwind Cheat Sheet](https://nerdcave.com/tailwind-cheat-sheet)
|
|
115
|
+
- [Tailwind Components](https://tailwindui.com/components)
|
|
116
|
+
|
|
117
|
+
## Custom CSS
|
|
118
|
+
|
|
119
|
+
### What's Included
|
|
120
|
+
|
|
121
|
+
The default custom CSS includes:
|
|
122
|
+
- Reset styles
|
|
123
|
+
- Navbar and Footer styles
|
|
124
|
+
- Card, Button, Form styles
|
|
125
|
+
- Utility classes
|
|
126
|
+
- Responsive design
|
|
127
|
+
|
|
128
|
+
### Using Custom CSS
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
// Example: Custom Button
|
|
132
|
+
<button class="btn btn-primary">Click Me</button>
|
|
133
|
+
|
|
134
|
+
// Example: Custom Card
|
|
135
|
+
<div class="card">
|
|
136
|
+
<h2>Card Title</h2>
|
|
137
|
+
<p>Some content</p>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
// Example: Custom Form
|
|
141
|
+
<form>
|
|
142
|
+
<input type="text" placeholder="Enter text" />
|
|
143
|
+
<button class="btn btn-primary">Submit</button>
|
|
144
|
+
</form>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Available Classes
|
|
148
|
+
|
|
149
|
+
**Buttons:**
|
|
150
|
+
- `.btn` - Base button
|
|
151
|
+
- `.btn-primary` - Primary button (blue)
|
|
152
|
+
- `.btn-danger` - Danger button (red)
|
|
153
|
+
- `.btn-grey` - Grey button
|
|
154
|
+
|
|
155
|
+
**Layout:**
|
|
156
|
+
- `.card` - Card container
|
|
157
|
+
- `.count-display` - Large number display
|
|
158
|
+
- `.counter-actions` - Button group
|
|
159
|
+
|
|
160
|
+
**Forms:**
|
|
161
|
+
- `input`, `textarea` - Styled inputs
|
|
162
|
+
- `form` - Styled form
|
|
163
|
+
|
|
164
|
+
## Switching Frameworks
|
|
165
|
+
|
|
166
|
+
### After Project Creation
|
|
167
|
+
|
|
168
|
+
If you want to switch frameworks after creating your project:
|
|
169
|
+
|
|
170
|
+
**To Bootstrap:**
|
|
171
|
+
1. Add Bootstrap CDN to `app.html`:
|
|
172
|
+
```html
|
|
173
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
174
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
2. Update your components with Bootstrap classes
|
|
178
|
+
|
|
179
|
+
**To Tailwind:**
|
|
180
|
+
1. Add Tailwind CDN to `app.html`:
|
|
181
|
+
```html
|
|
182
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
2. Update your components with Tailwind classes
|
|
186
|
+
|
|
187
|
+
**To Custom CSS:**
|
|
188
|
+
1. Remove framework CDN links from `app.html`
|
|
189
|
+
2. Update your components with custom classes
|
|
190
|
+
|
|
191
|
+
## Best Practices
|
|
192
|
+
|
|
193
|
+
### Bootstrap
|
|
194
|
+
- Use semantic HTML with Bootstrap classes
|
|
195
|
+
- Leverage Bootstrap's grid system
|
|
196
|
+
- Use Bootstrap components for consistency
|
|
197
|
+
- Customize with Bootstrap variables
|
|
198
|
+
|
|
199
|
+
### Tailwind
|
|
200
|
+
- Use utility classes directly in JSX
|
|
201
|
+
- Combine utilities for complex designs
|
|
202
|
+
- Use responsive prefixes (`md:`, `lg:`)
|
|
203
|
+
- Extract common patterns into components
|
|
204
|
+
|
|
205
|
+
### Custom CSS
|
|
206
|
+
- Keep styles in `<style>` tag in `app.html`
|
|
207
|
+
- Use BEM naming convention
|
|
208
|
+
- Create reusable utility classes
|
|
209
|
+
- Keep specificity low
|
|
210
|
+
|
|
211
|
+
## Tips
|
|
212
|
+
|
|
213
|
+
1. **Consistency** - Stick to one framework per project
|
|
214
|
+
2. **Performance** - CDN links are cached by browsers
|
|
215
|
+
3. **Customization** - All frameworks can be customized
|
|
216
|
+
4. **Learning** - Start with one framework and master it
|
|
217
|
+
5. **Components** - Build reusable components regardless of framework
|
|
218
|
+
|
|
219
|
+
## Examples
|
|
220
|
+
|
|
221
|
+
Check the example pages in your project to see the chosen framework in action!
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Styling Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Aziz App uses external CSS files instead of inline styles for better organization and maintainability.
|
|
6
|
+
|
|
7
|
+
## File Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
styles/
|
|
11
|
+
āāā globals.css ā Default custom CSS
|
|
12
|
+
āāā tailwind.css ā Tailwind CSS (when selected)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## globals.css
|
|
16
|
+
|
|
17
|
+
The default stylesheet that includes:
|
|
18
|
+
- CSS Reset
|
|
19
|
+
- Base body styles
|
|
20
|
+
- Navbar and Footer styles
|
|
21
|
+
- Card, Button, Form components
|
|
22
|
+
- Typography styles
|
|
23
|
+
- Utility classes
|
|
24
|
+
|
|
25
|
+
### Usage
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<!-- Already included in app.html -->
|
|
29
|
+
<link rel="stylesheet" href="styles/globals.css">
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Available Classes
|
|
33
|
+
|
|
34
|
+
**Layout:**
|
|
35
|
+
- `.card` - White card with shadow
|
|
36
|
+
- `#root` - Main content wrapper
|
|
37
|
+
|
|
38
|
+
**Buttons:**
|
|
39
|
+
- `.btn` - Base button style
|
|
40
|
+
- `.btn-primary` - Primary button (blue)
|
|
41
|
+
- `.btn-danger` - Danger button (red)
|
|
42
|
+
- `.btn-grey` - Grey button
|
|
43
|
+
|
|
44
|
+
**Counter:**
|
|
45
|
+
- `.count-display` - Large number display
|
|
46
|
+
- `.counter-actions` - Button group
|
|
47
|
+
|
|
48
|
+
**Forms:**
|
|
49
|
+
- `input`, `textarea` - Styled form inputs
|
|
50
|
+
- `form` - Flex column layout
|
|
51
|
+
|
|
52
|
+
**404:**
|
|
53
|
+
- `.not-found` - Centered 404 page
|
|
54
|
+
|
|
55
|
+
## tailwind.css
|
|
56
|
+
|
|
57
|
+
When using Tailwind CSS, this file provides:
|
|
58
|
+
- Tailwind directives (@tailwind base, components, utilities)
|
|
59
|
+
- Custom component classes
|
|
60
|
+
- Custom utility classes
|
|
61
|
+
- Theme extensions
|
|
62
|
+
|
|
63
|
+
### Custom Colors
|
|
64
|
+
|
|
65
|
+
```css
|
|
66
|
+
.text-primary { color: #61dafb; }
|
|
67
|
+
.bg-primary { background-color: #61dafb; }
|
|
68
|
+
.text-dark { color: #282c34; }
|
|
69
|
+
.bg-dark { background-color: #282c34; }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Custom Components
|
|
73
|
+
|
|
74
|
+
All the same classes from globals.css are available as Tailwind components:
|
|
75
|
+
- `.card`
|
|
76
|
+
- `.btn`, `.btn-primary`, `.btn-danger`, `.btn-grey`
|
|
77
|
+
- `.count-display`
|
|
78
|
+
- `.counter-actions`
|
|
79
|
+
|
|
80
|
+
## Customizing Styles
|
|
81
|
+
|
|
82
|
+
### Modify globals.css
|
|
83
|
+
|
|
84
|
+
Edit `styles/globals.css` to change:
|
|
85
|
+
- Colors
|
|
86
|
+
- Spacing
|
|
87
|
+
- Typography
|
|
88
|
+
- Component styles
|
|
89
|
+
|
|
90
|
+
```css
|
|
91
|
+
/* Example: Change primary color */
|
|
92
|
+
nav .brand {
|
|
93
|
+
color: #your-color;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.btn-primary {
|
|
97
|
+
background-color: #your-color;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Modify tailwind.css
|
|
102
|
+
|
|
103
|
+
Edit `styles/tailwind.css` to:
|
|
104
|
+
- Add custom components
|
|
105
|
+
- Add custom utilities
|
|
106
|
+
- Modify theme
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
@layer components {
|
|
110
|
+
.my-custom-card {
|
|
111
|
+
@apply bg-white p-6 rounded-lg shadow-xl;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Add New CSS Files
|
|
117
|
+
|
|
118
|
+
1. Create a new CSS file in `styles/`
|
|
119
|
+
2. Link it in `app.html`:
|
|
120
|
+
|
|
121
|
+
```html
|
|
122
|
+
<link rel="stylesheet" href="styles/my-custom.css">
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Best Practices
|
|
126
|
+
|
|
127
|
+
### Organization
|
|
128
|
+
- Keep global styles in `globals.css`
|
|
129
|
+
- Create separate files for large features
|
|
130
|
+
- Use meaningful class names
|
|
131
|
+
|
|
132
|
+
### Performance
|
|
133
|
+
- Minimize CSS file size
|
|
134
|
+
- Avoid deep nesting
|
|
135
|
+
- Use CSS variables for themes
|
|
136
|
+
|
|
137
|
+
### Maintainability
|
|
138
|
+
- Comment complex styles
|
|
139
|
+
- Group related styles
|
|
140
|
+
- Use consistent naming
|
|
141
|
+
|
|
142
|
+
## Responsive Design
|
|
143
|
+
|
|
144
|
+
### Custom CSS
|
|
145
|
+
|
|
146
|
+
```css
|
|
147
|
+
/* Mobile first approach */
|
|
148
|
+
.card {
|
|
149
|
+
padding: 16px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Tablet and up */
|
|
153
|
+
@media (min-width: 768px) {
|
|
154
|
+
.card {
|
|
155
|
+
padding: 24px;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Tailwind CSS
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// Use responsive prefixes
|
|
164
|
+
<div class="p-4 md:p-6 lg:p-8">
|
|
165
|
+
Responsive padding
|
|
166
|
+
</div>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Dark Mode
|
|
170
|
+
|
|
171
|
+
### Custom CSS
|
|
172
|
+
|
|
173
|
+
```css
|
|
174
|
+
/* Add dark mode support */
|
|
175
|
+
@media (prefers-color-scheme: dark) {
|
|
176
|
+
body {
|
|
177
|
+
background-color: #1a1a1a;
|
|
178
|
+
color: #f5f5f5;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.card {
|
|
182
|
+
background-color: #2a2a2a;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Tailwind CSS
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
// Use dark: prefix
|
|
191
|
+
<div class="bg-white dark:bg-gray-800">
|
|
192
|
+
Dark mode support
|
|
193
|
+
</div>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## CSS Variables
|
|
197
|
+
|
|
198
|
+
### Define Variables
|
|
199
|
+
|
|
200
|
+
```css
|
|
201
|
+
:root {
|
|
202
|
+
--primary-color: #61dafb;
|
|
203
|
+
--dark-color: #282c34;
|
|
204
|
+
--spacing: 16px;
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Use Variables
|
|
209
|
+
|
|
210
|
+
```css
|
|
211
|
+
.btn-primary {
|
|
212
|
+
background-color: var(--primary-color);
|
|
213
|
+
padding: var(--spacing);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Tips
|
|
218
|
+
|
|
219
|
+
1. **Start Simple** - Use the provided classes first
|
|
220
|
+
2. **Be Consistent** - Stick to one naming convention
|
|
221
|
+
3. **Mobile First** - Design for mobile, enhance for desktop
|
|
222
|
+
4. **Test Browsers** - Check in different browsers
|
|
223
|
+
5. **Optimize** - Remove unused styles
|
|
224
|
+
|
|
225
|
+
## Examples
|
|
226
|
+
|
|
227
|
+
### Custom Button
|
|
228
|
+
|
|
229
|
+
```css
|
|
230
|
+
/* In globals.css */
|
|
231
|
+
.btn-success {
|
|
232
|
+
background-color: #28a745;
|
|
233
|
+
color: white;
|
|
234
|
+
padding: 10px 22px;
|
|
235
|
+
border-radius: 8px;
|
|
236
|
+
border: none;
|
|
237
|
+
cursor: pointer;
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
// In your component
|
|
243
|
+
<button class="btn-success">Success!</button>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Custom Card
|
|
247
|
+
|
|
248
|
+
```css
|
|
249
|
+
/* In globals.css */
|
|
250
|
+
.card-highlight {
|
|
251
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
252
|
+
color: white;
|
|
253
|
+
padding: 24px;
|
|
254
|
+
border-radius: 10px;
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
// In your component
|
|
260
|
+
<div class="card-highlight">
|
|
261
|
+
<h2>Highlighted Card</h2>
|
|
262
|
+
</div>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Resources
|
|
266
|
+
|
|
267
|
+
- [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS)
|
|
268
|
+
- [CSS Tricks](https://css-tricks.com/)
|
|
269
|
+
- [Can I Use](https://caniuse.com/) - Browser compatibility
|
package/template/package.json
CHANGED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
GLOBAL STYLES
|
|
3
|
+
Base styles that work with all CSS frameworks
|
|
4
|
+
============================================================ */
|
|
5
|
+
|
|
6
|
+
/* Reset */
|
|
7
|
+
* {
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 0;
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Body */
|
|
14
|
+
body {
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
16
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
17
|
+
sans-serif;
|
|
18
|
+
-webkit-font-smoothing: antialiased;
|
|
19
|
+
-moz-osx-font-smoothing: grayscale;
|
|
20
|
+
background-color: #f5f5f5;
|
|
21
|
+
color: #333;
|
|
22
|
+
min-height: 100vh;
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Code */
|
|
28
|
+
code {
|
|
29
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* ============================================================
|
|
33
|
+
CUSTOM CSS FRAMEWORK STYLES (when not using Bootstrap/Tailwind)
|
|
34
|
+
============================================================ */
|
|
35
|
+
|
|
36
|
+
/* Navbar */
|
|
37
|
+
nav {
|
|
38
|
+
background-color: #282c34;
|
|
39
|
+
padding: 16px 32px;
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
gap: 24px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
nav .brand {
|
|
46
|
+
color: #61dafb;
|
|
47
|
+
font-size: 20px;
|
|
48
|
+
font-weight: bold;
|
|
49
|
+
cursor: pointer;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
nav a {
|
|
53
|
+
color: #ffffffcc;
|
|
54
|
+
text-decoration: none;
|
|
55
|
+
font-size: 15px;
|
|
56
|
+
transition: color 0.2s;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
nav a:hover,
|
|
60
|
+
nav a.active {
|
|
61
|
+
color: #61dafb;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Page wrapper */
|
|
65
|
+
#root {
|
|
66
|
+
flex: 1;
|
|
67
|
+
padding: 40px 32px;
|
|
68
|
+
max-width: 900px;
|
|
69
|
+
width: 100%;
|
|
70
|
+
margin: 0 auto;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Footer */
|
|
74
|
+
footer {
|
|
75
|
+
background-color: #282c34;
|
|
76
|
+
color: #888;
|
|
77
|
+
text-align: center;
|
|
78
|
+
padding: 16px;
|
|
79
|
+
font-size: 13px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Typography */
|
|
83
|
+
h1 {
|
|
84
|
+
margin-bottom: 16px;
|
|
85
|
+
color: #282c34;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
h2 {
|
|
89
|
+
margin-bottom: 12px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
p {
|
|
93
|
+
line-height: 1.6;
|
|
94
|
+
margin-bottom: 12px;
|
|
95
|
+
color: #555;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Card */
|
|
99
|
+
.card {
|
|
100
|
+
background: white;
|
|
101
|
+
border-radius: 10px;
|
|
102
|
+
padding: 24px;
|
|
103
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
104
|
+
margin-bottom: 20px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Buttons */
|
|
108
|
+
.btn {
|
|
109
|
+
display: inline-block;
|
|
110
|
+
padding: 10px 22px;
|
|
111
|
+
border: none;
|
|
112
|
+
border-radius: 8px;
|
|
113
|
+
cursor: pointer;
|
|
114
|
+
font-size: 15px;
|
|
115
|
+
transition: opacity 0.2s;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.btn:hover {
|
|
119
|
+
opacity: 0.85;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.btn-primary {
|
|
123
|
+
background-color: #61dafb;
|
|
124
|
+
color: #282c34;
|
|
125
|
+
font-weight: bold;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.btn-danger {
|
|
129
|
+
background-color: #ff6b6b;
|
|
130
|
+
color: white;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.btn-grey {
|
|
134
|
+
background-color: #ccc;
|
|
135
|
+
color: #333;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Counter */
|
|
139
|
+
.count-display {
|
|
140
|
+
font-size: 64px;
|
|
141
|
+
font-weight: bold;
|
|
142
|
+
color: #282c34;
|
|
143
|
+
margin: 16px 0;
|
|
144
|
+
text-align: center;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.counter-actions {
|
|
148
|
+
display: flex;
|
|
149
|
+
gap: 12px;
|
|
150
|
+
justify-content: center;
|
|
151
|
+
margin-top: 8px;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Forms */
|
|
155
|
+
form {
|
|
156
|
+
display: flex;
|
|
157
|
+
flex-direction: column;
|
|
158
|
+
gap: 12px;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
input,
|
|
162
|
+
textarea {
|
|
163
|
+
padding: 10px 14px;
|
|
164
|
+
border: 1px solid #ddd;
|
|
165
|
+
border-radius: 8px;
|
|
166
|
+
font-size: 15px;
|
|
167
|
+
outline: none;
|
|
168
|
+
transition: border-color 0.2s;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
input:focus,
|
|
172
|
+
textarea:focus {
|
|
173
|
+
border-color: #61dafb;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
textarea {
|
|
177
|
+
resize: vertical;
|
|
178
|
+
min-height: 100px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* 404 */
|
|
182
|
+
.not-found {
|
|
183
|
+
text-align: center;
|
|
184
|
+
padding: 60px 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.not-found h1 {
|
|
188
|
+
font-size: 80px;
|
|
189
|
+
color: #61dafb;
|
|
190
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
TAILWIND CSS STYLES
|
|
3
|
+
Custom styles when using Tailwind CSS
|
|
4
|
+
============================================================ */
|
|
5
|
+
|
|
6
|
+
@tailwind base;
|
|
7
|
+
@tailwind components;
|
|
8
|
+
@tailwind utilities;
|
|
9
|
+
|
|
10
|
+
/* Reset */
|
|
11
|
+
@layer base {
|
|
12
|
+
* {
|
|
13
|
+
@apply m-0 p-0 box-border;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
@apply min-h-screen flex flex-col bg-gray-50 text-gray-900;
|
|
18
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
19
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
20
|
+
sans-serif;
|
|
21
|
+
-webkit-font-smoothing: antialiased;
|
|
22
|
+
-moz-osx-font-smoothing: grayscale;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
code {
|
|
26
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Custom Components */
|
|
31
|
+
@layer components {
|
|
32
|
+
/* Page wrapper */
|
|
33
|
+
#root {
|
|
34
|
+
@apply flex-1 py-10 px-8 max-w-4xl w-full mx-auto;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Card */
|
|
38
|
+
.card {
|
|
39
|
+
@apply bg-white rounded-lg p-6 shadow-md mb-5;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Buttons */
|
|
43
|
+
.btn {
|
|
44
|
+
@apply inline-block py-2.5 px-6 border-0 rounded-lg cursor-pointer text-base transition-opacity;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.btn:hover {
|
|
48
|
+
@apply opacity-85;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.btn-primary {
|
|
52
|
+
@apply bg-primary text-dark font-bold;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.btn-danger {
|
|
56
|
+
@apply bg-red-500 text-white;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.btn-grey {
|
|
60
|
+
@apply bg-gray-300 text-gray-800;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Counter */
|
|
64
|
+
.count-display {
|
|
65
|
+
@apply text-6xl font-bold text-gray-800 my-4 text-center;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.counter-actions {
|
|
69
|
+
@apply flex gap-3 justify-center mt-2;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Forms */
|
|
73
|
+
form {
|
|
74
|
+
@apply flex flex-col gap-3;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
input,
|
|
78
|
+
textarea {
|
|
79
|
+
@apply py-2.5 px-3.5 border border-gray-300 rounded-lg text-base outline-none transition-colors;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
input:focus,
|
|
83
|
+
textarea:focus {
|
|
84
|
+
@apply border-primary ring-2 ring-primary ring-opacity-50;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
textarea {
|
|
88
|
+
@apply resize-y min-h-[100px];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* 404 */
|
|
92
|
+
.not-found {
|
|
93
|
+
@apply text-center py-16;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.not-found h1 {
|
|
97
|
+
@apply text-8xl text-primary;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Custom Utilities */
|
|
102
|
+
@layer utilities {
|
|
103
|
+
.text-primary {
|
|
104
|
+
color: #61dafb;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.bg-primary {
|
|
108
|
+
background-color: #61dafb;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.text-dark {
|
|
112
|
+
color: #282c34;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.bg-dark {
|
|
116
|
+
background-color: #282c34;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.border-primary {
|
|
120
|
+
border-color: #61dafb;
|
|
121
|
+
}
|
|
122
|
+
}
|