Bubble Card Module Editor schema documentation

June 16, 2026 · View on GitHub

This documentation covers all available options for creating editor schemas in Bubble Card modules. These schemas define the user interface presented to users when configuring your module.

image

Table of contents


Basic structure

A module editor schema is an array of objects, where each object represents a form field:

editor:
  - name: color
    label: "Color"
    selector:
      select:
        options:
          - label: "Red"
            value: "red"
          - label: "Blue"
            value: "blue"
  - name: icon_size
    label: "Icon Size"
    selector:
      number:
        min: 20
        max: 50
        unit_of_measurement: "px"

Accessing configuration values in your module code

When creating a Bubble Card module, you'll need to access the values configured by users through the editor. These values are available in your module's code through the this.config object.

Accessing configuration in JavaScript templates

In your module's code section, you can access the configured values using JavaScript template literals. The configuration values follow a specific structure:

this.config.module_id?.field_name

Where:

  • module_id is the ID of your module as defined in your module definition
  • field_name corresponds directly to the name property of the field in your editor schema
Example

If you have this editor schema:

editor:
  - name: color                # This becomes "color" in your code
    label: "Background Color"
    selector:
      ui_color: {}
  - name: size                 # This becomes "size" in your code
    label: "Icon Size"
    selector:
      number:
        min: 10
        max: 50
        unit_of_measurement: "px"
  - name: show_icon            # This becomes "show_icon" in your code
    label: "Show Icon"
    selector:
      boolean: {}

Then in your module's code section, you would access these values like this:

.bubble-icon-container {
  /* Access the "color" field */
  background: var(--${this.config.module_id?.color}-color) !important;
  
  /* Access the "size" field with a default value if undefined */
  --mdc-icon-size: ${this.config.module_id?.size || 24}px;
  
  /* Access the "show_icon" boolean field */
  display: ${this.config.module_id?.show_icon ? 'flex' : 'none'};
}

Remember to replace module_id with your actual module ID in your code.

Tips for working with configuration values

  • Use optional chaining: Always use the optional chaining operator (?.) when accessing nested configuration properties to prevent errors if the configuration is missing.

  • Provide default values if possible: In some cases, use the OR operator (||) to supply default values in case the configuration value is undefined.

Example: Complete module with editor and code

Complete module example

Here's a complete example of a module definition showing both the editor schema and how to use the values in the code:

icon_container_color:
  name: 'Example: Customize the icon container color'
  version: v1.1
  creator: Clooos
  link: https://github.com/Clooos/Bubble-Card/discussions/1231
  unsupported:
    - horizontal-buttons-stack
    - separator
  description: |
    A list of predefined colors to customize the icon container color.
    Configure this module via the editor or in YAML, for example:
    <br><br>
    <code-block><pre>
    icon_container_color: 
        color: light-blue
    </pre></code-block>
  code: |
    .bubble-icon-container {
      opacity: 1 !important;
      background: var(--${this.config.icon_container_color?.color}-color) !important;
    }
  editor:
    - name: color
      label: Color
      selector:
        ui_color:
          include_none: true

Field properties

Every field in your editor schema can have these common properties:

PropertyTypeDescription
namestringRequired. The key used to store the value in the module configuration
labelstringThe displayed name for the field
requiredbooleanWhether the field is required
disabledbooleanWhether the field is disabled
defaultanyDefault value if no value is provided

Field types

You can define fields using either the legacy type syntax or the modern selector syntax.

Important

Not all selector types have been tested with Bubble Card modules. Some selectors might not work correctly or might not be fully compatible. If you encounter an issue, please report it here.

Selector-based fields

Selector-based fields provide rich UI controls. Simply use the selector property with one of the following selector types:

Text input selectors

- name: title
  label: "Title"
  selector:
    text: {}
Options
OptionTypeDescription
multilinebooleanEnable multiline text input
typestringHTML input type (e.g., "email", "url", "password")
autocompletestringBrowser autocomplete attribute
prefixstringText to display before the input
suffixstringText to display after the input

