taste-lint 0.0.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/LICENSE.md +9 -0
- package/README.md +141 -0
- package/data/config.schema.json +123 -0
- package/data/corpus/blode-co-review.jsonl +80 -0
- package/data/corpus/copywriting.jsonl +139 -0
- package/data/corpus/typography.jsonl +53 -0
- package/data/rule-drafts/README.md +9 -0
- package/data/rule-drafts/interaction/interaction-layout-shift.yaml +54 -0
- package/data/rule-drafts/typography/typography-long-content-safety.yaml +60 -0
- package/data/rules/authoring/authoring-approval-every-step.yaml +44 -0
- package/data/rules/authoring/authoring-fixed-agent-quota.yaml +44 -0
- package/data/rules/authoring/authoring-generic-coding-advice.yaml +44 -0
- package/data/rules/authoring/authoring-generic-verification.yaml +45 -0
- package/data/rules/authoring/authoring-plan-vague-acceptance.yaml +43 -0
- package/data/rules/copywriting/copywriting-announced-honesty.yaml +43 -0
- package/data/rules/copywriting/copywriting-anthropomorphism.yaml +29 -0
- package/data/rules/copywriting/copywriting-artificial-balance.yaml +35 -0
- package/data/rules/copywriting/copywriting-bare-confirm-label.yaml +23 -0
- package/data/rules/copywriting/copywriting-boilerplate-offer.yaml +38 -0
- package/data/rules/copywriting/copywriting-canned-phrasing.yaml +53 -0
- package/data/rules/copywriting/copywriting-changed-supplied-facts.yaml +31 -0
- package/data/rules/copywriting/copywriting-claim-without-evidence.yaml +59 -0
- package/data/rules/copywriting/copywriting-click-here-links.yaml +22 -0
- package/data/rules/copywriting/copywriting-conditions-first.yaml +50 -0
- package/data/rules/copywriting/copywriting-confirmshaming.yaml +43 -0
- package/data/rules/copywriting/copywriting-cta-names-outcome.yaml +54 -0
- package/data/rules/copywriting/copywriting-dead-weight-hedges.yaml +58 -0
- package/data/rules/copywriting/copywriting-drafting-instruction-echo.yaml +31 -0
- package/data/rules/copywriting/copywriting-emoji-in-ui.yaml +20 -0
- package/data/rules/copywriting/copywriting-empty-state-no-action.yaml +51 -0
- package/data/rules/copywriting/copywriting-error-descriptions.yaml +53 -0
- package/data/rules/copywriting/copywriting-excessive-hedging.yaml +48 -0
- package/data/rules/copywriting/copywriting-fabricated-specificity.yaml +35 -0
- package/data/rules/copywriting/copywriting-filler-words.yaml +55 -0
- package/data/rules/copywriting/copywriting-flat-description.yaml +37 -0
- package/data/rules/copywriting/copywriting-friction-cta.yaml +53 -0
- package/data/rules/copywriting/copywriting-generic-audience.yaml +55 -0
- package/data/rules/copywriting/copywriting-generic-framing.yaml +35 -0
- package/data/rules/copywriting/copywriting-generic-language.yaml +35 -0
- package/data/rules/copywriting/copywriting-generic-validation.yaml +46 -0
- package/data/rules/copywriting/copywriting-idea-repetition.yaml +34 -0
- package/data/rules/copywriting/copywriting-latinisms.yaml +25 -0
- package/data/rules/copywriting/copywriting-leaked-error-message.yaml +23 -0
- package/data/rules/copywriting/copywriting-live-region-feedback.yaml +24 -0
- package/data/rules/copywriting/copywriting-machine-prose.yaml +73 -0
- package/data/rules/copywriting/copywriting-mechanism-over-outcome.yaml +33 -0
- package/data/rules/copywriting/copywriting-meta-commentary.yaml +48 -0
- package/data/rules/copywriting/copywriting-missing-reasoning-link.yaml +33 -0
- package/data/rules/copywriting/copywriting-nominalisations.yaml +45 -0
- package/data/rules/copywriting/copywriting-over-explanation.yaml +34 -0
- package/data/rules/copywriting/copywriting-passive-voice.yaml +53 -0
- package/data/rules/copywriting/copywriting-permission-benefit.yaml +43 -0
- package/data/rules/copywriting/copywriting-profile-register-mismatch.yaml +31 -0
- package/data/rules/copywriting/copywriting-promotional-docs-voice.yaml +58 -0
- package/data/rules/copywriting/copywriting-prompt-restatement.yaml +35 -0
- package/data/rules/copywriting/copywriting-punctuation-tics.yaml +35 -0
- package/data/rules/copywriting/copywriting-reader-first.yaml +59 -0
- package/data/rules/copywriting/copywriting-register-shift.yaml +58 -0
- package/data/rules/copywriting/copywriting-repetitive-transitions.yaml +48 -0
- package/data/rules/copywriting/copywriting-requirements-language.yaml +50 -0
- package/data/rules/copywriting/copywriting-searchable-headings.yaml +52 -0
- package/data/rules/copywriting/copywriting-semantic-links.yaml +23 -0
- package/data/rules/copywriting/copywriting-structural-symmetry.yaml +35 -0
- package/data/rules/copywriting/copywriting-success-state-specific.yaml +43 -0
- package/data/rules/copywriting/copywriting-temporal-words.yaml +55 -0
- package/data/rules/copywriting/copywriting-toast-successfully.yaml +22 -0
- package/data/rules/copywriting/copywriting-unexplained-action.yaml +33 -0
- package/data/rules/copywriting/copywriting-unnatural-polish.yaml +48 -0
- package/data/rules/copywriting/copywriting-unraised-objection.yaml +43 -0
- package/data/rules/copywriting/copywriting-unverifiable-proof.yaml +23 -0
- package/data/rules/copywriting/copywriting-vague-error.yaml +58 -0
- package/data/rules/copywriting/copywriting-vague-personal-request.yaml +43 -0
- package/data/rules/copywriting/copywriting-visual-direction-instruction.yaml +43 -0
- package/data/rules/craft/craft-affordance-mismatch.yaml +23 -0
- package/data/rules/craft/craft-decoration-no-role.yaml +27 -0
- package/data/rules/craft/craft-faux-product-chrome.yaml +22 -0
- package/data/rules/craft/craft-hover-only-affordance.yaml +23 -0
- package/data/rules/craft/craft-i18n-rtl-untested.yaml +23 -0
- package/data/rules/craft/craft-i18n-untested.yaml +28 -0
- package/data/rules/craft/craft-image-dimensions-and-priority.yaml +23 -0
- package/data/rules/craft/craft-inline-styles.yaml +24 -0
- package/data/rules/craft/craft-lazy-load-offscreen.yaml +28 -0
- package/data/rules/craft/craft-near-duplicate-scale.yaml +29 -0
- package/data/rules/craft/craft-token-drift.yaml +22 -0
- package/data/rules/craft/craft-viewport-scaling.yaml +25 -0
- package/data/rules/craft/craft-virtualize-large-lists.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-color-only-meaning.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-data-table-semantics.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-disabled-control-tooltip.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-document-language.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-icon-controls-labeled.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-image-alt-text.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-media-captions.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-semantic-html-first.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-skip-link-heading-order.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-tooltip-no-interactive.yaml +23 -0
- package/data/rules/interaction/interaction-broken-focus-trap.yaml +25 -0
- package/data/rules/interaction/interaction-dont-block-paste-ime.yaml +23 -0
- package/data/rules/interaction/interaction-error-association.yaml +24 -0
- package/data/rules/interaction/interaction-focus-visible.yaml +25 -0
- package/data/rules/interaction/interaction-inline-errors-first-focus.yaml +24 -0
- package/data/rules/interaction/interaction-input-affix-hit-target.yaml +23 -0
- package/data/rules/interaction/interaction-keyboard-operable.yaml +23 -0
- package/data/rules/interaction/interaction-labels-and-autocomplete.yaml +23 -0
- package/data/rules/interaction/interaction-lost-data-on-error.yaml +23 -0
- package/data/rules/interaction/interaction-mobile-input-font-size.yaml +24 -0
- package/data/rules/interaction/interaction-no-disable-while-submitting.yaml +23 -0
- package/data/rules/interaction/interaction-no-empty-state.yaml +26 -0
- package/data/rules/interaction/interaction-no-error-boundary.yaml +27 -0
- package/data/rules/interaction/interaction-no-error-state.yaml +26 -0
- package/data/rules/interaction/interaction-no-suspense-boundary.yaml +23 -0
- package/data/rules/interaction/interaction-not-restored.yaml +25 -0
- package/data/rules/interaction/interaction-on-dynamic-content.yaml +25 -0
- package/data/rules/interaction/interaction-optimistic-without-rollback.yaml +23 -0
- package/data/rules/interaction/interaction-out-of-order-responses.yaml +27 -0
- package/data/rules/interaction/interaction-target-size.yaml +26 -0
- package/data/rules/interaction/interaction-use-form-status-misuse.yaml +23 -0
- package/data/rules/product/product-nested-modals.yaml +26 -0
- package/data/rules/product/product-select-for-few-options.yaml +24 -0
- package/data/rules/schema/rule.schema.json +262 -0
- package/data/rules/tuning.json +1 -0
- package/data/rules/typography/typography-dashes.yaml +28 -0
- package/data/rules/typography/typography-ellipsis.yaml +27 -0
- package/data/rules/typography/typography-hover-weight-shift.yaml +24 -0
- package/data/rules/typography/typography-midpoint-separators.yaml +21 -0
- package/data/rules/typography/typography-multiplication-sign.yaml +27 -0
- package/data/rules/typography/typography-nbsp-value-unit.yaml +27 -0
- package/data/rules/typography/typography-readable-scale.yaml +23 -0
- package/data/rules/typography/typography-straight-quotes.yaml +37 -0
- package/data/rules/typography/typography-title-case-heading.yaml +49 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +6317 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +736 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5330 -0
- package/dist/index.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/microcopy-vague-error.md.
|
|
2
|
+
id: copywriting-vague-error
|
|
3
|
+
title: Error message with no cause and no next step
|
|
4
|
+
categoryId: actionable-microcopy
|
|
5
|
+
source:
|
|
6
|
+
line: 10
|
|
7
|
+
path: skills/ui-design/rules/microcopy-vague-error.md
|
|
8
|
+
repo: mblode/agent-skills
|
|
9
|
+
ruleId: microcopy-vague-error
|
|
10
|
+
unit:
|
|
11
|
+
- jsx-text
|
|
12
|
+
- attr-string
|
|
13
|
+
mechanical:
|
|
14
|
+
phrases:
|
|
15
|
+
- error occurred
|
|
16
|
+
- an error has occurred
|
|
17
|
+
- something went wrong
|
|
18
|
+
- please try again
|
|
19
|
+
- try again later
|
|
20
|
+
- oops
|
|
21
|
+
- invalid
|
|
22
|
+
- unexpected error
|
|
23
|
+
- an error occurred
|
|
24
|
+
- failed
|
|
25
|
+
question:
|
|
26
|
+
context:
|
|
27
|
+
- element
|
|
28
|
+
- docType
|
|
29
|
+
instructions: The TEXT is a message shown to a user after something failed. Return true when it tells the user neither what went wrong nor what to do next (for example "Something went wrong", "Invalid", "An error occurred. Please try again."). Return false when it names the cause or the recovery (what failed, what to check, where to go), when it is a sign-in credential message that is deliberately vague for security ("Wrong email or password"), or when the TEXT is not an error message at all.
|
|
30
|
+
criteria:
|
|
31
|
+
"true":
|
|
32
|
+
what: No cause and no recovery.
|
|
33
|
+
examples:
|
|
34
|
+
- Something went wrong
|
|
35
|
+
- Invalid
|
|
36
|
+
- Oops! An error occurred. Please try again.
|
|
37
|
+
"false":
|
|
38
|
+
what: Cause or recovery named, or a deliberate security message.
|
|
39
|
+
examples:
|
|
40
|
+
- Email already in use. Sign in instead.
|
|
41
|
+
- Couldn't reach the payment provider. Your card was not charged. Try again.
|
|
42
|
+
- Wrong email or password.
|
|
43
|
+
severity: major
|
|
44
|
+
fix:
|
|
45
|
+
hint: Write what happened, why when you know it, and the next step. Never blame the person and never clear the form.
|
|
46
|
+
preconditions:
|
|
47
|
+
notInCode: true
|
|
48
|
+
docType:
|
|
49
|
+
- ui
|
|
50
|
+
- unknown
|
|
51
|
+
- lesson
|
|
52
|
+
status: review-only
|
|
53
|
+
handWritten:
|
|
54
|
+
- mechanical
|
|
55
|
+
- question
|
|
56
|
+
- fix
|
|
57
|
+
- severityOverrides
|
|
58
|
+
- preconditions
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
id: copywriting-vague-personal-request
|
|
2
|
+
title: Personal request has an unspecified time expectation
|
|
3
|
+
categoryId: actionable-microcopy
|
|
4
|
+
source:
|
|
5
|
+
repo: mblode/ghostwriter
|
|
6
|
+
path: skills/ghostwriter/references/strategy.md
|
|
7
|
+
line: 1
|
|
8
|
+
unit:
|
|
9
|
+
- paragraph
|
|
10
|
+
- jsx-text
|
|
11
|
+
- attr-string
|
|
12
|
+
mechanical:
|
|
13
|
+
regex: \b(?:ASAP|soon|when you get a chance)\b
|
|
14
|
+
flags: giu
|
|
15
|
+
question:
|
|
16
|
+
context:
|
|
17
|
+
- docType
|
|
18
|
+
- headingAbove
|
|
19
|
+
- role
|
|
20
|
+
- element
|
|
21
|
+
instructions: Return true when a request uses a vague urgency phrase that makes its timing unclear. Return false for a deliberately open-ended invitation, quoted wording, or when the supplied text already names a concrete deadline. Never invent a deadline.
|
|
22
|
+
criteria:
|
|
23
|
+
"true":
|
|
24
|
+
what: The stated failure is supported by the supplied text.
|
|
25
|
+
examples:
|
|
26
|
+
- Please send the launch review ASAP.
|
|
27
|
+
"false":
|
|
28
|
+
what: The text is specific, justified, quoted, or outside this rule.
|
|
29
|
+
examples:
|
|
30
|
+
- Send the launch review by Thursday at noon.
|
|
31
|
+
severity: minor
|
|
32
|
+
fix:
|
|
33
|
+
hint: Use the actual deadline if known; otherwise clarify urgency without inventing a time.
|
|
34
|
+
preconditions:
|
|
35
|
+
notInCode: true
|
|
36
|
+
docType:
|
|
37
|
+
- personal
|
|
38
|
+
status: review-only
|
|
39
|
+
handWritten:
|
|
40
|
+
- mechanical
|
|
41
|
+
- question
|
|
42
|
+
- preconditions
|
|
43
|
+
- fix
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
id: copywriting-visual-direction-instruction
|
|
2
|
+
title: UI instruction depends on visual position
|
|
3
|
+
categoryId: actionable-microcopy
|
|
4
|
+
source:
|
|
5
|
+
repo: installed/copywriting
|
|
6
|
+
path: skills/copywriting/references/ui-states.md
|
|
7
|
+
line: 1
|
|
8
|
+
unit:
|
|
9
|
+
- paragraph
|
|
10
|
+
- jsx-text
|
|
11
|
+
- attr-string
|
|
12
|
+
mechanical:
|
|
13
|
+
regex: \b(?:above|below|left|right)\b
|
|
14
|
+
flags: giu
|
|
15
|
+
question:
|
|
16
|
+
context:
|
|
17
|
+
- docType
|
|
18
|
+
- headingAbove
|
|
19
|
+
- role
|
|
20
|
+
- element
|
|
21
|
+
instructions: Return true only when an instruction identifies a control solely by visual position, without naming the control or a semantic destination. Return false for named controls, keyboard arrow instructions, descriptions of physical directions, or text where position is the information requested.
|
|
22
|
+
criteria:
|
|
23
|
+
"true":
|
|
24
|
+
what: The stated failure is supported by the supplied text.
|
|
25
|
+
examples:
|
|
26
|
+
- Click the button on the right.
|
|
27
|
+
"false":
|
|
28
|
+
what: The text is specific, justified, quoted, or outside this rule.
|
|
29
|
+
examples:
|
|
30
|
+
- Select Save changes.
|
|
31
|
+
severity: minor
|
|
32
|
+
fix:
|
|
33
|
+
hint: Name the control or destination so the instruction works without seeing the layout.
|
|
34
|
+
preconditions:
|
|
35
|
+
notInCode: true
|
|
36
|
+
docType:
|
|
37
|
+
- ui
|
|
38
|
+
status: review-only
|
|
39
|
+
handWritten:
|
|
40
|
+
- mechanical
|
|
41
|
+
- question
|
|
42
|
+
- preconditions
|
|
43
|
+
- fix
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/slop-affordance-mismatch.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: craft-affordance-mismatch
|
|
4
|
+
title: Affordance styling with nothing behind it
|
|
5
|
+
categoryId: generic-decoration
|
|
6
|
+
source:
|
|
7
|
+
line: 10
|
|
8
|
+
path: skills/ui-design/rules/slop-affordance-mismatch.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: slop-affordance-mismatch
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
flags: gu
|
|
19
|
+
regex: cursor-pointer|hover:(bg|shadow|scale|border|ring|translate)-
|
|
20
|
+
severity: minor
|
|
21
|
+
fix:
|
|
22
|
+
hint: A card lifts on hover, the cursor turns into a hand, the border brightens, and clicking does nothing. The user has already committed to the click by the time they learn it was a decoration; they click again, assume the page is broken or slow, and then trust the next hover state less. This is worse t
|
|
23
|
+
status: review-only
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Hand-ported from mblode/agent-skills skills/ui-design/rules/slop-decoration-no-role.md. The detection there is a
|
|
2
|
+
# shell loop or pipeline; regex plus absent is the same check over one file.
|
|
3
|
+
id: craft-decoration-no-role
|
|
4
|
+
title: Stacked decorative layers with no role
|
|
5
|
+
categoryId: generic-decoration
|
|
6
|
+
source:
|
|
7
|
+
repo: mblode/agent-skills
|
|
8
|
+
path: skills/ui-design/rules/slop-decoration-no-role.md
|
|
9
|
+
line: 10
|
|
10
|
+
ruleId: slop-decoration-no-role
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit: [source]
|
|
16
|
+
mechanical:
|
|
17
|
+
flags: gus
|
|
18
|
+
regex:
|
|
19
|
+
"<(?:div|span)\\b(?=[^>]*?(?:\\babsolute\\b|\\bfixed\\b))(?=[^>]*?(?:pointer-events-none|ari\
|
|
20
|
+
a-hidden))(?=[^>]*?(?:gradient|bg-linear|bg-radial|\\bblur|backdrop-blur|mix-blend|opacity-))(?\
|
|
21
|
+
![^>]*?(?:size-\\[max\\(100%|pointer-fine:hidden|bg-clip-text|\\bmask-))[^>]*?/>"
|
|
22
|
+
severity: minor
|
|
23
|
+
fix:
|
|
24
|
+
hint: >-
|
|
25
|
+
A blurred blob, a grid overlay, a noise layer and a radial glow behind the heading: absolutely positioned elements that contain nothing and mean nothing. Cut them until each remaining layer has a job a reader could name.
|
|
26
|
+
status: review-only
|
|
27
|
+
handWritten: [mechanical, fix, status]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/slop-faux-product-chrome.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: craft-faux-product-chrome
|
|
4
|
+
title: Faux product chrome wrapping nothing
|
|
5
|
+
categoryId: generic-decoration
|
|
6
|
+
source:
|
|
7
|
+
line: 10
|
|
8
|
+
path: skills/ui-design/rules/slop-faux-product-chrome.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: slop-faux-product-chrome
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
unit:
|
|
15
|
+
- source
|
|
16
|
+
mechanical:
|
|
17
|
+
flags: gu
|
|
18
|
+
regex: rounded-full[^"`]*\bbg-(red|rose|yellow|amber|green|emerald)-[45]00
|
|
19
|
+
severity: minor
|
|
20
|
+
fix:
|
|
21
|
+
hint: "Three coloured dots in a row, a rounded bar with a URL typed into it, a laptop outline around an empty gradient panel: this is a drawing of a product where the product should be. A visitor reads it as a screenshot, leans in to see what the app actually looks like, and finds there is nothing to see. "
|
|
22
|
+
status: review-only
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/mobile-hover-only-affordance.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: craft-hover-only-affordance
|
|
4
|
+
title: Critical actions hidden behind hover-only affordances
|
|
5
|
+
categoryId: resilience
|
|
6
|
+
source:
|
|
7
|
+
line: 10
|
|
8
|
+
path: skills/ui-design/rules/mobile-hover-only-affordance.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: mobile-hover-only-affordance
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.ts"
|
|
14
|
+
- "**/*.tsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
flags: gu
|
|
19
|
+
regex: (group-hover|peer-hover|\bhover:):(opacity-100|visible|flex|block)
|
|
20
|
+
severity: minor
|
|
21
|
+
fix:
|
|
22
|
+
hint: 'Reveal-on-hover quietly disappears on touch: a row exposes "Edit / Delete / Share" only when the cursor enters, but a phone has no cursor. Touch users never discover the actions, or only via a frustrating long-press. The same pattern hides tooltips, secondary CTAs, and meaningful state ("3 unread") '
|
|
23
|
+
status: review-only
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/dark-i18n-rtl-untested.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: craft-i18n-rtl-untested
|
|
4
|
+
title: Layout uses physical (left/right) instead of logical (start/end) properties
|
|
5
|
+
categoryId: resilience
|
|
6
|
+
source:
|
|
7
|
+
line: 10
|
|
8
|
+
path: skills/ui-design/rules/dark-i18n-rtl-untested.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: dark-i18n-rtl-untested
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.ts"
|
|
14
|
+
- "**/*.tsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
flags: gu
|
|
19
|
+
regex: className="[^"]*\b(ml-|mr-|pl-|pr-|left-|right-|text-(left|right)|float-(left|right)|border-(l|r))\b
|
|
20
|
+
severity: minor
|
|
21
|
+
fix:
|
|
22
|
+
hint: 'Arabic, Hebrew, Persian, and Urdu read right-to-left. A layout using physical properties (`margin-left`, `padding-right`, `text-align: left`, Tailwind `ml-2`, `pr-4`, `text-left`) does not flip when document direction is `rtl`: icons land on the wrong side, "forward" chevrons point backward, padding'
|
|
23
|
+
status: review-only
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Hand-ported from mblode/agent-skills skills/ui-design/rules/dark-i18n-untested.md. The detection there is a
|
|
2
|
+
# shell loop or pipeline; regex plus absent is the same check over one file.
|
|
3
|
+
# The source filters matching lines through `rg -v dark:`; the negative lookahead is
|
|
4
|
+
# that filter on the same line.
|
|
5
|
+
id: craft-i18n-untested
|
|
6
|
+
title: Hardcoded light-mode token with no dark variant on the line
|
|
7
|
+
categoryId: resilience
|
|
8
|
+
source:
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
path: skills/ui-design/rules/dark-i18n-untested.md
|
|
11
|
+
line: 10
|
|
12
|
+
ruleId: dark-i18n-untested
|
|
13
|
+
scope:
|
|
14
|
+
include:
|
|
15
|
+
- "**/*.ts"
|
|
16
|
+
- "**/*.tsx"
|
|
17
|
+
unit: [source]
|
|
18
|
+
mechanical:
|
|
19
|
+
flags: gum
|
|
20
|
+
regex:
|
|
21
|
+
"^(?!.*dark:).*className=\"[^\"]*\\b(?:bg-white|bg-black|text-black|text-white|bg-gray-\\d{2\
|
|
22
|
+
,3}|text-gray-\\d{2,3}|border-gray-\\d{2,3})\\b[^\"]*\".*$"
|
|
23
|
+
severity: minor
|
|
24
|
+
fix:
|
|
25
|
+
hint: >-
|
|
26
|
+
bg-white, text-black and fixed grays break in dark mode: white surfaces glow, grays lose contrast, borders vanish. Use the semantic tokens (bg-background, text-foreground, border-border) or pair each with a dark: variant.
|
|
27
|
+
status: review-only
|
|
28
|
+
handWritten: [mechanical, fix, status]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/perf-image-dimensions-and-priority.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: craft-image-dimensions-and-priority
|
|
4
|
+
title: Set Image Dimensions and Priority Intentionally
|
|
5
|
+
categoryId: resilience
|
|
6
|
+
source:
|
|
7
|
+
line: 9
|
|
8
|
+
path: skills/ui-design/rules/perf-image-dimensions-and-priority.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: perf-image-dimensions-and-priority
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
flags: gus
|
|
19
|
+
regex: <img\b(?![^>]*\bwidth=)[^>]*>
|
|
20
|
+
severity: major
|
|
21
|
+
fix:
|
|
22
|
+
hint: Declare `width`/`height` (or aspect ratio) and prioritize only above-the-fold hero images. Undeclared dimensions shift the page as images arrive, and an unprioritized hero delays the largest paint.
|
|
23
|
+
status: review-only
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Hand-authored from shadcn-ui/lint (shadcn/no-inline-styles). The rule is re-expressed over
|
|
2
|
+
# taste-lint's extracted class lists; the original runs as an ESLint or oxlint plugin.
|
|
3
|
+
id: craft-inline-styles
|
|
4
|
+
title: Inline style object or style element in a component
|
|
5
|
+
categoryId: look-constraints
|
|
6
|
+
source:
|
|
7
|
+
repo: shadcn-ui/lint
|
|
8
|
+
path: README.md
|
|
9
|
+
line: 1
|
|
10
|
+
ruleId: shadcn/no-inline-styles
|
|
11
|
+
scope:
|
|
12
|
+
include: ["**/*.tsx", "**/*.jsx"]
|
|
13
|
+
exclude:
|
|
14
|
+
- "**/components/ui/**"
|
|
15
|
+
unit: [source]
|
|
16
|
+
mechanical:
|
|
17
|
+
flags: gu
|
|
18
|
+
regex: "style=\\{\\{|<style\\b"
|
|
19
|
+
severity: minor
|
|
20
|
+
fix:
|
|
21
|
+
hint: >-
|
|
22
|
+
Move the styling into utility classes or the theme. Inline styles bypass the design tokens, dark mode and the linter alike.
|
|
23
|
+
status: review-only
|
|
24
|
+
handWritten: [mechanical, fix, status, scope]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Hand-ported from mblode/agent-skills skills/ui-design/rules/perf-lazy-load-offscreen.md. The detection there is a
|
|
2
|
+
# shell loop or pipeline; regex plus absent is the same check over one file.
|
|
3
|
+
# The source's `(?i:hero|banner|...)` inline modifier is written out as letter
|
|
4
|
+
# classes so the regex compiles on Node 22 and 24 alike.
|
|
5
|
+
id: craft-lazy-load-offscreen
|
|
6
|
+
title: Hero or above-the-fold image marked loading lazy
|
|
7
|
+
categoryId: resilience
|
|
8
|
+
source:
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
path: skills/ui-design/rules/perf-lazy-load-offscreen.md
|
|
11
|
+
line: 9
|
|
12
|
+
ruleId: perf-lazy-load-offscreen
|
|
13
|
+
scope:
|
|
14
|
+
include:
|
|
15
|
+
- "**/*.tsx"
|
|
16
|
+
- "**/*.jsx"
|
|
17
|
+
unit: [source]
|
|
18
|
+
mechanical:
|
|
19
|
+
flags: gus
|
|
20
|
+
regex:
|
|
21
|
+
"<(?:img|Image)\\b(?=[^>]*loading=\"lazy\")(?=[^>]*(?:[Hh]ero|[Bb]anner|[Cc]over|[Mm]asthead\
|
|
22
|
+
|[Pp]riority))[^>]*>"
|
|
23
|
+
severity: minor
|
|
24
|
+
fix:
|
|
25
|
+
hint: >-
|
|
26
|
+
Never lazy-load the largest above-the-fold image; it delays the largest contentful paint. Load the hero eagerly (priority) and keep loading="lazy" for images below the fold.
|
|
27
|
+
status: review-only
|
|
28
|
+
handWritten: [mechanical, fix, status]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Hand-ported from mblode/agent-skills skills/ui-design/rules/slop-near-duplicate-scale.md. The detection there is a
|
|
2
|
+
# shell loop or pipeline; regex plus absent is the same check over one file.
|
|
3
|
+
# Nudges of 2px or less are excluded in the regex, as the source's second filter does.
|
|
4
|
+
# The source asks for a theme precondition; this port has none and stays review-only.
|
|
5
|
+
id: craft-near-duplicate-scale
|
|
6
|
+
title: Arbitrary pixel value one step off the scale
|
|
7
|
+
categoryId: look-constraints
|
|
8
|
+
source:
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
path: skills/ui-design/rules/slop-near-duplicate-scale.md
|
|
11
|
+
line: 10
|
|
12
|
+
ruleId: slop-near-duplicate-scale
|
|
13
|
+
scope:
|
|
14
|
+
include:
|
|
15
|
+
- "**/*.tsx"
|
|
16
|
+
- "**/*.jsx"
|
|
17
|
+
unit: [source]
|
|
18
|
+
mechanical:
|
|
19
|
+
flags: gu
|
|
20
|
+
regex:
|
|
21
|
+
"\\b(?:text|p|px|py|pt|pb|pl|pr|m|mt|mb|ml|mr|mx|my|gap|gap-[xy]|space-[xy]|rounded(?:-[a-z]\
|
|
22
|
+
+)?|leading|w|h|size|inset|top|bottom|left|right)-\\[(?!-?(?:[01](?:\\.\\d+)?|2(?:\\.0+)?)px\\]\
|
|
23
|
+
)-?\\d+(?:\\.\\d+)?px\\](?!:)"
|
|
24
|
+
severity: minor
|
|
25
|
+
fix:
|
|
26
|
+
hint: >-
|
|
27
|
+
text-[15px] beside text-sm and text-base is a third size that reads as a mistake, not a level. Step the scale, or register the value in the theme when it recurs. Check the theme first: with no scale defined there is nothing to be a near-duplicate of.
|
|
28
|
+
status: review-only
|
|
29
|
+
handWritten: [mechanical, fix, status]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/slop-token-drift.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: craft-token-drift
|
|
4
|
+
title: Arbitrary values drifting off the theme
|
|
5
|
+
categoryId: look-constraints
|
|
6
|
+
source:
|
|
7
|
+
line: 10
|
|
8
|
+
path: skills/ui-design/rules/slop-token-drift.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: slop-token-drift
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.css"
|
|
14
|
+
unit:
|
|
15
|
+
- source
|
|
16
|
+
mechanical:
|
|
17
|
+
flags: gu
|
|
18
|
+
regex: "@theme"
|
|
19
|
+
severity: minor
|
|
20
|
+
fix:
|
|
21
|
+
hint: "A theme exists so that sizes, colours, and radii repeat across a product and the eye reads them as one system. When a file reaches for five or six one-off bracket values, the surface stops agreeing with the rest of the app: headings land at sizes no other heading uses, a card corner is 3px rounder t"
|
|
22
|
+
status: review-only
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/mobile-viewport-scaling.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: craft-viewport-scaling
|
|
4
|
+
title: Missing viewport meta, 100vh on mobile, no safe-area insets
|
|
5
|
+
categoryId: resilience
|
|
6
|
+
source:
|
|
7
|
+
line: 10
|
|
8
|
+
path: skills/ui-design/rules/mobile-viewport-scaling.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: mobile-viewport-scaling
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.md"
|
|
14
|
+
- "**/*.mdx"
|
|
15
|
+
- "**/*.tsx"
|
|
16
|
+
- "**/*.jsx"
|
|
17
|
+
unit:
|
|
18
|
+
- source
|
|
19
|
+
mechanical:
|
|
20
|
+
flags: gu
|
|
21
|
+
regex: export const viewport|<meta name="viewport"
|
|
22
|
+
severity: minor
|
|
23
|
+
fix:
|
|
24
|
+
hint: 'Three quiet bugs ship together on mobile, each a one-line fix invisible in desktop testing: a missing `<meta name="viewport">` makes iOS Safari render at 980 px and zoom out; `100vh` includes the address bar (~60 px wrong on iOS); a fixed bottom bar covers the home-indicator notch and clips content.'
|
|
25
|
+
status: review-only
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/perf-virtualize-large-lists.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: craft-virtualize-large-lists
|
|
4
|
+
title: Virtualize Long Lists
|
|
5
|
+
categoryId: resilience
|
|
6
|
+
source:
|
|
7
|
+
line: 9
|
|
8
|
+
path: skills/ui-design/rules/perf-virtualize-large-lists.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: perf-virtualize-large-lists
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
absent: react-window|@tanstack/react-virtual|react-virtuoso|virtua
|
|
19
|
+
flags: gus
|
|
20
|
+
regex: <(?:ul|ol|tbody)\b[^>]*>\s*\{[^}]*\.map\(
|
|
21
|
+
severity: minor
|
|
22
|
+
fix:
|
|
23
|
+
hint: Large lists (roughly >50 visible items) should use virtualization/windowing. Rendering the whole dataset stalls scrolling and grows memory with the list.
|
|
24
|
+
status: review-only
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/a11y-color-only-meaning.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: interaction-a11y-color-only-meaning
|
|
4
|
+
title: Avoid Color-Only Meaning
|
|
5
|
+
categoryId: focus-and-a11y
|
|
6
|
+
source:
|
|
7
|
+
line: 9
|
|
8
|
+
path: skills/ui-design/rules/a11y-color-only-meaning.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: a11y-color-only-meaning
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
flags: gu
|
|
19
|
+
regex: \?[^:]*\b(text|bg|border)-(red|green|amber|emerald|rose|yellow)-\d
|
|
20
|
+
severity: major
|
|
21
|
+
fix:
|
|
22
|
+
hint: State carried by hue alone (a red row, a green dot, a colored border) is invisible to color-blind users and on washed-out screens. Pair color with text, an icon, or shape. Contrast ratios are axe's job, not this rule's.
|
|
23
|
+
status: review-only
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/a11y-data-table-semantics.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: interaction-a11y-data-table-semantics
|
|
4
|
+
title: Mark Up Data Tables With Real Table Semantics
|
|
5
|
+
categoryId: focus-and-a11y
|
|
6
|
+
source:
|
|
7
|
+
line: 9
|
|
8
|
+
path: skills/ui-design/rules/a11y-data-table-semantics.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: a11y-data-table-semantics
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
absent: <caption\b|scope="(col|row)"
|
|
19
|
+
flags: gu
|
|
20
|
+
regex: <table\b|role="(table|grid)"
|
|
21
|
+
severity: major
|
|
22
|
+
fix:
|
|
23
|
+
hint: Tabular data needs a real `<table>` with `<caption>`, header cells, and `scope`. Divs styled as a grid carry no row/column relationships, so screen readers read cells as a flat list. (Layout-only grids use CSS, not `<table>`.)
|
|
24
|
+
status: review-only
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/a11y-disabled-control-tooltip.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: interaction-a11y-disabled-control-tooltip
|
|
4
|
+
title: Do not put tooltips on disabled controls
|
|
5
|
+
categoryId: focus-and-a11y
|
|
6
|
+
source:
|
|
7
|
+
line: 10
|
|
8
|
+
path: skills/ui-design/rules/a11y-disabled-control-tooltip.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: a11y-disabled-control-tooltip
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
flags: gus
|
|
19
|
+
regex: <[^>]*\bdisabled\b[^>]*>[\s\S]{0,400}<(Tooltip|HoverCard)
|
|
20
|
+
severity: minor
|
|
21
|
+
fix:
|
|
22
|
+
hint: "A tooltip on a `disabled` button never reaches keyboard or screen-reader users: disabled controls are omitted from the tab order, so the reason the action is blocked is invisible. Mouse users see a hover hint; everyone else hits a dead control with no explanation."
|
|
23
|
+
status: review-only
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/a11y-document-language.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: interaction-a11y-document-language
|
|
4
|
+
title: Declare Document and Inline Language
|
|
5
|
+
categoryId: focus-and-a11y
|
|
6
|
+
source:
|
|
7
|
+
line: 9
|
|
8
|
+
path: skills/ui-design/rules/a11y-document-language.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: a11y-document-language
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
- "**/*.html"
|
|
16
|
+
unit:
|
|
17
|
+
- source
|
|
18
|
+
mechanical:
|
|
19
|
+
flags: gus
|
|
20
|
+
regex: <html(?![^>]*\blang=)[^>]*>
|
|
21
|
+
severity: major
|
|
22
|
+
fix:
|
|
23
|
+
hint: Set the primary language on `<html lang>` with a valid BCP 47 tag, and mark any inline passage in another language with its own `lang`. Without it, a screen reader reads everything with one pronunciation engine.
|
|
24
|
+
status: review-only
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/a11y-icon-controls-labeled.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: interaction-a11y-icon-controls-labeled
|
|
4
|
+
title: Label Icon-Only Controls
|
|
5
|
+
categoryId: focus-and-a11y
|
|
6
|
+
source:
|
|
7
|
+
line: 9
|
|
8
|
+
path: skills/ui-design/rules/a11y-icon-controls-labeled.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: a11y-icon-controls-labeled
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
flags: gus
|
|
19
|
+
regex: <button\b(?![^>]*(aria-label|aria-labelledby|title=))[^>]*>\s*<[A-Z][\w.]*[^>]*/>\s*</button>
|
|
20
|
+
severity: minor
|
|
21
|
+
fix:
|
|
22
|
+
hint: Any control with no visible text requires an accessible name. Without one, assistive tech announces nothing usable and the control cannot be identified.
|
|
23
|
+
status: review-only
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/a11y-image-alt-text.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: interaction-a11y-image-alt-text
|
|
4
|
+
title: Give Every Image a Correct Alt Attribute
|
|
5
|
+
categoryId: focus-and-a11y
|
|
6
|
+
source:
|
|
7
|
+
line: 9
|
|
8
|
+
path: skills/ui-design/rules/a11y-image-alt-text.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: a11y-image-alt-text
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
- "**/*.html"
|
|
16
|
+
unit:
|
|
17
|
+
- source
|
|
18
|
+
mechanical:
|
|
19
|
+
flags: gus
|
|
20
|
+
regex: <img\b(?![^>]*\balt=)[^>]*>
|
|
21
|
+
severity: major
|
|
22
|
+
fix:
|
|
23
|
+
hint: 'Every `<img>` needs an `alt`: describe the purpose for informative images, use an empty `alt=""` for decorative ones so screen readers skip them. A missing `alt` makes the file name get read aloud. The `alt` is also what renders when the image itself fails to load.'
|
|
24
|
+
status: review-only
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Ported from mblode/agent-skills skills/ui-design/rules/a11y-media-captions.md by scripts/port-rules.ts.
|
|
2
|
+
# Keys listed in handWritten are preserved on re-run; everything else is regenerated.
|
|
3
|
+
id: interaction-a11y-media-captions
|
|
4
|
+
title: Caption Video and Transcribe Audio
|
|
5
|
+
categoryId: focus-and-a11y
|
|
6
|
+
source:
|
|
7
|
+
line: 9
|
|
8
|
+
path: skills/ui-design/rules/a11y-media-captions.md
|
|
9
|
+
repo: mblode/agent-skills
|
|
10
|
+
ruleId: a11y-media-captions
|
|
11
|
+
scope:
|
|
12
|
+
include:
|
|
13
|
+
- "**/*.tsx"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
unit:
|
|
16
|
+
- source
|
|
17
|
+
mechanical:
|
|
18
|
+
absent: kind="captions"
|
|
19
|
+
flags: gu
|
|
20
|
+
regex: <video\b|<audio\b
|
|
21
|
+
severity: major
|
|
22
|
+
fix:
|
|
23
|
+
hint: Deaf and hard-of-hearing users get nothing from uncaptioned media. Video needs synchronised captions via `<track kind="captions">`; audio-only needs a text transcript. Auto-generated captions alone are not sufficient for meaning-critical media.
|
|
24
|
+
status: review-only
|