Creating components
This reference covers the process of creating a new component that follows CivicTheme conventions: atomic design placement, required files, variable registration, and the component checklist.
Atomic Design Levels
Determine where your component fits in the hierarchy:
Atom (01-atoms/)
A single UI element that cannot be broken down further
Button, Tag, Heading, Input
Molecule (02-molecules/)
A combination of atoms forming a functional group
Card, Accordion, Breadcrumb, Search
Organism (03-organisms/)
A complex section composed of molecules and atoms
Header, Footer, Banner, Navigation
Rules of thumb:
If it contains only HTML elements and no other CivicTheme components, it is an atom
If it includes other CivicTheme atoms or molecules via
{% include %}, it is a molecule or organismIf it represents a major page section, it is an organism
Single Directory Components (SDC)
CivicTheme uses Drupal's Single Directory Component (SDC) architecture. Each component lives in its own directory containing all related files. The .component.yml file registers the component with Drupal and defines its props schema using JSON Schema. Drupal validates props against this schema at render time, so incorrect prop types or missing required values will raise errors.
Components are referenced by namespace and machine name (e.g., civictheme:feature-card). In your sub-theme, new components are automatically registered under your sub-theme's namespace. To override a base theme component, add replaces: civictheme:component_name to your .component.yml.
Required Files
Create a directory for your component in the appropriate atomic level (e.g., your_theme/components/02-molecules/feature-card). Each component needs these files:
feature-card.component.yml
SDC metadata: name, status, description, props schema (JSON Schema with Drupal's metadata schema), and slots for rich content areas
feature-card.twig
HTML template with prop validation, BEM class construction, and nested includes
feature-card.scss
Styles using BEM naming, design tokens, and the ct-component-theme mixin
feature-card.stories.js
Storybook story with interactive controls for all props
feature-card.js
JavaScript using constructor pattern (only if the component has interactive behavior)
The .component.yml file is the starting point — it defines the component's interface. Props use JSON Schema types (string, boolean, object, array) with optional enum constraints and default values. Slots are used for content areas that accept rendered markup rather than simple values.
The conventions for each file type — Twig prop validation, SCSS theme mixins, JavaScript constructor patterns, Storybook controls, and the full .component.yml schema — are documented in the components system reference.
Registering Component Variables
If your component needs theme-specific color variables, define them in components/variables.components.scss using the naming convention $ct-[component]-[theme]-[property] with !default flags:
For details on the variable system, see Variables.
Drupal Integration
To use your component in Drupal's content authoring workflow, you need three pieces:
A paragraph type — with fields matching your component's props, using CivicTheme's field naming conventions (
field_c_p_for CivicTheme paragraph fields,field_p_for custom paragraph fields)A preprocess include — in
includes/that extracts Drupal field values and maps them to component props using utility functions likecivictheme_get_field_value()A Drupal template — a thin Twig template in
templates/paragraph/that includes your component
The implementation pattern and field naming conventions are documented in the mapping system reference. Template conventions are in the templates reference.
Component Checklist
Before considering your component complete, verify:
Last updated
Was this helpful?