Number selector

- name: opacity
  label: "Opacity"
  selector:
    number:
      min: 0
      max: 100
      step: 5
      unit_of_measurement: "%"
Options
OptionTypeDescription
minnumberMinimum value
maxnumberMaximum value
stepnumberStep value
modestringDisplay mode: "box" or "slider" (default: "slider")
unit_of_measurementstringUnit label
min_stepnumberMinimum step value

Boolean selector

- name: show_icon
  label: "Show Icon"
  selector:
    boolean: {}

No additional option for this selector.

Select selector

- name: theme
  label: "Theme"
  selector:
    select:
      options:
        - label: "Light"
          value: "light"
        - label: "Dark"
          value: "dark"
        - label: "Auto"
          value: "auto"
      multiple: false
      custom_value: false
      mode: "dropdown"
Options
OptionTypeDescription
optionsarrayList of options with label/value pairs, or simple string arrays
translation_keystringTranslation key for the options
multiplebooleanAllow multiple selection
custom_valuebooleanAllow custom values
modestringDisplay mode: "dropdown" or "list"

Color selector

- name: background_color
  label: "Background Color"
  selector:
    ui_color: {}
Options
OptionTypeDescription
default_colorstringDefault color to use if no color is selected
include_nonebooleanInclude an option to select no color
include_statebooleanInclude a color based on the entity state

Icon selector

- name: custom_icon
  label: "Custom Icon"
  selector:
    icon: {}

No additional option for this selector.

Condition selector

- name: conditions
  label: "Conditions"
  selector:
    condition: {}

The condition selector allows you to define complex conditions based on entity states, numeric values, time, and more. This is especially powerful for creating conditional UI elements or behaviors.

Using conditions in your module code

In your JavaScript code, you can use the checkConditionsMet function to evaluate conditions at runtime:

// Example of checking if conditions are met
if (!badgeConfig?.condition || (badgeConfig?.condition && checkConditionsMet([].concat(badgeConfig.condition), hass))) {
  // The condition is met or there is no condition defined
  // Show or activate your component here
}

Here's a simple example:

# Module configuration example
my_module:
  element_to_show:
    condition:
      - condition: state
        entity_id: light.living_room
        state: 'on'
      - condition: numeric_state
        entity_id: sensor.temperature
        above: 20
// In your module code
const elementConfig = this.config.my_module?.element_to_show;
if (!elementConfig?.condition || checkConditionsMet([].concat(elementConfig.condition), hass)) {
  // Show element when living room light is ON and temperature is above 20
}

No additional selector options.

Entity selector

- name: target_entity
  label: "Target Entity"
  selector:
    entity:
      filter:
        domain: light
Options
OptionTypeDescription
filter.domainstring | string[]Filter by entity domain(s)
filter.device_classstring | string[]Filter by device class(es)
filter.integrationstringFilter by integration
filter.supported_featuresnumber | number[]Filter by supported features flags
include_entitiesstring[]List of entities to include
exclude_entitiesstring[]List of entities to exclude
multiplebooleanAllow multiple selection

Device selector

- name: device
  label: "Device"
  selector:
    device:
      filter:
        integration: zwave
Options
OptionTypeDescription
filter.integrationstring | string[]Filter by integration(s)
filter.manufacturerstring | string[]Filter by manufacturer(s)
filter.modelstring | string[]Filter by model(s)
entity.domainstring | string[]Filter by entity domain(s)
entity.device_classstring | string[]Filter by entity device class(es)
multiplebooleanAllow multiple selection

Area selector

- name: area
  label: "Area"
  selector:
    area: {}
Options
OptionTypeDescription
entity.domainstring | string[]Filter by entities in area with domain(s)
entity.device_classstring | string[]Filter by entities in area with device class(es)
device.integrationstring | string[]Filter by devices in area with integration(s)
device.manufacturerstring | string[]Filter by devices in area with manufacturer(s)
device.modelstring | string[]Filter by devices in area with model(s)
multiplebooleanAllow multiple selection

