fix(tests): Correct Figma ingest test
This commit is contained in:
111
packages/dss-rules/rules/accessibility.json
Normal file
111
packages/dss-rules/rules/accessibility.json
Normal file
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"$schema": "../schemas/rule.schema.json",
|
||||
"id": "accessibility",
|
||||
"version": "1.0.0",
|
||||
"name": "Accessibility Rules",
|
||||
"description": "WCAG 2.1 AA compliance rules for accessible design",
|
||||
"category": "accessibility",
|
||||
"severity": "error",
|
||||
"rules": [
|
||||
{
|
||||
"id": "images-have-alt",
|
||||
"name": "Images Must Have Alt Text",
|
||||
"description": "All img elements must have meaningful alt text or be marked decorative",
|
||||
"severity": "error",
|
||||
"wcag": "1.1.1",
|
||||
"validation": {
|
||||
"type": "attribute-required",
|
||||
"element": "img",
|
||||
"attribute": "alt",
|
||||
"allowEmpty": true,
|
||||
"emptyMeansDecorative": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "buttons-have-text",
|
||||
"name": "Buttons Must Have Accessible Names",
|
||||
"description": "Button elements must have visible text or aria-label",
|
||||
"severity": "error",
|
||||
"wcag": "4.1.2",
|
||||
"validation": {
|
||||
"type": "accessible-name",
|
||||
"elements": ["button", "[role=button]"],
|
||||
"sources": ["text content", "aria-label", "aria-labelledby"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "form-labels",
|
||||
"name": "Form Inputs Must Have Labels",
|
||||
"description": "All form inputs must be associated with a label",
|
||||
"severity": "error",
|
||||
"wcag": "1.3.1",
|
||||
"validation": {
|
||||
"type": "label-association",
|
||||
"elements": ["input", "select", "textarea"],
|
||||
"methods": ["for/id", "aria-labelledby", "aria-label", "wrapper"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "focus-visible",
|
||||
"name": "Focus Must Be Visible",
|
||||
"description": "Interactive elements must have visible focus indicators",
|
||||
"severity": "error",
|
||||
"wcag": "2.4.7",
|
||||
"validation": {
|
||||
"type": "focus-style",
|
||||
"minContrastRatio": 3.0,
|
||||
"forbiddenPatterns": ["outline: none", "outline: 0", ":focus { outline: none }"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "color-not-only",
|
||||
"name": "Color Not Only Indicator",
|
||||
"description": "Information must not be conveyed by color alone",
|
||||
"severity": "warning",
|
||||
"wcag": "1.4.1",
|
||||
"guidelines": [
|
||||
"Error states need icon + color + text",
|
||||
"Links in text need underline or other indicator",
|
||||
"Status indicators need icon or pattern"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "touch-target-size",
|
||||
"name": "Minimum Touch Target Size",
|
||||
"description": "Interactive elements must be at least 44x44 CSS pixels",
|
||||
"severity": "warning",
|
||||
"wcag": "2.5.5",
|
||||
"validation": {
|
||||
"type": "size-check",
|
||||
"minWidth": 44,
|
||||
"minHeight": 44,
|
||||
"elements": ["button", "a", "[role=button]", "input[type=checkbox]", "input[type=radio]"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "keyboard-navigation",
|
||||
"name": "Keyboard Navigation",
|
||||
"description": "All functionality must be accessible via keyboard",
|
||||
"severity": "error",
|
||||
"wcag": "2.1.1",
|
||||
"validation": {
|
||||
"type": "keyboard-accessible",
|
||||
"requirements": [
|
||||
"All interactive elements focusable",
|
||||
"No keyboard traps",
|
||||
"Logical tab order",
|
||||
"Skip links for navigation"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"compliance": {
|
||||
"level": "AA",
|
||||
"standards": ["WCAG 2.1"],
|
||||
"testingTools": [
|
||||
"axe-core",
|
||||
"pa11y",
|
||||
"lighthouse"
|
||||
]
|
||||
}
|
||||
}
|
||||
75
packages/dss-rules/rules/colors.json
Normal file
75
packages/dss-rules/rules/colors.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"$schema": "../schemas/rule.schema.json",
|
||||
"id": "colors",
|
||||
"version": "1.0.0",
|
||||
"name": "Color Token Rules",
|
||||
"description": "Rules for color token usage and compliance",
|
||||
"category": "tokens",
|
||||
"severity": "error",
|
||||
"rules": [
|
||||
{
|
||||
"id": "no-hardcoded-colors",
|
||||
"name": "No Hardcoded Colors",
|
||||
"description": "All colors must use design tokens, not hardcoded hex/rgb values",
|
||||
"severity": "error",
|
||||
"patterns": {
|
||||
"forbidden": [
|
||||
"#[0-9a-fA-F]{3,8}",
|
||||
"rgb\\([^)]+\\)",
|
||||
"rgba\\([^)]+\\)",
|
||||
"hsl\\([^)]+\\)",
|
||||
"hsla\\([^)]+\\)"
|
||||
],
|
||||
"allowed": [
|
||||
"var\\(--[a-z-]+\\)",
|
||||
"\\$[a-z-]+",
|
||||
"colors\\.[a-z]+",
|
||||
"theme\\.[a-z]+"
|
||||
]
|
||||
},
|
||||
"exceptions": [
|
||||
"*.test.*",
|
||||
"*.spec.*",
|
||||
"**/fixtures/**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "semantic-color-naming",
|
||||
"name": "Semantic Color Naming",
|
||||
"description": "Colors must use semantic names (primary, error) not descriptive (blue, red)",
|
||||
"severity": "warning",
|
||||
"validation": {
|
||||
"type": "naming-convention",
|
||||
"pattern": "^(primary|secondary|accent|success|warning|error|info|neutral|background|foreground|border|muted)(-[a-z]+)?$"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "contrast-ratio",
|
||||
"name": "Minimum Contrast Ratio",
|
||||
"description": "Text/background combinations must meet WCAG AA standards",
|
||||
"severity": "error",
|
||||
"validation": {
|
||||
"type": "contrast-check",
|
||||
"minRatio": 4.5,
|
||||
"largeTextRatio": 3.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"tokens": {
|
||||
"required": [
|
||||
"colors.primary",
|
||||
"colors.secondary",
|
||||
"colors.background",
|
||||
"colors.foreground",
|
||||
"colors.border",
|
||||
"colors.error",
|
||||
"colors.success",
|
||||
"colors.warning"
|
||||
],
|
||||
"optional": [
|
||||
"colors.muted",
|
||||
"colors.accent",
|
||||
"colors.info"
|
||||
]
|
||||
}
|
||||
}
|
||||
125
packages/dss-rules/rules/components.json
Normal file
125
packages/dss-rules/rules/components.json
Normal file
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"$schema": "../schemas/rule.schema.json",
|
||||
"id": "components",
|
||||
"version": "1.0.0",
|
||||
"name": "Component Usage Rules",
|
||||
"description": "Rules for component implementation and usage patterns",
|
||||
"category": "components",
|
||||
"severity": "error",
|
||||
"rules": [
|
||||
{
|
||||
"id": "use-design-system-components",
|
||||
"name": "Use Design System Components",
|
||||
"description": "Prefer design system components over custom implementations",
|
||||
"severity": "error",
|
||||
"components": {
|
||||
"required": {
|
||||
"Button": {
|
||||
"import": "@dss/components",
|
||||
"forbiddenAlternatives": ["button", "a.btn", "div[role=button]"]
|
||||
},
|
||||
"Input": {
|
||||
"import": "@dss/components",
|
||||
"forbiddenAlternatives": ["input[type=text]", "textarea"]
|
||||
},
|
||||
"Select": {
|
||||
"import": "@dss/components",
|
||||
"forbiddenAlternatives": ["select", "div.dropdown"]
|
||||
},
|
||||
"Card": {
|
||||
"import": "@dss/components",
|
||||
"forbiddenAlternatives": ["div.card", "article"]
|
||||
},
|
||||
"Modal": {
|
||||
"import": "@dss/components",
|
||||
"forbiddenAlternatives": ["div.modal", "dialog"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "component-prop-validation",
|
||||
"name": "Required Component Props",
|
||||
"description": "Components must include required accessibility and functionality props",
|
||||
"severity": "error",
|
||||
"validation": {
|
||||
"Button": {
|
||||
"requiredProps": ["variant", "size"],
|
||||
"conditionalProps": {
|
||||
"loading": ["loadingText"],
|
||||
"icon": ["aria-label"]
|
||||
}
|
||||
},
|
||||
"Input": {
|
||||
"requiredProps": ["label", "name"],
|
||||
"conditionalProps": {
|
||||
"error": ["errorMessage"]
|
||||
}
|
||||
},
|
||||
"Modal": {
|
||||
"requiredProps": ["title", "onClose"],
|
||||
"recommendedProps": ["aria-describedby"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "component-composition",
|
||||
"name": "Component Composition Patterns",
|
||||
"description": "Follow recommended composition patterns for complex UIs",
|
||||
"severity": "info",
|
||||
"patterns": {
|
||||
"forms": {
|
||||
"structure": ["Form", "FormField", "Input/Select", "Button"],
|
||||
"guidelines": [
|
||||
"Wrap inputs in FormField for consistent labeling",
|
||||
"Use Form component for validation handling",
|
||||
"Place submit button inside Form"
|
||||
]
|
||||
},
|
||||
"lists": {
|
||||
"structure": ["List", "ListItem"],
|
||||
"guidelines": [
|
||||
"Use semantic list components for accessibility",
|
||||
"Implement virtualization for 50+ items"
|
||||
]
|
||||
},
|
||||
"navigation": {
|
||||
"structure": ["Nav", "NavItem", "NavLink"],
|
||||
"guidelines": [
|
||||
"Use Nav component for main navigation",
|
||||
"Implement active state handling"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "no-inline-styles",
|
||||
"name": "No Inline Styles on Components",
|
||||
"description": "Components should use className/variant props, not style attribute",
|
||||
"severity": "warning",
|
||||
"patterns": {
|
||||
"forbidden": [
|
||||
"style={{",
|
||||
"style={{"
|
||||
],
|
||||
"exceptions": [
|
||||
"dynamic positioning",
|
||||
"animations",
|
||||
"calculated values"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"adoption": {
|
||||
"thresholds": {
|
||||
"minimum": 60,
|
||||
"target": 80,
|
||||
"excellent": 95
|
||||
},
|
||||
"metrics": [
|
||||
"percentage_using_ds_components",
|
||||
"custom_component_count",
|
||||
"token_compliance_rate"
|
||||
]
|
||||
}
|
||||
}
|
||||
76
packages/dss-rules/rules/spacing.json
Normal file
76
packages/dss-rules/rules/spacing.json
Normal file
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"$schema": "../schemas/rule.schema.json",
|
||||
"id": "spacing",
|
||||
"version": "1.0.0",
|
||||
"name": "Spacing Token Rules",
|
||||
"description": "Rules for consistent spacing using design tokens",
|
||||
"category": "tokens",
|
||||
"severity": "warning",
|
||||
"rules": [
|
||||
{
|
||||
"id": "no-arbitrary-spacing",
|
||||
"name": "No Arbitrary Spacing Values",
|
||||
"description": "Spacing must use token scale (4px increments), not arbitrary values",
|
||||
"severity": "warning",
|
||||
"patterns": {
|
||||
"forbidden": [
|
||||
"margin:\\s*[0-9]+px",
|
||||
"padding:\\s*[0-9]+px",
|
||||
"gap:\\s*[0-9]+px"
|
||||
],
|
||||
"allowed": [
|
||||
"var\\(--spacing-[a-z0-9]+\\)",
|
||||
"\\$spacing-[a-z0-9]+",
|
||||
"spacing\\.[a-z0-9]+"
|
||||
]
|
||||
},
|
||||
"exceptions": [
|
||||
"0",
|
||||
"0px",
|
||||
"auto",
|
||||
"inherit"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "spacing-scale",
|
||||
"name": "Use Spacing Scale",
|
||||
"description": "Only use values from the defined spacing scale",
|
||||
"severity": "error",
|
||||
"validation": {
|
||||
"type": "scale-check",
|
||||
"allowedValues": [0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96, 128]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "consistent-component-spacing",
|
||||
"name": "Component Internal Spacing",
|
||||
"description": "Components should use consistent internal spacing patterns",
|
||||
"severity": "info",
|
||||
"guidelines": [
|
||||
"Use spacing.xs (4px) for tight groupings",
|
||||
"Use spacing.sm (8px) for related elements",
|
||||
"Use spacing.md (16px) for section separation",
|
||||
"Use spacing.lg (24px) for major sections",
|
||||
"Use spacing.xl (32px+) for page-level separation"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tokens": {
|
||||
"required": [
|
||||
"spacing.xs",
|
||||
"spacing.sm",
|
||||
"spacing.md",
|
||||
"spacing.lg",
|
||||
"spacing.xl"
|
||||
],
|
||||
"scale": {
|
||||
"xs": "4px",
|
||||
"sm": "8px",
|
||||
"md": "16px",
|
||||
"lg": "24px",
|
||||
"xl": "32px",
|
||||
"2xl": "48px",
|
||||
"3xl": "64px"
|
||||
}
|
||||
}
|
||||
}
|
||||
75
packages/dss-rules/rules/typography.json
Normal file
75
packages/dss-rules/rules/typography.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"$schema": "../schemas/rule.schema.json",
|
||||
"id": "typography",
|
||||
"version": "1.0.0",
|
||||
"name": "Typography Rules",
|
||||
"description": "Rules for consistent typography using design tokens",
|
||||
"category": "tokens",
|
||||
"severity": "warning",
|
||||
"rules": [
|
||||
{
|
||||
"id": "use-typography-scale",
|
||||
"name": "Use Typography Scale",
|
||||
"description": "Font sizes must use the defined typography scale",
|
||||
"severity": "error",
|
||||
"patterns": {
|
||||
"forbidden": [
|
||||
"font-size:\\s*[0-9]+px",
|
||||
"fontSize:\\s*[0-9]+"
|
||||
],
|
||||
"allowed": [
|
||||
"var\\(--font-size-[a-z]+\\)",
|
||||
"\\$font-size-[a-z]+",
|
||||
"typography\\.[a-z]+"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "semantic-text-elements",
|
||||
"name": "Use Semantic Text Elements",
|
||||
"description": "Use appropriate heading levels and text components",
|
||||
"severity": "warning",
|
||||
"validation": {
|
||||
"headingOrder": true,
|
||||
"maxH1PerPage": 1,
|
||||
"noSkippedLevels": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "line-height-consistency",
|
||||
"name": "Consistent Line Heights",
|
||||
"description": "Line heights should match the typography scale",
|
||||
"severity": "info",
|
||||
"guidelines": [
|
||||
"Use lineHeight.tight (1.25) for headings",
|
||||
"Use lineHeight.normal (1.5) for body text",
|
||||
"Use lineHeight.relaxed (1.75) for long-form content"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tokens": {
|
||||
"required": [
|
||||
"typography.h1",
|
||||
"typography.h2",
|
||||
"typography.h3",
|
||||
"typography.body",
|
||||
"typography.small",
|
||||
"typography.caption"
|
||||
],
|
||||
"scale": {
|
||||
"xs": "12px",
|
||||
"sm": "14px",
|
||||
"base": "16px",
|
||||
"lg": "18px",
|
||||
"xl": "20px",
|
||||
"2xl": "24px",
|
||||
"3xl": "30px",
|
||||
"4xl": "36px",
|
||||
"5xl": "48px"
|
||||
},
|
||||
"fontFamilies": {
|
||||
"sans": "Inter, system-ui, sans-serif",
|
||||
"mono": "JetBrains Mono, monospace"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user