Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66a376c752 | ||
|
|
765b0bb936 | ||
|
|
2e7acbf50f | ||
|
|
fc9956c648 | ||
|
|
e916556576 | ||
|
|
f9b65919cf |
@@ -201,6 +201,7 @@ Before delivering UI code, verify these items:
|
||||
- [ ] All icons from consistent icon set (Heroicons/Lucide)
|
||||
- [ ] Brand logos are correct (verified from Simple Icons)
|
||||
- [ ] Hover states don't cause layout shift
|
||||
- [ ] Use theme colors directly (bg-primary) not var() wrapper
|
||||
|
||||
### Interaction
|
||||
- [ ] All clickable elements have `cursor-pointer`
|
||||
|
||||
@@ -49,3 +49,4 @@ No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL
|
||||
48,Layout,Container Queries,Use @container for component-based responsiveness,Use @container and @lg: etc.,Media queries for component internals,@container @lg:grid-cols-2,@media (min-width: ...) inside component,Medium,https://github.com/tailwindlabs/tailwindcss-container-queries
|
||||
49,Interactivity,Group and Peer,Style based on parent/sibling state,group-hover peer-checked,JS for simple state interactions,group-hover:text-blue-500,onMouseEnter={() => setHover(true)},Low,https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
|
||||
50,Customization,Arbitrary Values,Use [] for one-off values,w-[350px] for specific needs,Creating config for single use,top-[117px] (if strictly needed),style={{ top: '117px' }},Low,https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values
|
||||
51,Colors,Theme color variables,Define colors in Tailwind theme and use directly,bg-primary text-success border-cta,bg-[var(--color-primary)] text-[var(--color-success)],bg-primary,bg-[var(--color-primary)],Medium,https://tailwindcss.com/docs/customizing-colors
|
||||
|
||||
|
@@ -49,3 +49,4 @@ No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL
|
||||
48,Layout,Container Queries,Use @container for component-based responsiveness,Use @container and @lg: etc.,Media queries for component internals,@container @lg:grid-cols-2,@media (min-width: ...) inside component,Medium,https://github.com/tailwindlabs/tailwindcss-container-queries
|
||||
49,Interactivity,Group and Peer,Style based on parent/sibling state,group-hover peer-checked,JS for simple state interactions,group-hover:text-blue-500,onMouseEnter={() => setHover(true)},Low,https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
|
||||
50,Customization,Arbitrary Values,Use [] for one-off values,w-[350px] for specific needs,Creating config for single use,top-[117px] (if strictly needed),style={{ top: '117px' }},Low,https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values
|
||||
51,Colors,Theme color variables,Define colors in Tailwind theme and use directly,bg-primary text-success border-cta,bg-[var(--color-primary)] text-[var(--color-success)],bg-primary,bg-[var(--color-primary)],Medium,https://tailwindcss.com/docs/customizing-colors
|
||||
|
||||
|
@@ -56,3 +56,12 @@ When modifying files, keep all agent workflows in sync:
|
||||
## Prerequisites
|
||||
|
||||
Python 3.x (no external dependencies required)
|
||||
|
||||
## Git Workflow
|
||||
|
||||
Never push directly to `main`. Always:
|
||||
|
||||
1. Create a new branch: `git checkout -b feat/... ` or `fix/...`
|
||||
2. Commit changes
|
||||
3. Push branch: `git push -u origin <branch>`
|
||||
4. Create PR: `gh pr create`
|
||||
|
||||
49
README.md
49
README.md
@@ -75,42 +75,23 @@ sudo apt update && sudo apt install python3
|
||||
winget install Python.Python.3.12
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
ui-ux-pro-max-skill/
|
||||
├── cli/ # CLI installer (uipro-cli)
|
||||
│ ├── package.json
|
||||
│ └── src/
|
||||
├── .claude/skills/ui-ux-pro-max/ # Claude Code skill
|
||||
│ ├── SKILL.md
|
||||
│ ├── scripts/
|
||||
│ │ ├── search.py
|
||||
│ │ └── core.py
|
||||
│ └── data/
|
||||
│ ├── styles.csv
|
||||
│ ├── colors.csv
|
||||
│ ├── typography.csv
|
||||
│ ├── charts.csv
|
||||
│ ├── products.csv
|
||||
│ ├── landing.csv
|
||||
│ ├── ux-guidelines.csv
|
||||
│ ├── prompts.csv
|
||||
│ └── stacks/
|
||||
├── .cursor/commands/ # Cursor command
|
||||
│ └── ui-ux-pro-max.md
|
||||
├── .windsurf/workflows/ # Windsurf workflow
|
||||
│ └── ui-ux-pro-max.md
|
||||
├── .agent/workflows/ # Antigravity workflow
|
||||
│ └── ui-ux-pro-max.md
|
||||
└── .shared/ui-ux-pro-max/ # Shared scripts & data
|
||||
├── scripts/
|
||||
└── data/
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
After installation, just chat with your AI assistant naturally. The skill will automatically activate when you request UI/UX work.
|
||||
### Claude Code
|
||||
|
||||
The skill activates automatically when you request UI/UX work. Just chat naturally:
|
||||
|
||||
```
|
||||
Build a landing page for my SaaS product
|
||||
```
|
||||
|
||||
### Cursor / Windsurf / Antigravity
|
||||
|
||||
Use the slash command to invoke the skill:
|
||||
|
||||
```
|
||||
/ui-ux-pro-max Build a landing page for my SaaS product
|
||||
```
|
||||
|
||||
### Example Prompts
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uipro-cli",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.3",
|
||||
"description": "CLI to install UI/UX Pro Max skill for AI coding assistants",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -12,7 +12,7 @@ const program = new Command();
|
||||
program
|
||||
.name('uipro')
|
||||
.description('CLI to install UI/UX Pro Max skill for AI coding assistants')
|
||||
.version('1.0.0');
|
||||
.version('1.0.3');
|
||||
|
||||
program
|
||||
.command('init')
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
import { mkdir } from 'node:fs/promises';
|
||||
import { mkdir, rm, access, cp } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { exec } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
import type { AIType } from '../types/index.js';
|
||||
import { AI_FOLDERS } from '../types/index.js';
|
||||
|
||||
export async function extractZip(zipPath: string, destDir: string): Promise<void> {
|
||||
const proc = Bun.spawn(['unzip', '-o', zipPath, '-d', destDir], {
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
});
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
const exitCode = await proc.exited;
|
||||
if (exitCode !== 0) {
|
||||
throw new Error(`Failed to extract zip: exit code ${exitCode}`);
|
||||
export async function extractZip(zipPath: string, destDir: string): Promise<void> {
|
||||
try {
|
||||
const isWindows = process.platform === 'win32';
|
||||
if (isWindows) {
|
||||
await execAsync(`powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${destDir}' -Force"`);
|
||||
} else {
|
||||
await execAsync(`unzip -o "${zipPath}" -d "${destDir}"`);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to extract zip: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function exists(path: string): Promise<boolean> {
|
||||
try {
|
||||
await access(path);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,29 +48,30 @@ export async function copyFolders(
|
||||
const targetPath = join(targetDir, folder);
|
||||
|
||||
// Check if source folder exists
|
||||
const sourceExists = await Bun.file(sourcePath).exists().catch(() => false);
|
||||
const sourceExists = await exists(sourcePath);
|
||||
if (!sourceExists) {
|
||||
// Try checking if it's a directory
|
||||
try {
|
||||
const proc = Bun.spawn(['test', '-d', sourcePath]);
|
||||
await proc.exited;
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Create target directory if needed
|
||||
await mkdir(targetPath, { recursive: true });
|
||||
|
||||
// Copy using cp -r
|
||||
const proc = Bun.spawn(['cp', '-r', `${sourcePath}/.`, targetPath], {
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
});
|
||||
|
||||
const exitCode = await proc.exited;
|
||||
if (exitCode === 0) {
|
||||
// Copy recursively
|
||||
try {
|
||||
await cp(sourcePath, targetPath, { recursive: true });
|
||||
copiedFolders.push(folder);
|
||||
} catch {
|
||||
// Try shell fallback for older Node versions
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
await execAsync(`xcopy "${sourcePath}" "${targetPath}" /E /I /Y`);
|
||||
} else {
|
||||
await execAsync(`cp -r "${sourcePath}/." "${targetPath}"`);
|
||||
}
|
||||
copiedFolders.push(folder);
|
||||
} catch {
|
||||
// Skip if copy fails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,9 +79,9 @@ export async function copyFolders(
|
||||
}
|
||||
|
||||
export async function cleanup(tempDir: string): Promise<void> {
|
||||
const proc = Bun.spawn(['rm', '-rf', tempDir], {
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
});
|
||||
await proc.exited;
|
||||
try {
|
||||
await rm(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
import type { Release } from '../types/index.js';
|
||||
|
||||
const REPO_OWNER = 'nextlevelbuilder';
|
||||
@@ -50,7 +51,7 @@ export async function downloadRelease(url: string, dest: string): Promise<void>
|
||||
}
|
||||
|
||||
const buffer = await response.arrayBuffer();
|
||||
await Bun.write(dest, buffer);
|
||||
await writeFile(dest, Buffer.from(buffer));
|
||||
}
|
||||
|
||||
export function getAssetUrl(release: Release): string | null {
|
||||
|
||||
Reference in New Issue
Block a user