v2.13.0

Customize components

Learn how to customize Bitrix24 UI components with the Tailwind Variants API for advanced, flexible, and maintainable styling.

Tailwind Variants

Bitrix24 UI components are styled using the Tailwind Variants API, which provides a powerful way to create variants and manage component styles.

Slots

Components can have multiple slots, each representing a distinct HTML element or section within the component. These slots allow for flexible content insertion and styling.

Let's take the Card component as an example which has multiple slots:

export default {
  slots: {
    root: 'bg-(--ui-color-design-filled-bg) border border-(--ui-color-design-filled-stroke) border-(length:--ui-design-filled-stroke-weight) text-(--ui-color-design-filled-content)',
    header: 'p-[24px] sm:px-[22px] sm:py-[15px]',
    body: 'p-[24px] sm:px-[22px] sm:py-[15px]',
    footer: 'p-[24px] sm:px-[22px] sm:py-[15px]'
  }
}

Some components don't have slots, they are just composed of a single root element. In this case, the theme only defines the base slot like the Container component for example:

export default {
  base: 'w-full max-w-(--b24ui-container-width) mx-auto px-4 sm:px-6 lg:px-8'
}
Components without slots don't have a b24ui prop, only the class prop is available to override styles.

Variants

Components support variants, which allow you to dynamically adjust the styles of different slots based on component props.

For example, the Avatar component uses a size variant to control its appearance:

src/theme/avatar.ts
export default {
  slots: {
    root: 'air-secondary-accent inline-flex items-center justify-center shrink-0 select-none rounded-full align-middle bg-(--ui-color-base-8) ring ring-(--ui-color-base-7)',
    image: 'h-full w-full rounded-[inherit] object-cover'
  },
  variants: {
    size: {
      sm: {
        root: 'size-[28px] text-(length:--ui-font-size-xs)/(--ui-font-line-height-reset)'
      },
      md: {
        root: 'size-[32px] text-(length:--ui-font-size-sm)/(--ui-font-line-height-reset)'
      },
      lg: {
        root: 'size-[42px] text-(length:--ui-font-size-2xl)/(--ui-font-line-height-reset)'
      }
    }
  },
  defaultVariants: {
    size: 'md'
  }
}

This way, the size prop will apply the corresponding styles to the root slot:

<template>
  <B24Avatar src="https://github.com/bitrix24.png" size="lg" />
</template>

Default Variants

The defaultVariants property sets the default value for each variant when no prop is passed.

For example, the Avatar component has its default size set to md:

src/theme/avatar.ts
export default {
  slots: {
    root: 'air-secondary-accent inline-flex items-center justify-center shrink-0 select-none rounded-full align-middle bg-(--ui-color-base-8) ring ring-(--ui-color-base-7)',
    image: 'h-full w-full rounded-[inherit] object-cover'
  },
  variants: {
    size: {
      sm: {
        root: 'size-[28px] text-(length:--ui-font-size-xs)/(--ui-font-line-height-reset)'
      },
      md: {
        root: 'size-[32px] text-(length:--ui-font-size-sm)/(--ui-font-line-height-reset)'
      },
      lg: {
        root: 'size-[42px] text-(length:--ui-font-size-2xl)/(--ui-font-line-height-reset)'
      }
    }
  },
  defaultVariants: {
    size: 'md'
  }
}

Compound Variants

Some components use the compoundVariants property to apply classes when multiple variant conditions are met at the same time.

For example, the Alert component uses the compoundVariants property to apply classes for a specific color and inverted combination:

src/theme/button.ts
export default {
  slots: {
    root: [
      'relative overflow-hidden w-full flex',
      'text-(--b24ui-color)',
      'bg-(--b24ui-background)',
      'border-(--b24ui-border-color) border-(length:--b24ui-border-width)',
      'rounded-(--ui-border-radius-md)'
    ].join(' ')
  },
  variants: {
    color: {
      'air-primary': { root: 'style-filled' },
      'air-primary-success': { root: 'style-filled-success' }
    },
    inverted: {
      true: '',
      false: ''
    }
  },
  compoundVariants: [
    {
      inverted: true,
      color: 'air-primary',
      class: {
        root: 'style-filled-inverted'
      }
    },
    {
      inverted: true,
      color: 'air-primary-success',
      class: {
        root: 'style-filled-success-inverted'
      }
    }
  ],
  defaultVariants: {
    color: 'primary',
    variant: 'solid'
  }
}

