mirror of
https://github.com/zulip/zulip.git
synced 2025-10-28 10:33:54 +00:00
inline_topic_edit: Disable save button and show tooltip on empty topic.
This commit disables the save button when the topic name is considered as empty as part of the `realm_mandatory_topics` being set to True. Since disabled elements do not fire events, it is not possible to trigger tippy tooltips on disabled elements – such as the Save button in the inline topic edit UI. Thus this commit adds a tooltip to the disabled save button by wrapping/unwrapping it inside a `span` wrapper pragmatically via the `ui_util.disable_element_and_add_tooltip` and `ui_util.enable_element_and_remove_tooltip` helper methods.
This commit is contained in:
@@ -57,6 +57,7 @@ import * as sub_store from "./sub_store.ts";
|
|||||||
import * as timerender from "./timerender.ts";
|
import * as timerender from "./timerender.ts";
|
||||||
import * as typing from "./typing.ts";
|
import * as typing from "./typing.ts";
|
||||||
import * as ui_report from "./ui_report.ts";
|
import * as ui_report from "./ui_report.ts";
|
||||||
|
import * as ui_util from "./ui_util.ts";
|
||||||
import * as upload from "./upload.ts";
|
import * as upload from "./upload.ts";
|
||||||
import {the} from "./util.ts";
|
import {the} from "./util.ts";
|
||||||
import * as util from "./util.ts";
|
import * as util from "./util.ts";
|
||||||
@@ -453,6 +454,25 @@ function handle_inline_topic_edit_change(this: HTMLInputElement): void {
|
|||||||
// as that probably means the user is trying to fix the error.
|
// as that probably means the user is trying to fix the error.
|
||||||
$inline_topic_edit_input.removeClass("invalid-input");
|
$inline_topic_edit_input.removeClass("invalid-input");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const $topic_edit_save_button = $inline_topic_edit_input
|
||||||
|
.closest(".topic_edit_form")
|
||||||
|
.find(".topic_edit_save");
|
||||||
|
if (realm.realm_mandatory_topics && util.is_topic_name_considered_empty(this.value)) {
|
||||||
|
// When the topic is mandatory in a realm and the new topic is considered empty,
|
||||||
|
// we disable the save button and show a tooltip with an error message.
|
||||||
|
ui_util.disable_element_and_add_tooltip(
|
||||||
|
$topic_edit_save_button,
|
||||||
|
$t({defaultMessage: "Topics are required in this organization."}),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($topic_edit_save_button.parent().hasClass("disabled-tooltip")) {
|
||||||
|
// If we reach here, it means the save button was disabled previously
|
||||||
|
// and the user has started typing in the input field, probably to fix
|
||||||
|
// the error. So, we re-enable the save button and remove the tooltip.
|
||||||
|
ui_util.enable_element_and_remove_tooltip($topic_edit_save_button);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function timer_text(seconds_left: number): string {
|
function timer_text(seconds_left: number): string {
|
||||||
|
|||||||
@@ -696,4 +696,13 @@ export function initialize(): void {
|
|||||||
instance.destroy();
|
instance.destroy();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tippy.delegate("body", {
|
||||||
|
target: ".disabled-tooltip",
|
||||||
|
trigger: "focus mouseenter",
|
||||||
|
appendTo: () => document.body,
|
||||||
|
onHidden(instance) {
|
||||||
|
instance.destroy();
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
|
import type * as tippy from "tippy.js";
|
||||||
|
|
||||||
import * as blueslip from "./blueslip.ts";
|
import * as blueslip from "./blueslip.ts";
|
||||||
import * as hash_parser from "./hash_parser.ts";
|
import * as hash_parser from "./hash_parser.ts";
|
||||||
@@ -271,3 +272,31 @@ export function matches_viewport_state(state_string: string): boolean {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function disable_element_and_add_tooltip($element: JQuery, tooltip_text: string): void {
|
||||||
|
// Since disabled elements do not fire events, it is not possible to trigger
|
||||||
|
// tippy tooltips on disabled elements. So, as a workaround, we wrap the
|
||||||
|
// disabled element in a span and show the tooltip on this wrapper instead.
|
||||||
|
// https://atomiks.github.io/tippyjs/v6/constructor/#disabled-elements
|
||||||
|
if ($element.prop("disabled")) {
|
||||||
|
// If already disabled, there's nothing to do.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$element.prop("disabled", true);
|
||||||
|
const $tooltip_target_wrapper = $("<span>");
|
||||||
|
$tooltip_target_wrapper.addClass("disabled-tooltip");
|
||||||
|
$tooltip_target_wrapper.attr("data-tippy-content", tooltip_text).attr("tabindex", "0");
|
||||||
|
$element.wrap($tooltip_target_wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function enable_element_and_remove_tooltip($element: JQuery): void {
|
||||||
|
// This method reverses the effects of disable_element_and_add_tooltip,
|
||||||
|
// and explicitly removes any attached tooltips on the wrapper to prevent
|
||||||
|
// ghost tooltips.
|
||||||
|
$element.prop("disabled", false);
|
||||||
|
const tooltip_wrapper: tippy.ReferenceElement = $element.parent(".disabled-tooltip")[0]!;
|
||||||
|
if (tooltip_wrapper?._tippy) {
|
||||||
|
tooltip_wrapper._tippy.destroy();
|
||||||
|
}
|
||||||
|
$element.unwrap(".disabled-tooltip");
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,6 +46,12 @@
|
|||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
clip-path: inset(-3px);
|
clip-path: inset(-3px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: default;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-button-label {
|
.action-button-label {
|
||||||
@@ -409,6 +415,12 @@
|
|||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
clip-path: inset(-3px);
|
clip-path: inset(-3px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: default;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button-neutral {
|
.icon-button-neutral {
|
||||||
|
|||||||
@@ -284,7 +284,7 @@
|
|||||||
|
|
||||||
/* these are converting grey things to "new grey".
|
/* these are converting grey things to "new grey".
|
||||||
:disabled rules are exploded for CSS selector performance reasons. */
|
:disabled rules are exploded for CSS selector performance reasons. */
|
||||||
button:disabled,
|
button:disabled:not(.action-button, .icon-button),
|
||||||
option:disabled,
|
option:disabled,
|
||||||
select:disabled,
|
select:disabled,
|
||||||
textarea:disabled,
|
textarea:disabled,
|
||||||
|
|||||||
Reference in New Issue
Block a user