gladvn 0.2.14 → 0.2.16
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 +13 -13
- package/bin/cli.js +18 -18
- package/dist/dev/components/GladvnLogo.d.ts +10 -0
- package/dist/dev/components/{GladcnLogo.d.ts.map → GladvnLogo.d.ts.map} +1 -1
- package/dist/dev/showcase/overview.d.ts.map +1 -1
- package/llms.txt +10 -10
- package/package.json +8 -3
- package/scripts/clean-imports.ts +2 -2
- package/scripts/postinstall.cjs +4 -4
- package/src/dev/App.tsx +4 -4
- package/src/dev/components/{GladcnLogo.tsx → GladvnLogo.tsx} +4 -4
- package/src/dev/index.css +1 -1
- package/src/dev/sections/forms.tsx +1 -1
- package/src/dev/sections/overview.tsx +2 -2
- package/src/dev/showcase/navigation-menu.tsx +2 -2
- package/src/dev/showcase/overview.tsx +134 -98
- package/src/dev/showcase/separator.tsx +2 -2
- package/src/styles/tokens.css +2 -2
- package/dist/dev/components/GladcnLogo.d.ts +0 -10
- /package/src/styles/{gladcn.css → gladvn.css} +0 -0
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# 🌊
|
|
1
|
+
# 🌊 gladvn
|
|
2
2
|
|
|
3
|
-
> **✨ [Explore the Interactive Showcase & Documentation](https://
|
|
3
|
+
> **✨ [Explore the Interactive Showcase & Documentation](https://gladvn.vercel.app/)**
|
|
4
4
|
|
|
5
|
-
A highly composable, accessible, and beautifully designed React component library. Built on top of [shadcn/ui](https://ui.shadcn.com/), [Base UI](https://base-ui.com/), and powered by **Tailwind CSS v4+**, `
|
|
5
|
+
A highly composable, accessible, and beautifully designed React component library. Built on top of [shadcn/ui](https://ui.shadcn.com/), [Base UI](https://base-ui.com/), and powered by **Tailwind CSS v4+**, `gladvn` provides a robust, zero-magic foundation for your next web application.
|
|
6
6
|
|
|
7
|
-
Designed with strict architectural principles, `
|
|
7
|
+
Designed with strict architectural principles, `gladvn` is optimized not just for human developers, but specifically for **AI coding assistants**, ensuring predictable styling and maintenance.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -24,7 +24,7 @@ Designed with strict architectural principles, `gladcn` is optimized not just fo
|
|
|
24
24
|
> [!WARNING]
|
|
25
25
|
> **Please use `npx` to clone the components into your project instead of installing via `npm`.** While installing via `npm` works, using `npx` (Option 1) gives you full control over the source code and styling, which is the core philosophy and intended way to use this library.
|
|
26
26
|
|
|
27
|
-
There are two ways to use `
|
|
27
|
+
There are two ways to use `gladvn` in your project. We highly recommend **Option 1** for maximum flexibility.
|
|
28
28
|
|
|
29
29
|
### Option 1: Clone components to your project (Recommended)
|
|
30
30
|
|
|
@@ -34,7 +34,7 @@ This approach automatically copies all component source code, hooks, and styles
|
|
|
34
34
|
npx gladvn init
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
*By default, this will create a `
|
|
37
|
+
*By default, this will create a `gladvn` folder at your project root. If you prefer to place it elsewhere, specify the path:*
|
|
38
38
|
```bash
|
|
39
39
|
npx gladvn init components/ui
|
|
40
40
|
```
|
|
@@ -42,7 +42,7 @@ npx gladvn init components/ui
|
|
|
42
42
|
**Usage:**
|
|
43
43
|
```tsx
|
|
44
44
|
// Import directly from your local folder
|
|
45
|
-
import { Button } from "@/
|
|
45
|
+
import { Button } from "@/gladvn/components/micro/button";
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
### Option 2: Install as an npm package
|
|
@@ -59,11 +59,11 @@ Update your main CSS file to scan the library for Tailwind utility classes and i
|
|
|
59
59
|
```css
|
|
60
60
|
@import "tailwindcss";
|
|
61
61
|
|
|
62
|
-
/* 1. Tell Tailwind to scan
|
|
62
|
+
/* 1. Tell Tailwind to scan gladvn for utility classes */
|
|
63
63
|
@source "../node_modules/gladvn/dist";
|
|
64
64
|
|
|
65
|
-
/* 2. Import
|
|
66
|
-
@import "gladvn/
|
|
65
|
+
/* 2. Import gladvn global CSS variables */
|
|
66
|
+
@import "gladvn/gladvn.css";
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
**Usage:**
|
|
@@ -75,14 +75,14 @@ import { Button, Card, CardHeader, CardTitle, CardContent } from "gladvn";
|
|
|
75
75
|
|
|
76
76
|
## 🏗️ Architecture: Micro vs. Macro
|
|
77
77
|
|
|
78
|
-
Most component libraries fail in their second year because developers become afraid to modify the core files. `
|
|
78
|
+
Most component libraries fail in their second year because developers become afraid to modify the core files. `gladvn` solves this with explicit architectural boundaries:
|
|
79
79
|
|
|
80
80
|
- **Micro Components** (`components/micro/`): "Dumb" presentational primitives (e.g., `Button`, `Badge`, `Input`). They do not contain internal React state (`useState`) or business logic. They strictly rely on props for rendering and avoid dictating layout boundaries (like `w-full`).
|
|
81
81
|
- **Macro Components** (`components/macro/`): "Smart" presets and compositions (e.g., `DatePicker`, `SelectPreset`, `PaginationPreset`). These components combine multiple Micro components and manage complex state, accessibility (a11y), and interactions. Macro components strictly reuse Micro components via pure composition.
|
|
82
82
|
|
|
83
83
|
## 🎨 Theming & Customization
|
|
84
84
|
|
|
85
|
-
`
|
|
85
|
+
`gladvn` uses standard CSS variables for theming, ensuring zero runtime parsing overhead. You can easily override these variables in your own CSS file.
|
|
86
86
|
|
|
87
87
|
```css
|
|
88
88
|
:root {
|
|
@@ -92,7 +92,7 @@ Most component libraries fail in their second year because developers become afr
|
|
|
92
92
|
}
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
If you cloned the components via `npx` (Option 1), you can modify the CSS directly inside the `
|
|
95
|
+
If you cloned the components via `npx` (Option 1), you can modify the CSS directly inside the `gladvn/styles/` directory.
|
|
96
96
|
|
|
97
97
|
---
|
|
98
98
|
|
package/bin/cli.js
CHANGED
|
@@ -15,17 +15,17 @@ const reset = "\x1b[0m";
|
|
|
15
15
|
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
16
16
|
console.log(`
|
|
17
17
|
Usage:
|
|
18
|
-
npx
|
|
18
|
+
npx gladvn init [destination]
|
|
19
19
|
|
|
20
20
|
Options:
|
|
21
|
-
[destination] The folder where components will be copied. Defaults to "
|
|
21
|
+
[destination] The folder where components will be copied. Defaults to "gladvn".
|
|
22
22
|
--help, -h Show this help message.
|
|
23
23
|
`);
|
|
24
24
|
process.exit(0);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// Find destination
|
|
28
|
-
let userDest = "
|
|
28
|
+
let userDest = "gladvn";
|
|
29
29
|
const args = process.argv.slice(2);
|
|
30
30
|
|
|
31
31
|
if (args[0] === "init") {
|
|
@@ -123,7 +123,7 @@ async function selectOption(message, options) {
|
|
|
123
123
|
|
|
124
124
|
async function main() {
|
|
125
125
|
console.log(`\n${cyan}╔══════════════════════════════════════════════════════════════════╗${reset}`);
|
|
126
|
-
console.log(`${cyan}║ ${bold}
|
|
126
|
+
console.log(`${cyan}║ ${bold}gladvn${reset}${cyan} — Initialization ║${reset}`);
|
|
127
127
|
console.log(`${cyan}╚══════════════════════════════════════════════════════════════════╝${reset}\n`);
|
|
128
128
|
|
|
129
129
|
let targetCss = "app/globals.css";
|
|
@@ -169,7 +169,7 @@ async function main() {
|
|
|
169
169
|
console.log(`\x1b[32m✔\x1b[0m \x1b[1mFound global CSS file\x1b[0m \x1b[90m…\x1b[0m \x1b[36m${targetCss}\x1b[0m`);
|
|
170
170
|
} else {
|
|
171
171
|
// We have more than 1 file, and environment is TTY
|
|
172
|
-
targetCss = await selectOption("Which CSS file should we inject
|
|
172
|
+
targetCss = await selectOption("Which CSS file should we inject gladvn styles into?", cssFiles);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
let cssFilePath = null;
|
|
@@ -184,7 +184,7 @@ async function main() {
|
|
|
184
184
|
dirsToCopy = fs.readdirSync(srcDir).filter(item => !excludeList.includes(item));
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
console.log(`\n\x1b[36mInitializing
|
|
187
|
+
console.log(`\n\x1b[36mInitializing gladvn components into ${userDest}...\x1b[0m`);
|
|
188
188
|
|
|
189
189
|
if (!fs.existsSync(destPath)) {
|
|
190
190
|
fs.mkdirSync(destPath, { recursive: true });
|
|
@@ -211,10 +211,10 @@ async function main() {
|
|
|
211
211
|
|
|
212
212
|
// 2. Inject CSS import
|
|
213
213
|
if (cssFilePath && fs.existsSync(cssFilePath)) {
|
|
214
|
-
const
|
|
214
|
+
const gladvnCssPath = path.resolve(destPath, "styles", "gladvn.css");
|
|
215
215
|
const cssDir = path.dirname(cssFilePath);
|
|
216
216
|
|
|
217
|
-
let relPath = path.relative(cssDir,
|
|
217
|
+
let relPath = path.relative(cssDir, gladvnCssPath);
|
|
218
218
|
if (!relPath.startsWith('.')) {
|
|
219
219
|
relPath = './' + relPath;
|
|
220
220
|
}
|
|
@@ -238,15 +238,15 @@ async function main() {
|
|
|
238
238
|
console.log(`\x1b[32m✔ Injected CSS import into ${targetCss}\x1b[0m`);
|
|
239
239
|
}
|
|
240
240
|
} else if (targetCss) {
|
|
241
|
-
console.log(`\x1b[33m⚠ CSS file not found at ${targetCss}. You will need to manually import ${userDest}/styles/
|
|
241
|
+
console.log(`\x1b[33m⚠ CSS file not found at ${targetCss}. You will need to manually import ${userDest}/styles/gladvn.css\x1b[0m`);
|
|
242
242
|
} else {
|
|
243
|
-
console.log(`\x1b[33m⚠ No CSS file configured. You will need to manually import ${userDest}/styles/
|
|
243
|
+
console.log(`\x1b[33m⚠ No CSS file configured. You will need to manually import ${userDest}/styles/gladvn.css into your project.\x1b[0m`);
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
// 2.5 Configure tsconfig.json
|
|
247
247
|
if (isTTY) {
|
|
248
248
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
249
|
-
const answer = await new Promise((resolve) => rl.question(`\n${yellow}? Do you want to configure tsconfig.json to use the @
|
|
249
|
+
const answer = await new Promise((resolve) => rl.question(`\n${yellow}? Do you want to configure tsconfig.json to use the @gladvn/* alias? (Y/n)${reset} `, resolve));
|
|
250
250
|
rl.close();
|
|
251
251
|
|
|
252
252
|
if (answer.trim().toLowerCase() !== 'n') {
|
|
@@ -255,20 +255,20 @@ async function main() {
|
|
|
255
255
|
let tsContent = fs.readFileSync(tsconfigPath, 'utf8');
|
|
256
256
|
const aliasPath = `./${userDest}/*`;
|
|
257
257
|
|
|
258
|
-
if (tsContent.includes('"@
|
|
259
|
-
console.log(`\x1b[90m⏭ @
|
|
258
|
+
if (tsContent.includes('"@gladvn/*"')) {
|
|
259
|
+
console.log(`\x1b[90m⏭ @gladvn/* alias already exists in tsconfig.json\x1b[0m`);
|
|
260
260
|
} else {
|
|
261
261
|
const pathsRegex = /"paths"\s*:\s*\{/;
|
|
262
262
|
if (pathsRegex.test(tsContent)) {
|
|
263
|
-
tsContent = tsContent.replace(pathsRegex, `"paths": {\n "@
|
|
263
|
+
tsContent = tsContent.replace(pathsRegex, `"paths": {\n "@gladvn/*": ["${aliasPath}"],`);
|
|
264
264
|
fs.writeFileSync(tsconfigPath, tsContent);
|
|
265
|
-
console.log(`\x1b[32m✔ Injected @
|
|
265
|
+
console.log(`\x1b[32m✔ Injected @gladvn/* alias into existing paths\x1b[0m`);
|
|
266
266
|
} else {
|
|
267
267
|
const compilerOptionsRegex = /"compilerOptions"\s*:\s*\{/;
|
|
268
268
|
if (compilerOptionsRegex.test(tsContent)) {
|
|
269
|
-
tsContent = tsContent.replace(compilerOptionsRegex, `"compilerOptions": {\n "paths": {\n "@
|
|
269
|
+
tsContent = tsContent.replace(compilerOptionsRegex, `"compilerOptions": {\n "paths": {\n "@gladvn/*": ["${aliasPath}"]\n },`);
|
|
270
270
|
fs.writeFileSync(tsconfigPath, tsContent);
|
|
271
|
-
console.log(`\x1b[32m✔ Injected paths object and @
|
|
271
|
+
console.log(`\x1b[32m✔ Injected paths object and @gladvn/* alias\x1b[0m`);
|
|
272
272
|
} else {
|
|
273
273
|
console.log(`\x1b[33m⚠ Could not find compilerOptions in tsconfig.json. Please add manually.\x1b[0m`);
|
|
274
274
|
}
|
|
@@ -316,7 +316,7 @@ async function main() {
|
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
if (!hasErrors) {
|
|
319
|
-
console.log(`\n\x1b[32m✨ Successfully initialized
|
|
319
|
+
console.log(`\n\x1b[32m✨ Successfully initialized gladvn files in ${userDest}!\x1b[0m`);
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface GladvnLogoProps {
|
|
2
|
+
className?: string;
|
|
3
|
+
/** Size of the icon SVG */
|
|
4
|
+
iconSize?: string;
|
|
5
|
+
/** Show icon only (default) or icon + wordmark */
|
|
6
|
+
variant?: "icon" | "wordmark";
|
|
7
|
+
}
|
|
8
|
+
export declare function GladvnLogo({ className, iconSize, variant, }: GladvnLogoProps): import("react").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=GladvnLogo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"GladvnLogo.d.ts","sourceRoot":"","sources":["../../../src/dev/components/GladvnLogo.tsx"],"names":[],"mappings":"AAEA,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;CAC/B;AAED,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,QAAmB,EACnB,OAAgB,GACjB,EAAE,eAAe,+BAiEjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overview.d.ts","sourceRoot":"","sources":["../../../src/dev/showcase/overview.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"overview.d.ts","sourceRoot":"","sources":["../../../src/dev/showcase/overview.tsx"],"names":[],"mappings":"AAmFA,MAAM,CAAC,OAAO,UAAU,eAAe,gCAkiCtC"}
|
package/llms.txt
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
#
|
|
1
|
+
# gladvn UI - AI Guidelines
|
|
2
2
|
|
|
3
|
-
You are an AI Coding Assistant helping a developer use the `
|
|
4
|
-
`
|
|
3
|
+
You are an AI Coding Assistant helping a developer use the `gladvn` UI library.
|
|
4
|
+
`gladvn` is a React component library built on top of Radix UI and Tailwind CSS, focusing on beautiful, accessible, and highly composable components.
|
|
5
5
|
|
|
6
|
-
Follow these strict guidelines when generating or modifying code that uses `
|
|
6
|
+
Follow these strict guidelines when generating or modifying code that uses `gladvn`:
|
|
7
7
|
|
|
8
8
|
## 1. Imports
|
|
9
9
|
- **Always** import components directly from the package root:
|
|
10
|
-
`import { Button, Card, Dialog } from "
|
|
11
|
-
- **Never** import from internal paths like
|
|
10
|
+
`import { Button, Card, Dialog } from "gladvn";`
|
|
11
|
+
- **Never** import from internal paths like `gladvn/dist/...` or `src/components/ui/...`.
|
|
12
12
|
|
|
13
13
|
## 2. Composition over Configuration
|
|
14
|
-
`
|
|
14
|
+
`gladvn` heavily uses a composable architecture. When building complex UI, always use the provided sub-components rather than passing large configuration objects.
|
|
15
15
|
|
|
16
16
|
**Correct (Composition):**
|
|
17
17
|
```tsx
|
|
18
|
-
import { Card, CardHeader, CardTitle, CardContent } from "
|
|
18
|
+
import { Card, CardHeader, CardTitle, CardContent } from "gladvn";
|
|
19
19
|
|
|
20
20
|
<Card>
|
|
21
21
|
<CardHeader>
|
|
@@ -36,7 +36,7 @@ import { Card, CardHeader, CardTitle, CardContent } from "@duongy96/gladcn";
|
|
|
36
36
|
## 3. Form Fields
|
|
37
37
|
When building forms, use the `Field` wrapper to automatically handle accessibility, labels, and error messages.
|
|
38
38
|
```tsx
|
|
39
|
-
import { Field, FieldLabel, FieldContent, FieldError, Input } from "
|
|
39
|
+
import { Field, FieldLabel, FieldContent, FieldError, Input } from "gladvn";
|
|
40
40
|
|
|
41
41
|
<Field error={errors.email?.message}>
|
|
42
42
|
<FieldLabel>Email Address</FieldLabel>
|
|
@@ -68,7 +68,7 @@ Always structure them with their respective Trigger and Content wrappers.
|
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
## 6. Icons
|
|
71
|
-
`
|
|
71
|
+
`gladvn` does not bundle an icon library by default, but relies on standard SVG icons (like `lucide-react`). When adding icons inside components like `Button` or `Empty`, use standard SVG elements or Lucide components.
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
*Note to AI: Always prioritize reading the JSDoc/TSDoc definitions of the imported components if you are unsure of the props.*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gladvn",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DO NOT 'npm install'. Use 'npx gladvn init' instead! A highly composable React component library built with Tailwind CSS.",
|
|
6
6
|
"keywords": [
|
|
@@ -12,11 +12,16 @@
|
|
|
12
12
|
"radix-ui"
|
|
13
13
|
],
|
|
14
14
|
"license": "MIT",
|
|
15
|
+
"homepage": "https://gladvn.vercel.app",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/duongacy/gladcn"
|
|
19
|
+
},
|
|
15
20
|
"main": "./dist/index.cjs",
|
|
16
21
|
"module": "./dist/index.js",
|
|
17
22
|
"types": "./dist/index.d.ts",
|
|
18
23
|
"bin": {
|
|
19
|
-
"
|
|
24
|
+
"gladvn": "bin/cli.js"
|
|
20
25
|
},
|
|
21
26
|
"exports": {
|
|
22
27
|
".": {
|
|
@@ -29,7 +34,7 @@
|
|
|
29
34
|
"default": "./dist/index.cjs"
|
|
30
35
|
}
|
|
31
36
|
},
|
|
32
|
-
"./
|
|
37
|
+
"./gladvn.css": "./src/styles/gladvn.css",
|
|
33
38
|
"./tokens.css": "./src/styles/tokens.css"
|
|
34
39
|
},
|
|
35
40
|
"files": [
|
package/scripts/clean-imports.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Project } from "ts-morph";
|
|
2
2
|
|
|
3
3
|
const project = new Project({
|
|
4
|
-
tsConfigFilePath: "/Users/y/Desktop/github/
|
|
4
|
+
tsConfigFilePath: "/Users/y/Desktop/github/gladvn/tsconfig.json",
|
|
5
5
|
});
|
|
6
6
|
|
|
7
7
|
const sourceFiles = project.getSourceFiles(
|
|
8
|
-
"/Users/y/Desktop/github/
|
|
8
|
+
"/Users/y/Desktop/github/gladvn/src/dev/showcase/**/*.tsx",
|
|
9
9
|
);
|
|
10
10
|
console.log(`Found ${sourceFiles.length} showcase files to process.`);
|
|
11
11
|
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -85,7 +85,7 @@ function injectImports(cssFilePath, tokensRelPath) {
|
|
|
85
85
|
let content = fs.readFileSync(cssFilePath, "utf8");
|
|
86
86
|
|
|
87
87
|
// Check if already configured
|
|
88
|
-
if (content.includes("gladvn/
|
|
88
|
+
if (content.includes("gladvn/gladvn.css")) {
|
|
89
89
|
console.log(
|
|
90
90
|
`${dim} ⏭ gladvn already configured in this file — skipped${reset}`,
|
|
91
91
|
);
|
|
@@ -95,7 +95,7 @@ function injectImports(cssFilePath, tokensRelPath) {
|
|
|
95
95
|
// Build the import lines
|
|
96
96
|
const sourceDirective = `@source "../node_modules/gladvn/dist";`;
|
|
97
97
|
const tokensImport = `@import "${tokensRelPath}";`;
|
|
98
|
-
const globalsImport = `@import "gladvn/
|
|
98
|
+
const globalsImport = `@import "gladvn/gladvn.css";`;
|
|
99
99
|
|
|
100
100
|
const imports = `\n/* gladvn */\n${sourceDirective}\n${tokensImport}\n${globalsImport}\n`;
|
|
101
101
|
|
|
@@ -109,7 +109,7 @@ function injectImports(cssFilePath, tokensRelPath) {
|
|
|
109
109
|
|
|
110
110
|
fs.writeFileSync(cssFilePath, content);
|
|
111
111
|
console.log(
|
|
112
|
-
`${green} ✅ Injected
|
|
112
|
+
`${green} ✅ Injected gladvn imports into ${path.basename(
|
|
113
113
|
cssFilePath,
|
|
114
114
|
)}${reset}`,
|
|
115
115
|
);
|
|
@@ -188,7 +188,7 @@ ${cyan}╔═══════════════════════
|
|
|
188
188
|
║ ${green}@import "tailwindcss";${cyan} ║
|
|
189
189
|
║ ${green}@source "../node_modules/gladvn/dist";${cyan} ║
|
|
190
190
|
║ ${green}@import "./tokens.css";${cyan} ║
|
|
191
|
-
║ ${green}@import "gladvn/
|
|
191
|
+
║ ${green}@import "gladvn/gladvn.css";${cyan} ║
|
|
192
192
|
║ ║
|
|
193
193
|
║ ${yellow}3. Use components:${cyan} ║
|
|
194
194
|
║ ║
|
package/src/dev/App.tsx
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "../components/macro/command-preset";
|
|
15
15
|
import { useDevContext } from "../dev/components/dev-context";
|
|
16
16
|
import { SizeToggle } from "../dev/components/showcase";
|
|
17
|
-
import {
|
|
17
|
+
import { GladvnLogo } from "../dev/components/GladvnLogo";
|
|
18
18
|
import { COMPONENTS } from "../dev/data";
|
|
19
19
|
import OverviewSection from "../dev/showcase/overview";
|
|
20
20
|
import {
|
|
@@ -164,7 +164,7 @@ export default function App() {
|
|
|
164
164
|
)}
|
|
165
165
|
</button>
|
|
166
166
|
<a href="/" className="inline-flex items-center hover:opacity-80 transition-opacity">
|
|
167
|
-
<
|
|
167
|
+
<GladvnLogo variant="wordmark" />
|
|
168
168
|
</a>
|
|
169
169
|
</div>
|
|
170
170
|
|
|
@@ -187,7 +187,7 @@ export default function App() {
|
|
|
187
187
|
<Button
|
|
188
188
|
variant="ghost"
|
|
189
189
|
iconOnly
|
|
190
|
-
render={<a href="https://github.com/duongacy/
|
|
190
|
+
render={<a href="https://github.com/duongacy/gladvn" target="_blank" rel="noreferrer" />}
|
|
191
191
|
nativeButton={false}
|
|
192
192
|
className="text-muted-foreground hover:text-foreground hidden sm:inline-flex"
|
|
193
193
|
>
|
|
@@ -296,7 +296,7 @@ export default function App() {
|
|
|
296
296
|
open={cmdOpen}
|
|
297
297
|
onOpenChange={setCmdOpen}
|
|
298
298
|
title="Tìm component"
|
|
299
|
-
description="Tìm kiếm nhanh component trong
|
|
299
|
+
description="Tìm kiếm nhanh component trong Gladvn UI"
|
|
300
300
|
>
|
|
301
301
|
<Command size="lg">
|
|
302
302
|
<CommandInput placeholder="Nhập tên component..." autoFocus />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cn } from "../../lib/utils";
|
|
2
2
|
|
|
3
|
-
interface
|
|
3
|
+
interface GladvnLogoProps {
|
|
4
4
|
className?: string;
|
|
5
5
|
/** Size of the icon SVG */
|
|
6
6
|
iconSize?: string;
|
|
@@ -8,11 +8,11 @@ interface GladcnLogoProps {
|
|
|
8
8
|
variant?: "icon" | "wordmark";
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export function
|
|
11
|
+
export function GladvnLogo({
|
|
12
12
|
className,
|
|
13
13
|
iconSize = "size-7",
|
|
14
14
|
variant = "icon",
|
|
15
|
-
}:
|
|
15
|
+
}: GladvnLogoProps) {
|
|
16
16
|
const icon = (
|
|
17
17
|
<svg
|
|
18
18
|
viewBox="0 0 32 32"
|
|
@@ -70,7 +70,7 @@ export function GladcnLogo({
|
|
|
70
70
|
<div className={cn("flex items-center gap-2.5", className)}>
|
|
71
71
|
{icon}
|
|
72
72
|
<span className="font-bold text-[15px] tracking-tight leading-none">
|
|
73
|
-
|
|
73
|
+
gladvn
|
|
74
74
|
</span>
|
|
75
75
|
</div>
|
|
76
76
|
);
|
package/src/dev/index.css
CHANGED
|
@@ -138,7 +138,7 @@ export default function FormsSection() {
|
|
|
138
138
|
<InputGroupAddon>
|
|
139
139
|
<InputGroupText>https://</InputGroupText>
|
|
140
140
|
</InputGroupAddon>
|
|
141
|
-
<InputGroupInput id="tf-group" placeholder="
|
|
141
|
+
<InputGroupInput id="tf-group" placeholder="gladvn.ui" />
|
|
142
142
|
<InputGroupAddon>
|
|
143
143
|
<InputGroupText>.com</InputGroupText>
|
|
144
144
|
</InputGroupAddon>
|
|
@@ -69,7 +69,7 @@ export default function OverviewSection() {
|
|
|
69
69
|
<div className="relative z-10 flex flex-col h-full">
|
|
70
70
|
<div>
|
|
71
71
|
<Badge color="secondary" className="mb-3 px-2.5 py-0.5 shadow-sm">
|
|
72
|
-
✨
|
|
72
|
+
✨ gladvn UI v0.2.1
|
|
73
73
|
</Badge>
|
|
74
74
|
<h2 className="text-3xl font-bold tracking-tight mb-2">
|
|
75
75
|
Crafted for Perfection
|
|
@@ -143,7 +143,7 @@ export default function OverviewSection() {
|
|
|
143
143
|
<h3 className="font-semibold">Quick Install</h3>
|
|
144
144
|
</div>
|
|
145
145
|
<p className="text-sm text-muted-foreground mb-4">
|
|
146
|
-
Available on npm. Add
|
|
146
|
+
Available on npm. Add gladvn to your project in seconds.
|
|
147
147
|
</p>
|
|
148
148
|
<div className="rounded-lg bg-muted/50 px-3 py-2.5 font-mono text-xs border border-border flex items-center justify-between">
|
|
149
149
|
<span className="truncate">npm i gladvn</span>
|
|
@@ -72,7 +72,7 @@ function NavigationMenuMicroShowcase() {
|
|
|
72
72
|
}
|
|
73
73
|
>
|
|
74
74
|
<div className="mb-2 mt-4 text-lg font-medium">
|
|
75
|
-
|
|
75
|
+
gladvn/ui
|
|
76
76
|
</div>
|
|
77
77
|
<p className="text-sm leading-tight text-muted-foreground">
|
|
78
78
|
Beautifully designed components built with Radix UI and
|
|
@@ -159,7 +159,7 @@ function NavigationMenuMicroShowcase() {
|
|
|
159
159
|
}
|
|
160
160
|
>
|
|
161
161
|
<div className="mb-2 mt-4 text-lg font-medium">
|
|
162
|
-
|
|
162
|
+
gladvn/ui
|
|
163
163
|
</div>
|
|
164
164
|
<p className="text-sm leading-tight text-muted-foreground">
|
|
165
165
|
Beautifully designed components built with Radix UI
|
|
@@ -17,9 +17,10 @@ import {
|
|
|
17
17
|
} from "lucide-react";
|
|
18
18
|
import { useEffect, useState } from "react";
|
|
19
19
|
import { toast } from "sonner";
|
|
20
|
-
import {
|
|
20
|
+
import { GladvnLogo } from "../../dev/components/GladvnLogo";
|
|
21
21
|
|
|
22
22
|
import { ProgressPreset as Progress } from "../../components/macro/progress-preset";
|
|
23
|
+
import { Avatar, AvatarFallback, AvatarImage } from "../../components/micro/avatar";
|
|
23
24
|
import { Badge } from "../../components/micro/badge";
|
|
24
25
|
import { Button } from "../../components/micro/button";
|
|
25
26
|
import {
|
|
@@ -34,7 +35,8 @@ import {
|
|
|
34
35
|
SelectContent,
|
|
35
36
|
SelectItem,
|
|
36
37
|
SelectTrigger,
|
|
37
|
-
SelectValue, SelectPortal
|
|
38
|
+
SelectValue, SelectPortal
|
|
39
|
+
} from "../../components/micro/select";
|
|
38
40
|
import { Switch } from "../../components/micro/switch";
|
|
39
41
|
import { ColorSwatch } from "../../dev/components/showcase";
|
|
40
42
|
import { COLORS, STATS } from "../../dev/data";
|
|
@@ -127,10 +129,10 @@ export default function OverviewSection() {
|
|
|
127
129
|
style={{ animationDelay: "100ms", animationFillMode: "both" }}
|
|
128
130
|
>
|
|
129
131
|
<span className="block text-foreground drop-shadow-sm">
|
|
130
|
-
|
|
132
|
+
Tinh tế. Đẳng cấp.
|
|
131
133
|
</span>
|
|
132
134
|
<span className="block mt-2 bg-gradient-to-r leading-[1.2] from-primary via-info to-primary bg-[length:200%_auto] bg-clip-text text-transparent animate-[spin_8s_linear_infinite] [animation-name:gradient] [animation-duration:8s] [animation-timing-function:linear] [animation-iteration-count:infinite]">
|
|
133
|
-
|
|
135
|
+
Sạch sẽ.
|
|
134
136
|
</span>
|
|
135
137
|
</h1>
|
|
136
138
|
|
|
@@ -138,11 +140,11 @@ export default function OverviewSection() {
|
|
|
138
140
|
className="max-w-2xl text-lg md:text-xl text-muted-foreground leading-relaxed mb-10 animate-fade-up"
|
|
139
141
|
style={{ animationDelay: "200ms", animationFillMode: "both" }}
|
|
140
142
|
>
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
Đa số component library bắt bạn phải phụ thuộc vào họ mãi mãi.
|
|
144
|
+
gladvn copy thẳng source code vào dự án của bạn —{" "}
|
|
143
145
|
<strong className="text-foreground">
|
|
144
|
-
không
|
|
145
|
-
|
|
146
|
+
không node_modules ẩn, không breaking change bất ngờ, không
|
|
147
|
+
vendor lock-in.
|
|
146
148
|
</strong>
|
|
147
149
|
</p>
|
|
148
150
|
</div>
|
|
@@ -212,18 +214,18 @@ export default function OverviewSection() {
|
|
|
212
214
|
<SelectValue placeholder="Chọn vùng" />
|
|
213
215
|
</SelectTrigger>
|
|
214
216
|
<SelectPortal>
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
217
|
+
<SelectContent>
|
|
218
|
+
<SelectItem value="edge">
|
|
219
|
+
Edge Network (Toàn cầu)
|
|
220
|
+
</SelectItem>
|
|
221
|
+
<SelectItem value="us-east">
|
|
222
|
+
US East (Virginia)
|
|
223
|
+
</SelectItem>
|
|
224
|
+
<SelectItem value="ap-se">
|
|
225
|
+
AP South East (Sing)
|
|
226
|
+
</SelectItem>
|
|
227
|
+
</SelectContent>
|
|
228
|
+
</SelectPortal>
|
|
227
229
|
</Select>
|
|
228
230
|
</div>
|
|
229
231
|
</div>
|
|
@@ -300,15 +302,14 @@ export default function OverviewSection() {
|
|
|
300
302
|
<section className="container max-w-6xl mx-auto space-y-12 px-4">
|
|
301
303
|
<div className="text-center max-w-2xl mx-auto space-y-4">
|
|
302
304
|
<h2 className="text-3xl md:text-4xl font-extrabold tracking-tight">
|
|
303
|
-
|
|
305
|
+
Rõ ràng từ đầu. Dùng lâu không sợ vỡ.
|
|
304
306
|
</h2>
|
|
305
307
|
<p className="text-muted-foreground text-lg">
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
<strong className="text-foreground">
|
|
310
|
-
{" "}
|
|
311
|
-
hưởng.
|
|
308
|
+
Nhiều dự án bắt đầu gãy ở năm thứ hai — ai cũng muốn sửa nhưng
|
|
309
|
+
không ai dám sửa vì không biết cái gì sẽ hỏng theo. gladvn chia code
|
|
310
|
+
thành{" "}
|
|
311
|
+
<strong className="text-foreground">các tầng rõ ràng</strong>
|
|
312
|
+
{", "}nên bạn luôn biết mình đang sửa ở đâu và ảnh hưởng đến đâu.
|
|
312
313
|
</p>
|
|
313
314
|
</div>
|
|
314
315
|
|
|
@@ -323,19 +324,19 @@ export default function OverviewSection() {
|
|
|
323
324
|
<SparklesIcon className="size-4" /> Điểm khác biệt lớn nhất
|
|
324
325
|
</div>
|
|
325
326
|
<h3 className="text-3xl md:text-5xl font-extrabold tracking-tight">
|
|
326
|
-
|
|
327
|
+
Code là của bạn, 100%
|
|
327
328
|
</h3>
|
|
328
329
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-2xl">
|
|
329
|
-
Chạy một lệnh
|
|
330
|
-
|
|
330
|
+
Chạy một lệnh — toàn bộ components, hooks, styles, contexts
|
|
331
|
+
được copy thẳng vào thư mục{" "}
|
|
331
332
|
<code className="text-sm bg-primary/20 text-primary px-1.5 py-0.5 rounded">
|
|
332
333
|
src/
|
|
333
334
|
</code>{" "}
|
|
334
|
-
của
|
|
335
|
+
của bạn.{" "}
|
|
335
336
|
<strong className="text-foreground">
|
|
336
|
-
Không
|
|
337
|
+
Không qua node_modules, không bị khóa vào bất kỳ ai
|
|
337
338
|
</strong>{" "}
|
|
338
|
-
— bạn đọc được, sửa được, xoá được từng dòng
|
|
339
|
+
— bạn đọc được, sửa được, xoá được từng dòng.
|
|
339
340
|
</p>
|
|
340
341
|
|
|
341
342
|
<div className="flex items-center gap-4 pt-2">
|
|
@@ -421,13 +422,13 @@ export default function OverviewSection() {
|
|
|
421
422
|
Sửa Macro — an toàn nhất
|
|
422
423
|
</h4>
|
|
423
424
|
<p className="text-sm text-muted-foreground leading-relaxed">
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
425
|
+
Bắt đầu ở đây. Mỗi Macro là một preset độc lập — thêm footer
|
|
426
|
+
cho DatePicker, bỏ nút đóng của Dialog, chỉnh placeholder
|
|
427
|
+
Combobox.{" "}
|
|
427
428
|
<strong className="text-foreground">
|
|
428
|
-
|
|
429
|
+
Sửa cái nào chỉ ảnh hưởng cái đó
|
|
429
430
|
</strong>
|
|
430
|
-
, không lan
|
|
431
|
+
, không lan sang đâu cả.
|
|
431
432
|
</p>
|
|
432
433
|
</div>
|
|
433
434
|
|
|
@@ -440,15 +441,15 @@ export default function OverviewSection() {
|
|
|
440
441
|
src/components/micro/
|
|
441
442
|
</div>
|
|
442
443
|
<h4 className="font-bold text-foreground text-base">
|
|
443
|
-
Sửa Micro —
|
|
444
|
+
Sửa Micro — cẩn thận hơn
|
|
444
445
|
</h4>
|
|
445
446
|
<p className="text-sm text-muted-foreground leading-relaxed">
|
|
446
|
-
Micro là nền
|
|
447
|
-
|
|
447
|
+
Micro là nền — mọi Macro đều xây trên nó. Sửa variant của
|
|
448
|
+
Button hay animation của Tooltip thì{" "}
|
|
448
449
|
<strong className="text-foreground">
|
|
449
|
-
|
|
450
|
-
</strong>
|
|
451
|
-
|
|
450
|
+
tất cả nơi dùng component đó đều thay đổi theo
|
|
451
|
+
</strong>
|
|
452
|
+
. Chỉ sửa khi bạn rõ mình đang làm gì.
|
|
452
453
|
</p>
|
|
453
454
|
</div>
|
|
454
455
|
|
|
@@ -461,16 +462,15 @@ export default function OverviewSection() {
|
|
|
461
462
|
src/index.css
|
|
462
463
|
</div>
|
|
463
464
|
<h4 className="font-bold text-foreground text-base">
|
|
464
|
-
Sửa CSS —
|
|
465
|
+
Sửa CSS — ảnh hưởng toàn bộ
|
|
465
466
|
</h4>
|
|
466
467
|
<p className="text-sm text-muted-foreground leading-relaxed">
|
|
467
|
-
CSS token
|
|
468
|
-
|
|
468
|
+
CSS token quyết định màu, font, border-radius cho tất cả.
|
|
469
|
+
Đổi một token ở đây thì{" "}
|
|
469
470
|
<strong className="text-foreground">
|
|
470
|
-
|
|
471
|
+
toàn bộ giao diện cập nhật ngay
|
|
471
472
|
</strong>
|
|
472
|
-
|
|
473
|
-
đổi design language, không phải để vá từng chỗ.
|
|
473
|
+
. Dùng khi muốn rebrand, không phải để vá lỗi lẻ tẻ.
|
|
474
474
|
</p>
|
|
475
475
|
</div>
|
|
476
476
|
|
|
@@ -486,15 +486,13 @@ export default function OverviewSection() {
|
|
|
486
486
|
</div>
|
|
487
487
|
<div className="relative z-10 space-y-4 mb-10">
|
|
488
488
|
<h3 className="text-2xl md:text-4xl font-extrabold tracking-tight">
|
|
489
|
-
Micro &
|
|
489
|
+
Micro & Macro
|
|
490
490
|
</h3>
|
|
491
491
|
<p className="text-muted-foreground max-w-lg text-lg leading-relaxed">
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
<strong className="text-foreground">
|
|
495
|
-
Micro
|
|
496
|
-
Mọi logic lắp ráp giao diện đều phải uỷ quyền (Delegate) hoàn
|
|
497
|
-
toàn cho Macro.
|
|
492
|
+
Micro là component thuần — chỉ lo style, không ép layout.
|
|
493
|
+
Macro là preset — lắp ghép Micro thành giao diện hoàn chỉnh.
|
|
494
|
+
<strong className="text-foreground block mt-2">
|
|
495
|
+
Micro không bao giờ tự quyết layout. Việc đó thuộc về Macro.
|
|
498
496
|
</strong>
|
|
499
497
|
</p>
|
|
500
498
|
</div>
|
|
@@ -558,12 +556,11 @@ export default function OverviewSection() {
|
|
|
558
556
|
Style Encapsulation
|
|
559
557
|
</h3>
|
|
560
558
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
561
|
-
Mỗi component là một hộp
|
|
562
|
-
|
|
563
|
-
<code>data-slot</code> —
|
|
564
|
-
trong API.{" "}
|
|
559
|
+
Mỗi component là một hộp kín về style. Muốn tuỳ chỉnh từ ngoài
|
|
560
|
+
thì dùng{" "}
|
|
561
|
+
<code>data-slot</code> — đã có sẵn contract rõ ràng.{" "}
|
|
565
562
|
<strong className="text-foreground">
|
|
566
|
-
Refactor
|
|
563
|
+
Refactor bên trong thoải mái mà không phá code bên ngoài.
|
|
567
564
|
</strong>
|
|
568
565
|
</p>
|
|
569
566
|
</div>
|
|
@@ -586,11 +583,11 @@ export default function OverviewSection() {
|
|
|
586
583
|
</div>
|
|
587
584
|
<div className="relative z-10 space-y-4">
|
|
588
585
|
<h3 className="text-2xl md:text-4xl font-extrabold tracking-tight">
|
|
589
|
-
|
|
586
|
+
Variant × Color
|
|
590
587
|
</h3>
|
|
591
588
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
|
|
592
|
-
|
|
593
|
-
|
|
589
|
+
Variant (solid, outline, ghost...) và Color (primary, destructive...)
|
|
590
|
+
là hai trục hoàn toàn độc lập. Kết hợp tự do mà không bị bùng nổ
|
|
594
591
|
class.
|
|
595
592
|
</p>
|
|
596
593
|
</div>
|
|
@@ -627,10 +624,10 @@ export default function OverviewSection() {
|
|
|
627
624
|
Zero-prop Defaults
|
|
628
625
|
</h3>
|
|
629
626
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
|
|
630
|
-
|
|
631
|
-
|
|
627
|
+
Quẳng component vào mà không truyền prop nào — nó vẫn chạy đẹp,
|
|
628
|
+
vẫn đúng behavior.{" "}
|
|
632
629
|
<strong className="text-foreground">
|
|
633
|
-
|
|
630
|
+
Không phải tra docs mỗi lần dùng.
|
|
634
631
|
</strong>
|
|
635
632
|
</p>
|
|
636
633
|
</div>
|
|
@@ -659,14 +656,13 @@ export default function OverviewSection() {
|
|
|
659
656
|
</div>
|
|
660
657
|
<div className="relative z-10 space-y-4">
|
|
661
658
|
<h3 className="text-2xl font-extrabold tracking-tight">
|
|
662
|
-
Headless
|
|
659
|
+
Headless + Style
|
|
663
660
|
</h3>
|
|
664
661
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
665
|
-
Keyboard
|
|
666
|
-
|
|
667
|
-
và thêm visual style, không tự implement logic tương tác.{" "}
|
|
662
|
+
Keyboard, focus, ARIA — Base UI lo hết. Micro component chỉ
|
|
663
|
+
thêm lớp style lên trên, không tự viết logic tương tác.{" "}
|
|
668
664
|
<strong className="text-foreground">
|
|
669
|
-
Behavior đúng
|
|
665
|
+
Behavior đúng sẵn, không cần test lại.
|
|
670
666
|
</strong>
|
|
671
667
|
</p>
|
|
672
668
|
</div>
|
|
@@ -691,14 +687,13 @@ export default function OverviewSection() {
|
|
|
691
687
|
</div>
|
|
692
688
|
<div className="relative z-10 space-y-4">
|
|
693
689
|
<h3 className="text-2xl md:text-4xl font-extrabold tracking-tight">
|
|
694
|
-
CSS Token
|
|
690
|
+
CSS Token
|
|
695
691
|
</h3>
|
|
696
692
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-lg">
|
|
697
|
-
Không component nào
|
|
698
|
-
|
|
699
|
-
từ hệ thống token.{" "}
|
|
693
|
+
Không component nào hardcode màu hay spacing. Tất cả đều
|
|
694
|
+
tham chiếu từ hệ thống token chung.{" "}
|
|
700
695
|
<strong className="text-foreground">
|
|
701
|
-
|
|
696
|
+
Đổi một token — cả app cập nhật.
|
|
702
697
|
</strong>
|
|
703
698
|
</p>
|
|
704
699
|
</div>
|
|
@@ -725,11 +720,12 @@ export default function OverviewSection() {
|
|
|
725
720
|
</div>
|
|
726
721
|
<div className="relative z-10 space-y-4">
|
|
727
722
|
<h3 className="text-2xl font-extrabold tracking-tight">
|
|
728
|
-
|
|
723
|
+
Polymorphism
|
|
729
724
|
</h3>
|
|
730
725
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
731
|
-
Dùng
|
|
732
|
-
|
|
726
|
+
Dùng <code>render</code> prop để đổi thẻ HTML root —
|
|
727
|
+
ví dụ biến Button thành Link. Không cần prop <code>as</code>
|
|
728
|
+
{" "}hay tạo wrapper lồng nhau.
|
|
733
729
|
</p>
|
|
734
730
|
</div>
|
|
735
731
|
<div className="relative z-10 mt-auto pt-6 space-y-3">
|
|
@@ -757,15 +753,14 @@ export default function OverviewSection() {
|
|
|
757
753
|
</div>
|
|
758
754
|
<div className="relative z-10 space-y-4">
|
|
759
755
|
<h3 className="text-2xl font-extrabold tracking-tight">
|
|
760
|
-
|
|
756
|
+
Stateless Primitive
|
|
761
757
|
</h3>
|
|
762
758
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
763
|
-
Micro component không
|
|
764
|
-
<code>useState</code> hay <code>useEffect</code>.
|
|
765
|
-
|
|
766
|
-
preset.{" "}
|
|
759
|
+
Micro component không chứa{" "}
|
|
760
|
+
<code>useState</code> hay <code>useEffect</code>. State nằm ở
|
|
761
|
+
Headless UI hoặc Macro.{" "}
|
|
767
762
|
<strong className="text-foreground">
|
|
768
|
-
|
|
763
|
+
Component càng đơn giản, càng ít bug.
|
|
769
764
|
</strong>
|
|
770
765
|
</p>
|
|
771
766
|
</div>
|
|
@@ -790,14 +785,13 @@ export default function OverviewSection() {
|
|
|
790
785
|
</div>
|
|
791
786
|
<div className="relative z-10 space-y-4">
|
|
792
787
|
<h3 className="text-2xl font-extrabold tracking-tight">
|
|
793
|
-
Accessibility
|
|
788
|
+
Accessibility
|
|
794
789
|
</h3>
|
|
795
790
|
<p className="text-muted-foreground text-base leading-relaxed">
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
<code>aria-hidden</code> để đảm bảo WCAG AAA/AA.{" "}
|
|
791
|
+
Semantic HTML, <code>aria-describedby</code> cho form,
|
|
792
|
+
icon trang trí tự ẩn khỏi screen reader.{" "}
|
|
799
793
|
<strong className="text-foreground">
|
|
800
|
-
|
|
794
|
+
Chuẩn WCAG — không cần nghĩ thêm.
|
|
801
795
|
</strong>
|
|
802
796
|
</p>
|
|
803
797
|
</div>
|
|
@@ -966,7 +960,7 @@ export default function OverviewSection() {
|
|
|
966
960
|
nền đen. Đây là điểm mà hầu hết thư viện bỏ cuộc.
|
|
967
961
|
</p>
|
|
968
962
|
<p className="text-muted-foreground text-xl leading-relaxed">
|
|
969
|
-
|
|
963
|
+
gladvn giải quyết bằng{" "}
|
|
970
964
|
<code className="text-sm bg-warning/20 text-warning px-1.5 py-0.5 rounded">
|
|
971
965
|
{"<ThemeWrapper>"}
|
|
972
966
|
</code>{" "}
|
|
@@ -986,7 +980,7 @@ export default function OverviewSection() {
|
|
|
986
980
|
<div className="relative z-10 grid sm:grid-cols-2 gap-6 max-w-3xl">
|
|
987
981
|
<div className="p-6 rounded-2xl border border-success/30 bg-success/10 shadow-sm flex flex-col gap-2">
|
|
988
982
|
<div className="text-success font-semibold text-lg flex items-center gap-2">
|
|
989
|
-
✅
|
|
983
|
+
✅ gladvn — ThemeWrapper
|
|
990
984
|
</div>
|
|
991
985
|
<p className="text-success/80 text-sm leading-relaxed">
|
|
992
986
|
Theme được tunnel xuyên qua Portal boundary. Dialog, Tooltip,
|
|
@@ -1055,21 +1049,63 @@ export default function OverviewSection() {
|
|
|
1055
1049
|
</div>
|
|
1056
1050
|
</section>
|
|
1057
1051
|
|
|
1052
|
+
{/* 🤝 CONTRIBUTORS */}
|
|
1053
|
+
<section className="container max-w-6xl mx-auto px-4 mb-24">
|
|
1054
|
+
<div className="flex flex-col items-center text-center space-y-8">
|
|
1055
|
+
<div className="space-y-4 max-w-2xl">
|
|
1056
|
+
<h2 className="text-3xl font-extrabold tracking-tight">
|
|
1057
|
+
Contributors
|
|
1058
|
+
</h2>
|
|
1059
|
+
</div>
|
|
1060
|
+
|
|
1061
|
+
<div className="flex flex-wrap justify-center gap-6">
|
|
1062
|
+
{[
|
|
1063
|
+
{
|
|
1064
|
+
name: "Ý Le",
|
|
1065
|
+
role: "Creator & Maintainer",
|
|
1066
|
+
avatar: "https://github.com/duongacy.png",
|
|
1067
|
+
url: "https://github.com/duongacy",
|
|
1068
|
+
}
|
|
1069
|
+
].map((user) => (
|
|
1070
|
+
<a
|
|
1071
|
+
key={user.name}
|
|
1072
|
+
href={user.url}
|
|
1073
|
+
target="_blank"
|
|
1074
|
+
rel="noreferrer"
|
|
1075
|
+
className="group flex flex-col items-center gap-3 p-4 rounded-2xl hover:bg-muted/50 transition-colors"
|
|
1076
|
+
>
|
|
1077
|
+
<Avatar className="size-16 border-2 border-transparent group-hover:border-primary/20 transition-all duration-300 group-hover:scale-105">
|
|
1078
|
+
<AvatarImage src={user.avatar} alt={user.name} />
|
|
1079
|
+
<AvatarFallback className="text-lg bg-primary/5 text-primary">{user.name.substring(0, 2).toUpperCase()}</AvatarFallback>
|
|
1080
|
+
</Avatar>
|
|
1081
|
+
<div className="text-center">
|
|
1082
|
+
<div className="font-semibold text-sm group-hover:text-primary transition-colors">{user.name}</div>
|
|
1083
|
+
<div className="text-xs text-muted-foreground mt-0.5">{user.role}</div>
|
|
1084
|
+
</div>
|
|
1085
|
+
</a>
|
|
1086
|
+
))}
|
|
1087
|
+
</div>
|
|
1088
|
+
|
|
1089
|
+
<Button variant="outline" className="mt-4 rounded-full" render={<a href="https://github.com/duongacy/gladcn" target="_blank" rel="noreferrer" />}>
|
|
1090
|
+
Trở thành Contributor
|
|
1091
|
+
</Button>
|
|
1092
|
+
</div>
|
|
1093
|
+
</section>
|
|
1094
|
+
|
|
1058
1095
|
{/* 🚀 FINAL CTA */}
|
|
1059
1096
|
<section className="container max-w-6xl mx-auto px-4">
|
|
1060
1097
|
<div className="rounded-[2.5rem] border-2 border-primary/40 bg-gradient-to-br from-primary/10 via-background to-info/5 p-10 md:p-16 shadow-2xl shadow-primary/5 text-center relative overflow-hidden">
|
|
1061
1098
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_60%_60%_at_50%_0%,rgba(var(--primary-rgb),0.15),transparent)] pointer-events-none" />
|
|
1062
1099
|
<div className="relative z-10 space-y-6 max-w-2xl mx-auto">
|
|
1063
1100
|
<h2 className="text-3xl md:text-5xl font-extrabold tracking-tight">
|
|
1064
|
-
|
|
1101
|
+
Thử ngay?
|
|
1065
1102
|
</h2>
|
|
1066
1103
|
<p className="text-muted-foreground text-lg leading-relaxed">
|
|
1067
|
-
|
|
1104
|
+
30 giây — toàn bộ code nằm trong{" "}
|
|
1068
1105
|
<code className="text-sm bg-primary/20 text-primary px-1.5 py-0.5 rounded">
|
|
1069
1106
|
src/
|
|
1070
1107
|
</code>{" "}
|
|
1071
|
-
của bạn
|
|
1072
|
-
tài liệu.
|
|
1108
|
+
của bạn. Không config, không đọc docs.
|
|
1073
1109
|
</p>
|
|
1074
1110
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-4 pt-2">
|
|
1075
1111
|
<button
|
|
@@ -21,7 +21,7 @@ function SeparatorMicroShowcase() {
|
|
|
21
21
|
codeString={`<div className="w-full max-w-sm rounded-lg border border-border bg-card p-6">
|
|
22
22
|
<div className="space-y-1">
|
|
23
23
|
<h4 className="text-sm font-medium leading-none">
|
|
24
|
-
|
|
24
|
+
Gladvn UI
|
|
25
25
|
</h4>
|
|
26
26
|
<p className="text-sm text-muted-foreground">
|
|
27
27
|
Bộ UI Component mã nguồn mở.
|
|
@@ -36,7 +36,7 @@ function SeparatorMicroShowcase() {
|
|
|
36
36
|
>
|
|
37
37
|
<div className="w-full max-w-sm rounded-lg border border-border bg-card p-6">
|
|
38
38
|
<div className="space-y-1">
|
|
39
|
-
<h4 className="text-sm font-medium leading-none">
|
|
39
|
+
<h4 className="text-sm font-medium leading-none">Gladvn UI</h4>
|
|
40
40
|
<p className="text-sm text-muted-foreground">
|
|
41
41
|
Bộ UI Component mã nguồn mở.
|
|
42
42
|
</p>
|
package/src/styles/tokens.css
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* gladvn - Design Tokens (Default Theme)
|
|
3
3
|
* ==========================================================================
|
|
4
4
|
* Copy this file into your project's CSS and customize the values below.
|
|
5
|
-
* These CSS variables control the entire look & feel of all
|
|
5
|
+
* These CSS variables control the entire look & feel of all gladvn components.
|
|
6
6
|
*
|
|
7
7
|
* Usage: Copy this content into your project's main CSS BEFORE the
|
|
8
|
-
* @import "gladvn/
|
|
8
|
+
* @import "gladvn/gladvn.css" line.
|
|
9
9
|
*
|
|
10
10
|
* Color format: oklch(lightness chroma hue)
|
|
11
11
|
* Docs: https://oklch.com
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
interface GladcnLogoProps {
|
|
2
|
-
className?: string;
|
|
3
|
-
/** Size of the icon SVG */
|
|
4
|
-
iconSize?: string;
|
|
5
|
-
/** Show icon only (default) or icon + wordmark */
|
|
6
|
-
variant?: "icon" | "wordmark";
|
|
7
|
-
}
|
|
8
|
-
export declare function GladcnLogo({ className, iconSize, variant, }: GladcnLogoProps): import("react").JSX.Element;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=GladcnLogo.d.ts.map
|
|
File without changes
|