diff --git a/README.md b/README.md
index a00de0c..4333724 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
[](https://github.com/tales-from-a-dev/flowbite-bundle/actions/workflows/ci.yml)


-[](https://flowbite.com)
+[](https://flowbite.com)
[](https://packagist.org/packages/tales-from-a-dev/flowbite-bundle)
[](https://github.com/tales-from-a-dev/flowbite-bundle/blob/main/LICENSE)
diff --git a/composer.json b/composer.json
index dd97bc8..4837897 100644
--- a/composer.json
+++ b/composer.json
@@ -21,7 +21,7 @@
"php": ">=8.1",
"symfony/http-kernel": "^6.4 || ^7.0 || ^8.0",
"symfony/twig-bridge": "^6.4 || ^7.0 || ^8.0",
- "tales-from-a-dev/twig-tailwind-extra": "^0.5"
+ "tales-from-a-dev/twig-tailwind-extra": "^1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.15",
diff --git a/docs/custom_form_types.md b/docs/custom_form_types.md
index fb7c6aa..4897adb 100644
--- a/docs/custom_form_types.md
+++ b/docs/custom_form_types.md
@@ -1,6 +1,6 @@
# Custom Form Types
-This bundle provide the following custom form types:
+This bundle provides the following custom form types:
## SwitchType
diff --git a/docs/index.md b/docs/index.md
index 534b74d..783be16 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -2,7 +2,7 @@
## Prerequisites
-This bundle requires **PHP 8.1+**, **Symfony 6.4+** and **Flowbite 1.6+**.
+This bundle requires **PHP 8.1+**, **Symfony 6.4+** and **Flowbite 4.0+**.
## Installation
@@ -34,16 +34,26 @@ return [
### Configuring Tailwind CSS
-Update your Tailwind configuration file to include the `templates` folder of the bundle:
+Update your Tailwind configuration to include the `templates` folder of the bundle:
+
+```css
+/* assets/styles/app.css */
+
+@source "../../vendor/tales-from-a-dev/flowbite-bundle/templates/**/*.html.twig";
+```
+
+#### Legacy Tailwind CSS configuration
+
+If you are using the legacy Tailwind CSS configuration, add the following line to your `tailwind.config.js` file:
```js
// tailwind.config.js
module.exports = {
- content: [
- //...
- "./vendor/tales-from-a-dev/flowbite-bundle/templates/**/*.html.twig"
- ],
+ content: [
+ //...
+ "./vendor/tales-from-a-dev/flowbite-bundle/templates/**/*.html.twig"
+ ],
}
```
@@ -60,9 +70,17 @@ twig:
- '@TalesFromADevFlowbite/form/default.html.twig'
```
-## Run the watcher
+### Compiling assets
+
+Finally, run one of the following commands to build your front-end assets:
+
+#### With [Tailwind bundle](https://symfony.com/bundles/TailwindBundle/current/index.html)
+
+```bash
+php bin/console tailwind:build
+```
-Finally, run the following command to compile the front-end assets via Webpack:
+#### With Webpack Encore
```bash
# With npm
diff --git a/docs/theme_customization.md b/docs/theme_customization.md
index 6b28a95..fdcc4a9 100644
--- a/docs/theme_customization.md
+++ b/docs/theme_customization.md
@@ -2,8 +2,8 @@
## Overriding CSS classes
-All used CSS classes are contained in [Twig blocks](https://github.com/talesfromadev/flowbite-bundle/blob/main/templates/form/default.twig#L244)
-which allows to customize the theme very easily.
+All CSS classes are contained in [Twig blocks](https://github.com/talesfromadev/flowbite-bundle/blob/main/templates/form/default.twig#L244)
+which allows customizing the theme very easily.
Create a new theme in your `templates` directory and make it use the bundle `default` theme:
@@ -13,7 +13,7 @@ Create a new theme in your `templates` directory and make it use the bundle `def
{% use '@TalesFromADevFlowbite/form/default.html.twig' %}
```
-Now, just override the desire block with any Tailwind CSS class you want:
+Now, override the desired block with any Tailwind CSS class you want:
```php
# templates/form/layout.html.twig
@@ -25,7 +25,7 @@ Now, just override the desire block with any Tailwind CSS class you want:
{%- endblock class_submit %}
```
-Finally, don't forget to update your `twig` configuration to use your newly created template:
+Finally, update your `twig` configuration to use your newly created template:
```yaml
# config/packages/twig.yaml
@@ -36,9 +36,9 @@ twig:
- 'form/layout.html.twig'
```
-## Class block list
+## Class blocks list
-Here is a list of all available class block:
+Here is a list of all available class blocks:
* Label
* class_label
@@ -60,12 +60,13 @@ Here is a list of all available class block:
* class_button
* class_submit
* Various
- * class_time_separator
+ * class_input_group
* class_addon
* class_widget_addon_prepend
* class_widget_addon_append
* class_addon_prepend
* class_addon_append
+ * class_time_separator
* class_help_text
* Error
* class_label_error
diff --git a/templates/form/default.html.twig b/templates/form/default.html.twig
index 3833bb3..7eeb923 100644
--- a/templates/form/default.html.twig
+++ b/templates/form/default.html.twig
@@ -13,32 +13,33 @@
{%- elseif type == 'file' -%}
{%- set attr_class = block('class_input_file') -%}
{%- endif -%}
- {%- set attr = attr|merge({'class': (attr_class ~ ' ' ~ attr.class|default(''))|trim}) -%}
+ {%- set attr_class = attr_class ~ ' ' ~ attr.class|default('') -%}
+ {%- set attr = attr|merge({'class': attr_class|trim|tailwind_merge}) -%}
{{- parent() -}}
{%- endif -%}
{%- endblock form_widget_simple -%}
{%- block textarea_widget -%}
- {%- set attr_class = attr_class|default(block('class_textarea')) -%}
- {%- set attr = attr|merge({'class': (attr_class ~ ' ' ~ attr.class|default(''))|trim}) -%}
+ {%- set attr_class = block('class_textarea') ~ ' ' ~ attr.class|default('') -%}
+ {%- set attr = attr|merge({'class': attr_class|trim|tailwind_merge}) -%}
{{- parent() -}}
{%- endblock textarea_widget -%}
{%- block choice_widget_collapsed -%}
- {%- set attr_class = attr_class|default(block('class_select')) -%}
- {%- set attr = attr|merge({'class': (attr_class ~ ' ' ~ attr.class|default(''))|trim}) -%}
+ {%- set attr_class = block('class_select') ~ ' ' ~ attr.class|default('') -%}
+ {%- set attr = attr|merge({'class': attr_class|trim|tailwind_merge}) -%}
{{- parent() -}}
{%- endblock choice_widget_collapsed -%}
{%- block checkbox_widget -%}
- {%- set attr_class = attr_class|default(block('class_input_checkbox')) -%}
- {%- set attr = attr|merge({'class': (attr_class ~ ' ' ~ attr.class|default(''))|trim}) -%}
+ {%- set attr_class = block('class_input_checkbox') ~ ' ' ~ attr.class|default('') -%}
+ {%- set attr = attr|merge({'class': attr_class|trim|tailwind_merge}) -%}
{{- form_label(form, null, { widget: parent() }) -}}
{%- endblock checkbox_widget -%}
{%- block radio_widget -%}
- {%- set attr_class = attr_class|default(block('class_input_radio')) -%}
- {%- set attr = attr|merge({'class': (attr_class ~ ' ' ~ attr.class|default(''))|trim}) -%}
+ {%- set attr_class = block('class_input_radio') ~ ' ' ~ attr.class|default('') -%}
+ {%- set attr = attr|merge({'class': attr_class|trim|tailwind_merge}) -%}
{{- form_label(form, null, { widget: parent() }) -}}
{%- endblock radio_widget -%}
@@ -52,9 +53,9 @@
{%- set append = not (money_pattern ends with '}}') -%}
{%- if prepend or append -%}
- {%- set attr_class = block('class_input_text') ~ ' ' ~ block('class_widget_addon_prepend') -%}
+ {%- set attr_class = block('class_input_text') ~ ' ' ~ block('class_widget_addon_append') -%}
{%- if prepend -%}
- {%- set attr_class = block('class_input_text') ~ ' ' ~ block('class_widget_addon_append') -%}
+ {%- set attr_class = block('class_input_text') ~ ' ' ~ block('class_widget_addon_prepend') -%}
{{ money_pattern|form_encode_currency }}
{%- endif -%}
{% with { attr_class: attr_class } %}{{- block('form_widget_simple') -}}{% endwith %}
@@ -69,7 +70,7 @@
{% block percent_widget -%}
{%- if symbol -%}
- {%- set attr_class = block('class_input_text') ~ ' ' ~ block('class_widget_addon_prepend') -%}
+ {%- set attr_class = block('class_input_text') ~ ' ' ~ block('class_widget_addon_append') -%}
{%- with { attr_class: attr_class } -%}{{- block('form_widget_simple') -}}{%- endwith -%}
{{ symbol|default('%') }}
@@ -90,9 +91,9 @@
{%- endif -%}
{{- date_pattern|replace({
- '{{ year }}': form_widget(form.year, { attr: { class: (block('class_widget_addon_append') ~ ' ' ~ attr_class_error|trim|tailwind_merge) }}),
- '{{ month }}': form_widget(form.month, { attr: { class: (block('class_widget_addon_prepend') ~ ' ' ~ attr_class_error|trim|tailwind_merge) }}),
- '{{ day }}': form_widget(form.day, { attr: { class: ('rounded-none' ~ attr_class_error)|trim|tailwind_merge }}),
+ '{{ year }}': form_widget(form.year, { attr: { 'class': block('class_input_group') ~ ' ' ~ attr_class_error|trim|tailwind_merge }}),
+ '{{ month }}': form_widget(form.month, { attr: { 'class': block('class_input_group') ~ ' ' ~ attr_class_error|trim|tailwind_merge }}),
+ '{{ day }}': form_widget(form.day, { attr: { 'class': block('class_input_group') ~ ' ' ~ attr_class_error|trim|tailwind_merge }}),
})|raw -}}
{%- endif -%}
@@ -108,27 +109,29 @@
{%- set attr_class_error = ' ' ~ block('class_input_error') -%}
{%- endif -%}
- {{- form_widget(form.hour, { attr: { class: ((with_minutes or with_seconds ? block('class_widget_addon_prepend') : '') ~ attr_class_error)|trim|tailwind_merge }}) -}}
+ {{- form_widget(form.hour, { attr: { 'class': ((with_minutes or with_seconds ? block('class_widget_addon_append') : '') ~ ' ' ~ attr_class_error)|trim|tailwind_merge }}) -}}
{%- if with_minutes -%}
:
- {{- form_widget(form.minute, { attr: { class: ((with_seconds ? 'rounded-none' : block('class_widget_addon_append')) ~ attr_class_error|trim|tailwind_merge) }}) -}}
+ {{- form_widget(form.minute, { attr: { 'class': ((with_seconds ? 'rounded-none' : block('class_widget_addon_prepend')) ~ ' ' ~ attr_class_error|trim|tailwind_merge) }}) -}}
{%- endif -%}
{%- if with_seconds -%}
:
- {{- form_widget(form.second, { attr: { class: (block('class_widget_addon_append') ~ attr_class_error)|trim|tailwind_merge }}) -}}
+ {{- form_widget(form.second, { attr: { 'class': (block('class_widget_addon_prepend') ~ ' ' ~ attr_class_error)|trim|tailwind_merge }}) -}}
{%- endif -%}
{%- endif -%}
{%- endblock time_widget -%}
{%- block button_widget -%}
- {%- set attr = attr|merge({'class': (attr.class|default(block('class_button')))|trim}) -%}
+ {%- set attr_class = block('class_button') ~ ' ' ~ attr.class|default('') -%}
+ {%- set attr = attr|merge({'class': attr_class|trim|tailwind_merge}) -%}
{{- parent() -}}
{%- endblock button_widget %}
{%- block submit_widget -%}
- {%- set attr = attr|merge({'class': (attr.class|default(block('class_submit')))|trim}) -%}
- {{- parent() -}}
+ {%- set attr_class = block('class_submit') ~ ' ' ~ attr.class|default('') -%}
+ {%- set attr = attr|merge({'class': attr_class|trim|tailwind_merge}) -%}
+ {{- block('submit_widget', 'form_div_layout.html.twig') -}}
{%- endblock submit_widget %}
{# Labels #}
@@ -152,15 +155,23 @@
{%- block checkbox_radio_label -%}
{#- Do not display the label if widget is not defined in order to prevent double label rendering -#}
{%- if widget is defined -%}
- {%- if checked and form.parent.vars.valid == false -%}
- {%- set valid = false -%}
+ {%- if checked -%}
+ {%- if form.parent is rootform -%}
+ {%- if form.vars.valid == false -%}
+ {%- set valid = false -%}
+ {%- endif -%}
+ {%- else -%}
+ {%- if form.parents.vars.valid == false -%}
+ {%- set valid = false -%}
+ {%- endif -%}
+ {%- endif -%}
{%- endif -%}
{%- set label_attr_class = (valid ? block('class_input_radio_label') : block('class_input_radio_label_error')) ~ ' ' ~ label_attr.class|default('') -%}
{%- set label_attr = label_attr|merge({'class': label_attr_class|trim|tailwind_merge}) -%}
{%- if not compound -%}
{% set label_attr = label_attr|merge({'for': id}) %}
{%- endif -%}
-
+
{{ widget|raw }}