---
title: Experience Components
slug: experience/experience-components
docTags: 
createdAt: 2026-05-13T08:57:31.555Z
---

## Overview

A **component** is the fundamental building block of a Purple Experience view. Every visible element — a list of articles, a navigation bar, a button, an image — is a component. Components are declared as JSON objects inside `views.json` and are identified by a `type` field. They all share a common set of base configuration properties (`id`, `class`, `template`, `sticky`, etc.) and can be conditionally shown or hidden at runtime.

## When to use this

Read this page to understand how any component is configured. The properties documented here apply to every component type — `list`, `section`, `html`, `swiper`, `subscription`, `content`, and all others. Type-specific properties are documented on each component's own page.

## Basic Example

```json
{
    "type": "html",
    "template": "headline",
    "id": "page-title",
    "class": "text-primary",
    "content": [{ "type": "html", "tag": "h1", "text": "Latest News" }]
}
```

This renders an `html` component using the `headline` template, assigns the element `id="page-title"` and CSS class `text-primary`. The `template` value is also set as an HTML attribute (`template="headline"`) so CSS selectors like `html-component[template="headline"]` can target it.

## Configuration

All components inherit Base configuration. These properties apply to every component type.

| Property     | Type            | Default | Description                                                                                             |
| ------------ | --------------- | ------- | ------------------------------------------------------------------------------------------------------- |
| `type`       | string          | —       | **Required.** Identifies which component to render (e.g. `list`, `section`, `html`, `swiper`)           |
| `template`   | string          | —       | Template variant to use. Controls layout; also set as an HTML attribute for CSS targeting               |
| `id`         | string          | —       | Sets the HTML `id` attribute on the element. Also used as the tracking key. Supports conditional values |
| `class`      | string \| array | —       | CSS class(es) to assign. Accepts a string, an array of strings, or conditional values                   |
| `sticky`     | boolean         | `false` | Makes the element CSS-sticky                                                                            |
| `isLazy`     | boolean         | —       | When true, the component is only initialised when it enters the viewport                                |
| `skipSSR`    | boolean         | `false` | Skip server-side rendering for this component — renders only on the client                              |
| `attributes` | object          | —       | Custom HTML attributes — see Attributes below                                                           |
| `condition`  | object          | —       | Condition that must be true for the component to render — see Conditions                                |

### `class` with conditional values

The `class` property supports conditional values, making it possible to apply CSS classes based on runtime context:

```json
{
    "type": "html",
    "class": {
        "value": "highlight",
        "condition": {
            "value": "$context.issue.purchased",
            "operation": "EQUALS",
            "compareValue": "true"
        },
        "fallback": "locked"
    }
}
```

Multiple classes can be combined using an array, where each entry can be a plain string or a conditional value:

```json
{
    "type": "html",
    "class": [
        "base-card",
        {
            "value": "is-new",
            "condition": { "value": "$context.issue.isNew", "operation": "EQUALS", "compareValue": "true" }
        }
    ]
}
```

### `attributes`

The `attributes` property adds HTML attributes to the component element.

```json
{
    "type": "html",
    "attributes": {
        "aria": {
            "label": "Close dialog",
            "expanded": "false"
        },
        "data": {
            "tracking-id": "hero-banner"
        },
        "html": {
            "role": "button",
            "popover": "auto"
        }
    }
}
```

| Sub-property | Description                                                                           |
| ------------ | ------------------------------------------------------------------------------------- |
| `aria`       | Adds `aria-*` attributes. Keys are automatically prefixed with `aria-` if not already |
| `data`       | Adds `data-*` attributes. Keys are automatically prefixed with `data-` if not already |
| `html`       | Arbitrary HTML attributes (`role`, `popover`)                                         |

### `condition`

The `condition` property controls whether the component is rendered at all. When the condition evaluates to false, the component is completely removed from the DOM — it is not hidden with CSS, it is not mounted.

```json
{
    "type": "subscription",
    "condition": {
        "value": "$context.platform",
        "operation": "EQUALS_NOT",
        "compareValue": "WEB"
    }
}
```

For more details, see:
TODO: insert link to Conditions

## Advanced Features

### `isLazy`

Lazy components are not initialised until they scroll into view. This is useful for heavy below-the-fold components to improve initial load performance. The component renders ghost placeholders until it enters the viewport.

### `skipSSR`

When true, the component is completely skipped during server-side rendering. This is useful for components that depend on browser APIs or user-specific state that is not available on the server (e.g., ads or components that read from `localStorage`).

### Template targeting in CSS

The `template` value is set as both an Angular class binding and an HTML attribute. This lets you use attribute selectors in CSS:

```css
my-component[template='card'] {
    display: grid;
}
my-component[template='list-item'] {
    display: flex;
}
```

### Component types available

| Type              | Description                                                 |
| ----------------- | ----------------------------------------------------------- |
| `section`         | Wraps other components — primary layout container           |
| `list`            | Renders a repeated component for each item in a data source |
| `swiper`          | Horizontally scrollable list based on Swiper.js             |
| `html`            | Renders an HTML element with a given tag                    |
| `content`         | Displays a single catalog content item (article, issue)     |
| `publication`     | Displays a single publication                               |
| `subscription`    | Displays a subscription plan                                |
| `search-field`    | Text input for full-text search                             |
| `search-result`   | Displays a single search result                             |
| `login`           | Login form using Purple Entitlement                         |
| `dropdown`        | Dropdown select element                                     |
| `toggle`          | Toggle switch                                               |
| `switch`          | Conditional component switcher                              |
| `bookmark`        | Bookmark button for content                                 |
| `toolbar`         | Toolbar with action buttons                                 |
| `menu`            | Navigation menu from the Catalog API                        |
| `widget`          | Embeds an external widget                                   |
| `action-executor` | Runs actions on component init                              |
| `ad`              | Displays a single ad slot                                   |

## Testing Notes / Edge Cases

- `condition`**&#x20;false = not mounted**: A component with a false condition is fully removed from the DOM. Data sources inside it are not initialised. If you are checking whether a list loaded data, first confirm its `condition` is true.
- `class`**&#x20;conditional with no fallback**: If the condition is false and no `fallback` is set, the class is not applied and no error is thrown. The element will have no class at all from that entry.
- `id`**&#x20;uniqueness**: If multiple instances of the same component appear (e.g. inside a list), avoid setting a static `id` — it will produce duplicate HTML IDs.
- `template`**&#x20;attribute**: The `template` attribute is set as a string on the host element. CSS selectors using it are case-sensitive.

## Related Topics

- TODO: insert link to Using Components
- [Data Sources Overview](docId\:fuMBUaBWeON_OTO5wfevf)
- TODO: insert link to Context System
- TODO: insert link to views.json
