Skip to content

zeroedin/pfv6-to-lit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

581 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PatternFly Elements v6

Web components implementing the PatternFly v6 design system.

Overview

PatternFly Elements v6 is a web component library built with LitElement that implements the PatternFly v6+ design system for non-React environments. This enables developers to use PatternFly v6+ component designs in Vue, Angular, Svelte, vanilla JavaScript, and server-side platforms like Drupal and Ruby on Rails.

Project Goals

  • 1:1 Visual Parity: Components must be visually identical to React PatternFly v6
  • Framework Agnostic: Work in any framework or vanilla JavaScript
  • Standards-Based: Built on Web Components standards (Custom Elements, Shadow DOM)
  • Design Token Integration: Use PatternFly v6 design tokens for theming

Getting Started

Prerequisites

  • Node.js 24.x (LTS) - See .nvmrc for version
  • npm 10+

Using Node Version Manager (nvm)

This project uses Node.js 24.x. We recommend using nvm for Node.js version management.

Install nvm:

macOS/Linux:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash

Or with wget:

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash

Windows:

Download and install nvm-windows

After installation:

# Install the project's Node.js version (reads from .nvmrc)
nvm install

# Use the project's Node.js version
nvm use

The .nvmrc file in the project root specifies the exact Node.js version. Running nvm use automatically switches to this version.

Installation

npm ci

What happens on postinstall:

  1. Cache PatternFly sources - Clones React PatternFly and core PatternFly to .cache/
  2. Copy React demos - Extracts React demo files to patternfly-react/ for comparison testing
  3. Copy PatternFly assets - Copies base CSS, fonts, and images to dev-server/

These steps ensure:

  • React component sources are available for conversion reference
  • Side-by-side React comparison demos for visual parity validation

Development

# Start development server
npm run start
# Opens http://localhost:8000 with the development index page

# Compile TypeScript
npm run compile

# Run linters
npm run lint

# Run unit tests
npm run test

# Run E2E tests
npm run e2e

Development Pages:

  • / - Main development index with auto-generated component list
  • /elements/pfv6-{name}/demo/ - Lit component demo index (lists all demos for the component)
  • /elements/pfv6-{name}/demo/{page}/ - Individual Lit component demo pages
  • /elements/pfv6-{name}/react/ - React component demo index (comparison demos)
  • /elements/pfv6-{name}/react/{page}/ - Individual React component demo pages

Component Conversion Workflow

This project uses specialized AI subagents to convert React PatternFly components to LitElement web components.

Finding the Next Component to Convert

Use the find subagent to identify the optimal next task or component based on dependency analysis:

Prompt:

Find the next task or component to convert

The find subagent:

  1. Regenerates tasks.json by running npm run deps:extract && npm run deps:tasks
  2. Detects which elements/pfv6-*/ directories exist
  3. Analyzes dependencies from PatternFly React source
  4. Recommends the next component to convert based on dependency order
  5. Provides reasoning and next steps

Converting a Component

Once you have a component recommendation, use a simple conversion prompt:

Prompt:

Convert {{ Component Name }} component

Replace {{ Component Name }} with the component name from the find recommendation (e.g., "Brand", "Spinner", "Divider").

Conversion Workflow:

The main conversation orchestrates the conversion by delegating to specialized subagents in phases:

Phase 1: Initial Setup

  • Verify component type (layout vs regular)
  • Verify .cache/ repositories exist

Phase 2: Component Implementation

  1. api-writer - Translates React props to LitElement properties and creates TypeScript component files
  2. face-elements-writer (conditional) - Adds Form-Associated Custom Element patterns for form controls
  3. 6 focused api-auditors (run in parallel):
    • api-bem-auditor - Detects BEM classes in Shadow DOM templates
    • api-import-auditor - Validates import patterns and unused code
    • api-property-auditor - Validates property decorators and React API parity
    • api-template-auditor - Validates template patterns and naming conventions
    • api-internals-auditor - Validates ElementInternals and focus delegation
    • api-lifecycle-auditor - Validates lifecycle patterns and event translation

Phase 3: Demo Creation 4. demo-writer - Converts React examples to HTML demos 5. layout-translator (conditional) - Translates React layout components to CSS classes 6. style-components (conditional) - Translates React styling components to semantic HTML

Phase 4: Demo Validation 7. demo-auditor - Validates 1:1 parity with React demos

Phase 5: CSS Translation 8. css-writer - Translates React CSS to Shadow DOM CSS with token-derived fallbacks 9. css-auditor - Validates CSS against React source

Phase 6: Accessibility Validation 10. aria-auditor - Validates ARIA patterns (property naming, IDREF, React parity, redundant roles) 11. element-internals-auditor (conditional) - Validates ElementInternals usage 12. face-elements-auditor (conditional) - Validates Form-Associated Custom Element implementation

Phase 7: Test Creation 13. test-spec-writer - Generates comprehensive unit tests 14. test-visual-writer - Creates visual regression tests 15. test-css-api-writer - Generates CSS API override tests

Phase 8: Test Analysis 16. test-runner (if failures) - Analyzes test failures and categorizes as fixable vs blocked

Each subagent runs in isolation and reports back to the main conversation, which manages the overall workflow.

Example workflow:

# Step 1: Find next task or component
> Find the next task or component to convert

# Agent responds with recommendation from tasks.json
# (e.g., "Next Component: NotificationBadge" or "Next Demo Task: AccordionBordered.tsx")

