friendsofvictoire/tab-widget
A Laravel package that provides a reusable tabbed widget for grouping content into switchable panels. Define tabs and their contents in PHP, then render a clean tabbed interface in dashboards or admin pages to keep dense information organized and easy to navigate.
Framework reality check first: friendsofvictoire/tab-widget is a Symfony bundle (FriendsOfVictoire/WidgetTabBundle), not a Laravel package. It will not auto-discover, it has no service provider, and it is built for the Victoire CMS widget ecosystem (Doctrine entities, Symfony DI, Twig, and Victoire's WidgetsBundle / BusinessEntityBundle). If your target is Laravel, stop here and read the last section — you are porting a concept, not installing a dependency.
Minimal steps if you are on a (legacy) Symfony app already running Victoire:
composer require friendsofvictoire/tab-widget — expect constraint fights; the last tagged release is 2016-08-22, so it pins Symfony 2.x/early 3.x era versions.app/AppKernel.php:
new FriendsOfVictoire\Bundle\WidgetTabBundle\WidgetTabBundle(),
(check the actual class name in composer.json → autoload.psr-4 and the bundle root file; Victoire bundles are inconsistent about the FriendsOfVictoireWidgetTabBundle vs WidgetTabBundle suffix).doctrine:schema:update --force or generate a migration) so the widget's entity tables exist.Where to look first (in this order):
Entity/ — the widget class and any child "tab"/"item" entity. This is the real API surface; everything else is plumbing.Resources/views/ — the Twig templates that render the tab markup. This is where you will spend 90% of your time.Resources/config/ — service definitions, and any widgets.yml/business_entity.yml style config that tells Victoire how the widget is registered.DependencyInjection/ — usually thin, but reveals config keys.First use case: drop a "Tab" widget into a Victoire page slot, define N tabs (label + content or a nested widget slot per pane), and render accessible tab markup on the front end. If your first attempt is "add the widget and see nothing," you have almost certainly hit a template override or a missing schema table, not a code bug.
Widget-as-container. Victoire widgets are persisted Doctrine entities rendered through Twig, so the idiomatic pattern is composition: the tab widget owns a collection of tab items, and each item either holds rich text/HTML or reserves a slot for nested widgets. Treat the widget entity as your DTO and never put render logic in it beyond what the bundle already does — push markup into templates.
Template override is the primary extension point. Do not edit vendored files. Override in your app:
app/Resources/FriendsOfVictoireWidgetTabBundle/views/...
or, cleaner, register a Twig path that wins over the bundle's. Most real-world work on this package is "same data model, different HTML" — a Bootstrap nav-tabs variant, an accordion fallback for mobile, ARIA-correct role="tablist" markup.
Compose with the rest of Victoire. If each pane can host nested widgets, the tab widget becomes a layout primitive: use it to build settings pages, product spec sheets, FAQ blocks. Keep panes shallow (2–5 tabs) because the admin drag-and-drop gets unwieldy and the front-end markup rarely degrades gracefully past that.
Config-driven registration. Victoire widgets are discovered via bundle config (widget name, label, business entity mapping). If you are adding a variant — say "Tab (vertical)" — the pattern is a second widget class reusing the same entity/table with a mode discriminator, plus its own template and registration entry. Copy the existing config block rather than inventing a new convention.
For a Laravel developer translating the idea: the equivalent is a Blade component (<x-tabs :items="$items">) with slots per pane, or a Livewire component if tabs need server round-trips. The Symfony bundle's "entity + Twig template + registration config" triad maps to "model + Blade view + service provider registration." Do not attempt to run this bundle under Laravel; there is no bridge and no maintained port.
"repositories": [{"type": "vcs", ...}]) rather than depending on Packagist.dev-master or with loose ~2.0 constraints. Expect composer update to resolve to something you did not intend. Pin everything and commit composer.lock.Resources/translations/. If the picker shows a raw key, your locale file is missing or the bundle's translations were not loaded (cache clear required).cache:clear and, in some setups, a manual wipe of the widget/HTML cache directory. "My template change did nothing" is nearly always cache.debug:container filtered on the widget service, debug:router for the admin routes, and Twig's dump() inside the widget template to see the actual entity shape — the entity's field names are undocumented, so inspect rather than guess.|raw usage in the templates before letting non-admin users author tab content.How can I help you explore Laravel packages today?