@atlashub/smartstack-cli 1.37.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.documentation/agents.html +147 -40
- package/.documentation/apex.html +1 -1
- package/.documentation/business-analyse.html +3 -3
- package/.documentation/cli-commands.html +2 -2
- package/.documentation/commands.html +14 -14
- package/.documentation/efcore.html +14 -14
- package/.documentation/gitflow.html +12 -12
- package/.documentation/hooks.html +41 -3
- package/.documentation/index.html +1 -1
- package/.documentation/init.html +2 -2
- package/.documentation/installation.html +11 -11
- package/.documentation/js/app.js +1 -1
- package/.documentation/ralph-loop.html +1 -1
- package/.documentation/test-web.html +4 -4
- package/config/mcp-defaults.json +62 -0
- package/dist/index.js +58 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +70010 -0
- package/dist/mcp-entry.mjs.map +1 -0
- package/package.json +14 -5
- package/templates/agents/gitflow/start.md +5 -4
- package/templates/agents/mcp-healthcheck.md +15 -13
- package/templates/mcp-scaffolding/component.tsx.hbs +298 -0
- package/templates/mcp-scaffolding/controller.cs.hbs +184 -0
- package/templates/mcp-scaffolding/entity-extension.cs.hbs +231 -0
- package/templates/mcp-scaffolding/frontend/api-client.ts.hbs +116 -0
- package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +133 -0
- package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +134 -0
- package/templates/mcp-scaffolding/migrations/seed-roles.cs.hbs +261 -0
- package/templates/mcp-scaffolding/service-extension.cs.hbs +53 -0
- package/templates/mcp-scaffolding/tests/controller.test.cs.hbs +413 -0
- package/templates/mcp-scaffolding/tests/entity.test.cs.hbs +239 -0
- package/templates/mcp-scaffolding/tests/repository.test.cs.hbs +441 -0
- package/templates/mcp-scaffolding/tests/security.test.cs.hbs +442 -0
- package/templates/mcp-scaffolding/tests/service.test.cs.hbs +390 -0
- package/templates/mcp-scaffolding/tests/validator.test.cs.hbs +428 -0
- package/templates/ralph/README.md +3 -3
- package/templates/ralph/ralph.config.yaml +2 -2
- package/templates/skills/admin/SKILL.md +42 -0
- package/templates/skills/business-analyse/_shared.md +79 -15
- package/templates/skills/business-analyse/questionnaire/01-context.md +4 -4
- package/templates/skills/business-analyse/questionnaire/02-stakeholders.md +3 -3
- package/templates/skills/business-analyse/questionnaire/03-scope.md +4 -4
- package/templates/skills/business-analyse/questionnaire/04-data.md +7 -7
- package/templates/skills/business-analyse/questionnaire/05-integrations.md +1 -1
- package/templates/skills/business-analyse/questionnaire/06-security.md +3 -3
- package/templates/skills/business-analyse/questionnaire/07-ui.md +1 -1
- package/templates/skills/business-analyse/questionnaire/08-performance.md +3 -3
- package/templates/skills/business-analyse/questionnaire/09-constraints.md +4 -4
- package/templates/skills/business-analyse/questionnaire/10-documentation.md +2 -2
- package/templates/skills/business-analyse/questionnaire/11-data-lifecycle.md +2 -2
- package/templates/skills/business-analyse/questionnaire/12-migration.md +1 -1
- package/templates/skills/business-analyse/questionnaire/13-cross-module.md +2 -2
- package/templates/skills/business-analyse/steps/step-01-discover.md +50 -25
- package/templates/skills/business-analyse/steps/step-03-specify.md +63 -0
- package/templates/skills/business-analyse/steps/step-04-validate.md +23 -1
- package/templates/skills/business-analyse/steps/step-05-handoff.md +248 -66
- package/templates/skills/business-analyse/templates/tpl-handoff.md +99 -23
- package/templates/skills/cc-agent/SKILL.md +129 -0
- package/templates/skills/cc-agent/references/agent-frontmatter.md +213 -0
- package/templates/skills/cc-agent/references/permission-modes.md +102 -0
- package/templates/skills/cc-agent/references/tools-reference.md +144 -0
- package/templates/skills/cc-agent/steps/step-00-init.md +134 -0
- package/templates/skills/cc-agent/steps/step-01-design.md +186 -0
- package/templates/skills/cc-agent/steps/step-02-generate.md +204 -0
- package/templates/skills/cc-agent/steps/step-03-validate.md +130 -0
- package/templates/skills/cc-agent/templates/agent-categorized.md +67 -0
- package/templates/skills/cc-agent/templates/agent-standalone.md +56 -0
- package/templates/skills/cc-agent/templates/agent-with-skills.md +94 -0
- package/templates/skills/cc-audit/SKILL.md +108 -0
- package/templates/skills/cc-audit/references/agent-checklist.md +91 -0
- package/templates/skills/cc-audit/references/hook-checklist.md +110 -0
- package/templates/skills/cc-audit/references/skill-checklist.md +70 -0
- package/templates/skills/cc-audit/steps/step-00-init.md +98 -0
- package/templates/skills/cc-audit/steps/step-01-scan.md +142 -0
- package/templates/skills/cc-audit/steps/step-02-analyze.md +158 -0
- package/templates/skills/cc-audit/steps/step-03-report.md +142 -0
- package/templates/skills/cc-skill/SKILL.md +134 -0
- package/templates/skills/cc-skill/references/best-practices.md +167 -0
- package/templates/skills/cc-skill/references/frontmatter-reference.md +182 -0
- package/templates/skills/cc-skill/references/skill-patterns.md +199 -0
- package/templates/skills/cc-skill/steps/step-00-init.md +119 -0
- package/templates/skills/cc-skill/steps/step-01-design.md +199 -0
- package/templates/skills/cc-skill/steps/step-02-generate.md +145 -0
- package/templates/skills/cc-skill/steps/step-03-steps.md +151 -0
- package/templates/skills/cc-skill/steps/step-04-validate.md +124 -0
- package/templates/skills/cc-skill/templates/skill-forked.md +85 -0
- package/templates/skills/cc-skill/templates/skill-progressive.md +102 -0
- package/templates/skills/cc-skill/templates/skill-simple.md +75 -0
- package/templates/skills/cc-skill/templates/step-template.md +82 -0
- package/templates/skills/check-version/SKILL.md +6 -0
- package/templates/skills/controller/templates.md +82 -0
- package/templates/skills/debug/SKILL.md +4 -0
- package/templates/skills/documentation/SKILL.md +1 -0
- package/templates/skills/efcore/SKILL.md +5 -0
- package/templates/skills/efcore/references/zero-downtime-patterns.md +227 -0
- package/templates/skills/efcore/steps/db/step-deploy.md +26 -5
- package/templates/skills/efcore/steps/migration/step-03-validate.md +19 -0
- package/templates/skills/efcore/steps/shared/step-00-init.md +21 -7
- package/templates/skills/explore/SKILL.md +28 -32
- package/templates/skills/feature-full/SKILL.md +1 -0
- package/templates/skills/gitflow/SKILL.md +8 -0
- package/templates/skills/gitflow/steps/step-start.md +45 -10
- package/templates/skills/mcp/SKILL.md +38 -18
- package/templates/skills/quick-search/SKILL.md +8 -1
- package/templates/skills/ralph-loop/SKILL.md +1 -1
- package/templates/skills/ralph-loop/steps/step-00-init.md +8 -68
- package/templates/skills/ralph-loop/steps/step-04-check.md +1 -1
- package/templates/skills/refactor/SKILL.md +1 -0
- package/templates/skills/review-code/SKILL.md +11 -3
- package/templates/skills/review-code/references/owasp-api-top10.md +243 -0
- package/templates/skills/review-code/references/security-checklist.md +86 -1
- package/templates/skills/review-code/references/smartstack-conventions.md +166 -0
- package/templates/skills/ui-components/SKILL.md +31 -438
- package/templates/skills/ui-components/accessibility.md +170 -0
- package/templates/skills/ui-components/patterns/data-table.md +39 -0
- package/templates/skills/ui-components/patterns/entity-card.md +77 -0
- package/templates/skills/ui-components/patterns/grid-layout.md +91 -0
- package/templates/skills/ui-components/patterns/kanban.md +43 -0
- package/templates/skills/ui-components/style-guide.md +86 -0
- package/templates/skills/utils/SKILL.md +1 -0
- package/templates/skills/validate/SKILL.md +1 -0
- package/templates/skills/workflow/SKILL.md +27 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# DataTable Pattern
|
|
2
|
+
|
|
3
|
+
## COMPONENT: DataTable
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { DataTable } from '@/components/ui/DataTable';
|
|
7
|
+
|
|
8
|
+
<DataTable
|
|
9
|
+
data={users}
|
|
10
|
+
columns={[
|
|
11
|
+
{ key: 'name', label: 'Name', sortable: true },
|
|
12
|
+
{ key: 'role', label: 'Role', render: (user) => <Badge>{user.role}</Badge> }
|
|
13
|
+
]}
|
|
14
|
+
pagination={{ pageSize: 10 }}
|
|
15
|
+
searchable
|
|
16
|
+
onRowClick={(user) => navigate(`/users/${user.id}`)}
|
|
17
|
+
/>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## COMPONENT: Tooltip
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { Tooltip } from '@/components/ui/Tooltip';
|
|
24
|
+
|
|
25
|
+
// Variants: default, error, warning, success, info
|
|
26
|
+
// Positions: top, bottom, left, right
|
|
27
|
+
|
|
28
|
+
<Tooltip content="Permission required" variant="error">
|
|
29
|
+
<button disabled>Protected action</button>
|
|
30
|
+
</Tooltip>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Disabled Button with Explanation Pattern
|
|
34
|
+
```tsx
|
|
35
|
+
const canExecute = hasPermission('module.action.execute');
|
|
36
|
+
<Tooltip content={!canExecute ? t('errors.noPermission') : undefined} variant="error" disabled={canExecute}>
|
|
37
|
+
<button disabled={!canExecute}>Action</button>
|
|
38
|
+
</Tooltip>
|
|
39
|
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# EntityCard Pattern (MANDATORY)
|
|
2
|
+
|
|
3
|
+
**ALWAYS use `EntityCard` for entity cards. NEVER use custom cards with divs.**
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { EntityCard, ProviderCard, TemplateCard } from '@/components/ui/EntityCard';
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## EntityCard Usage
|
|
10
|
+
```tsx
|
|
11
|
+
<EntityCard
|
|
12
|
+
avatar={{ letter: 'O', color: '#10a37f' }}
|
|
13
|
+
title="OpenAI" subtitle="openai"
|
|
14
|
+
description="OpenAI GPT models"
|
|
15
|
+
stats="15 model(s)"
|
|
16
|
+
badge={{ icon: Shield, tooltip: 'Admin API supported' }}
|
|
17
|
+
links={[{ icon: ExternalLink, label: 'Website', href: 'https://...' }]}
|
|
18
|
+
actions={[{ label: 'Config', onClick: () => {}, variant: 'primary' }]}
|
|
19
|
+
/>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## ProviderCard Usage (AI Providers)
|
|
23
|
+
```tsx
|
|
24
|
+
<ProviderCard name="OpenAI" code="openai" description="..." modelCount={15} color="#10a37f"
|
|
25
|
+
websiteUrl="..." docsUrl="..." apiKeyUrl="..." hasAdminKey />
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## TemplateCard Usage (Templates)
|
|
29
|
+
```tsx
|
|
30
|
+
<TemplateCard name="Welcome" code="welcome" category="Transactional" isActive isSystem
|
|
31
|
+
icon={Mail} translationsCount={3} onClick={() => {}} onEdit={() => {}} onDelete={() => {}} />
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## EntityCard Props
|
|
35
|
+
| Prop | Type |
|
|
36
|
+
|------|------|
|
|
37
|
+
| `avatar` | `{ letter, color, imageUrl? }` |
|
|
38
|
+
| `title`, `subtitle`, `description` | `string` |
|
|
39
|
+
| `stats` | `string` |
|
|
40
|
+
| `badge` | `{ icon?, tooltip?, color? }` |
|
|
41
|
+
| `links` | `Array<{ icon, label, href?, onClick? }>` |
|
|
42
|
+
| `actions` | `Array<{ label, href?, onClick?, variant, icon?, disabled? }>` |
|
|
43
|
+
|
|
44
|
+
## Action Variants (EntityCard)
|
|
45
|
+
| Variant | Style |
|
|
46
|
+
|---------|-------|
|
|
47
|
+
| `primary` | `bg-[var(--color-accent-600)] text-white` |
|
|
48
|
+
| `secondary` | `bg-[var(--bg-secondary)] text-[var(--text-secondary)]` |
|
|
49
|
+
| `ghost` | `text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]` (NO border!) |
|
|
50
|
+
|
|
51
|
+
## Custom Cards (Status, Dashboard)
|
|
52
|
+
|
|
53
|
+
Button alignment pattern at bottom (mandatory for custom cards):
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
// WARNING: h-full flex flex-col + flex-1 + mt-auto
|
|
57
|
+
<div className="h-full flex flex-col rounded-[var(--radius-card)] border ...">
|
|
58
|
+
{/* Header */}
|
|
59
|
+
<div className="px-4 py-3 bg-gradient-to-r from-[var(--color-accent-500)]/10 ...">
|
|
60
|
+
{/* ... */}
|
|
61
|
+
</div>
|
|
62
|
+
{/* Content with flex-1 */}
|
|
63
|
+
<div className="flex-1 flex flex-col p-4">
|
|
64
|
+
{/* Variable content */}
|
|
65
|
+
{/* WARNING: mt-auto for button at bottom */}
|
|
66
|
+
<button className="mt-auto w-full ...">Action</button>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## When to Use EntityCard vs Custom
|
|
72
|
+
|
|
73
|
+
| EntityCard for | Custom for |
|
|
74
|
+
|----------------|------------|
|
|
75
|
+
| Homogeneous entity lists | Dashboard stats cards |
|
|
76
|
+
| Catalogs | Cards with complex interactive states |
|
|
77
|
+
| Clickable grids | Cards with integrated forms |
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Grid Layout Patterns
|
|
2
|
+
|
|
3
|
+
## Responsive Grid
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
// Standard
|
|
7
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
|
8
|
+
{items.map(item => <EntityCard key={item.id} {...mapToCardProps(item)} />)}
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
// With empty state
|
|
12
|
+
{items.length === 0 ? (
|
|
13
|
+
<div className="text-center py-12"><p>No items</p></div>
|
|
14
|
+
) : (
|
|
15
|
+
<div className="grid ...">...</div>
|
|
16
|
+
)}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Detail Page Template
|
|
20
|
+
|
|
21
|
+
### Structure
|
|
22
|
+
```tsx
|
|
23
|
+
<div className="container mx-auto px-4 py-6 max-w-7xl space-y-6">
|
|
24
|
+
{/* Header */}
|
|
25
|
+
<div className="flex items-center gap-4">
|
|
26
|
+
<button onClick={() => navigate(-1)} className="p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)]">
|
|
27
|
+
<ArrowLeft className="w-5 h-5 text-[var(--text-secondary)]" />
|
|
28
|
+
</button>
|
|
29
|
+
<div className="flex-1">
|
|
30
|
+
<h1 className="text-xl sm:text-2xl font-bold text-[var(--text-primary)]">{title}</h1>
|
|
31
|
+
<p className="text-sm text-[var(--text-secondary)]">{subtitle}</p>
|
|
32
|
+
</div>
|
|
33
|
+
<div className="flex items-center gap-2">
|
|
34
|
+
{/* Status badges */}
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
{/* Pill Tabs */}
|
|
39
|
+
<div className="flex gap-1 p-1 bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)]">
|
|
40
|
+
{tabs.map(tab => (
|
|
41
|
+
<button
|
|
42
|
+
key={tab.id}
|
|
43
|
+
className={`px-4 py-2 rounded-[var(--radius-button)] font-medium ${
|
|
44
|
+
activeTab === tab.id
|
|
45
|
+
? 'bg-[var(--color-accent-600)] text-white'
|
|
46
|
+
: 'text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]'
|
|
47
|
+
}`}
|
|
48
|
+
>
|
|
49
|
+
{tab.label}
|
|
50
|
+
</button>
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
{/* Tab Content */}
|
|
55
|
+
<div className="min-h-[400px]">{/* ... */}</div>
|
|
56
|
+
</div>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Info Card Pattern
|
|
60
|
+
```tsx
|
|
61
|
+
<div className="p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]">
|
|
62
|
+
<div className="flex items-center justify-between mb-4">
|
|
63
|
+
<h3 className="text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2">
|
|
64
|
+
<Icon className="w-5 h-5" />
|
|
65
|
+
{title}
|
|
66
|
+
</h3>
|
|
67
|
+
<button className="flex items-center gap-1 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]">
|
|
68
|
+
<Edit3 className="w-4 h-4" />
|
|
69
|
+
{t('common:edit')}
|
|
70
|
+
</button>
|
|
71
|
+
</div>
|
|
72
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
73
|
+
<div className="p-3 rounded-lg bg-[var(--bg-secondary)]">
|
|
74
|
+
<p className="text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1">{label}</p>
|
|
75
|
+
<p className="text-sm text-[var(--text-primary)] font-medium">{value}</p>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Error Display Pattern
|
|
82
|
+
```tsx
|
|
83
|
+
{error && (
|
|
84
|
+
<div className="p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]">
|
|
85
|
+
<div className="flex items-center gap-2 text-[var(--error-text)]">
|
|
86
|
+
<AlertTriangle className="w-5 h-5" />
|
|
87
|
+
<span>{error}</span>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Kanban Board Pattern
|
|
2
|
+
|
|
3
|
+
## Structure
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
<div className="flex gap-4 overflow-x-auto pb-4">
|
|
7
|
+
{columns.map(column => (
|
|
8
|
+
<div key={column.id} className="flex-shrink-0 w-72">
|
|
9
|
+
{/* Column Header */}
|
|
10
|
+
<div className="flex items-center justify-between mb-3 px-2">
|
|
11
|
+
<h3 className="font-medium text-[var(--text-primary)]">{column.title}</h3>
|
|
12
|
+
<span className="text-xs text-[var(--text-tertiary)] bg-[var(--bg-secondary)] px-2 py-0.5 rounded-full">
|
|
13
|
+
{column.items.length}
|
|
14
|
+
</span>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
{/* Column Cards */}
|
|
18
|
+
<div className="space-y-2">
|
|
19
|
+
{column.items.map(item => (
|
|
20
|
+
<div
|
|
21
|
+
key={item.id}
|
|
22
|
+
className="p-3 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] cursor-pointer"
|
|
23
|
+
>
|
|
24
|
+
<p className="text-sm font-medium text-[var(--text-primary)]">{item.title}</p>
|
|
25
|
+
<p className="text-xs text-[var(--text-secondary)] mt-1">{item.description}</p>
|
|
26
|
+
</div>
|
|
27
|
+
))}
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
))}
|
|
31
|
+
</div>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Column Status Mapping
|
|
35
|
+
|
|
36
|
+
Use CSS variables for column header colors:
|
|
37
|
+
|
|
38
|
+
| Column Status | Header Accent |
|
|
39
|
+
|--------------|---------------|
|
|
40
|
+
| To Do / Pending | `var(--info-dot)` |
|
|
41
|
+
| In Progress | `var(--color-accent-500)` |
|
|
42
|
+
| Review | `var(--warning-dot)` |
|
|
43
|
+
| Done | `var(--success-dot)` |
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Style Guide
|
|
2
|
+
|
|
3
|
+
## CRITICAL: CSS VARIABLES (NEVER HARDCODE COLORS)
|
|
4
|
+
|
|
5
|
+
**NEVER use hardcoded Tailwind colors.** ALWAYS use CSS variables for theme compliance.
|
|
6
|
+
|
|
7
|
+
### Status Colors
|
|
8
|
+
| Status | Background | Text | Border | Dot (solid) |
|
|
9
|
+
|--------|------------|------|--------|-------------|
|
|
10
|
+
| **Info** (Pending, Business) | `--info-bg` | `--info-text` | `--info-border` | `--info-dot` |
|
|
11
|
+
| **Success** (Active) | `--success-bg` | `--success-text` | `--success-border` | `--success-dot` |
|
|
12
|
+
| **Warning** (Suspended, Owner) | `--warning-bg` | `--warning-text` | `--warning-border` | `--warning-dot` |
|
|
13
|
+
| **Error** (Danger, Archive) | `--error-bg` | `--error-text` | `--error-border` | `--error-dot` |
|
|
14
|
+
| **Accent** (Personal, Primary) | `--accent-bg` | `--accent-text` | `--accent-border` | `--color-accent-500` |
|
|
15
|
+
|
|
16
|
+
### Badge Pattern
|
|
17
|
+
```tsx
|
|
18
|
+
// CORRECT - Uses CSS variables
|
|
19
|
+
<span className="px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--info-bg)] text-[var(--info-text)]">
|
|
20
|
+
Info Badge
|
|
21
|
+
</span>
|
|
22
|
+
|
|
23
|
+
// WRONG - Hardcoded Tailwind colors
|
|
24
|
+
<span className="bg-blue-500/10 text-blue-500">Info Badge</span>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Status Config Pattern
|
|
28
|
+
```tsx
|
|
29
|
+
// CORRECT
|
|
30
|
+
const STATUS_CONFIG = {
|
|
31
|
+
Pending: { bgColor: 'bg-[var(--info-bg)]', color: 'text-[var(--info-text)]', borderColor: 'border-[var(--info-border)]' },
|
|
32
|
+
Active: { bgColor: 'bg-[var(--success-bg)]', color: 'text-[var(--success-text)]', borderColor: 'border-[var(--success-border)]' },
|
|
33
|
+
Suspended: { bgColor: 'bg-[var(--warning-bg)]', color: 'text-[var(--warning-text)]', borderColor: 'border-[var(--warning-border)]' },
|
|
34
|
+
Archived: { bgColor: 'bg-[var(--bg-tertiary)]', color: 'text-[var(--text-tertiary)]', borderColor: 'border-[var(--border-color)]' }
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// WRONG - dark: variants are obsolete
|
|
38
|
+
const STATUS_CONFIG = {
|
|
39
|
+
Active: { bgColor: 'bg-emerald-50 dark:bg-emerald-900/20', ... }
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## BUTTON VARIANTS
|
|
44
|
+
|
|
45
|
+
### Action Buttons (Status changes)
|
|
46
|
+
```tsx
|
|
47
|
+
// Success action (Activate)
|
|
48
|
+
<button className="px-4 py-2 rounded-[var(--radius-button)] bg-[var(--success-dot)] text-white hover:opacity-90">
|
|
49
|
+
Activate
|
|
50
|
+
</button>
|
|
51
|
+
|
|
52
|
+
// Warning action (Suspend)
|
|
53
|
+
<button className="px-4 py-2 rounded-[var(--radius-button)] bg-[var(--warning-dot)] text-white hover:opacity-90">
|
|
54
|
+
Suspend
|
|
55
|
+
</button>
|
|
56
|
+
|
|
57
|
+
// Danger action (Archive/Delete)
|
|
58
|
+
<button className="px-4 py-2 rounded-[var(--radius-button)] bg-[var(--error-dot)] text-white hover:opacity-90">
|
|
59
|
+
Archive
|
|
60
|
+
</button>
|
|
61
|
+
|
|
62
|
+
// Primary action
|
|
63
|
+
<button className="px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)]">
|
|
64
|
+
Save
|
|
65
|
+
</button>
|
|
66
|
+
|
|
67
|
+
// Ghost action (NO BORDER!)
|
|
68
|
+
<button className="px-4 py-2 rounded-[var(--radius-button)] text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]">
|
|
69
|
+
Refresh
|
|
70
|
+
</button>
|
|
71
|
+
|
|
72
|
+
// Secondary action
|
|
73
|
+
<button className="px-4 py-2 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]">
|
|
74
|
+
Cancel
|
|
75
|
+
</button>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Button Rules
|
|
79
|
+
| Variant | Background | Text | Border | Hover |
|
|
80
|
+
|---------|------------|------|--------|-------|
|
|
81
|
+
| **Primary** | `--color-accent-600` | `white` | none | `--color-accent-700` |
|
|
82
|
+
| **Success** | `--success-dot` | `white` | none | `opacity-90` |
|
|
83
|
+
| **Warning** | `--warning-dot` | `white` | none | `opacity-90` |
|
|
84
|
+
| **Danger** | `--error-dot` | `white` | none | `opacity-90` |
|
|
85
|
+
| **Secondary** | `--bg-secondary` | `--text-secondary` | none | `--bg-hover` |
|
|
86
|
+
| **Ghost** | transparent | `--text-secondary` | **NONE** | `--bg-hover` |
|
|
@@ -156,6 +156,33 @@ workflowsApi.execute(workflowId, variables)
|
|
|
156
156
|
□ Tests: trigger, emails, variables
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
+
## RELATION WITH DOMAIN EVENTS
|
|
160
|
+
|
|
161
|
+
Workflow triggers (`TriggerAsync`) are the **primary mechanism** for cross-process automation (emails, webhooks, multi-step flows).
|
|
162
|
+
|
|
163
|
+
**Domain Events** (MediatR `INotificationHandler<T>`) are a complementary pattern for **in-process** side effects (audit logging, cache invalidation, read-model updates).
|
|
164
|
+
|
|
165
|
+
**Recommended pattern:** Domain Event handler bridges to Workflow triggers:
|
|
166
|
+
```csharp
|
|
167
|
+
// OrderCreatedEventHandler calls TriggerAsync for cross-process actions
|
|
168
|
+
public async Task Handle(OrderCreatedEvent notification, CancellationToken ct)
|
|
169
|
+
{
|
|
170
|
+
await _workflowService.TriggerAsync("order.created",
|
|
171
|
+
new Dictionary<string, object>{ ["orderId"] = notification.OrderId }, ct: ct);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**When to use which:**
|
|
176
|
+
| Scenario | Mechanism |
|
|
177
|
+
|----------|-----------|
|
|
178
|
+
| Send email after entity creation | Workflow Trigger |
|
|
179
|
+
| Invalidate cache after entity update | Domain Event |
|
|
180
|
+
| Log audit trail | Domain Event |
|
|
181
|
+
| Multi-step business process with delays | Workflow Trigger |
|
|
182
|
+
| Notify multiple services of same change | Domain Event → Workflow Trigger |
|
|
183
|
+
|
|
184
|
+
See `review-code/references/smartstack-conventions.md` (Domain Events section) for the full implementation pattern.
|
|
185
|
+
|
|
159
186
|
## ABSOLUTE RULES
|
|
160
187
|
|
|
161
188
|
| DO | DON'T |
|