Skip to content

Commit 6fb5f66

Browse files
committed
chore: make agent instruction for the custom vue components shorter
AdminForth/1849/issue--if-this-was-prompt-ted-
1 parent 6196e9f commit 6fb5f66

1 file changed

Lines changed: 12 additions & 135 deletions

File tree

  • adminforth/commands/createApp/templates/.agents/skills/adminforth-custom-vue

adminforth/commands/createApp/templates/.agents/skills/adminforth-custom-vue/SKILL.md.hbs

Lines changed: 12 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ user-invocable: true
1515
- Installing frontend packages used only by custom AdminForth Vue code.
1616
- Any task that produces visible UI in an AdminForth app, even when the task says nothing about how it should look.
1717

18-
## Non-Negotiable UI Defaults
18+
## Adminforth UI Defaults
1919

20-
Apply all of these to every piece of UI you write under `custom/`, including when the user gave no design
20+
Apply all of these to every piece of UI you write under `custom/`, especially when the user gave no design
2121
instructions at all. These are the defaults, not options — do not ask whether the user wants them, and do
2222
not wait for a follow-up prompt about styling or dark mode.
2323

@@ -26,145 +26,32 @@ not wait for a follow-up prompt about styling or dark mode.
2626
component covers the case.
2727
2. **Buttons come from AFCL with an explicit intent.** Primary/confirming action is the default filled
2828
accent `<Button>`. Secondary, cancel, and "back" actions are stroked `<Button variant="secondary">`.
29-
Destructive actions are `<Button variant="danger">`. Never hand-roll a `<button>` with your own
30-
background classes.
29+
Destructive actions are `<Button variant="danger">`.
3130
3. **Form controls come from AFCL.** `Input`, `Textarea`, `Select`, `Checkbox`, `Toggle`, `DatePicker`,
32-
`Dropzone`. Never a bare `<input>`, `<select>`, or `<textarea>` styled by hand — that is the main way
31+
`Dropzone`. Preferably not a bare `<input>`, `<select>`, or `<textarea>` styled by hand — that is the main way
3332
custom pages end up looking foreign.
3433
4. **Accents use `lightPrimary` / `darkPrimary`.** Anything that carries brand or "this is the important
3534
one" meaning — accent fills, highlighted values, active states, links, focus emphasis, the main chart
3635
series — should use `bg-lightPrimary dark:bg-darkPrimary`, `text-lightPrimary dark:text-darkPrimary`,
37-
`text-lightPrimaryContrast dark:text-darkPrimaryContrast` on top of an accent fill, or
38-
`bg-lightPrimaryOpacity dark:bg-darkPrimaryOpacity` for a subtle tint. Hardcoding an accent
39-
(`bg-blue-600`, `text-indigo-500`) breaks apps whose theme sets a different brand color.
36+
`text-lightPrimaryContrast dark:text-darkPrimaryContrast`.
4037
5. **Everything else may use Tailwind's stock palette.** `bg-white`, `bg-gray-50`, `text-gray-700`,
4138
`text-red-600`, `border-gray-200`, `bg-pink-500`, and friends are all fine for neutrals, surfaces,
4239
borders, and semantic colors. The theme tokens in the table below are still the better choice when a
4340
block sits directly next to built-in AdminForth chrome and should match it exactly — but they are a
4441
recommendation, not a restriction.
4542
6. **Dark theme is part of writing the class, not a later pass.** Every color utility must be written as a
46-
light/dark pair: `bg-white dark:bg-gray-900`, `text-gray-700 dark:text-gray-300`,
47-
`bg-lightForm dark:bg-darkForm`. This matters most with stock Tailwind colors, which have no built-in
43+
light/dark pair: `bg-white dark:bg-gray-900`, `text-gray-700 dark:text-gray-300`.
44+
This matters most with stock Tailwind colors, which have no built-in
4845
dark behavior — a `bg-gray-50` with no `dark:` counterpart is a defect, fix it before finishing.
4946
`light*`/`dark*` token pairs satisfy this by construction. Dark mode is class-based
5047
(`darkMode: 'class'`), so `dark:` variants work everywhere in `custom/`.
51-
7. **Non-color utilities are unrestricted.** Tailwind spacing, sizing, radius, flex/grid, and font-size
52-
utilities are fine and encouraged. Match AFCL's own rhythm so custom blocks sit naturally next to
53-
built-in ones: `rounded-lg`, `text-sm`, `p-4`, `gap-2`/`gap-4`.
54-
8. **Icons come from the prerendered Iconify packages** already present in the SPA:
48+
7. **Icons come from the prerendered Iconify packages** already present in the SPA:
5549
`@iconify-prerendered/vue-flowbite` (default), plus `-heroicons`, `-humbleicons`, and `-flag`.
5650
Do not add an icon dependency to `custom/package.json` for these.
57-
9. **Never build Tailwind class names dynamically.** `custom/` is copied into the SPA sources and scanned
51+
8. **Never build Tailwind class names dynamically.** `custom/` is copied into the SPA sources and scanned
5852
statically by Tailwind, so `` `text-${color}-600` `` produces no CSS. Write full class strings and pick
5953
between them.
6054

