{% extends 'form_div_layout.html.twig' %} {# Tailwind CSS Form Theme with Dark Mode & Animations Support #} {# ======================================== FORM ROW - Container for each field ======================================== #} {% block form_row -%}
{{- form_label(form) -}} {{- form_widget(form) -}} {{- form_errors(form) -}} {{- form_help(form) -}}
{%- endblock form_row %} {# ======================================== BUTTON ROW - Special layout for buttons ======================================== #} {% block button_row -%}
{{- form_widget(form) -}}
{%- endblock button_row %} {# ======================================== FORM LABELS ======================================== #} {% block form_label -%} {% if label is not same as(false) -%} {% if not compound -%} {% set label_attr = label_attr|merge({'for': id}) %} {%- endif %} {% if required -%} {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %} {%- endif %} {% if label is empty -%} {%- if label_format is not empty -%} {% set label = label_format|replace({ '%name%': name, '%id%': id, }) %} {%- else -%} {% set label = name|humanize %} {%- endif -%} {%- endif -%} {{- label|trans({}, translation_domain) -}} {%- if required -%} * {%- endif -%} {%- endif %} {%- endblock form_label %} {# ======================================== TEXT INPUTS (text, email, password, url, tel, number, etc.) ======================================== #} {% block form_widget_simple -%} {%- set type = type|default('text') -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors duration-200 ' ~ (errors|length > 0 ? 'border-red-500 dark:border-red-400 focus:ring-red-500 focus:border-red-500' : 'border-gray-300 dark:border-gray-600') ~ ' bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 disabled:bg-gray-100 dark:disabled:bg-gray-900 disabled:cursor-not-allowed')|trim }) -%} {%- endblock form_widget_simple %} {# ======================================== TEXTAREA ======================================== #} {% block textarea_widget -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors duration-200 resize-y ' ~ (errors|length > 0 ? 'border-red-500 dark:border-red-400 focus:ring-red-500 focus:border-red-500' : 'border-gray-300 dark:border-gray-600') ~ ' bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 disabled:bg-gray-100 dark:disabled:bg-gray-900 disabled:cursor-not-allowed')|trim }) -%} {%- endblock textarea_widget %} {# ======================================== CHECKBOX - Single checkbox ======================================== #} {% block checkbox_widget -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' h-4 w-4 rounded border-gray-300 dark:border-gray-600 text-indigo-600 focus:ring-indigo-500 focus:ring-offset-0 transition-colors duration-200 disabled:cursor-not-allowed disabled:opacity-50')|trim }) -%} {%- endblock checkbox_widget %} {# ======================================== CHECKBOX ROW - Special layout for checkbox with label on right ======================================== #} {% block checkbox_row -%}
{{- form_widget(form) -}}
{{- form_label(form, null, {label_attr: {class: 'font-medium text-gray-700 dark:text-gray-300'}}) -}} {{- form_help(form) -}}
{{- form_errors(form) -}}
{%- endblock checkbox_row %} {# ======================================== RADIO BUTTON ======================================== #} {% block radio_widget -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' h-4 w-4 border-gray-300 dark:border-gray-600 text-indigo-600 focus:ring-indigo-500 focus:ring-offset-0 transition-colors duration-200 disabled:cursor-not-allowed disabled:opacity-50')|trim }) -%} {%- endblock radio_widget %} {# ======================================== SELECT / DROPDOWN (collapsed choice) ======================================== #} {% block choice_widget_collapsed -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors duration-200 ' ~ (errors|length > 0 ? 'border-red-500 dark:border-red-400 focus:ring-red-500 focus:border-red-500' : 'border-gray-300 dark:border-gray-600') ~ ' bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 disabled:bg-gray-100 dark:disabled:bg-gray-900 disabled:cursor-not-allowed')|trim }) -%} {%- if required and placeholder is none and not placeholder_in_choices and not multiple and (attr.size is not defined or attr.size <= 1) -%} {% set required = false %} {%- endif -%} {%- endblock choice_widget_collapsed %} {# ======================================== EXPANDED CHOICE (checkboxes or radios) ======================================== #} {% block choice_widget_expanded -%}
{%- for child in form %}
{{- form_widget(child) -}}
{{- form_label(child, null, {label_attr: {class: 'font-medium text-gray-700 dark:text-gray-300'}, translation_domain: choice_translation_domain}) -}}
{% endfor -%}
{%- endblock choice_widget_expanded %} {# ======================================== FILE INPUT ======================================== #} {% block file_widget -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' block w-full text-sm text-gray-500 dark:text-gray-400 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 dark:file:bg-indigo-900 file:text-indigo-700 dark:file:text-indigo-100 hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800 file:transition-colors file:duration-200 border border-gray-300 dark:border-gray-600 rounded-lg cursor-pointer bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500')|trim }) -%} {%- endblock file_widget %} {# ======================================== BUTTON ======================================== #} {% block button_widget -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' inline-flex items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-lg text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-4 focus:ring-indigo-300 dark:focus:ring-indigo-800 transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed')|trim }) -%} {%- if label is empty -%} {%- if label_format is not empty -%} {% set label = label_format|replace({ '%name%': name, '%id%': id, }) %} {%- else -%} {% set label = name|humanize %} {%- endif -%} {%- endif -%} {%- endblock button_widget %} {# ======================================== SUBMIT BUTTON ======================================== #} {% block submit_widget -%} {%- set type = type|default('submit') -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' w-full inline-flex items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-lg text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-4 focus:ring-indigo-300 dark:focus:ring-indigo-800 transition-colors duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed')|trim }) -%} {{ block('button_widget') }} {%- endblock submit_widget %} {# ======================================== RESET BUTTON ======================================== #} {% block reset_widget -%} {%- set type = type|default('reset') -%} {%- set attr = attr|merge({ class: (attr.class|default('') ~ ' w-full inline-flex items-center justify-center px-6 py-3 border border-gray-300 dark:border-gray-600 text-base font-medium rounded-lg text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-700 transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed')|trim }) -%} {{ block('button_widget') }} {%- endblock reset_widget %} {# ======================================== FORM ERRORS ======================================== #} {% block form_errors -%} {%- if errors|length > 0 -%}
{%- for error in errors -%}

{{ error.message }}

{%- endfor -%}
{%- endif -%} {%- endblock form_errors %} {# ======================================== FORM HELP TEXT ======================================== #} {% block form_help -%} {%- if help is not empty -%} {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' mt-2 text-sm text-gray-500 dark:text-gray-400')|trim}) -%}

{%- if translation_domain is same as(false) -%} {%- if help_html is same as(false) -%} {{- help -}} {%- else -%} {{- help|raw -}} {%- endif -%} {%- else -%} {%- if help_html is same as(false) -%} {{- help|trans(help_translation_parameters, translation_domain) -}} {%- else -%} {{- help|trans(help_translation_parameters, translation_domain)|raw -}} {%- endif -%} {%- endif -%}

{%- endif -%} {%- endblock form_help %} {# ======================================== HIDDEN INPUT ======================================== #} {% block hidden_widget -%} {%- set type = type|default('hidden') -%} {{ block('form_widget_simple') }} {%- endblock hidden_widget %} {# ======================================== COLLECTION WIDGET ======================================== #} {% block collection_widget -%}
{{- block('form_widget') -}}
{%- endblock collection_widget %} {# ======================================== ATTRIBUTES HELPER ======================================== #} {% block attributes -%} {%- for attrname, attrvalue in attr -%} {{- " " -}} {%- if attrname in ['placeholder', 'title'] -%} {{- attrname }}="{{ translation_domain is same as(false) ? attrvalue : attrvalue|trans({}, translation_domain) }}" {%- elseif attrvalue is same as(true) -%} {{- attrname }}="{{ attrname }}" {%- elseif attrvalue is not same as(false) -%} {{- attrname }}="{{ attrvalue }}" {%- endif -%} {%- endfor -%} {%- endblock attributes %}