combat-ui / core-opendxp-bundle
OpenDXP wrapper bundle for Combat UI: curated, configurable areabricks built on the Combat UI Core Symfony bundle
Package info
github.com/Combat-Marketing/combat-ui-opendxp-bundle
Type:opendxp-bundle
pkg:composer/combat-ui/core-opendxp-bundle
Requires
- php: ~8.4.0 || ~8.5.0
- combat-ui/core-bundle: ^0.6.3
- open-dxp/opendxp: ^1.0
Requires (Dev)
- codeception/codeception: ^5.3.5
- codeception/module-asserts: ^3.2
- codeception/module-symfony: ^3.8
- codeception/stub: ^4.3
- phpstan/phpstan: 2.1.33
- phpstan/phpstan-symfony: ^2.0.9
- phpunit/phpunit: ^10.5
README
OpenDXP wrapper bundle for Combat UI. It ships a curated set of configurable
areabricks built on top of the combat-ui/core-bundle Symfony bundle, so editors can compose pages
from Combat UI sections and components directly in the OpenDXP document editor.
Requirements
- PHP 8.4 or 8.5
- OpenDXP ^1.0
combat-ui/core-bundle(installed automatically as a dependency)
Installation
composer require combat-ui/core-opendxp-bundle
The bundle is discovered through its composer type (opendxp-bundle) and registers its dependencies
(CombatUICoreBundle, WebpackEncoreBundle) itself. Enable and install it from the OpenDXP bundle
manager, or via CLI:
bin/console opendxp:bundle:enable CombatUIOpenDxpBundle bin/console opendxp:bundle:install CombatUIOpenDxpBundle bin/console assets:install
assets:install publishes the prebuilt Combat UI Encore build to public/bundles/combatuicore/build;
the core bundle wires the combat_ui Encore build there automatically.
Layout integration
Load the Combat UI assets once in your document layout and expose an areablock for the bricks:
<!DOCTYPE html> <html lang="{{ document.getProperty('language') }}"> <head> {{ cui_assets() }} {{ cui_theme_tokens() }} </head> <body> <main> {{ opendxp_areablock('content', { allowed: [ 'cui-hero', 'cui-page-intro', 'cui-cta', 'cui-content', 'cui-card-grid', 'cui-feature-grid', 'cui-stats', 'cui-logo-strip', 'cui-team', 'cui-events', 'cui-contact', 'cui-accordion', 'cui-tabs', 'cui-carousel', 'cui-media', 'cui-map', ] }) }} </main> </body> </html>
The bricks are full-width bands that bring their own .cui-container wrappers, so place the areablock
in a full-bleed region of the layout rather than inside another container.
Theme editor
The bundle adds a Combat UI Theme entry to the admin Extras menu (users need the
combat_ui_theme permission, registered on install). The panel lists every Combat UI design token,
grouped as in the framework's tokens.css — typography, colors, spacing, surfaces, and so on — with
the framework default shown as placeholder. Color tokens take a separate light and dark value;
the dark value feeds both the prefers-color-scheme: dark media query and the explicit
[data-theme="dark"] pin, exactly mirroring the framework's selector structure.
Saved overrides are stored in the OpenDXP settings store (scope combat_ui) and served as a
generated stylesheet from /cui/theme.css. Add {{ cui_theme_tokens() }} to your layout after
{{ cui_assets() }} — it renders a <link> with a content hash (long-lived immutable caching) and
renders nothing while no token is overridden. Because tokens are CSS custom properties, no rebuild
of the framework CSS is involved; the override stylesheet simply wins by cascade order.
The token schema (groups, descriptions, defaults) is read from the blocks.json manifest shipped
with the core bundle's prebuilt assets, so the editor stays in sync with the framework version you
have installed.
Bricks
All bricks live in the Combat UI namespace (src/Document/Areabrick) with templates under
templates/areas/<brick-id>/view.html.twig. Structural options (variant, tone, spacing, width, …)
are configured through the brick dialog (pencil icon); content is edited inline where possible.
| Brick | ID | Dialog options | Inline editables |
|---|---|---|---|
| Hero | cui-hero |
variant (split/background/overlay/text), title tag, alignment, width, media position, eyebrow, title, lead, background image | WYSIWYG body, media image, primary/secondary links |
| Page intro | cui-page-intro |
variant (landing/case/vacancy/campaign/full-bleed), tone, alignment, title tag, eyebrow, title, lead, meta lines | WYSIWYG body, primary/secondary links |
| Call to action | cui-cta |
variant (simple/split/full-bleed/sticky), tone, title tag, section spacing, eyebrow, title, lead | WYSIWYG body, primary/secondary links |
| Rich text | cui-content |
section spacing, tone, container width | WYSIWYG prose |
| Card grid | cui-card-grid |
columns, gap, card style (featured/compact/flat/borderless), category filter chips + label, section spacing, tone, container width | per card: image, category, title, excerpt, link |
| Feature grid | cui-feature-grid |
columns, gap, alignment, section options | per feature: icon, title, copy |
| Statistics | cui-stats |
columns, gap, alignment, section options | per stat: value, label |
| Logo strip | cui-logo-strip |
section options | per logo: image, name fallback |
| Team | cui-team |
card style (flat/borderless/leadership), photo shape, alignment, columns, gap, section options | per member: photo, name, role, department, bio, email |
| Events | cui-events |
columns, card style (featured/compact), section options | per event: date, title, category, time, location, status, excerpt, link |
| Contact cards | cui-contact |
columns, card style (flat/borderless/inverse), alignment, section options | per card: eyebrow, title, copy, email, phone, link |
| Accordion | cui-accordion |
variant (ghost), open first item | per item: summary, WYSIWYG body |
| Tabs | cui-tabs |
— | per tab: label, WYSIWYG content |
| Carousel | cui-carousel |
autoplay, interval, transition, looping, arrows/pagination, width | per slide: image, caption |
| Media | cui-media |
style (figure / full-width / banner / media card / overlay card), aspect ratio, optional video, media link (banner: whole image, card: media region), eyebrow, title, container width, alignment, row orientation, reversed order (content before media), card chrome (flat/borderless), scrim, corner radius | image; caption (figure); WYSIWYG body + links (card/overlay) |
| Map | cui-map |
center, zoom, clustering, fit bounds, scroll-wheel zoom | per marker: label, latitude, longitude |
Notes
- The card/section bricks (card grid, feature grid, statistics, logo strip, team, events, contact,
media) render through the curated
@CombatUICorecomponent templates and therefore need acombat-ui/core-bundlerelease that ships them (newer than 0.6.1.2). Until that release, the local test suite runs against a siblingcombat-ui-bundlecheckout. - Brick auto-registration relies on OpenDXP's default
documents.areas.autoload: true; if you disabled it, tag the brick classes withopendxp.area.brickyourself. - Image editables render the original asset by default. Override a brick template in your app
(
templates/bundles/CombatUIOpenDxpBundle/areas/<brick-id>/view.html.twig) to apply thumbnail configurations. - Brand-wide component defaults (e.g. default button variant) can be set via the core bundle's
combat_ui_core.component_defaultsconfiguration.
Development
Run the Codeception unit suite:
composer install composer test # codecept run Unit
The suite covers the bundle contract (nice name, dependent bundles, container extension), every
brick's AsAreabrick id, template location and dialog-box editables, and renders each brick view
template through the real Combat UI core templates — with the opendxp_* editables stubbed — in
both frontend and editmode.
License
GPL-3.0-or-later — see LICENSE.