|
112 | 112 |
|
113 | 113 | .schema-title { |
114 | 114 | margin: 0; |
115 | | - padding: 14px 14px; |
116 | 115 | background: var(--header-bg); |
117 | 116 | color: var(--table-header-text); |
118 | 117 | font-size: 1.3rem; |
119 | 118 | line-height: 1.25; |
120 | 119 | text-align: center; |
121 | 120 | text-transform: none; |
122 | | - transition: filter 140ms ease; |
| 121 | + transition: background-color 140ms ease; |
| 122 | + display: flex; |
| 123 | + align-items: center; |
| 124 | + justify-content: center; |
123 | 125 | cursor: default; |
124 | 126 | } |
125 | 127 |
|
126 | 128 | .schema-title:hover { |
127 | | - filter: brightness(0.96); |
| 129 | + background: var(--header-bg); |
| 130 | + background: color-mix(in srgb, var(--header-bg) 92%, #000 8%); |
128 | 131 | } |
129 | 132 |
|
130 | 133 | .schema-title-content { |
131 | 134 | display: inline-flex; |
132 | 135 | align-items: center; |
| 136 | + justify-content: center; |
133 | 137 | gap: 8px; |
134 | | - } |
135 | | - |
136 | | - .schema-title-link { |
137 | | - color: inherit; |
138 | | - text-decoration: none; |
139 | | - border-radius: 999px; |
140 | | - padding: 3px 10px; |
141 | | - transition: |
142 | | - background-color 140ms ease, |
143 | | - box-shadow 140ms ease, |
144 | | - transform 140ms ease; |
145 | | - } |
146 | | - |
147 | | - .schema-title-link:hover, |
148 | | - .schema-title-link:focus-visible { |
149 | | - text-decoration: none; |
150 | | - background: rgba(255, 255, 255, 0.6); |
151 | | - box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.18); |
152 | | - transform: translateY(-1px); |
| 138 | + width: 100%; |
| 139 | + padding: 14px 14px; |
153 | 140 | } |
154 | 141 |
|
155 | 142 | .schema-title-icon { |
|
186 | 173 | line-height: 1.2; |
187 | 174 | font-size: 1.2rem; |
188 | 175 | background: #fff; |
189 | | - transition: background-color 140ms ease; |
| 176 | + transition: background-color 0.15s ease; |
190 | 177 | cursor: default; |
191 | 178 | } |
192 | 179 |
|
193 | 180 | .schema-field:hover { |
194 | | - background: #eaeaea; |
| 181 | + background: #f0f0f0; |
195 | 182 | box-shadow: none; |
196 | 183 | } |
197 | 184 |
|
| 185 | + .schema-title[data-bs-toggle="tooltip"], |
| 186 | + .schema-field[data-bs-toggle="tooltip"] { |
| 187 | + cursor: pointer; |
| 188 | + } |
| 189 | + |
198 | 190 | .schema-field-content { |
199 | 191 | display: inline-flex; |
200 | 192 | align-items: center; |
|
230 | 222 | stroke-linecap: round; |
231 | 223 | stroke-linejoin: round; |
232 | 224 | marker-end: url(#connector-arrowhead); |
233 | | - pointer-events: stroke; |
234 | | - cursor: pointer; |
| 225 | + pointer-events: none; |
| 226 | + cursor: default; |
235 | 227 | transition: |
236 | 228 | opacity 120ms ease, |
237 | 229 | stroke-width 120ms ease; |
|
855 | 847 | const heading = document.createElement("h2"); |
856 | 848 | heading.className = "schema-title"; |
857 | 849 | heading.id = `title-${tableId}`; |
858 | | - const headingTooltipMarkdown = firstMarkdownParagraph(table.description); |
| 850 | + const tableDocHref = CONFIG.tableDocs[table.name]; |
| 851 | + const headingTooltipMarkdown = [ |
| 852 | + firstMarkdownParagraph(table.description), |
| 853 | + tableDocHref ? `[Open table page](${tableDocHref})` : "", |
| 854 | + ] |
| 855 | + .filter(Boolean) |
| 856 | + .join("\n\n"); |
859 | 857 | if (headingTooltipMarkdown) { |
860 | 858 | heading.setAttribute("data-bs-toggle", "tooltip"); |
861 | 859 | heading.setAttribute("data-bs-title", headingTooltipMarkdown); |
862 | 860 | heading.setAttribute("data-md-description", headingTooltipMarkdown); |
863 | 861 | heading.setAttribute("data-bs-custom-class", "schema-tooltip"); |
864 | 862 | heading.setAttribute("data-bs-placement", "top"); |
865 | 863 | } |
866 | | - const tableDocHref = CONFIG.tableDocs[table.name]; |
867 | | - const titleContent = document.createElement(tableDocHref ? "a" : "span"); |
868 | | - titleContent.className = `schema-title-content${tableDocHref ? " schema-title-link" : ""}`; |
869 | | - if (tableDocHref) { |
870 | | - titleContent.href = tableDocHref; |
871 | | - titleContent.setAttribute("aria-label", `${table.name} table documentation`); |
872 | | - } |
| 864 | + const titleContent = document.createElement("span"); |
| 865 | + titleContent.className = "schema-title-content"; |
873 | 866 | const iconPath = CONFIG.tableIcons[table.name]; |
874 | 867 | if (iconPath) { |
875 | 868 | const icon = document.createElement("span"); |
|
1079 | 1072 | if (!window.bootstrap || !window.bootstrap.Tooltip) { |
1080 | 1073 | return; |
1081 | 1074 | } |
1082 | | - const hideDelayMs = 150; |
1083 | 1075 | const elements = document.querySelectorAll('[data-bs-toggle="tooltip"]'); |
1084 | 1076 | for (const el of elements) { |
1085 | 1077 | const existing = window.bootstrap.Tooltip.getInstance(el); |
|
1089 | 1081 | const markdown = |
1090 | 1082 | el.getAttribute("data-md-description") || el.getAttribute("data-bs-title") || ""; |
1091 | 1083 | const htmlTitle = markdownToHtml(markdown); |
1092 | | - const tooltip = new window.bootstrap.Tooltip(el, { |
| 1084 | + new window.bootstrap.Tooltip(el, { |
1093 | 1085 | container: "body", |
1094 | | - trigger: "manual", |
| 1086 | + trigger: "click", |
1095 | 1087 | html: true, |
1096 | 1088 | sanitize: false, |
1097 | 1089 | title: htmlTitle, |
1098 | 1090 | }); |
1099 | 1091 |
|
1100 | | - let hideTimer = null; |
1101 | | - const clearHideTimer = () => { |
1102 | | - if (hideTimer) { |
1103 | | - window.clearTimeout(hideTimer); |
1104 | | - hideTimer = null; |
| 1092 | + // Keep only one diagram tooltip open at a time. |
| 1093 | + el.addEventListener("show.bs.tooltip", () => { |
| 1094 | + for (const otherEl of elements) { |
| 1095 | + if (otherEl === el) { |
| 1096 | + continue; |
| 1097 | + } |
| 1098 | + const otherTooltip = window.bootstrap.Tooltip.getInstance(otherEl); |
| 1099 | + if (otherTooltip) { |
| 1100 | + otherTooltip.hide(); |
| 1101 | + } |
| 1102 | + } |
| 1103 | + }); |
| 1104 | + } |
| 1105 | + |
| 1106 | + if (document.body.dataset.schemaTooltipDismissBound !== "true") { |
| 1107 | + document.body.dataset.schemaTooltipDismissBound = "true"; |
| 1108 | + document.addEventListener("click", (event) => { |
| 1109 | + const target = event.target; |
| 1110 | + if (!(target instanceof Element)) { |
| 1111 | + return; |
1105 | 1112 | } |
1106 | | - }; |
1107 | | - const showTooltip = () => { |
1108 | | - clearHideTimer(); |
1109 | | - tooltip.show(); |
1110 | | - }; |
1111 | | - const scheduleHide = () => { |
1112 | | - clearHideTimer(); |
1113 | | - hideTimer = window.setTimeout(() => { |
1114 | | - tooltip.hide(); |
1115 | | - }, hideDelayMs); |
1116 | | - }; |
1117 | | - |
1118 | | - el.addEventListener("mouseenter", showTooltip); |
1119 | | - el.addEventListener("focusin", showTooltip); |
1120 | | - el.addEventListener("mouseleave", scheduleHide); |
1121 | | - el.addEventListener("focusout", scheduleHide); |
1122 | | - el.addEventListener("shown.bs.tooltip", () => { |
1123 | | - const tipEl = |
1124 | | - typeof tooltip.getTipElement === "function" ? tooltip.getTipElement() : tooltip.tip; |
1125 | | - if (!tipEl || tipEl.dataset.hoverBound === "true") { |
| 1113 | + if (target.closest('[data-bs-toggle="tooltip"], .tooltip')) { |
1126 | 1114 | return; |
1127 | 1115 | } |
1128 | | - tipEl.dataset.hoverBound = "true"; |
1129 | | - tipEl.addEventListener("mouseenter", clearHideTimer); |
1130 | | - tipEl.addEventListener("mouseleave", scheduleHide); |
| 1116 | + const activeElements = document.querySelectorAll('[data-bs-toggle="tooltip"]'); |
| 1117 | + for (const el of activeElements) { |
| 1118 | + const tooltip = window.bootstrap.Tooltip.getInstance(el); |
| 1119 | + if (tooltip) { |
| 1120 | + tooltip.hide(); |
| 1121 | + } |
| 1122 | + } |
1131 | 1123 | }); |
1132 | 1124 | } |
1133 | 1125 | } |
|
1521 | 1513 | renderTables(tables); |
1522 | 1514 | initTooltips(); |
1523 | 1515 | drawConnectors(state.relations); |
1524 | | - setupConnectorHover(); |
1525 | 1516 | setLoadingState(false, "", "loading"); |
1526 | 1517 | setLegendState(true); |
1527 | 1518 | } catch (err) { |
|
0 commit comments