61-
## AFCL Component Inventory
62-
63-
All of these are imported from `@/afcl` and are already theme-aware and dark-mode-ready:
64-
65-
```ts
66-
import { Button, LinkButton, ButtonGroup, Link, Input, Textarea, Select, Checkbox, Toggle,
67-
DatePicker, Dropzone, Card, Table, Dialog, Modal, Tooltip, VerticalTabs,
68-
ProgressBar, Spinner, Skeleton, JsonViewer, CountryFlag,
69-
AreaChart, BarChart, PieChart, MixedChart, TreeMapChart } from '@/afcl';
70-
```
71-
72-
- Actions: `Button` (`variant`: `primary` | `secondary` | `danger`; also `loader`, `disabled`, `active`,
73-
`shadow`), `LinkButton` (same variants, navigates via `to`), `ButtonGroup`, `Link`.
74-
- Inputs: `Input` (requires `type`, supports `v-model`, `fullWidth`, `readonly`, `prefix`/`suffix` props
75-
or slots), `Textarea`, `Select` (`:options="[{ label, value }]"`, `multiple`, `placeholder`),
76-
`Checkbox`, `Toggle`, `DatePicker`, `Dropzone`.
77-
- Layout and data: `Card`, `Table` (client or server-side data, sorting, pagination), `VerticalTabs`,
78-
`Modal`, `Dialog`, `Tooltip`.
79-
- Feedback: `Spinner`, `Skeleton`, `ProgressBar`.
80-
- Charts: `AreaChart`, `BarChart`, `PieChart`, `MixedChart`, `TreeMapChart` — prefer these over pulling in
81-
a new charting library, they already follow theme colors.
82-
83-
Before writing a bespoke widget, check this list. Reusing an AFCL component is always the preferred
84-
answer to "make a button / input / table / modal / chart".
85-
86-
## Theme Color Tokens
87-
88-
These light/dark pairs follow the app's configured theme automatically. The accent rows are the ones you
89-
should actually reach for by default (rule 4); the rest are available when you want a custom block to
90-
match built-in AdminForth chrome pixel-for-pixel instead of approximating it with stock grays. Every
91-
`light*` token has a `dark*` twin.
92-
93-
| Need | Classes |
94-
| --- | --- |
95-
| **Accent (brand) text** | `text-lightPrimary dark:text-darkPrimary` |
96-
| **Accent fill** | `bg-lightPrimary dark:bg-darkPrimary` |
97-
| **Text on accent fill** | `text-lightPrimaryContrast dark:text-darkPrimaryContrast` |
98-
| **Subtle accent tint** | `bg-lightPrimaryOpacity dark:bg-darkPrimaryOpacity` |
99-
| Panel / form surface | `bg-lightForm dark:bg-darkForm` |
100-
| Panel border | `border-lightFormBorder dark:border-darkFormBorder` |
101-
| Section heading strip | `bg-lightFormHeading dark:bg-darkFormHeading` |
102-
| Card surface | `bg-lightCardBackground dark:bg-darkCardBackground` |
103-
| Card border | `border-lightCardBorder dark:border-darkCardBorder` |
104-
| Strong / title text | `text-lightCardTitle dark:text-darkCardTitle` |
105-
| Muted / secondary text | `text-lightCardDescription dark:text-darkCardDescription` |
106-
| Body and table text | `text-lightListTableText dark:text-darkListTableText` |
107-
| Table heading text | `text-lightListTableHeadingText dark:text-darkListTableHeadingText` |
108-
| Divider / separator | `border-lightListBorder dark:border-darkListBorder` |
109-
| Error / invalid text | `text-lightInputErrorColor dark:text-darkInputErrorColor` |
110-
| Required marker | `text-lightRequiredIconColor dark:text-darkRequiredIconColor` |
111-
| Focus ring | `focus:ring-lightFocusRing dark:focus:ring-darkFocusRing` |
112-
113-
The complete token list lives in `node_modules/adminforth/dist/modules/styles.js`. Look a name up there
114-
instead of inventing one — an unknown token silently produces no CSS.
115-
116-
## Default Panel Recipe
117-
118-
When a task asks for "a panel", "a summary block", "a small form", or any custom page area with no visual
119-
spec, start from this shape. It is theme-correct and dark-ready with no extra work:
120-
121-
```vue
122-
<template>
123-
<div class="rounded-lg border border-lightFormBorder dark:border-darkFormBorder
124-
bg-lightForm dark:bg-darkForm p-4">
125-
<h3 class="text-lg font-semibold text-lightCardTitle dark:text-darkCardTitle">
126-
\{{ meta?.title || 'Orders overview' }}
127-
</h3>
128-
<p class="mt-1 text-sm text-lightCardDescription dark:text-darkCardDescription">
129-
Totals for the current filter
130-
</p>
131-
132-
<div class="mt-4 grid gap-3 sm:grid-cols-2">
133-
<Input type="text" v-model="query" full-width placeholder="Search orders" />
134-
<Select v-model="period" :options="periodOptions" placeholder="Period" />
135-
</div>
136-
137-
<div class="mt-4 flex items-center gap-2">
138-
<Button :loader="loading" @click="apply">Apply</Button>
139-
<Button variant="secondary" @click="reset">Reset</Button>
140-
</div>
141-
142-
<p v-if="error" class="mt-2 text-sm text-lightInputErrorColor dark:text-darkInputErrorColor">
143-
\{{ error }}
144-
</p>
145-
</div>
146-
</template>
147-
148-
<script setup lang="ts">
149-
import { ref } from 'vue';
150-
import { Button, Input, Select } from '@/afcl';
151-
152-
defineProps<{ meta?: { title?: string } }>();
153-
154-
const query = ref('');
155-
const period = ref(null);
156-
const loading = ref(false);
157-
const error = ref('');
158-
const periodOptions = [
159-
{ label: 'Last 7 days', value: '7' },
160-
{ label: 'Last 30 days', value: '30' },
161-
];
162-
163-
function apply() { /* ... */ }
164-
function reset() { query.value = ''; period.value = null; }
165-
</script>
166-
```
167-
16855
## Dark Theme Self-Check
16956