Theme selector

- name: card_theme
  label: "Card Theme"
  selector:
    theme: {}
Options
OptionTypeDescription
include_defaultbooleanInclude the default theme

Action selector

- name: tap_action
  label: "Tap Action"
  selector:
    action: {}
Options
OptionTypeDescription
actionsstring[]List of allowed actions (e.g., ["more-info", "toggle", "call-service", "navigate", "url", "none"])

Time selector

- name: start_time
  label: "Start Time"
  selector:
    time: {}

No additional option for this selector.

Date selector

- name: event_date
  label: "Event Date"
  selector:
    date: {}
Options
OptionTypeDescription
minstringMinimum date in ISO format (YYYY-MM-DD)
maxstringMaximum date in ISO format (YYYY-MM-DD)

Datetime selector

- name: event_datetime
  label: "Event Date and Time"
  selector:
    datetime: {}
Options
OptionTypeDescription
minstringMinimum datetime in ISO format
maxstringMaximum datetime in ISO format

Media selector

- name: media
  label: "Media"
  selector:
    media: {}
Options
OptionTypeDescription
filter_media_sourcebooleanFilter media sources
filter_local_mediabooleanFilter local media

Attribute selector

This selector works only if combined to an entity selector at the same level. Inside an object selector item, if the entity field next to it is empty the attribute list falls back to the card's configured entity, matching the common runtime pattern where items inherit the card entity.

- name: attribute
  label: "Attribute"
  selector:
    attribute: {}
Options
OptionTypeDescription
entity_idstringRequired: Entity ID to select attribute from
hide_attributesstring[]List of attributes to exclude

State selector

This selector works only if combined to an entity selector at the same level.

- name: target_state
  label: "Target State"
  selector:
    state: {}
Options
OptionTypeDescription
entity_idstringRequired: Entity ID to select state from
attributestringSelect from entity attribute rather than state

Target selector

- name: target
  label: "Target"
  selector:
    target:
      entity:
        domain: light
Options
OptionTypeDescription
entityobjectEntity filters (same as entity selector)
deviceobjectDevice filters (same as device selector)
areaobjectArea filters (same as area selector)

Config entry selector

- name: config_entry
  label: "Integration"
  selector:
    config_entry:
      domain: zwave_js
Options
OptionTypeDescription
domainstringFilter by domain

Addon selector

- name: addon
  label: "Add-on"
  selector:
    addon: {}
Options
OptionTypeDescription
namestringFilter by add-on name

Location selector

- name: location
  label: "Location"
  selector:
    location:
      radius: true
      icon: "mdi:home"
Options
OptionTypeDescription
radiusbooleanAllow setting a radius around the location
iconstringIcon to show on the map

Object selector

The object selector lets users enter structured objects defined by a set of sub-fields. Each sub-field uses its own selector (e.g., text, number, icon). It can capture a single object or a list when multiple is true. Use label_field and description_field to control the label and secondary text displayed for each item. The output is an object or a list of objects.

When multiple is true, each item row has a drag handle to reorder the list and a duplicate button that inserts a deep copy of the item right below it.

- name: main_item
  label: "Main item"
  selector:
    object:
      fields:
        name:
          label: "Name"
          selector:
            text: {}
        icon:
          label: "Icon"
          selector:
            icon: {}
      label_field: name
      description_field: icon
      multiple: true

Fields that share a group are rendered together inside a collapsible section (the group name becomes the section title, group_icon its optional icon). The stored configuration stays flat — grouping only affects the editor UI, so adding groups to an existing module is fully backward compatible. Fields without a group render at the top level as usual:

- name: items
  label: "Items"
  selector:
    object:
      fields:
        name:
          label: "Name"
          selector:
            text: {}
        background_color:
          label: "Background color"
          group: "Appearance"
          group_icon: "mdi:palette"
          selector:
            ui_color: {}
        text_color:
          label: "Text color"
          group: "Appearance"
          selector:
            ui_color: {}
      multiple: true
