create-coline-app 2.5.0 → 2.5.1
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/package.json +1 -1
- package/src/cli.test.ts +2 -2
- package/templates/backendless/.agents/skills/coline-ui-design/SKILL.md +22 -0
- package/templates/backendless/.agents/skills/coline-ui-review/SKILL.md +8 -0
- package/templates/backendless/examples/board.tsx +6 -11
- package/templates/backendless/examples/settings.tsx +4 -8
- package/templates/backendless/examples/triage.tsx +9 -19
- package/templates/backendless/package.json +2 -2
package/package.json
CHANGED
package/src/cli.test.ts
CHANGED
|
@@ -53,10 +53,10 @@ describe("runCreate", () => {
|
|
|
53
53
|
};
|
|
54
54
|
expect(packageJson.name).toBe("team-crm");
|
|
55
55
|
expect(packageJson.dependencies["@colineapp/sdk"]).toBe("^0.4.0");
|
|
56
|
-
expect(packageJson.dependencies["@colineapp/ui"]).toBe("^0.4.
|
|
56
|
+
expect(packageJson.dependencies["@colineapp/ui"]).toBe("^0.4.1");
|
|
57
57
|
expect(packageJson.dependencies.react).toBe("^19.0.0");
|
|
58
58
|
expect(packageJson.dependencies["react-dom"]).toBe("^19.0.0");
|
|
59
|
-
expect(packageJson.devDependencies["create-coline-app"]).toBe("^2.5.
|
|
59
|
+
expect(packageJson.devDependencies["create-coline-app"]).toBe("^2.5.1");
|
|
60
60
|
const main = await readFile(join(dir, "main.tsx"), "utf8");
|
|
61
61
|
expect(main).toContain("ColineAppProvider");
|
|
62
62
|
expect(main).toContain("AppPage");
|
|
@@ -65,3 +65,25 @@ states. No pretend search, dead menus, invented metrics, or static success toast
|
|
|
65
65
|
|
|
66
66
|
Run the adjacent `coline-ui-review` skill before finishing. If your model cannot
|
|
67
67
|
inspect images, say so; mechanical checks alone do not establish visual quality.
|
|
68
|
+
|
|
69
|
+
## Use the shared controls
|
|
70
|
+
|
|
71
|
+
- Views: `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`. The raised selection
|
|
72
|
+
and content motion are built in. Do not handwrite tab buttons or underline tabs.
|
|
73
|
+
- Filters and value pickers: `FilterMenu` with `value`, `onValueChange`,
|
|
74
|
+
`aria-label`, and `options: [{ value, label }]`. This uses Coline's dropdown,
|
|
75
|
+
including its checked items, surface and animated highlight. Avoid native
|
|
76
|
+
selects for these product controls. Use `DropdownMenu` directly for actions.
|
|
77
|
+
- Dialogs: `Dialog` / `DialogContent` include motion and a dismiss button. Use
|
|
78
|
+
`DialogTitle` and `DialogDescription`; keep content inside the viewport.
|
|
79
|
+
- Buttons: use variants without custom background overrides. Set `type="submit"`
|
|
80
|
+
explicitly inside forms. Other buttons do not submit forms by default.
|
|
81
|
+
|
|
82
|
+
The default `PageToolbar` has no top/bottom border. Keep the header simple and
|
|
83
|
+
use whitespace to separate controls from content. Don't draw another border
|
|
84
|
+
around the table or add a background strip to every row.
|
|
85
|
+
|
|
86
|
+
App-local CSS variables scoped to a page are not available in portalled dialogs
|
|
87
|
+
and menus. Use host tokens for shared controls; put decorative app variables at
|
|
88
|
+
`:root` if both the page and portals need them. Upgrading the UI dependency and
|
|
89
|
+
rebuilding updates shared defaults; copied app CSS continues to override them.
|
|
@@ -37,3 +37,11 @@ Keep preview cleanup scoped. The screenshot command closes its own server. For
|
|
|
37
37
|
interactive QA, retain the terminal session or exact child-process PID you started
|
|
38
38
|
and stop only that process. Never use broad `pkill -f` or `killall` commands: other
|
|
39
39
|
apps may be running previews at the same time.
|
|
40
|
+
|
|
41
|
+
Check dialog buttons in both themes: page-scoped CSS variables do not inherit
|
|
42
|
+
into portals. Exercise form submission, Escape/close, tab keyboard navigation,
|
|
43
|
+
and filter menu selection. Capture every actual app view, not only the default
|
|
44
|
+
preview tab. Inspect motion and reduced-motion behavior as well as still images.
|
|
45
|
+
Keep the number of attached images within the model/provider's request limit;
|
|
46
|
+
review a small representative set, compact context before accumulating more,
|
|
47
|
+
and record provider failures separately from app failures.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FilterMenu,
|
|
3
3
|
AppPage,
|
|
4
4
|
PageToolbar,
|
|
5
5
|
Input,
|
|
@@ -65,10 +65,10 @@ export function Example({ state = "ready" }: { state?: string }) {
|
|
|
65
65
|
const [items, setItems] = React.useState(state === "empty" ? [] : initial);
|
|
66
66
|
const [search, setSearch] = React.useState("");
|
|
67
67
|
const [failure, setFailure] = React.useState(state === "error" || state === "denied");
|
|
68
|
-
const moveControls = React.useRef(new Map<string,
|
|
68
|
+
const moveControls = React.useRef(new Map<string, HTMLButtonElement>());
|
|
69
69
|
function move(id: string, stage: string) {
|
|
70
70
|
setItems((current) => current.map((item) => (item.id === id ? { ...item, stage } : item)));
|
|
71
|
-
// Moving between columns remounts the
|
|
71
|
+
// Moving between columns remounts the trigger. Keep keyboard users on the story.
|
|
72
72
|
requestAnimationFrame(() => moveControls.current.get(id)?.focus());
|
|
73
73
|
}
|
|
74
74
|
function add() {
|
|
@@ -147,20 +147,15 @@ export function Example({ state = "ready" }: { state?: string }) {
|
|
|
147
147
|
<p className="example-description">{item.description}</p>
|
|
148
148
|
<label className="example-field">
|
|
149
149
|
Move to
|
|
150
|
-
<
|
|
151
|
-
className="example-
|
|
150
|
+
<FilterMenu
|
|
151
|
+
className="example-filter"
|
|
152
152
|
aria-label={`Move ${item.title} to`}
|
|
153
153
|
value={item.stage}
|
|
154
154
|
ref={(element) => {
|
|
155
155
|
if (element) moveControls.current.set(item.id, element);
|
|
156
156
|
else moveControls.current.delete(item.id);
|
|
157
157
|
}}
|
|
158
|
-
|
|
159
|
-
>
|
|
160
|
-
{stages.map((value) => (
|
|
161
|
-
<option key={value}>{value}</option>
|
|
162
|
-
))}
|
|
163
|
-
</select>
|
|
158
|
+
onValueChange={(value) => move(item.id, value)} options={stages.map((value) => ({ value, label: value }))} />
|
|
164
159
|
</label>
|
|
165
160
|
</BoardCard>
|
|
166
161
|
))}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FilterMenu,
|
|
3
3
|
AppPage,
|
|
4
4
|
SettingsSection,
|
|
5
5
|
Input,
|
|
@@ -80,15 +80,11 @@ export function Example({ state = "ready" }: { state?: string }) {
|
|
|
80
80
|
</label>
|
|
81
81
|
<label className="example-field">
|
|
82
82
|
Frequency
|
|
83
|
-
<
|
|
84
|
-
className="example-
|
|
83
|
+
<FilterMenu
|
|
84
|
+
className="example-filter"
|
|
85
85
|
disabled={!form.digest}
|
|
86
86
|
value={form.cadence}
|
|
87
|
-
|
|
88
|
-
>
|
|
89
|
-
<option>Weekly</option>
|
|
90
|
-
<option>Monthly</option>
|
|
91
|
-
</select>
|
|
87
|
+
onValueChange={(value) => setForm({ ...form, cadence: value })} aria-label="Frequency" options={["Weekly", "Monthly"].map((value) => ({ value, label: value }))} />
|
|
92
88
|
</label>
|
|
93
89
|
</SettingsSection>
|
|
94
90
|
<div className="flex items-center justify-end gap-3 py-6">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FilterMenu,
|
|
3
3
|
AppPage,
|
|
4
4
|
PageToolbar,
|
|
5
5
|
Input,
|
|
@@ -123,16 +123,11 @@ export function Example({ state = "ready" }: { state?: string }) {
|
|
|
123
123
|
value={search}
|
|
124
124
|
onChange={(event) => setSearch(event.target.value)}
|
|
125
125
|
/>
|
|
126
|
-
<
|
|
126
|
+
<FilterMenu
|
|
127
127
|
aria-label="Filter by status"
|
|
128
|
-
className="example-
|
|
128
|
+
className="example-filter"
|
|
129
129
|
value={status}
|
|
130
|
-
|
|
131
|
-
>
|
|
132
|
-
{["All requests", "Needs review", "In progress", "Planned"].map((value) => (
|
|
133
|
-
<option key={value}>{value}</option>
|
|
134
|
-
))}
|
|
135
|
-
</select>
|
|
130
|
+
onValueChange={(value) => setStatus(value)} options={["All requests", "Needs review", "In progress", "Planned"].map((value) => ({ value, label: value }))} />
|
|
136
131
|
<span className="example-meta">{visible.length} requests</span>
|
|
137
132
|
</PageToolbar>
|
|
138
133
|
{state === "loading" ? (
|
|
@@ -223,23 +218,18 @@ export function Example({ state = "ready" }: { state?: string }) {
|
|
|
223
218
|
<p className="example-description">{detail.detail}</p>
|
|
224
219
|
<label className="example-field">
|
|
225
220
|
Status
|
|
226
|
-
<
|
|
227
|
-
className="example-
|
|
221
|
+
<FilterMenu
|
|
222
|
+
className="example-filter"
|
|
228
223
|
value={detail.status}
|
|
229
|
-
|
|
224
|
+
onValueChange={(value) =>
|
|
230
225
|
setRecords((current) =>
|
|
231
226
|
current.map((record) =>
|
|
232
227
|
record.id === detail.id
|
|
233
|
-
? { ...record, status:
|
|
228
|
+
? { ...record, status: value }
|
|
234
229
|
: record,
|
|
235
230
|
),
|
|
236
231
|
)
|
|
237
|
-
}
|
|
238
|
-
>
|
|
239
|
-
{["Needs review", "In progress", "Planned"].map((value) => (
|
|
240
|
-
<option key={value}>{value}</option>
|
|
241
|
-
))}
|
|
242
|
-
</select>
|
|
232
|
+
} aria-label="Status" options={["Needs review", "In progress", "Planned"].map((value) => ({ value, label: value }))} />
|
|
243
233
|
</label>
|
|
244
234
|
<div className="example-meta">{detail.category}</div>
|
|
245
235
|
</DetailPanel>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@colineapp/sdk": "^0.4.0",
|
|
17
|
-
"@colineapp/ui": "^0.4.
|
|
17
|
+
"@colineapp/ui": "^0.4.1",
|
|
18
18
|
"react": "^19.0.0",
|
|
19
19
|
"react-dom": "^19.0.0",
|
|
20
20
|
"zod": "^4.3.6"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/react": "^19.0.0",
|
|
24
24
|
"@types/react-dom": "^19.0.0",
|
|
25
|
-
"create-coline-app": "^2.5.
|
|
25
|
+
"create-coline-app": "^2.5.1",
|
|
26
26
|
"typescript": "^5.8.2",
|
|
27
27
|
"vitest": "^3.2.4",
|
|
28
28
|
"tailwindcss": "^4.3.0",
|