diff --git a/app/views/administrate/application/_form.html.erb b/app/views/administrate/application/_form.html.erb
index 93222057f1..d1182bbba1 100644
--- a/app/views/administrate/application/_form.html.erb
+++ b/app/views/administrate/application/_form.html.erb
@@ -13,48 +13,23 @@ and renders all form fields for a resource's editable attributes.
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Form
%>
+<%# locals: (page:) %>
<%= form_with(model: page.resource, url: [namespace, page.resource], scope: page.resource, local: true, class: "form") do |f| %>
- <% if page.resource.errors.any? %>
-
-
- <%= t(
- "administrate.form.errors",
- pluralized_errors: pluralize(page.resource.errors.count, t("administrate.form.error")),
- resource_name: display_resource_name(page.resource_name, singular: true)
- ) %>
-
-
-
- <% page.resource.errors.full_messages.each do |message| %>
- - <%= message %>
- <% end %>
-
-
- <% end %>
-
- <% page.attributes(controller.action_name).each do |title, attributes| -%>
-
- <% end -%>
-
-
- <%= f.submit %>
-
+
+ <%= render "form_errors", page: page, f: f %>
+
+ <%= render(
+ partial: "form_group",
+ layout: "form_group_layout",
+ collection: page.attributes(controller.action_name).to_a,
+ as: :form_group,
+ locals: {
+ page: page,
+ f: f,
+ }
+ ) %>
+
+ <%= render "form_actions", page: page, f: f %>
+
<% end %>
diff --git a/app/views/administrate/application/_form_actions.html.erb b/app/views/administrate/application/_form_actions.html.erb
new file mode 100644
index 0000000000..64e79ad9c1
--- /dev/null
+++ b/app/views/administrate/application/_form_actions.html.erb
@@ -0,0 +1,5 @@
+<%# locals: (page:, f:) %>
+
+
+ <%= f.submit %>
+
diff --git a/app/views/administrate/application/_form_errors.html.erb b/app/views/administrate/application/_form_errors.html.erb
new file mode 100644
index 0000000000..77928d1b4a
--- /dev/null
+++ b/app/views/administrate/application/_form_errors.html.erb
@@ -0,0 +1,18 @@
+<%# locals: (page:, f:) %>
+<% return if page.resource.errors.empty? %>
+
+
+
+ <%= t(
+ "administrate.form.errors",
+ pluralized_errors: pluralize(page.resource.errors.count, t("administrate.form.error")),
+ resource_name: display_resource_name(page.resource_name, singular: true)
+ ) %>
+
+
+
+ <% page.resource.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
diff --git a/app/views/administrate/application/_form_group.html.erb b/app/views/administrate/application/_form_group.html.erb
new file mode 100644
index 0000000000..2b79c151b8
--- /dev/null
+++ b/app/views/administrate/application/_form_group.html.erb
@@ -0,0 +1,14 @@
+<%# locals: (page:, f:, form_group:, form_group_counter: nil, form_group_iteration: nil) %>
+<% attributes = form_group.second %>
+
+<%= render(
+ partial: "form_item",
+ layout: "form_item_layout",
+ collection: attributes,
+ as: :attribute,
+ locals: {
+ page: page,
+ f: f,
+ form_group: form_group,
+ }
+) %>
diff --git a/app/views/administrate/application/_form_group_layout.html.erb b/app/views/administrate/application/_form_group_layout.html.erb
new file mode 100644
index 0000000000..17bbbed2a9
--- /dev/null
+++ b/app/views/administrate/application/_form_group_layout.html.erb
@@ -0,0 +1,17 @@
+<%# locals: (page:, f:, form_group:, form_group_counter: nil, form_group_iteration: nil) %>
+<% group_title = form_group.first %>
+
+<% if group_title.present? %>
+ <%# grouped attributes: { title => attributes } %>
+
+<% else %>
+ <%# non-grouped attributes: { "" => attributes } %>
+
+ <%= yield %>
+
+<% end %>
diff --git a/app/views/administrate/application/_form_item.html.erb b/app/views/administrate/application/_form_item.html.erb
new file mode 100644
index 0000000000..434c6a13e5
--- /dev/null
+++ b/app/views/administrate/application/_form_item.html.erb
@@ -0,0 +1,3 @@
+<%# locals: (page:, f:, form_group:, attribute:, attribute_counter: nil, attribute_iteration: nil) %>
+
+<%= render_field attribute, f: f %>
diff --git a/app/views/administrate/application/_form_item_hint.html.erb b/app/views/administrate/application/_form_item_hint.html.erb
new file mode 100644
index 0000000000..5d81ba89b8
--- /dev/null
+++ b/app/views/administrate/application/_form_item_hint.html.erb
@@ -0,0 +1,8 @@
+<%# locals: (page:, f:, form_group:, attribute:) %>
+
+<% hint_key = "administrate.field_hints.#{page.resource_name}.#{attribute.name}" %>
+<% if I18n.exists?(hint_key) -%>
+
+ <%= I18n.t(hint_key) %>
+
+<% end -%>
diff --git a/app/views/administrate/application/_form_item_layout.html.erb b/app/views/administrate/application/_form_item_layout.html.erb
new file mode 100644
index 0000000000..a784ac8e1c
--- /dev/null
+++ b/app/views/administrate/application/_form_item_layout.html.erb
@@ -0,0 +1,6 @@
+<%# locals: (page:, f:, form_group:, attribute:, attribute_counter: nil, attribute_iteration: nil) %>
+
+
+ <%= yield %>
+ <%= render "form_item_hint", page: page, f: f, form_group: form_group, attribute: attribute %>
+