@pixerate/editor 0.223.6 → 0.223.8
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/dist/tools/skill-evals.d.cts +23 -1
- package/dist/tools/skill-evals.d.ts +23 -1
- package/package.json +1 -1
- package/skills/README.md +8 -3
- package/skills/pixerate-accessibility-audit/SKILL.md +98 -0
- package/skills/pixerate-accessibility-audit/evals/button-label-contrast.json +97 -0
- package/skills/pixerate-accessibility-audit/evals/distinct-for-cvd.json +160 -0
- package/skills/pixerate-accessibility-audit/evals/icon-non-text-contrast.json +109 -0
- package/skills/pixerate-brand-application/SKILL.md +99 -0
- package/skills/pixerate-brand-application/evals/apply-palette.json +148 -0
- package/skills/pixerate-brand-application/evals/readable-on-brand.json +104 -0
- package/skills/pixerate-brand-application/evals/snap-to-palette.json +148 -0
- package/skills/pixerate-color/SKILL.md +8 -0
- package/skills/pixerate-effect-authoring/SKILL.md +7 -0
- package/skills/pixerate-effect-look-development/SKILL.md +96 -0
- package/skills/pixerate-effect-look-development/evals/fade-in.json +55 -0
- package/skills/pixerate-effect-look-development/evals/seamless-loop.json +66 -0
- package/skills/pixerate-effect-look-development/evals/subtle-preset.json +49 -0
- package/skills/pixerate-generation/SKILL.md +7 -0
- package/skills/pixerate-generation-budgeted-batch/SKILL.md +99 -0
- package/skills/pixerate-generation-budgeted-batch/evals/drafts-within-budget.json +101 -0
- package/skills/pixerate-generation-budgeted-batch/evals/right-model-for-format.json +124 -0
- package/skills/pixerate-generation-budgeted-batch/evals/vary-earlier.json +101 -0
|
@@ -20,7 +20,7 @@ export interface SkillEvalCheck extends SkillEvalToolCall {
|
|
|
20
20
|
}
|
|
21
21
|
export interface SkillEval {
|
|
22
22
|
prompt: string;
|
|
23
|
-
fixture: SpreadsheetEvalFixture | ImageEvalFixture | VectorEvalFixture | PaintEvalFixture | VideoEvalFixture | ChartEvalFixture | DiagramEvalFixture | RichTextEvalFixture | AnimationEvalFixture;
|
|
23
|
+
fixture: SpreadsheetEvalFixture | ImageEvalFixture | VectorEvalFixture | PaintEvalFixture | VideoEvalFixture | ChartEvalFixture | DiagramEvalFixture | RichTextEvalFixture | AnimationEvalFixture | GenerationEvalFixture | EffectEvalFixture;
|
|
24
24
|
checks: SkillEvalCheck[];
|
|
25
25
|
solution: SkillEvalToolCall[];
|
|
26
26
|
}
|
|
@@ -54,6 +54,8 @@ export interface VectorEvalFixture {
|
|
|
54
54
|
id: string;
|
|
55
55
|
params?: Record<string, unknown>;
|
|
56
56
|
}>;
|
|
57
|
+
/** Also register the colour tools (`check_color_contrast`, `check_color_palette`, ...). */
|
|
58
|
+
colorTools?: boolean;
|
|
57
59
|
}
|
|
58
60
|
export interface PaintEvalFixture {
|
|
59
61
|
editor: 'paint';
|
|
@@ -87,6 +89,26 @@ export interface AnimationEvalFixture {
|
|
|
87
89
|
/** Tool calls that build the starting scene (`set_animation_artwork_svg`, `insert_shots`), run in order. */
|
|
88
90
|
setup?: SkillEvalToolCall[];
|
|
89
91
|
}
|
|
92
|
+
export interface GenerationEvalFixture {
|
|
93
|
+
editor: 'generation';
|
|
94
|
+
/** The host's model catalogue (`ModelCapabilities` records). */
|
|
95
|
+
models: Array<Record<string, unknown>>;
|
|
96
|
+
/** Price in USD per output, by `quality` (`default` for requests without one); adds `estimate_generation`. */
|
|
97
|
+
prices?: Record<string, number>;
|
|
98
|
+
/** Earlier generations in the history: a model id and the request it ran. */
|
|
99
|
+
history?: Array<{
|
|
100
|
+
id: string;
|
|
101
|
+
model: string;
|
|
102
|
+
request: Record<string, unknown>;
|
|
103
|
+
}>;
|
|
104
|
+
}
|
|
105
|
+
export interface EffectEvalFixture {
|
|
106
|
+
editor: 'effect';
|
|
107
|
+
/** The fake effect provider's effect to author (e.g. `fake.invert`). */
|
|
108
|
+
effectId: string;
|
|
109
|
+
/** Tool calls that prepare the session, run in order. */
|
|
110
|
+
setup?: SkillEvalToolCall[];
|
|
111
|
+
}
|
|
90
112
|
/** One eval file of a skill. */
|
|
91
113
|
export interface SkillEvalFile {
|
|
92
114
|
skill: string;
|
|
@@ -20,7 +20,7 @@ export interface SkillEvalCheck extends SkillEvalToolCall {
|
|
|
20
20
|
}
|
|
21
21
|
export interface SkillEval {
|
|
22
22
|
prompt: string;
|
|
23
|
-
fixture: SpreadsheetEvalFixture | ImageEvalFixture | VectorEvalFixture | PaintEvalFixture | VideoEvalFixture | ChartEvalFixture | DiagramEvalFixture | RichTextEvalFixture | AnimationEvalFixture;
|
|
23
|
+
fixture: SpreadsheetEvalFixture | ImageEvalFixture | VectorEvalFixture | PaintEvalFixture | VideoEvalFixture | ChartEvalFixture | DiagramEvalFixture | RichTextEvalFixture | AnimationEvalFixture | GenerationEvalFixture | EffectEvalFixture;
|
|
24
24
|
checks: SkillEvalCheck[];
|
|
25
25
|
solution: SkillEvalToolCall[];
|
|
26
26
|
}
|
|
@@ -54,6 +54,8 @@ export interface VectorEvalFixture {
|
|
|
54
54
|
id: string;
|
|
55
55
|
params?: Record<string, unknown>;
|
|
56
56
|
}>;
|
|
57
|
+
/** Also register the colour tools (`check_color_contrast`, `check_color_palette`, ...). */
|
|
58
|
+
colorTools?: boolean;
|
|
57
59
|
}
|
|
58
60
|
export interface PaintEvalFixture {
|
|
59
61
|
editor: 'paint';
|
|
@@ -87,6 +89,26 @@ export interface AnimationEvalFixture {
|
|
|
87
89
|
/** Tool calls that build the starting scene (`set_animation_artwork_svg`, `insert_shots`), run in order. */
|
|
88
90
|
setup?: SkillEvalToolCall[];
|
|
89
91
|
}
|
|
92
|
+
export interface GenerationEvalFixture {
|
|
93
|
+
editor: 'generation';
|
|
94
|
+
/** The host's model catalogue (`ModelCapabilities` records). */
|
|
95
|
+
models: Array<Record<string, unknown>>;
|
|
96
|
+
/** Price in USD per output, by `quality` (`default` for requests without one); adds `estimate_generation`. */
|
|
97
|
+
prices?: Record<string, number>;
|
|
98
|
+
/** Earlier generations in the history: a model id and the request it ran. */
|
|
99
|
+
history?: Array<{
|
|
100
|
+
id: string;
|
|
101
|
+
model: string;
|
|
102
|
+
request: Record<string, unknown>;
|
|
103
|
+
}>;
|
|
104
|
+
}
|
|
105
|
+
export interface EffectEvalFixture {
|
|
106
|
+
editor: 'effect';
|
|
107
|
+
/** The fake effect provider's effect to author (e.g. `fake.invert`). */
|
|
108
|
+
effectId: string;
|
|
109
|
+
/** Tool calls that prepare the session, run in order. */
|
|
110
|
+
setup?: SkillEvalToolCall[];
|
|
111
|
+
}
|
|
90
112
|
/** One eval file of a skill. */
|
|
91
113
|
export interface SkillEvalFile {
|
|
92
114
|
skill: string;
|
package/package.json
CHANGED
package/skills/README.md
CHANGED
|
@@ -63,6 +63,10 @@ request like "clean up this export" finds it.
|
|
|
63
63
|
| [`pixerate-rich-text-revise`](pixerate-rich-text-revise/SKILL.md) | Rich text (`pixerate-rich-text`) | Proofreading, renaming terms with exceptions and tightening, as minimal targeted edits. |
|
|
64
64
|
| [`pixerate-animation-motion-graphics`](pixerate-animation-motion-graphics/SKILL.md) | Animation (`pixerate-animation-editor`) | One idea per shot, staggered entrances, natural easing, holds to read, fitting a length, checks and export. |
|
|
65
65
|
| [`pixerate-animation-logo-reveal`](pixerate-animation-logo-reveal/SKILL.md) | Animation (`pixerate-animation-editor`) | A short reveal built from the logo's parts, landing on the beat and ending on the held, finished logo. |
|
|
66
|
+
| [`pixerate-generation-budgeted-batch`](pixerate-generation-budgeted-batch/SKILL.md) | Generation (`pixerate-generation`) | The right model for the format, plan and estimate before spending, drafts cheap and finals once, safe retries, variations from the history. |
|
|
67
|
+
| [`pixerate-effect-look-development`](pixerate-effect-look-development/SKILL.md) | Effects (`pixerate-effect-authoring`) | Tune a look in a few moves, save it as a preset, animate with eased keyframes, seamless loops. |
|
|
68
|
+
| [`pixerate-accessibility-audit`](pixerate-accessibility-audit/SKILL.md) | Cross-domain (`pixerate-color`) | Text and non-text contrast, colour-blind-safe meaning, both modes, smallest fixes and a report, in any editor. |
|
|
69
|
+
| [`pixerate-brand-application`](pixerate-brand-application/SKILL.md) | Cross-domain (`pixerate-color`) | Brand roles mapped to exact palette values, near-misses snapped, readable text on brand colours, derivatives and house-style checks. |
|
|
66
70
|
| [`pixerate-talking-head-edit`](pixerate-talking-head-edit/SKILL.md) | Video (`pixerate-video-editor`) | Talking-head cleanup by transcript: fillers, long pauses and stutters found in one pass and cut as one plan reviewed before it applies. Owns the dialogue tools. |
|
|
67
71
|
| [`pixerate-bgm-alignment`](pixerate-bgm-alignment/SKILL.md) | Video (`pixerate-video-editor`) | Background music: beats and cuts on the beat, ducking under speech, loudness in LUFS. Owns the music tools. |
|
|
68
72
|
|
|
@@ -126,11 +130,12 @@ same change.
|
|
|
126
130
|
`packages/core/tests/agent-skill-evals.test.ts`. An eval has a `prompt` (the task, in the
|
|
127
131
|
user's words), a `fixture` (the starting document: `{ "editor": "spreadsheet", "rows" }`,
|
|
128
132
|
`{ "editor": "image", "width", "height", "background", "shapes" }` or `{ "editor":
|
|
129
|
-
"vector", "width", "height", "setup" }` with commands that draw the starting art,
|
|
133
|
+
"vector", "width", "height", "setup", "colorTools" }` with commands that draw the starting art,
|
|
130
134
|
`{ "editor": "paint", "width", "height", "setup" }` `{ "editor": "video", "setup" }` or `{ "editor":
|
|
131
135
|
"chart", "setup" }` `{ "editor": "diagram", "setup" }` with tool calls,
|
|
132
|
-
`{ "editor": "rich-text", "html" }`,
|
|
133
|
-
`{ "editor": "animation", "setup" }`
|
|
136
|
+
`{ "editor": "rich-text", "html" }`,
|
|
137
|
+
`{ "editor": "animation", "setup" }`, `{ "editor": "generation", "models", "prices", "history" }`
|
|
138
|
+
(a fake host that records each generation) or `{ "editor": "effect", "effectId", "setup" }`), `checks` (a read-only
|
|
134
139
|
tool, or `run_command` with a read-only command such as `vector.list`, its `args`, what its result must match in `expect`, and `why`) and a `solution` (the
|
|
135
140
|
tool calls an expert would make). The test proves each eval: some check fails on the fixture,
|
|
136
141
|
and all pass after the solution. A model harness runs the same file with the model in place
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixerate-accessibility-audit
|
|
3
|
+
description: The accessibility audit workflow across Pixerate editors - checking text contrast (WCAG AA 4.5:1, large text 3:1), non-text contrast for icons, borders and controls (3:1), colour-only meaning and palettes under colour-vision deficiencies, light and dark modes, type readability, and fixing what fails with the smallest change, then reporting what was checked and changed. Use when asked to audit, check or fix accessibility, contrast, legibility, readability or colour-blind safety of a design, chart, icon, document, UI or brand palette, or to meet WCAG, or when check_color_contrast, check_color_palette or check_dual_color_contrast are available. Load with pixerate-color, which lists the colour tools, and the skill for the editor that holds the design.
|
|
4
|
+
metadata:
|
|
5
|
+
kind: workflow
|
|
6
|
+
reference: pixerate-color
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Auditing accessibility
|
|
10
|
+
|
|
11
|
+
An accessibility audit finds what some readers cannot see or tell apart, fixes it with the
|
|
12
|
+
smallest change that keeps the design's intent, and reports both. Measure, never eyeball:
|
|
13
|
+
every text and background pair gets a contrast ratio, every set of colours that carries meaning
|
|
14
|
+
gets a colour-vision check, and every fix is measured again.
|
|
15
|
+
|
|
16
|
+
This skill is the method. `pixerate-color` has the colour tools; read colours from the design
|
|
17
|
+
with its editor's tools (`vector.list` in the vector editor, `get_chart` and
|
|
18
|
+
`check_chart_colors` for charts, `measure_region` for an image).
|
|
19
|
+
|
|
20
|
+
## Goal and quality bar
|
|
21
|
+
|
|
22
|
+
- Normal text at least 4.5:1 against its background, large text (24 px, or 18.5 px bold) at
|
|
23
|
+
least 3:1 (`check_color_contrast`, with `large: true` for large text).
|
|
24
|
+
- Icons, borders, focus rings, chart lines and control outlines at least 3:1 against what they
|
|
25
|
+
sit on.
|
|
26
|
+
- Colours that carry meaning (status, series, categories) distinct under protanopia,
|
|
27
|
+
deuteranopia and tritanopia (`check_color_palette` `ok: true`), and not the only cue (add a
|
|
28
|
+
label, shape or pattern where meaning matters).
|
|
29
|
+
- Both light and dark modes pass when the design has them (`check_dual_color_contrast`).
|
|
30
|
+
- Fixes change as little as possible: the text colour rather than the brand background, a
|
|
31
|
+
darker shade of the same hue rather than a new hue.
|
|
32
|
+
- A report lists each pair checked, its ratio before and after, and what changed.
|
|
33
|
+
|
|
34
|
+
## Inputs to confirm
|
|
35
|
+
|
|
36
|
+
- **The standard:** WCAG 2 AA (the default) or AAA.
|
|
37
|
+
- **What may change:** usually text and icon colours; brand backgrounds and logos only with
|
|
38
|
+
approval.
|
|
39
|
+
- **Modes:** light, dark or both.
|
|
40
|
+
|
|
41
|
+
## Working method
|
|
42
|
+
|
|
43
|
+
1. **Inventory.** Read every foreground and background pair from the design's editor: text on
|
|
44
|
+
surfaces, icons on cards, lines on plots, status colours.
|
|
45
|
+
**Check:** each pair has a role (normal text, large text, graphic, decorative).
|
|
46
|
+
2. **Measure.** `check_color_contrast` for each pair (`large: true` for large text);
|
|
47
|
+
`check_color_palette` for sets of meaningful colours; `check_dual_color_contrast` for dual
|
|
48
|
+
colours.
|
|
49
|
+
**Check:** a list of failures with their ratios.
|
|
50
|
+
3. **Fix the smallest thing.** Use the `suggestion` the contrast check returns (a lightness that
|
|
51
|
+
passes), or a darker or lighter shade of the same hue; for palettes, replace the clashing
|
|
52
|
+
colours with ones that differ in lightness as well as hue (blue and orange rather than red and
|
|
53
|
+
green). Apply with the editor's own tools (`vector.setStyle`, `update_chart_series`).
|
|
54
|
+
**Check:** measure the pair again; it passes.
|
|
55
|
+
4. **Meaning without colour.** Where a palette carries meaning, make sure a label, icon or shape
|
|
56
|
+
carries it too.
|
|
57
|
+
5. **Report** pairs, ratios before and after, and anything left that needs a decision (a brand
|
|
58
|
+
colour that cannot pass with any text colour).
|
|
59
|
+
|
|
60
|
+
## Decision table
|
|
61
|
+
|
|
62
|
+
| Element | Requirement | Tool |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| Body text, labels | 4.5:1 | `check_color_contrast` |
|
|
65
|
+
| Large or bold headings | 3:1 | `check_color_contrast` with `large: true` |
|
|
66
|
+
| Icons, borders, focus rings, chart lines | 3:1 | `check_color_contrast` |
|
|
67
|
+
| Status or series colours | Distinct under CVD | `check_color_palette` |
|
|
68
|
+
| Light and dark themes | Both pass | `check_dual_color_contrast` |
|
|
69
|
+
| Decorative graphics, disabled controls, logos | No requirement | Note them as exempt |
|
|
70
|
+
|
|
71
|
+
## Recipes
|
|
72
|
+
|
|
73
|
+
**Fix a button label.** `check_color_contrast` `{ foreground: label, background: button }` →
|
|
74
|
+
use its suggested lightness or a dark shade of the button's hue → apply → check again.
|
|
75
|
+
|
|
76
|
+
**Colour-blind-safe status colours.** `check_color_palette` with the three colours → replace with
|
|
77
|
+
a set that varies in lightness (`#0072b2`, `#e69f00`, `#000000`) → check again; keep the labels.
|
|
78
|
+
|
|
79
|
+
**A faint icon.** `check_color_contrast` icon stroke against the card; darken the stroke until it
|
|
80
|
+
reaches 3:1.
|
|
81
|
+
|
|
82
|
+
## Pitfalls
|
|
83
|
+
|
|
84
|
+
- **Eyeballing contrast.** Screens and eyes vary; measure every pair.
|
|
85
|
+
- **Changing the brand colour** to fix text; change the text first.
|
|
86
|
+
- **Large-text allowance on small text.** 3:1 applies only to large or bold-large text.
|
|
87
|
+
- **Translucent colours** are measured composited over their real backdrop; pass the opaque
|
|
88
|
+
backdrop.
|
|
89
|
+
- **Red and green only** for meaning fails the most common colour-vision deficiency.
|
|
90
|
+
- **Fixing one mode** and breaking the other in a dual theme.
|
|
91
|
+
|
|
92
|
+
## Tools used
|
|
93
|
+
|
|
94
|
+
- `check_color_contrast`: text and graphic contrast, with a suggested passing lightness
|
|
95
|
+
- `check_color_palette`: distinctness under colour-vision deficiencies
|
|
96
|
+
- `check_dual_color_contrast`, `derive_dual_color`: light and dark modes
|
|
97
|
+
- `inspect_color`: parse and convert a colour
|
|
98
|
+
- `blend_colors`: shades and tints of a hue
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "Our 'Buy now' button fails accessibility review: the label is hard to read on the button. Fix the label colour so it meets WCAG AA for normal text, keeping the button's brand blue.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "vector",
|
|
5
|
+
"width": 200,
|
|
6
|
+
"height": 80,
|
|
7
|
+
"colorTools": true,
|
|
8
|
+
"setup": [
|
|
9
|
+
{
|
|
10
|
+
"id": "vector.addShape",
|
|
11
|
+
"params": {
|
|
12
|
+
"kind": "rect",
|
|
13
|
+
"x": 20,
|
|
14
|
+
"y": 20,
|
|
15
|
+
"width": 160,
|
|
16
|
+
"height": 40,
|
|
17
|
+
"name": "Button",
|
|
18
|
+
"fill": "#4da3ff",
|
|
19
|
+
"stroke": null
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "vector.addShape",
|
|
24
|
+
"params": {
|
|
25
|
+
"kind": "rect",
|
|
26
|
+
"x": 60,
|
|
27
|
+
"y": 32,
|
|
28
|
+
"width": 80,
|
|
29
|
+
"height": 16,
|
|
30
|
+
"name": "Label",
|
|
31
|
+
"fill": "#ffffff",
|
|
32
|
+
"stroke": null
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
"checks": [
|
|
38
|
+
{
|
|
39
|
+
"why": "label on button at least 4.5:1",
|
|
40
|
+
"tool": "run_command",
|
|
41
|
+
"args": {
|
|
42
|
+
"id": "vector.list"
|
|
43
|
+
},
|
|
44
|
+
"expect": {
|
|
45
|
+
"result": {
|
|
46
|
+
"nodes": {
|
|
47
|
+
"$expr": "(() => { const L = (h) => { const c = [1, 3, 5].map((i) => parseInt(h.replace('#', '').padEnd(6, '0').slice(i - 1, i + 1), 16) / 255).map((x) => (x <= 0.04045 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4)); return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]; }; const cr = (a, b) => { const [x, y] = [L(a), L(b)].sort((p, q) => q - p); return (x + 0.05) / (y + 0.05); }; return cr(v.find((n) => n.name === 'Label').fill, v.find((n) => n.name === 'Button').fill) >= 4.5; })()"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"why": "the button keeps its blue",
|
|
54
|
+
"tool": "run_command",
|
|
55
|
+
"args": {
|
|
56
|
+
"id": "vector.list"
|
|
57
|
+
},
|
|
58
|
+
"expect": {
|
|
59
|
+
"result": {
|
|
60
|
+
"nodes": {
|
|
61
|
+
"$some": {
|
|
62
|
+
"name": "Button",
|
|
63
|
+
"fill": "#4da3ff"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"solution": [
|
|
71
|
+
{
|
|
72
|
+
"tool": "check_color_contrast",
|
|
73
|
+
"args": {
|
|
74
|
+
"foreground": "#ffffff",
|
|
75
|
+
"background": "#4da3ff"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"tool": "run_command",
|
|
80
|
+
"args": {
|
|
81
|
+
"id": "vector.setStyle",
|
|
82
|
+
"params": {
|
|
83
|
+
"ids": [
|
|
84
|
+
{
|
|
85
|
+
"$read": "run_command",
|
|
86
|
+
"args": {
|
|
87
|
+
"id": "vector.list"
|
|
88
|
+
},
|
|
89
|
+
"path": "result.nodes.1.id"
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"fill": "#0b1f33"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "These three status dots (OK, warning, error) must be told apart by colour-blind users too. Fix their colours.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "vector",
|
|
5
|
+
"width": 120,
|
|
6
|
+
"height": 40,
|
|
7
|
+
"colorTools": true,
|
|
8
|
+
"setup": [
|
|
9
|
+
{
|
|
10
|
+
"id": "vector.addShape",
|
|
11
|
+
"params": {
|
|
12
|
+
"kind": "ellipse",
|
|
13
|
+
"x": 10,
|
|
14
|
+
"y": 10,
|
|
15
|
+
"width": 20,
|
|
16
|
+
"height": 20,
|
|
17
|
+
"name": "OK",
|
|
18
|
+
"fill": "#2ca02c",
|
|
19
|
+
"stroke": null
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "vector.addShape",
|
|
24
|
+
"params": {
|
|
25
|
+
"kind": "ellipse",
|
|
26
|
+
"x": 50,
|
|
27
|
+
"y": 10,
|
|
28
|
+
"width": 20,
|
|
29
|
+
"height": 20,
|
|
30
|
+
"name": "Warning",
|
|
31
|
+
"fill": "#bcbd22",
|
|
32
|
+
"stroke": null
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "vector.addShape",
|
|
37
|
+
"params": {
|
|
38
|
+
"kind": "ellipse",
|
|
39
|
+
"x": 90,
|
|
40
|
+
"y": 10,
|
|
41
|
+
"width": 20,
|
|
42
|
+
"height": 20,
|
|
43
|
+
"name": "Error",
|
|
44
|
+
"fill": "#d62728",
|
|
45
|
+
"stroke": null
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"checks": [
|
|
51
|
+
{
|
|
52
|
+
"why": "the three colours pass the colour-vision check",
|
|
53
|
+
"tool": "check_color_palette",
|
|
54
|
+
"args": {
|
|
55
|
+
"colors": {
|
|
56
|
+
"$read": "run_command",
|
|
57
|
+
"args": {
|
|
58
|
+
"id": "vector.list"
|
|
59
|
+
},
|
|
60
|
+
"path": "result.nodes.*.fill"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"expect": {
|
|
64
|
+
"ok": true
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"why": "still three dots",
|
|
69
|
+
"tool": "run_command",
|
|
70
|
+
"args": {
|
|
71
|
+
"id": "vector.list"
|
|
72
|
+
},
|
|
73
|
+
"expect": {
|
|
74
|
+
"result": {
|
|
75
|
+
"nodes": {
|
|
76
|
+
"$length": 3
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"solution": [
|
|
83
|
+
{
|
|
84
|
+
"tool": "check_color_palette",
|
|
85
|
+
"args": {
|
|
86
|
+
"colors": [
|
|
87
|
+
"#2ca02c",
|
|
88
|
+
"#bcbd22",
|
|
89
|
+
"#d62728"
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"tool": "run_command",
|
|
95
|
+
"args": {
|
|
96
|
+
"id": "vector.setStyle",
|
|
97
|
+
"params": {
|
|
98
|
+
"ids": [
|
|
99
|
+
{
|
|
100
|
+
"$read": "run_command",
|
|
101
|
+
"args": {
|
|
102
|
+
"id": "vector.list"
|
|
103
|
+
},
|
|
104
|
+
"path": "result.nodes.0.id"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"fill": "#0072b2"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"tool": "run_command",
|
|
113
|
+
"args": {
|
|
114
|
+
"id": "vector.setStyle",
|
|
115
|
+
"params": {
|
|
116
|
+
"ids": [
|
|
117
|
+
{
|
|
118
|
+
"$read": "run_command",
|
|
119
|
+
"args": {
|
|
120
|
+
"id": "vector.list"
|
|
121
|
+
},
|
|
122
|
+
"path": "result.nodes.1.id"
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
"fill": "#e69f00"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"tool": "run_command",
|
|
131
|
+
"args": {
|
|
132
|
+
"id": "vector.setStyle",
|
|
133
|
+
"params": {
|
|
134
|
+
"ids": [
|
|
135
|
+
{
|
|
136
|
+
"$read": "run_command",
|
|
137
|
+
"args": {
|
|
138
|
+
"id": "vector.list"
|
|
139
|
+
},
|
|
140
|
+
"path": "result.nodes.2.id"
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"fill": "#000000"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"tool": "check_color_palette",
|
|
149
|
+
"args": {
|
|
150
|
+
"colors": {
|
|
151
|
+
"$read": "run_command",
|
|
152
|
+
"args": {
|
|
153
|
+
"id": "vector.list"
|
|
154
|
+
},
|
|
155
|
+
"path": "result.nodes.*.fill"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"prompt": "The outline icon on this card is too faint. Make sure it meets the WCAG contrast for non-text graphics (3:1) against the card.",
|
|
3
|
+
"fixture": {
|
|
4
|
+
"editor": "vector",
|
|
5
|
+
"width": 120,
|
|
6
|
+
"height": 120,
|
|
7
|
+
"colorTools": true,
|
|
8
|
+
"setup": [
|
|
9
|
+
{
|
|
10
|
+
"id": "vector.addShape",
|
|
11
|
+
"params": {
|
|
12
|
+
"kind": "rect",
|
|
13
|
+
"x": 0,
|
|
14
|
+
"y": 0,
|
|
15
|
+
"width": 120,
|
|
16
|
+
"height": 120,
|
|
17
|
+
"name": "Card",
|
|
18
|
+
"fill": "#ffffff",
|
|
19
|
+
"stroke": null
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "vector.addShape",
|
|
24
|
+
"params": {
|
|
25
|
+
"kind": "ellipse",
|
|
26
|
+
"x": 40,
|
|
27
|
+
"y": 40,
|
|
28
|
+
"width": 40,
|
|
29
|
+
"height": 40,
|
|
30
|
+
"name": "Icon",
|
|
31
|
+
"fill": null,
|
|
32
|
+
"stroke": "#c8c8c8",
|
|
33
|
+
"strokeWidth": 2
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"checks": [
|
|
39
|
+
{
|
|
40
|
+
"why": "the icon stroke against the card is at least 3:1",
|
|
41
|
+
"tool": "check_color_contrast",
|
|
42
|
+
"args": {
|
|
43
|
+
"foreground": {
|
|
44
|
+
"$read": "run_command",
|
|
45
|
+
"args": {
|
|
46
|
+
"id": "vector.list"
|
|
47
|
+
},
|
|
48
|
+
"path": "result.nodes.1.stroke"
|
|
49
|
+
},
|
|
50
|
+
"background": {
|
|
51
|
+
"$read": "run_command",
|
|
52
|
+
"args": {
|
|
53
|
+
"id": "vector.list"
|
|
54
|
+
},
|
|
55
|
+
"path": "result.nodes.0.fill"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"expect": {
|
|
59
|
+
"ratio": {
|
|
60
|
+
"$min": 3
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"why": "the card is unchanged",
|
|
66
|
+
"tool": "run_command",
|
|
67
|
+
"args": {
|
|
68
|
+
"id": "vector.list"
|
|
69
|
+
},
|
|
70
|
+
"expect": {
|
|
71
|
+
"result": {
|
|
72
|
+
"nodes": {
|
|
73
|
+
"$some": {
|
|
74
|
+
"name": "Card",
|
|
75
|
+
"fill": "#ffffff"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"solution": [
|
|
83
|
+
{
|
|
84
|
+
"tool": "check_color_contrast",
|
|
85
|
+
"args": {
|
|
86
|
+
"foreground": "#c8c8c8",
|
|
87
|
+
"background": "#ffffff"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"tool": "run_command",
|
|
92
|
+
"args": {
|
|
93
|
+
"id": "vector.setStyle",
|
|
94
|
+
"params": {
|
|
95
|
+
"ids": [
|
|
96
|
+
{
|
|
97
|
+
"$read": "run_command",
|
|
98
|
+
"args": {
|
|
99
|
+
"id": "vector.list"
|
|
100
|
+
},
|
|
101
|
+
"path": "result.nodes.1.id"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"stroke": "#767676"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|