diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/container/v2/container/README.md b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/container/v2/container/README.md
index 1fb501d511..38234a3768 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/container/v2/container/README.md
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/container/v2/container/README.md
@@ -25,6 +25,7 @@ Adaptive Form container written in HTL.
* Thank you message
* Ability to drop other adaptive form components
* Auto save feature for Drafts
+* Loader overlay during form submission to prevent multiple submits
### Use Object
The Adaptive Form Container component uses the `com.adobe.cq.forms.core.components.models.form.FormContainer` Sling Model for its Use-object.
@@ -86,7 +87,9 @@ BLOCK cmp-adaptiveform-container
Apply a `data-cmp-is="adaptiveFormContainer"` attribute to the `cmp-adaptiveform-container` block to enable initialization of the JavaScript component.
-Applying `data-cmp-adaptiveform-container-loader` attribute to the div specifically for applying the loader class on it, it is to ensure that the loading icon should not appear over components.
+Applying `data-cmp-adaptiveform-container-loader` attribute to the div specifically for applying the loader class on it, it is to ensure that the loading icon should not appear over components.
+
+During the form submission, the form element `form.cmp-adaptiveform-container` toggles the class `cmp-adaptiveform-container--submitting` and the loader inside becomes visible. The class is removed once validation fails, submission succeeds or errors out, or the thank you page/message is shown.
Applying `data-cmp-custom-functions-module-url` attribute to the div to point to the edge delivery URL of the custom functions file. Custom Functions exported from this file will be registered in Function Runtime.
This Url should whitelist the AEM author/publish domain in the Cross Origin Resource Sharing (CORS) configuration.
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/_cq_dialog/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/_cq_dialog/.content.xml
index 4886b1c14d..2e4584bb04 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/_cq_dialog/.content.xml
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/_cq_dialog/.content.xml
@@ -49,10 +49,10 @@
@@ -80,9 +80,9 @@
`;
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v1/radiobutton/radiobutton.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v1/radiobutton/radiobutton.html
index e20edfe163..b380efe7aa 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v1/radiobutton/radiobutton.html
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v1/radiobutton/radiobutton.html
@@ -13,7 +13,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
-
+ aria-label="${radioButton.optionScreenReaderLabels[itemList.index]}" tabindex="0"/>
${radioButton.enumNames[itemList.index] @ context = 'html'}
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/.content.xml
new file mode 100644
index 0000000000..cd3ddd1d64
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/.content.xml
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/.content.xml
new file mode 100644
index 0000000000..f212697391
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/.content.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/README.md b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/README.md
new file mode 100644
index 0000000000..0af3f2df52
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/README.md
@@ -0,0 +1,115 @@
+
+RadioButton (v2)
+====
+Adaptive form Radio Button component written in HTL.
+
+## Features
+
+* Provides the following type of input in form of radio button:
+ * string
+ * boolean
+ * number
+* Alignment of Options (`horizontal` or `vertical`)
+* Styles
+* Allows replacing this component with other component (as mentioned below).
+
+## Changes in v2
+
+- Root element changed from `div` to `fieldset` for better semantics and accessibility.
+- Label and help icon are now rendered inside a native `legend`.
+- Added modifier class `cmp-adaptiveform-radiobutton--v2` on the root block.
+- Extracted options markup to `widget.html` template (no functional change).
+- Documented `cmp-adaptiveform-radiobutton__widget` BEM element.
+- Client library categories remain the same as v1 (runtime/editor).
+
+### Use Object
+The Form Radio Button component uses the `com.adobe.cq.forms.core.components.models.form.RadioButton` Sling Model for its Use-object.
+
+### Edit Dialog Properties
+The following properties are written to JCR for this Radio Button component and are expected to be available as `Resource` properties:
+
+1. `./name` - defines the name of the field, which will be submitted with the form data
+2. `./jcr:title` - defines the label to use for this field
+3. `./hideTitle` - if set to `true`, the label of this field will be hidden
+4. `./type` - defines the type of values(string, boolean, number) which can be accepted
+5. `./enum` - an array[] of type, defines the available values for selection
+6. `./enumNames` - an array[] of strings, defines the display value of the enum
+7. `./default` - defines the default option of the field
+8. `./alignment` - defines how should the options be displayed, horizontally or vertically.
+9. `./description` - defines a help message that can be rendered in the field as a hint for the user
+10. `./required` - if set to `true`, this field will be marked as required, not allowing the form to be submitted until the field has a value
+11. `./requiredMessage` - defines the message displayed as tooltip when submitting the form if the value is left empty
+12. `./readOnly` - if set to `true`, the filed will be read only
+13. `./fieldType` - defines the type of the component
+
+
+## Client Libraries
+The component provides a `core.forms.components.radiobutton.v1.runtime` client library category that contains the Javascript runtime for the component.
+It should be added to a relevant site client library using the `embed` property.
+
+It also provides a `core.forms.components.radiobutton.v1.editor` editor client library category that includes
+JavaScript handling for dialog interaction. It is already included by its edit dialog.
+
+Note: v2 uses the v1 client library categories for both runtime and editor.
+
+## BEM Description
+```
+BLOCK cmp-adaptiveform-radiobutton
+ MODIFIER cmp-adaptiveform-radiobutton--v2
+ ELEMENT cmp-adaptiveform-radiobutton__label
+ ELEMENT cmp-adaptiveform-radiobutton__label-container
+ ELEMENT cmp-adaptiveform-radiobutton__widget
+ ELEMENT cmp-adaptiveform-radiobutton__option
+ ELEMENT cmp-adaptiveform-radiobutton__option-label
+ ELEMENT cmp-adaptiveform-radiobutton__option__widget
+ ELEMENT cmp-adaptiveform-radiobutton__questionmark
+ ELEMENT cmp-adaptiveform-radiobutton__shortdescription
+ ELEMENT cmp-adaptiveform-radiobutton__longdescription
+ ELEMENT cmp-adaptiveform-radiobutton__errormessage
+```
+
+### Note
+By placing the class names `cmp-adaptiveform-radiobutton__label` and `cmp-adaptiveform-radiobutton__questionmark` within the `cmp-adaptiveform-radiobutton__label-container` class, you create a logical grouping of the label and question mark elements. This approach simplifies the process of maintaining a consistent styling for both elements.
+
+## JavaScript Data Attribute Bindings
+
+The following attributes must be added for the initialization of the radio-button component in the form view:
+1. `data-cmp-is="adaptiveFormRadioButton"`
+2. `data-cmp-adaptiveformcontainer-path="${formstructparser.formContainerPath}"`
+
+
+
+The following are optional attributes that can be added to the component in the form view:
+1. `data-cmp-valid` having a boolean value to indicate whether the field is currently valid or not
+2. `data-cmp-required` having a boolean value to indicate whether the field is currently required or not
+3. `data-cmp-readonly` having a boolean value to indicate whether the field is currently readonly or not
+4. `data-cmp-active` having a boolean value to indicate whether the field is currently active or not
+5. `data-cmp-visible` having a boolean value to indicate whether the field is currently visible or not
+6. `data-cmp-enabled` having a boolean value to indicate whether the field is currently enabled or not
+
+## Replace feature:
+We support replace feature that allows replacing Reset Button component to any of the below components:
+
+* Check Box Group
+* Drop down
+
+
+## Information
+* **Vendor**: Adobe
+* **Version**: v2
+* **Compatibility**: Cloud
+* **Status**: production-ready
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/.content.xml
new file mode 100644
index 0000000000..564d04a5c1
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/.content.xml
@@ -0,0 +1,3 @@
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/.content.xml
new file mode 100644
index 0000000000..a29e33d085
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/.content.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/js.txt
new file mode 100644
index 0000000000..b85fb16f9f
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/js.txt
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright 2022 Adobe
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###############################################################################
+
+#base=js
+radiobuttonview.js
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/js/radiobuttonview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/js/radiobuttonview.js
new file mode 100644
index 0000000000..472354ab66
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/clientlibs/site/js/radiobuttonview.js
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright 2022 Adobe
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+(function() {
+
+ "use strict";
+ class RadioButton extends FormView.FormOptionFieldBase {
+
+ static NS = FormView.Constants.NS;
+ /**
+ * Each FormField has a data attribute class that is prefixed along with the global namespace to
+ * distinguish between them. If a component wants to put a data-attribute X, the attribute in HTML would be
+ * data-{NS}-{IS}-x=""
+ * @type {string}
+ */
+ static IS = "adaptiveFormRadioButton";
+ static bemBlock = 'cmp-adaptiveform-radiobutton';
+ static selectors = {
+ self: "[data-" + this.NS + '-is="' + this.IS + '"]',
+ widgets: `.${RadioButton.bemBlock}__widget`,
+ widget: `.${RadioButton.bemBlock}__option__widget`,
+ label: `.${RadioButton.bemBlock}__label`,
+ description: `.${RadioButton.bemBlock}__longdescription`,
+ qm: `.${RadioButton.bemBlock}__questionmark`,
+ errorDiv: `.${RadioButton.bemBlock}__errormessage`,
+ tooltipDiv: `.${RadioButton.bemBlock}__shortdescription`,
+ option: `.${RadioButton.bemBlock}__option`,
+ optionLabel: `.${RadioButton.bemBlock}__option-label`
+ };
+
+ constructor(params) {
+ super(params);
+ this.qm = this.element.querySelector(RadioButton.selectors.qm);
+ }
+
+ getWidgets() {
+ return this.element.querySelector(RadioButton.selectors.widgets);
+ }
+
+ getWidget() {
+ return this.element.querySelectorAll(RadioButton.selectors.widget);
+ }
+
+ getDescription() {
+ return this.element.querySelector(RadioButton.selectors.description);
+ }
+
+ getLabel() {
+ return this.element.querySelector(RadioButton.selectors.label);
+ }
+
+ getQuestionMarkDiv() {
+ return this.element.querySelector(RadioButton.selectors.qm);
+ }
+
+ getTooltipDiv() {
+ return this.element.querySelector(RadioButton.selectors.tooltipDiv);
+ }
+
+ getErrorDiv() {
+ return this.element.querySelector(RadioButton.selectors.errorDiv);
+ }
+
+ getOptions() {
+ return this.element.querySelectorAll(RadioButton.selectors.option);
+ }
+
+ #addWidgetListeners(optionWidget) {
+ optionWidget.addEventListener('change', (e) => {
+ this.setModelValue(e.target.value);
+ });
+ optionWidget.addEventListener('focus', (e) => {
+ this.setActive();
+ });
+ optionWidget.addEventListener('blur', (e) => {
+ this.setInactive();
+ });
+ }
+
+ setModel(model) {
+ super.setModel(model);
+ this.widget.forEach(optionWidget => {
+ this.#addWidgetListeners(optionWidget);
+ });
+ }
+
+ updateEnabled(enabled, state) {
+ this.element.setAttribute(FormView.Constants.DATA_ATTRIBUTE_ENABLED, enabled);
+ let widgets = this.widget;
+ widgets.forEach(widget => {
+ if (enabled === false) {
+ if(state.readOnly === false){
+ widget.setAttribute(FormView.Constants.HTML_ATTRS.DISABLED, "disabled");
+ }
+ } else if (state.readOnly === false) {
+ widget.removeAttribute(FormView.Constants.HTML_ATTRS.DISABLED);
+ }
+ });
+ }
+
+ updateReadOnly(readonly) {
+ let widgets = this.widget;
+ this.element.setAttribute(FormView.Constants.DATA_ATTRIBUTE_READONLY, readonly);
+ widgets.forEach(widget => {
+ if (readonly === true) {
+ widget.setAttribute(FormView.Constants.HTML_ATTRS.DISABLED, "disabled");
+ } else {
+ widget.removeAttribute(FormView.Constants.HTML_ATTRS.DISABLED);
+ }
+ });
+ }
+
+ updateValidity(validity) {
+ if(validity.valid === undefined) {
+ this.element.removeAttribute(FormView.Constants.DATA_ATTRIBUTE_VALID);
+ this.widget.forEach(widget => widget.removeAttribute(FormView.Constants.ARIA_INVALID));
+ } else {
+ this.element.setAttribute(FormView.Constants.DATA_ATTRIBUTE_VALID, validity.valid);
+ this.widget.forEach(widget => widget.setAttribute(FormView.Constants.ARIA_INVALID, !validity.valid));
+ }
+ }
+
+ updateValue(modelValue) {
+ this.widget.forEach(widget => {
+ if (modelValue != null && widget.value != null && (modelValue.toString() == widget.value.toString())) {
+ widget.checked = true;
+ widget.setAttribute(FormView.Constants.HTML_ATTRS.CHECKED, FormView.Constants.HTML_ATTRS.CHECKED);
+ } else {
+ widget.checked = false;
+ widget.removeAttribute(FormView.Constants.HTML_ATTRS.CHECKED);
+ }
+ }, this)
+ super.updateEmptyStatus();
+ }
+
+ #createRadioOption(value, itemLabel) {
+ const optionTemplate = `
+
+
+
`;
+
+ const container = document.createElement('div'); // Create a container element to hold the template
+ container.innerHTML = optionTemplate;
+ let addedOptionWidget = container.querySelector(RadioButton.selectors.widget);
+ if(this._model.readOnly === true || this._model.enabled === false) {
+ addedOptionWidget.setAttribute("disabled", true);
+ if(this._model.readOnly === true) {
+ addedOptionWidget.setAttribute("aria-readonly", true);
+ }
+ }
+ this.#addWidgetListeners(addedOptionWidget);
+ return container.firstElementChild; // Return the first child, which is the created option
+ }
+
+ updateEnum(newEnums) {
+ super.updateEnumForRadioButtonAndCheckbox(newEnums, this.#createRadioOption);
+ // refresh the widget references, to dynamically added options
+ this.widget = this.getWidget();
+ }
+
+ updateEnumNames(newEnumNames) {
+ super.updateEnumNamesForRadioButtonAndCheckbox(newEnumNames, this.#createRadioOption);
+ // refresh the widget references, to dynamically added options
+ this.widget = this.getWidget();
+ }
+
+ updateRequired(required, state) {
+ if (this.widget) {
+ this.element.toggleAttribute("required", required);
+ this.element.setAttribute("data-cmp-required", required);
+ }
+ }
+
+ syncMarkupWithModel() {
+ super.syncMarkupWithModel();
+ this.#syncWidgetName();
+ }
+
+ #syncWidgetName() {
+ const name = this.getModel()?.name;
+ this.widget.forEach(widget => {
+ widget.setAttribute("name", `${this.id}_${name}`);
+ });
+ }
+ }
+
+ FormView.Utils.setupField(({element, formContainer}) => {
+ return new RadioButton({element, formContainer});
+ }, RadioButton.selectors.self);
+
+})();
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/radiobutton.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/radiobutton.html
new file mode 100644
index 0000000000..0c4e846a7a
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/radiobutton.html
@@ -0,0 +1,53 @@
+
+
+
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/radiobutton.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/radiobutton.js
new file mode 100644
index 0000000000..56b6a4e059
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/radiobutton.js
@@ -0,0 +1,36 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Copyright 2025 Adobe
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+use(function() {
+
+ var clientlibsArr = [ 'core.forms.components.base.v1.editor' ];
+ var labelPath = 'core/fd/components/af-commons/v1/fieldTemplates/label.html';
+ var shortDescriptionPath = "core/fd/components/af-commons/v1/fieldTemplates/shortDescription.html";
+ var longDescriptionPath = "core/fd/components/af-commons/v1/fieldTemplates/longDescription.html";
+ var questionMarkPath = "core/fd/components/af-commons/v1/fieldTemplates/questionMark.html"
+ var errorMessagePath = "core/fd/components/af-commons/v1/fieldTemplates/errorMessage.html";
+ var legendPath = "core/fd/components/af-commons/v1/fieldTemplates/legend.html"
+ return {
+ labelPath : labelPath,
+ shortDescriptionPath : shortDescriptionPath,
+ longDescriptionPath : longDescriptionPath,
+ questionMarkPath : questionMarkPath,
+ errorMessagePath : errorMessagePath,
+ legendPath : legendPath,
+ clientlibs : clientlibsArr
+ }
+});
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/widget.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/widget.html
new file mode 100644
index 0000000000..efd6bd1ba3
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v2/radiobutton/widget.html
@@ -0,0 +1,34 @@
+
+
+