ducrot/twigcn-bundle
TwigcnBundle brings shadcn/ui-inspired, accessible UI components to Symfony & Twig. Install the PHP bundle plus the @ducrot/twigcn-ui NPM package and compile Tailwind CSS to use ready-made, themeable components in your templates.
Install the Bundle
composer require ducrot/twigcn-bundle
The bundle auto-registers via Symfony Flex.
Install NPM Dependencies
npm install @ducrot/twigcn-ui
For AssetMapper projects, expose the package:
php bin/console importmap:require @ducrot/twigcn-ui
Configure Tailwind
Create a tailwind.css file at your project root (outside assets/):
@import "tailwindcss";
@import "@ducrot/twigcn-ui/styles";
@source "../vendor/ducrot/twigcn-bundle/templates";
@source "./templates/**/*.html.twig";
Build with:
npx @tailwindcss/cli -i tailwind.css -o assets/styles/app.css --watch
Enable Stimulus Controllers
Create/update assets/controllers.json:
{
"controllers": {
"@ducrot/twigcn-ui": {
"accordion": { "enabled": true },
"dialog": { "enabled": true }
}
}
}
First Component Usage In a Twig template, use a component like:
<twig:Twigcn:Button variant="primary">Click Me</twig:Twigcn:Button>
Component Selection
Choose components from the Available Components section.
Example: Use <twig:Twigcn:Card> for feature highlights or <twig:Twigcn:Tabs> for multi-step forms.
Slot-Based Customization Leverage slots for nested content:
<twig:Twigcn:Card>
<twig:Twigcn:CardHeader>
<h3>Feature Title</h3>
</twig:Twigcn:CardHeader>
<twig:Twigcn:CardContent>
<p>Detailed content here.</p>
</twig:Twigcn:CardContent>
</twig:Twigcn:Card>
Form Integration Pair form components with Symfony forms:
<twig:Twigcn:Field>
<twig:Twigcn:Label for="email">Email</twig:Twigcn:Label>
{{ form_row(form.email) }}
</twig:Twigcn:Field>
Dynamic Data Binding Use Twig logic to conditionally render components:
{% if user.hasPermission('admin') %}
<twig:Twigcn:Button variant="destructive">Delete</twig:Twigcn:Button>
{% endif %}
Stimulus Interactivity Combine with Stimulus for dynamic behavior:
<twig:Twigcn:DrawerTrigger for="settings-drawer" data-action="click->theme#toggleDrawer">
Settings
</twig:Twigcn:DrawerTrigger>
Theming Consistency
Override CSS variables in tailwind.css to maintain brand consistency:
:root {
--primary: {{ app.config.primary_color }};
--secondary: {{ app.config.secondary_color }};
}
Tailwind Class Scanning
@source directives for new template paths causes Tailwind to miss classes.npx @tailwindcss/cli -i tailwind.css -o assets/styles/app.css --watch
Stimulus Controller Registration
Dialog, Drawer) fail silently if controllers aren’t registered.controllers.json or bootstrap.js includes all required controllers. For Vite setups, ensure vite-plugin-symfony is configured.AssetMapper vs. Webpack Encore
pentatrion/vite-bundle as shown in the README.Dark Mode Toggle
localStorage or a cookie:
document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', document.documentElement.className.includes('dark') ? 'dark' : 'light');
Component Naming Conflicts
<twig:Twigcn:Empty> maps to EmptyState).Tailwind JIT Mode
tailwind.config.js if needed:
module.exports = {
jit: false,
};
Inspect Stimulus Controllers Check if controllers are loaded in the browser console:
console.log(Stimulus.controllers);
Ensure @ducrot/twigcn-ui controllers appear.
Tailwind Class Errors
Use the Tailwind CLI with --verbose to debug missing classes:
npx @tailwindcss/cli -i tailwind.css -o assets/styles/app.css --verbose
Symfony UX TwigComponent Debugging
Enable Twig debug mode in config/packages/dev/twig.yaml:
twig:
debug: true
strict_variables: true
Vite/HMR Issues For Vite projects, clear the cache and rebuild:
npm run build
php bin/console cache:clear
Custom Components
Extend the bundle by creating new Twig components in src/Twigcn/ and register them in the bundle’s Resources/config/twigcn.php.
Override Default Templates
Override bundle templates by placing them in templates/bundles/Twigcn/. Example:
templates/
bundles/
Twigcn/
Button/
button.html.twig
Add New Stimulus Controllers
Extend the existing Stimulus controllers in @ducrot/twigcn-ui by importing and registering additional controllers in assets/controllers.json or bootstrap.js.
Tailwind Plugin Integration
Add custom Tailwind plugins to tailwind.config.js:
module.exports = {
plugins: [
require('@ducrot/twigcn-ui/tailwind'),
require('your-custom-plugin'),
],
};
Symfony Form Integration
Create custom form types that render Twigcn components by extending AbstractType and overriding buildForm()/configureOptions().
Example:
use Ducrot\TwigcnBundle\Form\TwigcnType;
class CustomFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('email', TwigcnType::class, [
'component' => 'Input',
'variant' => 'outline',
]);
}
}
Accessibility Audits Use tools like axe to validate component accessibility. Twigcn components are designed to be WAI-ARIA compliant, but customizations may introduce issues.
```markdown
---
How can I help you explore Laravel packages today?