This document explains in simple terms how we determine the value for each of the 7 data-* attributes we add to PatternFly components.
Each component gets analyzed by 7 functions (one per "bucket"). These functions look at:
- Component name (e.g., "Button", "Card", "TextInput")
- Props (e.g.,
variant="primary",isDisabled={true},onClick={...}) - Parent context (where the component is used - e.g., inside a Form, Modal, Toolbar)
- Children (for some components, we analyze child elements to infer variants)
Function: inferRole(componentName)
What it does:
- Takes the component name (e.g., "Button", "Card", "TextInput")
- Converts it to lowercase
- Looks it up in a
roleMapobject that maps component names to semantic roles - Returns a more descriptive role than the component name itself
Examples:
Button→"button"Card→"card"TextInput→"text-input"AccordionItem→"accordion-section"(more descriptive than just "accordion-item")ActionListItem→"action-item"(more descriptive)
Special cases:
- Icons (components ending with "Icon") → always
"icon" - Brand → always
"logo" - Some structural children return
null(they don't get a role)
Props used: None (only uses component name)
Function: inferPurpose(componentName, props)
What it does:
- Takes component name and props
- Checks component name patterns (e.g., includes "button", "card", "form")
- Checks specific props to determine purpose
- Returns a purpose that describes the component's function
Common purposes:
"action"- Buttons, clickable elements"display"- Cards, lists, text that shows information"input"- Text inputs, selects, checkboxes, form controls"navigation"- Links, nav items, tabs, pagination"form-container"- Forms, wizards"guidance"- Tooltips, hints, popovers"selection"- Toggle groups, tree view items"status-tracking"- Progress bars, spinners
Props checked:
onClick,onSubmit→ indicates actionhref→ indicates navigationisSelectable,isClickable→ for cardsonClose,isDismissible→ for labels (filter purpose)color→ for labels (status-indicator purpose)actionprop → for Forms (to infer purpose like "create", "edit")
Examples:
- Button with
onClick→"action" - Link with
href→"navigation" - Card with
isSelectable→"selectable" - Form with
action="/api/create"→ purpose inferred from action URL
Function: inferVariant(componentName, props) + sometimes analyzeChildren() functions
What it does:
- Takes component name and props
- Checks for
variantprop (most common) - Checks for other visual/style props (e.g.,
size,color,orientation) - For some components, analyzes children to infer variants
- Returns a string or array of variant names (can combine multiple variants)
Props checked:
variant→ most common (e.g.,variant="primary",variant="danger")size→ for size variants (e.g.,size="sm",size="lg")orientation→ for orientation (e.g.,orientation="vertical")isFilled,isCompact,isSticky→ boolean style propscolor→ for color variantsformat→ for Timestamp (12-hour vs 24-hour)headingLevel→ for Title (h1-h6)
Children analysis (for some components):
InputGroup→analyzeInputGroupChildren()checks for buttons/icons/text on left/rightList→analyzeListChildren()checks for icons in list itemsLoginForm→analyzeLoginFormChildren()checks for password toggles, header utilitiesDualListSelector→ checks children for tooltips, search, actionsMasthead→ checks for vertical navMenu/Dropdown/Select→ checks children for various menu features
Examples:
- Button with
variant="primary"→"primary" - Card with
isSelectable→"selectable" - InputGroup with icon on left →
"with-icon-before" - List with icons →
"with-icons" - Timestamp with
format="12-hour"→"12-hour"
Note: Variants can combine (e.g., "primary-danger" for a primary button that's also danger)
Function: inferContext(componentName, props, parentContext, parentPurpose)
What it does:
- Takes component name, props, and parent context/purpose
- Checks if component should inherit context from parent
- Returns a context string describing where the component is typically used
Common contexts:
"form"- Inside forms"modal"- Inside modals"overlay"- Inside modals or drawers (overlay components)"toolbar"- Inside toolbars"table"- Inside tables"card"- Inside cards"page"- On pages (rendered as"in-page"in HTML)"masthead"- In the top navigation bar"sidebar"- In sidebars"wizard"- Inside wizards"authentication"- Inside login forms
How it works:
- First checks if component has a specific context (e.g.,
LoginForm→"authentication") - Then checks
parentContext(inherited from parent viafindParentContext()in transform.js) - For Forms, checks
parentPurpose- if Form has purpose like "create", children get context "create" (not "form") - Defaults to a common context if no parent context found
Special cases:
Page→ returnsnull(it's the root), but its children get"page"contextToolbar→ provides"toolbar"context to its childrenWizard→ provides"wizard"context to its childrenSidebar→ provides"sidebar"context to its childrenModalandDrawer→ both return"overlay"contextdata-context="page"→ rendered asdata-context="in-page"in HTML
Props checked:
isModal→ for Wizard (determines if overlay or page context)parentContext→ inherited from parent componentparentPurpose→ inherited from Form parent (for purpose-based context)
Function: inferState(componentName, props)
What it does:
- Takes component name and props
- Checks for state-related props (disabled, checked, selected, open, etc.)
- Returns a state string describing the current state
Common states:
"disabled"- Component is disabled"checked"- Checkbox/radio is checked"unchecked"- Checkbox/radio is unchecked"selected"- Item is selected"unselected"- Item is not selected"open"- Menu/dropdown/modal is open"closed"- Menu/dropdown/modal is closed"expanded"- Accordion/tree item is expanded"collapsed"- Accordion/tree item is collapsed"read-only"- Input is read-only"edit"- InlineEdit is in edit mode"error"- Input has error validation"warning"- Input has warning validation"active"- Component is active/current"loading"- Component is loading
Props checked:
isDisabled,disabled→"disabled"isChecked,checked→"checked"isSelected,selected→"selected"isOpen,open→"open"or"closed"isExpanded,expanded→"expanded"or"collapsed"isReadOnly,readOnly→"read-only"isInvalid,invalid,validated="error"→"error"validated="warning"→"warning"isActive,active→"active"isCurrent→"current"(for wizard steps)isVisited→"visited"(for wizard steps)
Special cases:
- Some components don't have states (display components like Timestamp, Title)
- Some states are component-specific (e.g., wizard steps have "visited", "current", "disabled")
- HelperText state is detected and applied to the form input it's associated with
Examples:
- Button with
isDisabled={true}→"disabled" - Checkbox with
isChecked={true}→"checked" - Menu with
isOpen={true}→"open" - Input with
validated="error"→"error"
Function: inferActionType(componentName, props)
What it does:
- Takes component name and props
- Determines the type of action the component performs
- Only applies to interactive components
Common action types:
"destructive"- Dangerous actions (delete, remove) - fromvariant="danger""navigation"- Navigation actions (links, tabs, pagination, skip links)"actionable"- Alert links that perform actions"toggle"- Toggle actions (Switch, toggle groups)"selection"- Selection actions (ToggleGroup, TreeView)"form"- Form actions (Wizard)"determinate"- Progress with measurable value (Progress, ProgressStepper)"indeterminate"- Progress without measurable value (Spinner)
Props checked:
variant="danger"→"destructive"href→"navigation"actionTypeprop → if explicitly set
Special cases:
- Most components return
null(no action-type needed) - Only interactive components get action-type
- Progress components use action-type to distinguish determinate vs indeterminate
Examples:
- Button with
variant="danger"→"destructive" - Link with
href→"navigation" - Switch →
"toggle" - Progress →
"determinate" - Spinner →
"indeterminate"
Function: inferSize(componentName, props)
What it does:
- Takes component name and props
- Checks for size-related props
- Returns a size string
Common sizes:
"compact"- Compact spacing"default"- Default spacing"small","sm"- Small size"medium","md"- Medium size"large","lg"- Large size"extra-small","xs"- Extra small"extra-large","xl"- Extra large
Props checked:
size→ most common (e.g.,size="sm",size="lg")isCompact,compact→"compact"- Component-specific size props
Special cases:
- Most components return
null(size not applicable) - Only components that have meaningful size variants get this attribute
- Icons have size variants (sm, md, lg, xl, 2xl, 3xl)
- Progress has size variants (small, large)
- Spinner has size variants (extra-small, small, medium, large)
Examples:
- Icon with
size="lg"→"lg" - Progress with
size="small"→"small" - Spinner with
size="large"→"large"
Converts JSX props array to a Map for easy lookup. Handles both StringLiteral and Literal types.
Traverses up the AST to find parent component and determine its context. Returns:
{ context, purpose }for Forms (so children can inherit purpose)- Context string for other parents (Page, Sidebar, Toolbar, Wizard, LoginForm)
nullif no parent context found
Some components analyze their children to infer variants:
analyzeInputGroupChildren()- Checks for buttons/icons/text on left/rightanalyzeListChildren()- Checks for icons in list itemsanalyzeLoginFormChildren()- Checks for password toggles, header utilitiesanalyzeDualListSelectorChildren()- Checks for tooltips, search, actionsanalyzeMastheadChildren()- Checks for vertical navanalyzeMenuChildren()- Checks for menu features (search, favorites, etc.)
Each component goes through all 7 functions in order:
inferRole()- What it IS (from component name)inferPurpose()- What it DOES (from name + props)inferVariant()- How it LOOKS (from props + sometimes children)inferContext()- Where it's USED (from parent context)inferState()- Current STATE (from props)inferActionType()- Type of ACTION (from name + props)inferSize()- SIZE (from props)
If a function returns null, that attribute is not added to the component.