diff --git a/web/src/tippyjs.ts b/web/src/tippyjs.ts index 3815469bdf..78fbf87405 100644 --- a/web/src/tippyjs.ts +++ b/web/src/tippyjs.ts @@ -258,6 +258,20 @@ export function initialize(): void { appendTo: () => document.body, }); + tippy.delegate("body", { + target: ".add-task-wrapper", + onShow(instance) { + const $elem = $(instance.reference); + const content = $elem.attr("data-tippy-content"); + if (content === undefined) { + return false; + } + instance.setContent(content); + return undefined; + }, + appendTo: () => document.body, + }); + $("body").on( "blur", ".message_control_button, .delete-selected-drafts-button-container", diff --git a/web/src/todo_widget.ts b/web/src/todo_widget.ts index 19781bd9a0..83bfab2047 100644 --- a/web/src/todo_widget.ts +++ b/web/src/todo_widget.ts @@ -1,4 +1,5 @@ import $ from "jquery"; +import _ from "lodash"; import assert from "minimalistic-assert"; import {z} from "zod"; @@ -404,6 +405,13 @@ export function activate({ const html = render_widgets_todo_widget(); $elem.html(html); + // This throttling ensures that the function runs only after the user stops typing. + const throttled_update_add_task_button = _.throttle(update_add_task_button, 300); + $elem.find("input.add-task").on("keyup", (e) => { + e.stopPropagation(); + throttled_update_add_task_button(); + }); + $elem.find("input.todo-task-list-title").on("keyup", (e) => { e.stopPropagation(); update_edit_controls(); @@ -444,13 +452,10 @@ export function activate({ const task = $elem.find("input.add-task").val()?.trim() ?? ""; const desc = $elem.find("input.add-desc").val()?.trim() ?? ""; - if (task === "") { - return; - } - $elem.find("input.add-task").val("").trigger("focus"); $elem.find("input.add-desc").val(""); + // This case should not generally occur. const task_exists = task_data.name_in_use(task); if (task_exists) { $elem.find(".widget-error").text($t({defaultMessage: "Task already exists"})); @@ -462,6 +467,30 @@ export function activate({ }); } + function update_add_task_button(): void { + const task = $elem.find("input.add-task").val()?.trim() ?? ""; + const task_exists = task_data.name_in_use(task); + const $add_task_wrapper = $elem.find(".add-task-wrapper"); + const $add_task_button = $elem.find("button.add-task"); + + if (task === "") { + $add_task_wrapper.attr( + "data-tippy-content", + $t({defaultMessage: "Name the task before adding."}), + ); + $add_task_button.prop("disabled", true); + } else if (task_exists) { + $add_task_wrapper.attr( + "data-tippy-content", + $t({defaultMessage: "Cannot add duplicate task."}), + ); + $add_task_button.prop("disabled", true); + } else { + $add_task_wrapper.removeAttr("data-tippy-content"); + $add_task_button.prop("disabled", false); + } + } + function render_results(): void { const widget_data = task_data.get_widget_data(); const html = render_widgets_todo_widget_tasks(widget_data); @@ -487,6 +516,8 @@ export function activate({ const data = task_data.handle.strike.outbound(key); callback(data); }); + + update_add_task_button(); } const handle_events = function (events: Event[]): void { diff --git a/web/styles/widgets.css b/web/styles/widgets.css index f8057358b1..55b4409d7c 100644 --- a/web/styles/widgets.css +++ b/web/styles/widgets.css @@ -237,6 +237,13 @@ button { transition: 0.2s ease; transition-property: background-color, border-color, color; } + + &:disabled { + cursor: not-allowed; + filter: saturate(0); + background-color: var(--color-background-zulip-button-disabled); + color: hsl(0deg 3% 52%); + } } } @@ -308,3 +315,17 @@ input { .current-user-vote { background-color: hsl(156deg 10% 90% / 90%); } + +.add-task-wrapper { + display: inline; + position: relative; + z-index: 1; + + /* Unlike other browsers like Chrome, Microsoft Edge, etc., + Firefox does not automatically display the "not-allowed" + cursor for disabled elements. The below css ensures that the + correct cursor is shown across all browsers. */ + &:hover { + cursor: not-allowed; + } +} diff --git a/web/templates/widgets/todo_widget.hbs b/web/templates/widgets/todo_widget.hbs index 0a593c2217..a7c5f110e4 100644 --- a/web/templates/widgets/todo_widget.hbs +++ b/web/templates/widgets/todo_widget.hbs @@ -13,7 +13,9 @@
- +
+ +