friendsofvictoire/button-widget
Provides a configurable button widget for the Victoire CMS page builder. Editors insert call-to-action buttons and set labels, links, styles, and target options through a visual form, so no template edits or custom markup are required.
This bundle is a single-purpose Victoire CMS widget: it adds a "Button" entry to Victoire's widget picker so editors can drop a styled CTA (label, link, target, maybe style variant) into any widget slot. It is not a standalone button library — it has no meaning outside a Symfony application already running Victoire. Confirm that first: if bin/console debug:router | grep victoire returns nothing, installing this bundle will get you nowhere.
Minimal sequence:
composer require friendsofvictoire/button-widget
Then register the bundle (FriendsOfVictoire\WidgetButtonBundle\FriendsOfVictoireWidgetButtonBundle) in app/AppKernel.php (Symfony 2/3, which is what Victoire's era implies) or config/bundles.php:
bin/console assets:install --symlink
bin/console cache:clear
Where to look first, in this order:
vendor/friendsofvictoire/button-widget/Widget/ — the widget class. This file is the package: its @Widget annotation (name, icon, slot defaults) and its properties define everything an editor can configure.Resources/views/Widget/*.html.twig — the entire public rendering surface. Read this before you promise a designer anything.Resources/config/ — form type and service wiring, if the widget exposes one.First use case: open a page in the Victoire editor, add a widget to a slot, pick "Button", fill in the label and pick a link through Victoire's link picker, save, view the page. That round-trip is the whole integration test — if it works, the bundle is wired correctly (assets, cache, annotation discovery, template).
Editor-driven authoring. The normal workflow is 100% in the Victoire UI: editors create buttons per page slot, business entities (pages/templates) expose the widget's fields as part of their form. Treat the widget's properties as content schema — changing them later means migrating existing business entities.
Template override, not vendor edits. Copy the widget template into your app's override path and own it:
app/Resources/FriendsOfVictoireWidgetButtonBundle/views/Widget/button.html.twig
# Symfony 4/5: templates/bundles/FriendsOfVictoireWidgetButtonBundle/
This is where you attach your design system classes (btn btn--primary), add rel="noopener" logic, or wrap the anchor in a <span> for icon layout. Keep the block structure intact so Victoire's slot rendering and any inline-edit attributes survive.
Reuse via Victoire templates. Rather than re-configuring the same button on every page, place it once in a Victoire template business entity and inherit. This is the Victoire-native equivalent of a component and avoids duplicating link configuration across pages.
Link handling. The widget typically stores a Victoire Link entity rather than a raw URL string, so render defensively:
{% if widget.link is defined and widget.link %}
<a href="{{ widget.link.url }}" target="{{ widget.link.target|default('_self') }}"
{% if widget.link.target == '_blank' %}rel="noopener"{% endif %}>
{{ widget.label }}
</a>
{% endif %}
If you need the raw URL programmatically (sitemap, analytics, nav mirroring), read it from the business entity after render rather than re-parsing markup.
Styling as a field, not a fork. If the widget exposes a class/variant property, map it through a whitelist in the template ({% set variant = widget.style in ['primary','ghost'] ? widget.style : 'primary' %}) instead of letting free-text classes through — it keeps the CSS contract with your theme honest.
Extending fields. To add an icon picker or analytics ID, subclass the widget and override its form type + template in your own bundle, or copy the bundle in as src/Widget/Button and drop the composer dependency. Given the package size, forking is often the pragmatic answer; a subclass is cleaner only if you plan to keep the upstream package updated.
@Widget\Widget, no PHP 8 attribute support). Pin the version explicitly in composer.json, and expect fatal errors on modern PHP before anything else. Check the widget class for @ annotations before assuming the bundle will even load.vendor/ (Victoire registers widget directories via a compiler pass — if you installed with --no-scripts or moved the bundle, discovery breaks silently).assets:install --symlink and check web/bundles/friendsofvictoirewidgetbutton/ exists.href or throw on widget.link.url. Guard it in the template as shown above; this is the most common runtime error with link-based widgets.vendor/. Composer update silently reverts it, and the fix lands in a file nobody reviews. Override the template; fork only if you need entity changes.{{ dump(widget) }} in the widget template is faster than reading Victoire's slot-resolution code. For discovery issues, inspect the container for the widget tag (bin/console debug:container --tag=<victoire widget tag>) — the tag name is visible in the bundle's compiler pass or Victoire core.Resources/public CSS/JS (published asset override in your own bundle). Those three cover virtually every customization this widget supports.How can I help you explore Laravel packages today?