17057
Run this over every file you touched before reporting the work as done:
@@ -177,8 +64,6 @@ Run this over every file you touched before reporting the work as done:
17764
dark mode.
17865
- Accents are `lightPrimary`/`darkPrimary`, not a hardcoded blue or indigo.
17966
- No raw `#hex` or `rgb()` in templates or `<style>` blocks.
180-
- Any raw `<button>`, `<input>`, `<select>`, or `<textarea>` has a justification; otherwise replace it with
181-
the AFCL equivalent.
18267
18368
```
18469
❌ <button class="bg-blue-600 text-white rounded px-4 py-2">Save</button>
@@ -187,14 +72,8 @@ Run this over every file you touched before reporting the work as done:
18772
❌ <div class="bg-white border border-gray-200 text-gray-800">
18873
✅ <div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700
18974
text-gray-800 dark:text-gray-200">
190-
✅ <div class="bg-lightForm dark:bg-darkForm border border-lightFormBorder
191-
dark:border-darkFormBorder text-lightListTableText dark:text-darkListTableText">
192-
19375
❌ <p class="text-red-600">\{{ error }}</p>
19476
✅ <p class="text-red-600 dark:text-red-400">\{{ error }}</p>
195-
196-
❌ <span class="font-semibold text-blue-600 dark:text-blue-400">\{{ total }}</span>
197-
✅ <span class="font-semibold text-lightPrimary dark:text-darkPrimary">\{{ total }}</span>
19877
```
19978
20079
## `custom/` Directory and `@@/`
@@ -322,11 +201,11 @@ show: {
322201
@update:model-value="onInput"
323202
/>
324203
325-
<p v-if="errorMessage" class="text-sm text-lightInputErrorColor dark:text-darkInputErrorColor">
204+
<p v-if="errorMessage" class="text-sm">
326205
\{{ errorMessage }}
327206
</p>
328207
329-
<p v-else-if="isEmpty" class="text-sm text-lightCardDescription dark:text-darkCardDescription">
208+
<p v-else-if="isEmpty" class="text-sm">
330209
Value is currently empty
331210
</p>
332211
</div>
@@ -414,7 +293,7 @@ function syncState() {
414293
415294
```vue
416295
<template>
417-
<div class="flex items-center gap-2 text-lightListTableText dark:text-darkListTableText">
296+
<div class="flex items-center gap-2">
418297
<span>
419298
\{{ meta?.filler?.repeat(record.number_of_rooms || 0) }}
420299
</span>
@@ -530,6 +409,4 @@ options: {
530409
- Reach for an AFCL component before writing markup; use `lightPrimary`/`darkPrimary` for accents; write
531410
the `dark:` variant in the same edit as the light one. These are defaults for every UI task, not polish
532411
to be added when someone asks for it.
533-
- Stock Tailwind colors are fine for neutrals and semantic states — just never leave one without its
534-
`dark:` counterpart.
535412
- When you are done, re-read your diff against the Dark Theme Self-Check above before reporting completion.

0 commit comments

Comments
 (0)