# Step 2: Convert the component
> Convert NotificationBadge component

# Main conversation delegates to each subagent through all phases:
#   - api-writer creates component files
#   - 6 api-auditors validate in parallel
#   - demo-writer creates demos
#   - css-writer translates CSS
#   - aria-auditor validates accessibility
#   - test-spec-writer creates tests
#   - ... (continues through all phases)

Architecture Note:

The conversion workflow is orchestrated directly from the main conversation (not from a nested subagent). This architecture prevents memory accumulation and allows each specialized subagent to complete and release resources before the next phase begins.

For more details on the conversion process and individual subagent capabilities, see CLAUDE.md and the subagent documentation in agents/.

Project Structure

/elements/              - Web component implementations
  /pfv6-card/          - Example: Card component
    pfv6-card.ts       - Component TypeScript
    pfv6-card.css      - Component styles
    /demo/             - Component demo files (minimal HTML fragments)
      index.html       - Primary demo page
      variants.html    - Additional demos (optional)
    /test/             - Component unit tests
      pfv6-card.spec.ts

/lib/                  - Shared utilities and contexts
/styles/               - Distributed styles (layout integration CSS)
  layout.css           - Layout integration for display: contents components
/dev-server/           - Development server configuration
  index.html           - Main development page (served at /)
  /plugins/            - Custom dev server plugins (routing, import maps, demo discovery)
  /styles/             - Global styles and PatternFly base CSS
  /assets/             - Static resources
/tests/                - E2E test files and page objects
/docs/                 - Project documentation

Demo Files: Each component's /demo/ folder contains simple HTML fragments (no boilerplate). The dev server automatically wraps them using dev-server/index.html as the template, replacing only the <main> content with the demo markup.

Component Naming Convention

All components use the pfv6- prefix:

  • pfv6-button
  • pfv6-card
  • pfv6-modal
  • etc.

Architecture Decisions

PatternFly CSS Strategy

Demo CSS Files:

Our demos use two PatternFly CSS files:

  • base.css - Core PatternFly design tokens and base styles

    • Copied from @patternfly/react-core/dist/styles/base.css
    • Used by all demos (Lit and React)
    • Location: /dev-server/styles/patternfly/base.css
  • patternfly.css - Full PatternFly CSS (includes component styles and layout utilities)

    • Part of the patternfly-react distribution
    • Used by all demos (Lit and React)
    • Location: /patternfly-react/dist/patternfly.css

Why patternfly.css for Lit demos?

While Lit components use Shadow DOM with scoped styles, we still need patternfly.css for layout utility classes like pf-v6-l-flex, pf-v6-l-gallery, and pf-v6-l-grid.

Layout components are NOT converted to custom elements. Instead, demos use raw HTML with PatternFly layout CSS classes:

  • ✅ Component demos: Use custom elements (<pfv6-card>, <pfv6-button>)
  • ✅ Layout usage: Use HTML + CSS classes (<div class="pf-v6-l-flex pf-m-row">)

This approach maintains pixel-perfect parity with React while leveraging PatternFly's battle-tested layout system.

Layout Integration CSS (styles/layout.css)

Required Stylesheet: When using PatternFly layout classes (.pf-v6-l-flex, .pf-v6-l-grid, etc.) with certain web components, you must include layout.css for proper spacing.

Affected Components:

  • pfv6-divider
  • pfv6-skeleton
  • pfv6-backdrop
  • pfv6-background-image

Usage:

<!-- Include alongside PatternFly CSS -->
<link rel="stylesheet" href="/path/to/patternfly.css">
<link rel="stylesheet" href="/path/to/layout.css">

Why This File Exists:

These components use display: contents to act as invisible wrappers, allowing their inner elements to participate directly in parent layouts. However, display: contents makes the custom element invisible to CSS child selectors like .pf-v6-l-flex > *, so PatternFly's built-in layout spacing doesn't apply.

The layout.css file bridges this gap by:

  1. Targeting these specific custom elements inside layout containers
  2. Setting CSS custom properties (--_layout-*) on the custom element
  3. Component shadow DOM CSS reads these properties to apply correct spacing

How It Works:

/* In layout.css - targets custom elements inside flex containers */
.pf-v6-l-flex > pfv6-divider {
  --_layout-margin-inline-end: var(--pf-v6-l-flex--spacer--column);
}

/* In pfv6-divider.css - consumes the variable */
div {
  margin-inline-end: var(--_layout-margin-inline-end);
}

Supported Layouts: Flex, Grid, Gallery, Stack, Level, Split, Bullseye


For Contributors - Adding New display: contents Components:

  1. Add component to :is() selector lists in styles/layout.css
  2. Consume --_layout-* variables in component shadow DOM CSS
  3. Test in Flex, Grid, and Gallery layouts to verify spacing

Documentation

  • See CLAUDE.md for comprehensive development guidelines
  • See docs/ for component documentation

Tech Stack

  • TypeScript - Compiled to ES6 JavaScript
  • Lit - Web component framework
  • PatternFly v6 - Design system and tokens
  • @web/dev-server - Development server
  • @web/test-runner - Unit testing
  • Playwright - E2E testing
  • Wireit - Task orchestration

Contributing

See CLAUDE.md for detailed coding standards and guidelines.

License

MIT

Resources

About

A Patternfly v6+ conversion to LitElement web components

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors