diff --git a/src/FormCollection/.gitattributes b/src/FormCollection/.gitattributes
new file mode 100644
index 00000000000..17bf7a840e9
--- /dev/null
+++ b/src/FormCollection/.gitattributes
@@ -0,0 +1,3 @@
+/.gitattributes export-ignore
+/.gitignore export-ignore
+/Resources/assets/test export-ignore
diff --git a/src/FormCollection/DependencyInjection/FormCollectionExtension.php b/src/FormCollection/DependencyInjection/FormCollectionExtension.php
new file mode 100644
index 00000000000..3266037fd37
--- /dev/null
+++ b/src/FormCollection/DependencyInjection/FormCollectionExtension.php
@@ -0,0 +1,32 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\UX\FormCollection\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\HttpKernel\DependencyInjection\Extension;
+use Symfony\UX\FormCollection\Form\UXCollectionType;
+
+/**
+ * @internal
+ */
+class FormCollectionExtension extends Extension
+{
+ public function load(array $configs, ContainerBuilder $container)
+ {
+ $container
+ ->setDefinition('form.ux_collection', new Definition(UXCollectionType::class))
+ ->addTag('form.type')
+ ->setPublic(false)
+ ;
+ }
+}
diff --git a/src/FormCollection/Form/UXCollectionType.php b/src/FormCollection/Form/UXCollectionType.php
new file mode 100644
index 00000000000..42affc88800
--- /dev/null
+++ b/src/FormCollection/Form/UXCollectionType.php
@@ -0,0 +1,77 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\UX\FormCollection\Form;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\CollectionType;
+use Symfony\Component\Form\FormInterface;
+use Symfony\Component\Form\FormView;
+use Symfony\Component\OptionsResolver\Options;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+/**
+ * @final
+ * @experimental
+ */
+class UXCollectionType extends AbstractType
+{
+ public function getParent()
+ {
+ return CollectionType::class;
+ }
+
+ public function configureOptions(OptionsResolver $resolver)
+ {
+ $defaultButtonAddOptions = [
+ 'label' => 'Add',
+ 'class' => '',
+ ];
+ $defaultButtonDeleteOptions = [
+ 'label' => 'Remove',
+ 'class' => '',
+ ];
+ $resolver->setDefaults([
+ 'button_add_options' => $defaultButtonAddOptions,
+ 'button_delete_options' => $defaultButtonDeleteOptions,
+ ]);
+
+ $resolver->setAllowedTypes('button_add_options', 'array');
+ $resolver->setAllowedTypes('button_delete_options', 'array');
+
+ $resolver->setNormalizer('button_add_options', function (Options $options, $value) use ($defaultButtonAddOptions) {
+ $value['label'] = $value['label'] ?? $defaultButtonAddOptions['label'];
+ $value['class'] = $value['class'] ?? $defaultButtonAddOptions['class'];
+
+ return $value;
+ });
+ $resolver->setNormalizer('button_delete_options', function (Options $options, $value) use ($defaultButtonDeleteOptions) {
+ $value['label'] = $value['label'] ?? $defaultButtonDeleteOptions['label'];
+ $value['class'] = $value['class'] ?? $defaultButtonDeleteOptions['class'];
+
+ return $value;
+ });
+ }
+
+ public function finishView(FormView $view, FormInterface $form, array $options)
+ {
+ parent::finishView($view, $form, $options);
+
+ $view->vars['button_add_options'] = $options['button_add_options'];
+ $view->vars['button_delete_options'] = $options['button_delete_options'];
+ $view->vars['prototype_name'] = $options['prototype_name'];
+ }
+
+ public function getBlockPrefix()
+ {
+ return 'ux_collection';
+ }
+}
diff --git a/src/FormCollection/FormCollectionBundle.php b/src/FormCollection/FormCollectionBundle.php
new file mode 100644
index 00000000000..7eae8679a47
--- /dev/null
+++ b/src/FormCollection/FormCollectionBundle.php
@@ -0,0 +1,22 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\UX\FormCollection;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * @final
+ * @experimental
+ */
+class FormCollectionBundle extends Bundle
+{
+}
diff --git a/src/FormCollection/LICENSE b/src/FormCollection/LICENSE
new file mode 100644
index 00000000000..ad85e173748
--- /dev/null
+++ b/src/FormCollection/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2020-2021 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/src/FormCollection/README.md b/src/FormCollection/README.md
new file mode 100644
index 00000000000..d34a380e400
--- /dev/null
+++ b/src/FormCollection/README.md
@@ -0,0 +1,190 @@
+# UX Form Collection
+
+Symfony UX Form collection is a Symfony bundle providing light UX for collection
+in Symfony Forms.
+
+## Installation
+
+UX Form Collection requires PHP 7.2+ and Symfony 4.4+.
+
+Install this bundle using Composer and Symfony Flex:
+
+```sh
+composer require symfony/ux-form-collection
+
+# Don't forget to install the JavaScript dependencies as well and compile
+yarn install --force
+yarn encore dev
+```
+
+Also make sure you have at least version 2.0 of [@symfony/stimulus-bridge](https://github.com/symfony/stimulus-bridge)
+in your `package.json` file.
+
+## Use predefined theme
+
+You need to select the right theme from the one you are using:
+
+```yaml
+# config/packages/twig.yaml
+twig:
+ # For bootstrap for example
+ form_themes: ['@FormCollection/form_theme_div.html.twig']
+```
+
+There are 2 predefined themes available:
+
+- `@FormCollection/form_theme_div.html.twig`
+- `@FormCollection/form_theme_table.html.twig`
+
+[Check the Symfony doc](https://symfony.com/doc/4.4/form/form_themes.html) for the different ways to set themes in Symfony.
+
+## Use a custom form theme
+
+Consider your `BlogFormType` form set up and with a comments field that is a `CollectionType`, you can
+render it in your template:
+
+```twig
+{% macro commentFormRow(commentForm) %}
+