feat: show description on click

This commit is contained in:
sokumon 2026-02-06 15:17:59 +05:30
parent 83617f20f6
commit f2b5c3f60f
7 changed files with 105 additions and 5 deletions

View file

@ -82,7 +82,8 @@
"documentation_url",
"placeholder",
"oldfieldname",
"oldfieldtype"
"oldfieldtype",
"show_description_on_click"
],
"fields": [
{
@ -633,6 +634,12 @@
"fieldtype": "Select",
"label": "Button Color",
"options": "\nDefault\nPrimary\nInfo\nSuccess\nWarning\nDanger"
},
{
"default": "0",
"fieldname": "show_description_on_click",
"fieldtype": "Check",
"label": "Show Description on Click"
}
],
"grid_page_length": 50,
@ -640,7 +647,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2026-01-06 01:37:29.723265",
"modified": "2026-02-06 15:13:03.688027",
"modified_by": "Administrator",
"module": "Core",
"name": "DocField",

View file

@ -14,10 +14,10 @@ class DocField(Document):
if TYPE_CHECKING:
from frappe.types import DF
alignment: DF.Literal["", "Left", "Center", "Right"]
allow_bulk_edit: DF.Check
allow_in_quick_entry: DF.Check
allow_on_submit: DF.Check
alignment: DF.Literal["", "Left", "Center", "Right"]
bold: DF.Check
button_color: DF.Literal["", "Default", "Primary", "Info", "Success", "Warning", "Danger"]
collapsible: DF.Check
@ -117,6 +117,7 @@ class DocField(Document):
search_index: DF.Check
set_only_once: DF.Check
show_dashboard: DF.Check
show_description_on_click: DF.Check
show_on_timeline: DF.Check
sort_options: DF.Check
sticky: DF.Check

View file

@ -1,3 +1,4 @@
import { createPopper } from "@popperjs/core";
frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control {
static horizontal = true;
make() {
@ -7,7 +8,7 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control
// set description
this.set_max_width();
this.info_card_display = false;
// set initial value if set
if (this.df.initial_value) {
this.set_value(this.df.initial_value);
@ -147,6 +148,7 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control
me.set_description();
me.set_label();
me.set_doc_url();
// me.set_info_url();
me.set_mandatory(me.value);
me.set_bold();
me.set_required();
@ -189,6 +191,7 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control
}
}
set_label(label) {
const me = this;
if (label) this.df.label = label;
if (this.only_input || this.df.label == this._label) return;
@ -197,14 +200,64 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control
this.label_span.innerHTML =
(icon ? '<i class="' + icon + '"></i> ' : "") +
__(this.df.label, null, this.df.parent) || "&nbsp;";
if (this.df.show_description_on_click) {
$(`<a>${frappe.utils.icon("message-circle-question-mark", "sm")}</a>`).appendTo(
$(this.label_span)
);
this.$info_card = $("<div class='info-card'></div>").appendTo(this.label_span);
$(this.label_area).css({
display: "flex",
gap: "6px",
"align-items": "center",
"white-space": "nowrap",
});
let popper = createPopper(
$(this.label_span).find("a").get(0),
this.$info_card.get(0),
{
modifiers: [
{
name: "offset",
options: {
offset: [0, 8],
},
},
],
}
);
$(this.label_span)
.find("a")
.on("click", (event) => {
event.preventDefault();
me.$info_card.html("");
let card = new frappe.ui.SidebarCard({
// title: "Trial ends in 3 days",
// icon: "info",
message: me.df.description,
parent: me.$info_card,
// primary_action_icon: "zap",
// primary_action_label: "Upgrade",
close_button: true,
// primary_action: () => {},
});
if (me.info_card_display) {
me.info_card_display = false;
me.$info_card.removeAttr("data-show");
} else {
me.info_card_display = true;
me.$info_card.attr("data-show", "");
popper.update();
}
});
}
this._label = this.df.label;
}
set_doc_url() {
if (this.df.show_description_on_click) return;
let unsupported_fieldtypes = frappe.model.no_value_type.filter(
(x) => frappe.model.table_fields.indexOf(x) === -1
);
if (
!this.df.label ||
!this.df?.documentation_url ||
@ -214,6 +267,7 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control
let $help = this.$wrapper.find("span.help");
$help.empty();
$(`<a
href="${frappe.utils.escape_html(this.df.documentation_url)}"
target="_blank"
@ -224,6 +278,7 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control
}
set_description(description) {
if (this.df.show_description_on_click) return;
if (description !== undefined) {
this.df.description = description;
}

View file

@ -1,4 +1,5 @@
<div class="sidebar-card d-inline-flex flex-column px-2 py-2">
{% if(!card.close_button) { %}
<div>
<div class="card-title-container">
{%= frappe.utils.icon(card.icon, "sm", "", "", "card-icon") %}
@ -6,5 +7,17 @@
</div>
<div class="sidebar-card-description">{{ card.message }}</div>
</div>
{% } else { %}
<div class="card-title-container card-close-button">
{%= frappe.utils.icon(card.icon, "sm", "", "", "card-icon") %}
<span class="flex flex-column">
<div class="sidebar-card-title">{{ card.title }}</div>
<div class="sidebar-card-description">{{ card.message }}</div>
</span>
{%= frappe.utils.icon("x","sm", "", "", "card-icon") %}
</div>
{% } %}
{% if(card.primary_action_label) { %}
<button class="sidebar-card-button btn">{{ frappe.utils.icon(card.primary_action_icon, "sm", "", "", "", true) }}{{ card.primary_action_label }}</button>
{% } %}
</div>

View file

@ -8,6 +8,9 @@ frappe.ui.SidebarCard = class SidebarCard {
this.setup();
}
make() {
if (!this.icon) {
this.icon = "info";
}
this.card = $(
frappe.render_template("sidebar_card", {
card: this,

View file

@ -174,3 +174,15 @@ body {
.margin-right {
margin-right: var(--margin-sm);
}
.info-card {
display: none;
}
.info-card[data-show] {
display: block;
z-index: 1;
.sidebar-card {
box-shadow: 0px 18px 22px -6px rgba(0, 0, 0, 0.1), 0px 0px 6px 3px rgba(0, 0, 0, 0.03),
0px 0px 1.5px 0px rgba(0, 0, 0, 0.18);
}
}

View file

@ -10,6 +10,14 @@
@include get_textstyle("base", "medium");
}
}
.card-close-button {
align-items: normal;
.card-icon {
flex-shrink: 0;
margin-top: 2px;
margin-bottom: 2px;
}
}
.sidebar-card {
width: 100%;
background-color: var(--surface-modal);
@ -19,6 +27,7 @@
}
.sidebar-card-description {
@include get_textstyle("sm", "regular");
white-space: wrap;
}
.sidebar-card-button {
display: flex;