Customize theme

You have multiple ways to customize the appearance of Bitrix24 UI components, you can do it for all components at once or on a per-component basis.

Tailwind Variants uses tailwind-merge under the hood to merge classes so you don't have to worry about conflicting classes.
You can explore the theme for each component in two ways:
  • Check the Theme section in the documentation of each individual component.
  • Browse the source code directly in the GitHub repository at src/theme.

Global config

Override the theme of a component for every instance in your app from app.config.ts, using the same structure as the theme object itself.

Override the theme of a component for every instance in your app from vite.config.ts, using the same structure as the theme object itself.

You can customize the slots, variants, compoundVariants and defaultVariants of any component:

app/app.config.ts
export default defineAppConfig({
  b24ui: {
    button: {
      slots: {
        base: 'font-bold'
      },
      defaultVariants: {
        size: 'lg'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'

export default defineConfig({
  plugins: [
    vue(),
    bitrix24UIPluginVite({
      b24ui: {
        button: {
          slots: {
            base: 'font-bold'
          },
          defaultVariants: {
            size: 'lg'
          }
        }
      }
    })
  ]
})

By default these classes are merged onto the component's own. Set a slot to a function to replace them instead — it receives the slot's own classes so you can keep part of them:

app/app.config.ts
export default defineAppConfig({
  b24ui: {
    button: {
      slots: {
        label: () => 'text-base font-bold'
      }
    }
  }
})
bitrix24UIPluginVite({
  b24ui: {
    button: {
      slots: {
        label: () => 'text-base font-bold'
      }
    }
  }
})
Where you write the replacer changes what it replaces.In global config it takes the place of the slot's own classes, so variants and compoundVariants still merge on top — a replaced base still gets its size and colour classes.In the b24ui and class props it runs after variants have resolved, so it replaces everything, variants included.
To remove the default classes from all components at once, use the theme.unstyled option instead.

Theme component

The Theme component overrides slots and prop defaults for every descendant, without touching the rest of the app. It takes priority over global config, and the b24ui and class props still win over it.

Its slots accept the same (defaults) => classes function form. It resolves at the same point as the b24ui prop, so a replacer written there replaces the resolved classes, variants included.

<template>
  <B24Theme
    :b24ui="{
      button: {
        base: 'rounded-full'
      }
    }"
  >
    <div class="flex items-center gap-2">
      <B24Button label="Button" color="air-primary-success" />
      <B24Button label="Button" color="air-secondary-accent-1" />
      <B24Button label="Button" color="air-boost" />
    </div>
  </B24Theme>
</template>

b24ui prop

You can override a component's slots using the b24ui prop. This takes priority over both global config and resolved variants.

<template>
  <B24Button
    use-dropdown
    size="md"
    color="air-primary"
    :b24ui="{
      trailingIcon: 'rotate-90 size-10'
    }"
  >
    Button
  </B24Button>
</template>
In this example, the trailingIcon slot is overwritten with size-10 even though the md size variant would apply a size-(--ui-btn-icon-size) class to it.

A slot value can also be a function to replace its classes instead of merging them. Here it runs after variants have resolved, so it receives the slot's fully resolved class string — and replaces all of it. In global config the same form replaces only the slot's own classes; see the note there.

<template>
  <B24Button :b24ui="{ label: () => 'text-base font-bold' }" label="Button" />
</template>
To remove the default classes from all components at once, use the theme.unstyled option.

class prop

Use the class prop to override the classes of the root or base slot. This takes priority over both global config and resolved variants.

<template>
  <B24Button class="font-bold rounded-full">Button</B24Button>
</template>
In this example, the font-bold class will override the default font-medium class on this button.