Options
OptionTypeDescription
fieldsobjectMap of field keys to field schemas. Each field supports a label, a description, a nested selector (any selector type), and an optional group. Keys starting with __ or bc_group_ are reserved for the editor's internal UI state.
fields.*.groupstringRenders the field inside a collapsible section with this title. Fields sharing the same group end up in the same section. UI-only: the stored value stays flat.
fields.*.group_iconstringOptional icon (Material Design Icons) for the field's group section.
fields.*.visible_ifstringJS expression evaluated against the item's current data as item, the live hass object and the card's config as card (e.g. item.target === 'card'). hass and card may be undefined (early renders, dialogs the card config can't be found from) — guard them (card && card.entity). The field only renders while the expression is truthy; sections whose fields are all hidden disappear. Re-evaluated live on every change. Broken expressions fail open (field stays visible).
fields.*.warn_ifstringJS expression with the same item / hass / card arguments as visible_if, including the same need to guard hass and card. While truthy, the field shows warn_text — e.g. warn about a missing entity (item.entity && hass && !hass.states[item.entity]) or an option that has no effect without another one. Broken expressions fail silent (no warning).
fields.*.warn_textstringThe warning message displayed while warn_if is truthy, rendered as an amber warning alert above the field.
fields.*.defaultanyFor text-based sub-fields, the declared default is shown as the input's placeholder so users can see what applies when the field is left empty. Single-select dropdowns render the default as the selected value while the key is unset (display only — picking the default or clearing the dropdown stores nothing, so unset and default stay the same config).
fields.*.variant_ofstringMarks this field as an alternative representation ("variant") of the named base field — e.g. a state→color map or a JS expression next to a static color. The form collapses the family into one mode dropdown (the base mode — labelled Static unless the base field sets its own variant — plus each variant's variant label) and only the active variant's input. The dropdown is UI-only: stored values keep their original keys, and opening an existing config selects whichever variant already has data. If an inactive variant also has data, a helper line warns that the module's priority rules decide which wins. The family renders inside a light visual cluster (thin left rail), so the mode dropdown and its value field read as one unit.
fields.*.variantstringDisplay label of this variant in the family's mode dropdown (e.g. "State map", "JS"). Defaults to the field key. On the base field it instead renames the base mode's dropdown label (default "Static") — e.g. variant: Single next to a "Multiple" variant.
fields.*.cluster_ofstringRenders this field inside the named base field's visual cluster (the same thin-left-rail box variant families use) instead of as a standalone row — purely visual grouping for fields that form one logical unit, e.g. a mode select plus its parameters. Rule of thumb: variants swap which key is stored, clusters only group real fields visually. Nothing is synthetic or swapped: every member is a real stored field and keeps its own visible_if. A hidden base hides the whole cluster; while no member is visible the base renders flat (no rail). Composes with variants — members append after the variant rows.
label_fieldstringProperty key used as the item label in the UI (useful when multiple is true).
description_fieldstring | listProperty key used as an optional item description in the UI. A list of keys falls back to the first one with a value; list values render comma-separated.
multiplebooleanAllow entering a list of objects. If true, the resulting value is a list.

Backup selector

- name: backup
  label: "Backup"
  selector:
    backup:
      integration: google_assistant
Options
OptionTypeDescription
integrationstringFilter backups by integration

Assistance selector

- name: assistance_pipeline
  label: "Assistance Pipeline"
  selector:
    assistance: {}

No additional option for this selector.

Label selector

- name: labels
  label: "Labels"
  selector:
    label:
      multiple: true
Options
OptionTypeDescription
multiplebooleanAllow multiple selection

Language selector

- name: language
  label: "Language"
  selector:
    language: {}

No additional option for this selector.

Schedule selector

- name: schedule
  label: "Schedule"
  selector:
    schedule: {}

No additional option for this selector.

Template selector

- name: template
  label: "Template"
  selector:
    template: {}

No additional option for this selector.

File selector

- name: config_file
  label: "Configuration File"
  selector:
    file:
      accept: ".yaml,.json"
Options
OptionTypeDescription
acceptstringComma-separated list of acceptable file extensions

QR code selector

- name: qr_data
  label: "QR Code Data"
  selector:
    qr_code: {}

No additional option for this selector.

Conversation agent selector

- name: agent
  label: "Conversation Agent"
  selector:
    conversation_agent: {}

No additional option for this selector.

Duration selector

- name: timeout
  label: "Timeout"
  selector:
    duration:
      enable_day: false
Options
OptionTypeDescription
enable_daybooleanInclude days in the duration selector

Dashboard selector

- name: dashboard
  label: "Dashboard"
  selector:
    dashboard:
      include_dashboards: ["lovelace"]
Options
OptionTypeDescription
include_dashboardsstring[]List of dashboards to include

Floor selector

- name: floor
  label: "Floor"
  selector:
    floor: {}

No additional option for this selector.

Legacy type-based fields

While selector-based fields are recommended, you can also use the legacy type syntax:

String field

- name: title
  label: "Title"
  type: string

Integer field

- name: count
  label: "Count"
  type: integer
  valueMin: 0
  valueMax: 100

Float field

- name: opacity
  label: "Opacity"
  type: float

Boolean field

- name: enabled
  label: "Enabled"
  type: boolean

Select field

- name: mode
  label: "Mode"
  type: select
  options:
    - ["auto", "Automatic"]
    - ["manual", "Manual"]

Multi-select field

- name: features
  label: "Features"
  type: multi_select
  options:
    - ["animations", "Animations"]
    - ["colors", "Custom Colors"]
    - ["icons", "Custom Icons"]

Advanced structure

Grid layout

You can organize fields in a grid layout:

- type: grid
  name: appearance
  schema:
    - name: color
      label: "Color"
      selector:
        select:
          options:
            - label: "Red"
              value: "red"
            - label: "Blue"
              value: "blue"
    - name: size
      label: "Size"
      selector:
        number:
          min: 10
          max: 100
Options
OptionTypeDescription
column_min_widthstringMinimum column width (CSS value)
schemaarrayFields in the grid

Expandable sections

You can create collapsible sections:

- type: expandable
  name: advanced_settings
  title: "Advanced Settings"
  icon: "mdi:tune"
  expanded: false
  schema:
    - name: animation_speed
      label: "Animation Speed"
      selector:
        number:
          min: 1
          max: 10
Options
OptionTypeDescription
titlestringSection title
iconstringSection icon (Material Design Icons)
expandedbooleanInitially expanded
schemaarrayFields in the section

Best practices

  1. Keep it simple: Only include fields that users actually need to configure
  2. Use clear labels: Make field labels descriptive but concise
  3. Provide defaults: Set sensible default values where possible
  4. Group related fields: Use grid or expandable sections to organize complex options
  5. Add descriptions: Use the description property to explain complex options
  6. Test your UI: Ensure your form is user-friendly before sharing

Example: Complete module editor schema

editor:
  - name: color_mode
    label: "Color Mode"
    selector:
      select:
        options:
          - label: "Custom Color"
            value: "custom"
          - label: "Theme Color"
            value: "theme"
  - name: custom_color
    label: "Custom Color"
    selector:
      ui_color: {}
  - type: expandable
    title: "Advanced Settings"
    expanded: false
    schema:
      - name: animation
        label: "Animation"
        selector:
          boolean: {}
      - name: animation_speed
        label: "Animation Speed"
        selector:
          number:
            min: 1
            max: 10
            step: 0.1
      - name: opacity
        label: "Opacity"
        selector:
          number:
            min: 0
            max: 100
            unit_of_measurement: "%"

This schema creates a form with a select dropdown for color mode, a color picker, and an expandable section with animation controls. This is the example shown in the screenshot at the top of this documentation.

References

This documentation is based on Home Assistant's form schemas: