diff --git a/skills/wp-patterns/SKILL.md b/skills/wp-patterns/SKILL.md new file mode 100644 index 0000000..cc87213 --- /dev/null +++ b/skills/wp-patterns/SKILL.md @@ -0,0 +1,215 @@ +--- +name: wp-patterns +description: "Generate technically correct, design-distinctive WordPress block patterns. Use when creating block patterns, starter page patterns, template patterns, template part patterns, or improving pattern design quality. Covers pattern registration (PHP headers, auto/manual), block markup syntax, theme.json design tokens, categories, template types, accessibility, and i18n/escaping." +compatibility: "WordPress 6.9 with PHP 7.2.24 or later. Requires 6.0+ for auto-registration, 6.7+ for full preset support. Patterns use block markup (HTML comments with JSON), PHP file headers, and theme.json presets." +--- + +# WordPress Block Patterns + +## Purpose + +Generate production-grade WordPress block patterns that are: +1. **Technically correct** — valid block markup, proper PHP escaping and i18n, correct file headers +2. **Design-distinctive** — avoid generic AI aesthetics through intentional layout, color, and typography choices +3. **Theme-compatible** — use preset slugs that adapt across themes and style variations +4. **Accessible** — sequential heading levels, descriptive alt text, sufficient contrast, meaningful button labels + +## Guardrails + +Before writing any pattern, internalize these constraints: + +1. **Block markup only** — all visual design is expressed through block comment attributes and theme.json presets. No inline ` + + +
+ + + +``` + +### Hardcoded Colors +```json +// WRONG: hardcoded hex when a preset exists +{"style":{"color":{"background":"#000000","text":"#ffffff"}}} + +// CORRECT: use theme presets for theme compatibility +{"backgroundColor":"contrast","textColor":"base"} +``` + +Use hardcoded values only when no suitable preset exists and the design requires a specific color. Always prefer presets — they adapt to theme changes and style variations. + +### Missing Escaping and i18n +```php +// WRONG: raw text, not translatable, not escaped +

Our Services

+ +// WRONG: translatable but not escaped +

+ +// CORRECT: escaped and translatable +

+``` + +### Query-Dependent PHP +```php +// WRONG: runs at registration time, not render time + 3 ) ); ?> + +// CORRECT: use Query Loop block for dynamic content + +``` + +### Unclosed or Mismatched Blocks +```html + + +
+ +

Title

+ + + + + + + + +``` + +Every `` must have a matching `` and nesting must be properly ordered. + +### Placeholder Image URLs +```html + + + + +<?php esc_attr_e( 'Featured image', 'theme-slug' ); ?> +``` + +## Accessibility Failures + +### Missing Alt Text +```html + + +
+ + + + +``` + +Decorative images (backgrounds, dividers) can use empty alt, but informational images must describe content. + +### Skipped Heading Levels +```html + + Section Title + Subsection + + + Section Title + Subsection +``` + +Patterns should use `h2` as the top level (h1 is the page title). Descend sequentially: h2 → h3 → h4. + +### Insufficient Color Contrast +When using dark backgrounds, verify text presets provide adequate contrast: +- `{"backgroundColor":"contrast","textColor":"base"}` — typically safe (dark bg, light text) +- Custom color combinations must meet WCAG 2.1 AA (4.5:1 for body text, 3:1 for large text) + +### Non-Descriptive Button Text +```html + +Click Here +Read More + + + + +``` + +### Missing ARIA on Decorative Elements +Spacer blocks should include `aria-hidden="true"` (WordPress adds this automatically). If generating custom separator patterns, ensure decorative elements don't announce to screen readers. diff --git a/skills/wp-patterns/references/block-markup-reference.md b/skills/wp-patterns/references/block-markup-reference.md new file mode 100644 index 0000000..e582fa0 --- /dev/null +++ b/skills/wp-patterns/references/block-markup-reference.md @@ -0,0 +1,220 @@ +# Block Markup Reference + +## Comment Syntax + +WordPress blocks are serialized as HTML comments with JSON attributes. + +```html + +
Inner content
+ + + (self-closing, no inner content) +``` + +Rules: +- Opening tag: `` +- Core blocks omit namespace: `` (not `core/heading`) +- JSON must be valid — no trailing commas, strings double-quoted +- Self-closing blocks (spacer, separator, image with no caption): end with `/-->` +- Every opening comment **must** have a matching closing comment + +## Most-Used Blocks in Patterns + +### Layout Blocks + +**Group** — primary container, supports all layout types: +```html + +
+ +
+ +``` + +Layout types: +- `{"type":"constrained"}` — centered with max-width (default for sections) +- `{"type":"constrained","contentSize":"800px","wideSize":"1200px"}` — custom widths +- `{"type":"flex","flexWrap":"nowrap"}` — horizontal row +- `{"type":"flex","orientation":"vertical"}` — vertical stack +- `{"type":"grid","columnCount":3}` — CSS grid with fixed columns +- `{"type":"grid","minimumColumnWidth":"250px"}` — responsive auto-fill grid + +Tag name override: `{"tagName":"section"}`, `{"tagName":"header"}`, `{"tagName":"footer"}` + +**Columns / Column:** +```html + +
+ +
+ +
+ + +
+ +
+ +
+ +``` + +### Content Blocks + +**Heading:** +```html + +

