diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 123c2da607ec5..e94e0ab9ca9cf 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -2811,6 +2811,7 @@ team_permission_desc = Permission
 team_unit_desc = Allow Access to Repository Sections
 team_unit_disabled = (Disabled)
 
+form.name_been_taken = The organisation name "%s" has already been taken.
 form.name_reserved = The organization name "%s" is reserved.
 form.name_pattern_not_allowed = The pattern "%s" is not allowed in an organization name.
 form.create_org_not_allowed = You are not allowed to create an organization.
@@ -2832,15 +2833,28 @@ settings.visibility.private_shortname = Private
 
 settings.update_settings = Update Settings
 settings.update_setting_success = Organization settings have been updated.
-settings.change_orgname_prompt = Note: Changing the organization name will also change your organization's URL and free the old name.
-settings.change_orgname_redirect_prompt = The old name will redirect until it is claimed.
+
+settings.rename = Rename Organization
+settings.rename_desc = Changing the organization name will also change your organization's URL and free the old name.
+settings.rename_success = Organization %[1]s have been renamed to %[2]s successfully.
+settings.rename_no_change = Organization name is no change.
+settings.rename_new_org_name = New Organization Name
+settings.rename_failed = Rename Organization failed because of internal error
+settings.rename_notices_1 = This operation CANNOT be undone.
+settings.rename_notices_2 = The old name will redirect until it is claimed.
+
 settings.update_avatar_success = The organization's avatar has been updated.
 settings.delete = Delete Organization
 settings.delete_account = Delete This Organization
 settings.delete_prompt = The organization will be permanently removed. This CANNOT be undone!
+settings.name_confirm = Enter the organization name as confirmation:
+settings.delete_notices_1 = This operation CANNOT be undone.
+settings.delete_notices_2 = This operation will permanently delete all the repositories of %s including code, issues, comments, wiki data and collaborator settings.
+settings.delete_notices_3 = This operation will permanently delete all the packages of %s.
+settings.delete_notices_4 = This operation will permanently delete all the projects of %s.
 settings.confirm_delete_account = Confirm Deletion
-settings.delete_org_title = Delete Organization
-settings.delete_org_desc = This organization will be deleted permanently. Continue?
+settings.delete_failed = Delete Organization failed because of internal error
+settings.delete_successful = Organization %s has been deleted successfully.
 settings.hooks_desc = Add webhooks which will be triggered for all repositories under this organization.
 
 settings.labels_desc = Add labels which can be used on issues for all repositories under this organization.
diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go
index 9dd0a98160e60..2bc1e8bc43388 100644
--- a/routers/web/org/setting.go
+++ b/routers/web/org/setting.go
@@ -18,6 +18,7 @@ import (
 	repo_module "code.gitea.io/gitea/modules/repository"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/templates"
+	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/modules/web"
 	shared_user "code.gitea.io/gitea/routers/web/shared/user"
 	user_setting "code.gitea.io/gitea/routers/web/user/setting"
@@ -31,8 +32,6 @@ import (
 const (
 	// tplSettingsOptions template path for render settings
 	tplSettingsOptions templates.TplName = "org/settings/options"
-	// tplSettingsDelete template path for render delete repository
-	tplSettingsDelete templates.TplName = "org/settings/delete"
 	// tplSettingsHooks template path for render hook settings
 	tplSettingsHooks templates.TplName = "org/settings/hooks"
 	// tplSettingsLabels template path for render labels settings
@@ -71,26 +70,6 @@ func SettingsPost(ctx *context.Context) {
 
 	org := ctx.Org.Organization
 
-	if org.Name != form.Name {
-		if err := user_service.RenameUser(ctx, org.AsUser(), form.Name); err != nil {
-			if user_model.IsErrUserAlreadyExist(err) {
-				ctx.Data["Err_Name"] = true
-				ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form)
-			} else if db.IsErrNameReserved(err) {
-				ctx.Data["Err_Name"] = true
-				ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplSettingsOptions, &form)
-			} else if db.IsErrNamePatternNotAllowed(err) {
-				ctx.Data["Err_Name"] = true
-				ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form)
-			} else {
-				ctx.ServerError("RenameUser", err)
-			}
-			return
-		}
-
-		ctx.Org.OrgLink = setting.AppSubURL + "/org/" + url.PathEscape(org.Name)
-	}
-
 	if form.Email != "" {
 		if err := user_service.ReplacePrimaryEmailAddress(ctx, org.AsUser(), form.Email); err != nil {
 			ctx.Data["Err_Email"] = true
@@ -163,42 +142,27 @@ func SettingsDeleteAvatar(ctx *context.Context) {
 	ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
 }
 
-// SettingsDelete response for deleting an organization
-func SettingsDelete(ctx *context.Context) {
-	ctx.Data["Title"] = ctx.Tr("org.settings")
-	ctx.Data["PageIsOrgSettings"] = true
-	ctx.Data["PageIsSettingsDelete"] = true
-
-	if ctx.Req.Method == http.MethodPost {
-		if ctx.Org.Organization.Name != ctx.FormString("org_name") {
-			ctx.Data["Err_OrgName"] = true
-			ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_org_name"), tplSettingsDelete, nil)
-			return
-		}
-
-		if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil {
-			if repo_model.IsErrUserOwnRepos(err) {
-				ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
-				ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
-			} else if packages_model.IsErrUserOwnPackages(err) {
-				ctx.Flash.Error(ctx.Tr("form.org_still_own_packages"))
-				ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
-			} else {
-				ctx.ServerError("DeleteOrganization", err)
-			}
-		} else {
-			log.Trace("Organization deleted: %s", ctx.Org.Organization.Name)
-			ctx.Redirect(setting.AppSubURL + "/")
-		}
+// SettingsDeleteOrgPost response for deleting an organization
+func SettingsDeleteOrgPost(ctx *context.Context) {
+	if ctx.Org.Organization.Name != ctx.FormString("org_name") {
+		ctx.JSONError(ctx.Tr("form.enterred_invalid_org_name"))
 		return
 	}
 
-	if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
-		ctx.ServerError("RenderUserOrgHeader", err)
+	if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false /* no purge */); err != nil {
+		if repo_model.IsErrUserOwnRepos(err) {
+			ctx.JSONError(ctx.Tr("form.org_still_own_repo"))
+		} else if packages_model.IsErrUserOwnPackages(err) {
+			ctx.JSONError(ctx.Tr("form.org_still_own_packages"))
+		} else {
+			log.Error("DeleteOrganization: %v", err)
+			ctx.JSONError(util.Iif(ctx.Doer.IsAdmin, err.Error(), string(ctx.Tr("org.settings.delete_failed"))))
+		}
 		return
 	}
 
-	ctx.HTML(http.StatusOK, tplSettingsDelete)
+	ctx.Flash.Success(ctx.Tr("org.settings.delete_successful", ctx.Org.Organization.Name))
+	ctx.JSONRedirect(setting.AppSubURL + "/")
 }
 
 // Webhooks render webhook list page
@@ -250,3 +214,40 @@ func Labels(ctx *context.Context) {
 
 	ctx.HTML(http.StatusOK, tplSettingsLabels)
 }
+
+// SettingsRenamePost response for renaming organization
+func SettingsRenamePost(ctx *context.Context) {
+	form := web.GetForm(ctx).(*forms.RenameOrgForm)
+	if ctx.HasError() {
+		ctx.JSONError(ctx.GetErrMsg())
+		return
+	}
+
+	oldOrgName, newOrgName := ctx.Org.Organization.Name, form.NewOrgName
+
+	if form.OrgName != oldOrgName {
+		ctx.JSONError(ctx.Tr("form.enterred_invalid_org_name"))
+		return
+	}
+	if newOrgName == oldOrgName {
+		ctx.JSONError(ctx.Tr("org.settings.rename_no_change"))
+		return
+	}
+
+	if err := user_service.RenameUser(ctx, ctx.Org.Organization.AsUser(), newOrgName); err != nil {
+		if user_model.IsErrUserAlreadyExist(err) {
+			ctx.JSONError(ctx.Tr("org.form.name_been_taken", newOrgName))
+		} else if db.IsErrNameReserved(err) {
+			ctx.JSONError(ctx.Tr("org.form.name_reserved", newOrgName))
+		} else if db.IsErrNamePatternNotAllowed(err) {
+			ctx.JSONError(ctx.Tr("org.form.name_pattern_not_allowed", newOrgName))
+		} else {
+			log.Error("RenameOrganization: %v", err)
+			ctx.JSONError(util.Iif(ctx.Doer.IsAdmin, err.Error(), string(ctx.Tr("org.settings.rename_failed"))))
+		}
+		return
+	}
+
+	ctx.Flash.Success(ctx.Tr("org.settings.rename_success", oldOrgName, newOrgName))
+	ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(newOrgName) + "/settings")
+}
diff --git a/routers/web/web.go b/routers/web/web.go
index 4012231c4b712..3040375def2c6 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -964,7 +964,8 @@ func registerWebRoutes(m *web.Router) {
 					addSettingsVariablesRoutes()
 				}, actions.MustEnableActions)
 
-				m.Methods("GET,POST", "/delete", org.SettingsDelete)
+				m.Post("/rename", web.Bind(forms.RenameOrgForm{}), org.SettingsRenamePost)
+				m.Post("/delete", org.SettingsDeleteOrgPost)
 
 				m.Group("/packages", func() {
 					m.Get("", org.Packages)
diff --git a/services/forms/org.go b/services/forms/org.go
index db182f7e96b5b..2ac18ef25cc63 100644
--- a/services/forms/org.go
+++ b/services/forms/org.go
@@ -36,7 +36,6 @@ func (f *CreateOrgForm) Validate(req *http.Request, errs binding.Errors) binding
 
 // UpdateOrgSettingForm form for updating organization settings
 type UpdateOrgSettingForm struct {
-	Name                      string `binding:"Required;Username;MaxSize(40)" locale:"org.org_name_holder"`
 	FullName                  string `binding:"MaxSize(100)"`
 	Email                     string `binding:"MaxSize(255)"`
 	Description               string `binding:"MaxSize(255)"`
@@ -53,6 +52,11 @@ func (f *UpdateOrgSettingForm) Validate(req *http.Request, errs binding.Errors)
 	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
+type RenameOrgForm struct {
+	OrgName    string `binding:"Required"`
+	NewOrgName string `binding:"Required;Username;MaxSize(40)" locale:"org.org_name_holder"`
+}
+
 // ___________
 // \__    ___/___ _____    _____
 //   |    |_/ __ \\__  \  /     \
diff --git a/templates/org/settings/delete.tmpl b/templates/org/settings/delete.tmpl
deleted file mode 100644
index e1ef471e34124..0000000000000
--- a/templates/org/settings/delete.tmpl
+++ /dev/null
@@ -1,35 +0,0 @@
-{{template "org/settings/layout_head" (dict "ctxData" . "pageClass" "organization settings delete")}}
-
-			
-				
-				
-					
-						
{{svg "octicon-alert"}} {{ctx.Locale.Tr "org.settings.delete_prompt"}}
-					
-					
-				
-			
 
-
-
-	
-	
-		
{{ctx.Locale.Tr "org.settings.delete_org_desc"}}
-	
-	{{template "base/modal_actions_confirm" .}}
-
 
-
-{{template "org/settings/layout_footer" .}}
diff --git a/templates/org/settings/navbar.tmpl b/templates/org/settings/navbar.tmpl
index ce792f667c4f9..58475de7e7a31 100644
--- a/templates/org/settings/navbar.tmpl
+++ b/templates/org/settings/navbar.tmpl
@@ -41,8 +41,5 @@
 			
 		
 		{{end}}
-		
-			{{ctx.Locale.Tr "org.settings.delete"}}
-		
 	
 
diff --git a/templates/org/settings/options.tmpl b/templates/org/settings/options.tmpl
index f4583bbe366b6..d94bb4c62b2e5 100644
--- a/templates/org/settings/options.tmpl
+++ b/templates/org/settings/options.tmpl
@@ -1,101 +1,97 @@
 {{template "org/settings/layout_head" (dict "ctxData" . "pageClass" "organization settings options")}}
-			
-				
-				
+
+{{template "org/settings/options_dangerzone" .}}
+
 {{template "org/settings/layout_footer" .}}
diff --git a/templates/org/settings/options_dangerzone.tmpl b/templates/org/settings/options_dangerzone.tmpl
new file mode 100644
index 0000000000000..01cf3fd4051dc
--- /dev/null
+++ b/templates/org/settings/options_dangerzone.tmpl
@@ -0,0 +1,93 @@
+
+
+	
+		
+			
+				
{{ctx.Locale.Tr "org.settings.rename"}}
+				
{{ctx.Locale.Tr "org.settings.rename_desc"}}
+			
+			
+				
+			
+		
+
+		
+			
+				
{{ctx.Locale.Tr "org.settings.delete_account"}}
+				
{{ctx.Locale.Tr "org.settings.delete_prompt"}}
+			
+			
+				
+			
+		
+	
+
+
+
+	
+	
+		
+			- {{ctx.Locale.Tr "org.settings.rename_notices_1"}}
 
+			- {{ctx.Locale.Tr "org.settings.rename_notices_2"}}
 
+		
+		
+	
+
+
+
+	
+	
+		
+			- {{ctx.Locale.Tr "org.settings.delete_notices_1"}}
 
+			- {{ctx.Locale.Tr "org.settings.delete_notices_2" .Org.Name}}
 
+			- {{ctx.Locale.Tr "org.settings.delete_notices_3" .Org.Name}}
 
+			- {{ctx.Locale.Tr "org.settings.delete_notices_4" .Org.Name}}
 
+		
+		
+	
+
diff --git a/web_src/css/base.css b/web_src/css/base.css
index b50abf79f1d2c..dc58fb850a134 100644
--- a/web_src/css/base.css
+++ b/web_src/css/base.css
@@ -30,6 +30,10 @@
   --page-spacing: 16px; /* space between page elements */
   --page-margin-x: 32px; /* minimum space on left and right side of page */
   --page-space-bottom: 64px; /* space between last page element and footer */
+
+  /* z-index */
+  --z-index-modal: 1001; /* modal dialog, hard-coded from Fomantic modal.css */
+  --z-index-toast: 1002; /* should be larger than modal */
 }
 
 @media (min-width: 768px) and (max-width: 1200px) {
diff --git a/web_src/css/modules/dimmer.css b/web_src/css/modules/dimmer.css
index 89248213707e3..7d1ca6171aa9e 100644
--- a/web_src/css/modules/dimmer.css
+++ b/web_src/css/modules/dimmer.css
@@ -20,7 +20,7 @@
   opacity: 1;
 }
 
-.ui.dimmer > * {
+.ui.dimmer > .ui.modal {
   position: static;
   margin-top: auto !important;
   margin-bottom: auto !important;
diff --git a/web_src/css/modules/toast.css b/web_src/css/modules/toast.css
index 1145f3b1b58be..330d3b176eb39 100644
--- a/web_src/css/modules/toast.css
+++ b/web_src/css/modules/toast.css
@@ -3,7 +3,7 @@
   position: fixed;
   opacity: 0;
   transition: all .2s ease;
-  z-index: 500;
+  z-index: var(--z-index-toast);
   border-radius: var(--border-radius);
   box-shadow: 0 8px 24px var(--color-shadow);
   display: flex;
diff --git a/web_src/fomantic/build/components/dropdown.js b/web_src/fomantic/build/components/dropdown.js
index 85530c79912ee..3ad098486516b 100644
--- a/web_src/fomantic/build/components/dropdown.js
+++ b/web_src/fomantic/build/components/dropdown.js
@@ -525,7 +525,7 @@ $.fn.dropdown = function(parameters) {
               return true;
             }
             if(settings.onShow.call(element) !== false) {
-              settings.onAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items
+              $module.fomanticExt.onDropdownAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items
               module.animate.show(function() {
                 if( module.can.click() ) {
                   module.bind.intent();
@@ -753,7 +753,7 @@ $.fn.dropdown = function(parameters) {
               if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
                 module.show();
               }
-              settings.onAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items
+              $module.fomanticExt.onDropdownAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items
             }
           ;
           if(settings.useLabels && module.has.maxSelections()) {
@@ -3994,8 +3994,6 @@ $.fn.dropdown.settings = {
   onShow        : function(){},
   onHide        : function(){},
 
-  onAfterFiltered: function(){}, // GITEA-PATCH: callback to correctly handle the filtered items
-
   /* Component */
   name           : 'Dropdown',
   namespace      : 'dropdown',
diff --git a/web_src/fomantic/build/components/modal.js b/web_src/fomantic/build/components/modal.js
index 420ecc250baa1..3f578ccfccc7d 100644
--- a/web_src/fomantic/build/components/modal.js
+++ b/web_src/fomantic/build/components/modal.js
@@ -467,7 +467,7 @@ $.fn.modal = function(parameters) {
             ignoreRepeatedEvents = false;
             return false;
           }
-
+          $module.fomanticExt.onModalBeforeHidden.call(element); // GITEA-PATCH: handle more UI updates before hidden
           if( module.is.animating() || module.is.active() ) {
             if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
               module.remove.active();
@@ -641,7 +641,7 @@ $.fn.modal = function(parameters) {
               $module
                   .off('mousedown' + elementEventNamespace)
               ;
-            }           
+            }
             $dimmer
               .off('mousedown' + elementEventNamespace)
             ;
@@ -877,7 +877,7 @@ $.fn.modal = function(parameters) {
                       ? $(document).scrollTop() + settings.padding
                       : $(document).scrollTop() + (module.cache.contextHeight - module.cache.height - settings.padding),
                   marginLeft: -(module.cache.width / 2)
-                }) 
+                })
               ;
             } else {
               $module
@@ -886,7 +886,7 @@ $.fn.modal = function(parameters) {
                     ? -(module.cache.height / 2)
                     : settings.padding / 2,
                   marginLeft: -(module.cache.width / 2)
-                }) 
+                })
               ;
             }
             module.verbose('Setting modal offset for legacy mode');
diff --git a/web_src/js/features/common-fetch-action.ts b/web_src/js/features/common-fetch-action.ts
index 5b6430779fd06..93597134540d8 100644
--- a/web_src/js/features/common-fetch-action.ts
+++ b/web_src/js/features/common-fetch-action.ts
@@ -1,5 +1,5 @@
 import {request} from '../modules/fetch.ts';
-import {showErrorToast} from '../modules/toast.ts';
+import {hideToastsAll, showErrorToast} from '../modules/toast.ts';
 import {addDelegatedEventListener, submitEventSubmitter} from '../utils/dom.ts';
 import {confirmModal} from './comp/ConfirmModal.ts';
 import type {RequestOpts} from '../types.ts';
@@ -24,6 +24,7 @@ function fetchActionDoRedirect(redirect: string) {
 
 async function fetchActionDoRequest(actionElem: HTMLElement, url: string, opt: RequestOpts) {
   try {
+    hideToastsAll();
     const resp = await request(url, opt);
     if (resp.status === 200) {
       let {redirect} = await resp.json();
@@ -35,7 +36,9 @@ async function fetchActionDoRequest(actionElem: HTMLElement, url: string, opt: R
         window.location.reload();
       }
       return;
-    } else if (resp.status >= 400 && resp.status < 500) {
+    }
+
+    if (resp.status >= 400 && resp.status < 500) {
       const data = await resp.json();
       // the code was quite messy, sometimes the backend uses "err", sometimes it uses "error", and even "user_error"
       // but at the moment, as a new approach, we only use "errorMessage" here, backend can use JSONError() to respond.
diff --git a/web_src/js/modules/fomantic/dropdown.ts b/web_src/js/modules/fomantic/dropdown.ts
index 02fee5a267d85..ccc22073d7fe5 100644
--- a/web_src/js/modules/fomantic/dropdown.ts
+++ b/web_src/js/modules/fomantic/dropdown.ts
@@ -9,9 +9,9 @@ const fomanticDropdownFn = $.fn.dropdown;
 // use our own `$().dropdown` function to patch Fomantic's dropdown module
 export function initAriaDropdownPatch() {
   if ($.fn.dropdown === ariaDropdownFn) throw new Error('initAriaDropdownPatch could only be called once');
-  $.fn.dropdown.settings.onAfterFiltered = onAfterFiltered;
   $.fn.dropdown = ariaDropdownFn;
   $.fn.fomanticExt.onResponseKeepSelectedItem = onResponseKeepSelectedItem;
+  $.fn.fomanticExt.onDropdownAfterFiltered = onDropdownAfterFiltered;
   (ariaDropdownFn as FomanticInitFunction).settings = fomanticDropdownFn.settings;
 }
 
@@ -71,7 +71,7 @@ function updateSelectionLabel(label: HTMLElement) {
   }
 }
 
-function onAfterFiltered(this: any) {
+function onDropdownAfterFiltered(this: any) {
   const $dropdown = $(this).closest('.ui.dropdown'); // "this" can be the "ui dropdown" or "