Heading text

+ +``` + +**Paragraph:** +```html + +

Body text

+ +``` + +**Image:** +```html + +
+ Descriptive alt text +
+ +``` + +**Cover:** +```html + +
+ + +
+ +
+
+ +``` + +**Buttons / Button:** +```html + +
+ + + + + + +
+ +``` + +**Spacer:** +```html + + + +``` + +**Separator:** +```html + +
+ +``` + +**Media & Text:** +```html + +
+
+ +
+
+ Description +
+
+ +``` + +**Query Loop (post listing):** +```html + +
+ + + + + +
+ +``` + +## Style Attribute Structure + +The `style` attribute holds custom values (not preset slugs): + +```json +{ + "style": { + "spacing": { + "padding": {"top":"var:preset|spacing|50","right":"var:preset|spacing|50","bottom":"var:preset|spacing|50","left":"var:preset|spacing|50"}, + "margin": {"top":"0","bottom":"0"}, + "blockGap": "var:preset|spacing|30" + }, + "border": { + "radius": "8px", + "width": "1px", + "color": "var:preset|color|contrast", + "style": "solid" + }, + "color": { + "background": "#1a1a2e", + "text": "#ffffff", + "gradient": "linear-gradient(135deg,rgb(6,147,227) 0%,rgb(155,81,224) 100%)" + }, + "typography": { + "fontSize": "clamp(1rem, 2vw, 1.5rem)", + "lineHeight": "1.4", + "letterSpacing": "-0.02em" + } + } +} +``` + +Preset reference syntax in style values: `var:preset|{type}|{slug}` (not CSS `var()`) + +## Preset Class Naming Convention + +When using preset slugs (not inline style), blocks get CSS classes: +- `"backgroundColor":"primary"` → `has-primary-background-color has-background` +- `"textColor":"contrast"` → `has-contrast-color has-text-color` +- `"fontSize":"large"` → `has-large-font-size` +- `"fontFamily":"heading"` → `has-heading-font-family` +- `"gradient":"vivid-cyan-blue-to-vivid-purple"` → `has-vivid-cyan-blue-to-vivid-purple-gradient-background has-background` + +## Block Locking + +Prevent users from modifying pattern structure: + +```json +{ + "lock": {"move": true, "remove": true} +} +``` + +On container blocks, `templateLock` constrains children: +- `"templateLock":"all"` — no insert, move, or remove +- `"templateLock":"insert"` — no adding/removing, can move +- `"templateLock":"contentOnly"` — only text/media editable, structure locked + +## Block Alignment + +Use `align` attribute for wide/full-width: +```json +{"align":"wide"} +{"align":"full"} +``` diff --git a/skills/wp-patterns/references/design-with-tokens.md b/skills/wp-patterns/references/design-with-tokens.md new file mode 100644 index 0000000..c926ad6 --- /dev/null +++ b/skills/wp-patterns/references/design-with-tokens.md @@ -0,0 +1,152 @@ +# Design with Tokens + +How to translate design intent into WordPress block attributes using theme.json presets. + +## Core Principle + +In block patterns, **all visual design** is expressed through: +1. **Preset slugs** — reference theme.json values by name (preferred) +2. **Style attributes** — inline custom values in block JSON (fallback) +3. **Block nesting** — layout and composition via container blocks + +Never use inline `