yummy-guide-generic-administrate 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +31 -0
- data/app/assets/javascripts/yummy_guide_administrate/column_resizer.js +66 -0
- data/app/assets/javascripts/yummy_guide_administrate/tooltips.js +214 -0
- data/app/assets/stylesheets/yummy_guide_administrate/_tooltips.scss +85 -0
- data/app/assets/stylesheets/yummy_guide_administrate/components.scss +271 -0
- data/app/dashboards/yummy_guide/administrate/application_dashboard.rb +11 -0
- data/app/helpers/yummy_guide/administrate/collection_helper.rb +128 -0
- data/app/helpers/yummy_guide/administrate/tooltip_helper.rb +57 -0
- data/app/views/yummy_guide/administrate/administrate/application/_collection.html.erb +22 -4
- data/lib/yummy_guide/administrate/engine.rb +2 -2
- data/lib/yummy_guide/administrate/version.rb +1 -1
- data/lib/yummy_guide/administrate.rb +1 -0
- data/spec/yummy_guide/administrate/application_dashboard_spec.rb +17 -0
- data/spec/yummy_guide/administrate/collection_helper_spec.rb +132 -0
- data/spec/yummy_guide/administrate/column_resizer_asset_spec.rb +40 -66
- data/spec/yummy_guide/administrate/tooltip_asset_spec.rb +63 -0
- data/spec/yummy_guide/administrate/tooltip_helper_spec.rb +96 -0
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3940f84fd25e7fe60419f17273656e50af22465caf4bbfa29e1ac209d03b5bd4
|
|
4
|
+
data.tar.gz: 3bc3455f747754d483ee5329c5d4991289eaac0630961a808558f551e7f9c819
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b9843e5fdc03dd2e08330368cb267ac888fa1d5327bad40550b44a0960881d6d4cd87b77a0e2cad10f70d3d04f503d88b39192f20f82e4e3adc04910e5af3a7e
|
|
7
|
+
data.tar.gz: ba1be8f0226de1a9bd37650827529ea7b5c59d2d680f4d31066f86246fcb3085a87b9a5c1b6c91ccce5d7ffd0360e98d5f2bc281a07426f07987edef714a1503
|
data/README.md
CHANGED
|
@@ -43,6 +43,8 @@ bundle install
|
|
|
43
43
|
- datetime フィルターや checkbox group の組み立てを補助する helper
|
|
44
44
|
- `YummyGuide::Administrate::FilterControlsHelper`
|
|
45
45
|
- dashboard の Field 型フィルター定義から Filter ボタンとモーダルフォームを描画する helper
|
|
46
|
+
- `YummyGuide::Administrate::TooltipHelper`
|
|
47
|
+
- 管理画面内で補足説明 tooltip を描画する helper
|
|
46
48
|
- `YummyGuide::Administrate::DatetimeInputHelper`
|
|
47
49
|
- 管理画面フォーム用の date + time 入力 helper
|
|
48
50
|
- `YummyGuide::Administrate::NumberInputHelper`
|
|
@@ -58,6 +60,7 @@ bundle install
|
|
|
58
60
|
- `filter_form.js`
|
|
59
61
|
- `sticky_left_columns.js`
|
|
60
62
|
- `sticky_table_headers.js`
|
|
63
|
+
- `tooltips.js`
|
|
61
64
|
- `components.css`
|
|
62
65
|
- 共通 field
|
|
63
66
|
- `YummyGuide::Administrate::Fields::JsonPrettyField`
|
|
@@ -109,12 +112,15 @@ class Admin::ApplicationController < Administrate::ApplicationController
|
|
|
109
112
|
helper YummyGuide::Administrate::FilterControlsHelper
|
|
110
113
|
helper YummyGuide::Administrate::FilterFormHelper
|
|
111
114
|
helper YummyGuide::Administrate::NumberInputHelper
|
|
115
|
+
helper YummyGuide::Administrate::TooltipHelper
|
|
112
116
|
end
|
|
113
117
|
```
|
|
114
118
|
|
|
115
119
|
`NumberInputHelper` は `Administrate::ApplicationController` の view helper として
|
|
116
120
|
自動適用されます。`Administrate::ApplicationController` を継承しない独自 admin
|
|
117
121
|
controller で同じ挙動が必要な場合だけ、上記のように明示的に読み込んでください。
|
|
122
|
+
`TooltipHelper` も `Administrate::ApplicationController` の view helper として
|
|
123
|
+
自動適用されます。
|
|
118
124
|
|
|
119
125
|
### Collection partial
|
|
120
126
|
|
|
@@ -461,6 +467,30 @@ Admin/Administrate 画面では、`number_field` / `number_field_tag` を
|
|
|
461
467
|
`range_field` / `range_field_tag` は対象外で、従来どおり `type="range"` として描画
|
|
462
468
|
されます。raw HTML の `<input type="number">` は helper を通らないため対象外です。
|
|
463
469
|
|
|
470
|
+
### Tooltip helper
|
|
471
|
+
|
|
472
|
+
ラベルやボタンの横に補足説明用の tooltip アイコンを表示する場合は、
|
|
473
|
+
`admin_tooltip` を使います。PC では hover / focus 時に表示し、モバイルではタップで
|
|
474
|
+
表示・非表示を切り替えます。
|
|
475
|
+
|
|
476
|
+
```erb
|
|
477
|
+
<%= f.label :published_at %>
|
|
478
|
+
<%= admin_tooltip("公開日時を過ぎると公開ページに表示されます。") %>
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
説明本文に改行などの HTML を含める場合は block を渡します。`text` 引数と block を
|
|
482
|
+
同時に指定した場合は block が優先されます。
|
|
483
|
+
|
|
484
|
+
```erb
|
|
485
|
+
<%= admin_tooltip do %>
|
|
486
|
+
Add - 調整レコードを追加表示するようにします。<br>
|
|
487
|
+
Only - 調整レコードのみを表示します。
|
|
488
|
+
<% end %>
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
block を使わない場合、tooltip 本文はテキストとして扱われ、HTML は描画しません。
|
|
492
|
+
見た目と表示制御には `components.css` と `tooltips.js` の読み込みが必要です。
|
|
493
|
+
|
|
464
494
|
### Asset の読み込み
|
|
465
495
|
|
|
466
496
|
この engine の asset はホストアプリ側で明示的に読み込んでください。
|
|
@@ -473,6 +503,7 @@ Admin/Administrate 画面では、`number_field` / `number_field_tag` を
|
|
|
473
503
|
//= require yummy_guide_administrate/filter_form
|
|
474
504
|
//= require yummy_guide_administrate/sticky_left_columns
|
|
475
505
|
//= require yummy_guide_administrate/sticky_table_headers
|
|
506
|
+
//= require yummy_guide_administrate/tooltips
|
|
476
507
|
```
|
|
477
508
|
|
|
478
509
|
```scss
|
|
@@ -71,6 +71,11 @@
|
|
|
71
71
|
return preciseNumber(value) + 'px';
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
function parsedPixelValue(value) {
|
|
75
|
+
var parsedValue = parseFloat(value || '0');
|
|
76
|
+
return Number.isNaN(parsedValue) ? 0 : preciseNumber(parsedValue);
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
function measuredWidth(element) {
|
|
75
80
|
if (!element) return 0;
|
|
76
81
|
|
|
@@ -307,6 +312,7 @@
|
|
|
307
312
|
indexByColumnId: indexByColumnId
|
|
308
313
|
};
|
|
309
314
|
tableStates.set(table, state);
|
|
315
|
+
refreshCssStickyLeftColumns(table);
|
|
310
316
|
|
|
311
317
|
return state;
|
|
312
318
|
}
|
|
@@ -375,6 +381,7 @@
|
|
|
375
381
|
table.style.setProperty(columnWidthVariable(index), widthValue);
|
|
376
382
|
setAdjustedColumn(table, index, true);
|
|
377
383
|
applyColgroupWidth(table, state.columnCount, index, widthValue);
|
|
384
|
+
refreshCssStickyLeftColumns(table);
|
|
378
385
|
}
|
|
379
386
|
|
|
380
387
|
function clearTableColumnWidth(table, columnId) {
|
|
@@ -385,6 +392,65 @@
|
|
|
385
392
|
table.style.removeProperty(columnWidthVariable(index));
|
|
386
393
|
setAdjustedColumn(table, index, false);
|
|
387
394
|
clearColgroupWidth(table, state.columnCount, index);
|
|
395
|
+
refreshCssStickyLeftColumns(table);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function stickyColumnIndexes(table, className) {
|
|
399
|
+
var row = table && table.querySelector('thead tr');
|
|
400
|
+
if (!row) return [];
|
|
401
|
+
|
|
402
|
+
return directCells(row).map(function(cell, index) {
|
|
403
|
+
return cell.classList && cell.classList.contains(className) ? index : null;
|
|
404
|
+
}).filter(function(index) {
|
|
405
|
+
return index !== null;
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function managedColumnWidth(table, index) {
|
|
410
|
+
var colgroup = table && table.querySelector('colgroup[data-admin-column-resizer-colgroup], colgroup[data-fixed-header-colgroup]');
|
|
411
|
+
var col = colgroup && colgroup.children[index];
|
|
412
|
+
|
|
413
|
+
return col ? parsedPixelValue(col.style.width) : 0;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function stickyColumnWidth(table, header, index, widthVariable) {
|
|
417
|
+
return measuredWidth(header) ||
|
|
418
|
+
managedColumnWidth(table, index) ||
|
|
419
|
+
parsedPixelValue(header && header.style && header.style.getPropertyValue(widthVariable));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function applyStickyColumnPosition(table, index, leftVariable, left, widthVariable, width) {
|
|
423
|
+
Array.from(table.querySelectorAll('thead tr, tbody tr, tfoot tr')).forEach(function(row) {
|
|
424
|
+
var cell = directCells(row)[index];
|
|
425
|
+
if (!cell) return;
|
|
426
|
+
|
|
427
|
+
cell.style.setProperty(leftVariable, cssPixelValue(left));
|
|
428
|
+
if (width) {
|
|
429
|
+
cell.style.setProperty(widthVariable, cssPixelValue(width));
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function refreshCssStickyLeftColumnSet(table, className, leftVariable, widthVariable) {
|
|
435
|
+
var headerRow = table && table.querySelector('thead tr');
|
|
436
|
+
if (!headerRow) return;
|
|
437
|
+
|
|
438
|
+
var headerCells = directCells(headerRow);
|
|
439
|
+
var left = 0;
|
|
440
|
+
|
|
441
|
+
stickyColumnIndexes(table, className).forEach(function(index) {
|
|
442
|
+
var width = stickyColumnWidth(table, headerCells[index], index, widthVariable);
|
|
443
|
+
|
|
444
|
+
applyStickyColumnPosition(table, index, leftVariable, left, widthVariable, width);
|
|
445
|
+
left += width;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function refreshCssStickyLeftColumns(table) {
|
|
450
|
+
if (!table || table.getAttribute('aria-hidden') === 'true' || table.classList.contains(FIXED_HEADER_TABLE_CLASS)) return;
|
|
451
|
+
|
|
452
|
+
refreshCssStickyLeftColumnSet(table, 'sticky-left', '--sticky-left', '--sticky-width');
|
|
453
|
+
refreshCssStickyLeftColumnSet(table, 'sticky-left-mobile', '--sticky-mobile-left', '--sticky-mobile-width');
|
|
388
454
|
}
|
|
389
455
|
|
|
390
456
|
function applyColumnWidth(columnId, width, key) {
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
var TRIGGER_SELECTOR = "[data-admin-tooltip-trigger='true']";
|
|
3
|
+
var TOOLTIP_ID = "admin-tooltip";
|
|
4
|
+
var TOOLTIP_CLASS = "admin-tooltip";
|
|
5
|
+
var VISIBLE_CLASS = "admin-tooltip--visible";
|
|
6
|
+
var MOBILE_MEDIA_QUERY = "(max-width: 767px)";
|
|
7
|
+
var EDGE_GAP = 8;
|
|
8
|
+
var OFFSET = 8;
|
|
9
|
+
var activeTrigger = null;
|
|
10
|
+
var hoveredTrigger = null;
|
|
11
|
+
var focusedTrigger = null;
|
|
12
|
+
var tooltipElement = null;
|
|
13
|
+
|
|
14
|
+
function isMobile() {
|
|
15
|
+
return window.matchMedia && window.matchMedia(MOBILE_MEDIA_QUERY).matches;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function closestTrigger(target) {
|
|
19
|
+
if (!target || !target.closest) return null;
|
|
20
|
+
|
|
21
|
+
return target.closest(TRIGGER_SELECTOR);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function clamp(value, min, max) {
|
|
25
|
+
return Math.min(Math.max(value, min), max);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getTooltipElement() {
|
|
29
|
+
if (tooltipElement) return tooltipElement;
|
|
30
|
+
|
|
31
|
+
tooltipElement = document.createElement("div");
|
|
32
|
+
tooltipElement.id = TOOLTIP_ID;
|
|
33
|
+
tooltipElement.className = TOOLTIP_CLASS;
|
|
34
|
+
tooltipElement.setAttribute("role", "tooltip");
|
|
35
|
+
document.body.appendChild(tooltipElement);
|
|
36
|
+
|
|
37
|
+
return tooltipElement;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function tooltipContent(trigger) {
|
|
41
|
+
var contentId = trigger.getAttribute("data-admin-tooltip-content-id");
|
|
42
|
+
var template = contentId ? document.getElementById(contentId) : null;
|
|
43
|
+
if (template) {
|
|
44
|
+
return {
|
|
45
|
+
html: template.innerHTML,
|
|
46
|
+
text: ""
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
var text = trigger.getAttribute("data-admin-tooltip-text") || "";
|
|
51
|
+
return {
|
|
52
|
+
html: "",
|
|
53
|
+
text: text.trim() ? text : ""
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function setTriggerState(trigger, expanded) {
|
|
58
|
+
if (!trigger) return;
|
|
59
|
+
|
|
60
|
+
trigger.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
61
|
+
|
|
62
|
+
if (expanded) {
|
|
63
|
+
trigger.setAttribute("aria-describedby", TOOLTIP_ID);
|
|
64
|
+
} else {
|
|
65
|
+
trigger.removeAttribute("aria-describedby");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function positionTooltip() {
|
|
70
|
+
if (!activeTrigger || !tooltipElement || !tooltipElement.classList.contains(VISIBLE_CLASS)) return;
|
|
71
|
+
|
|
72
|
+
var targetRect = activeTrigger.getBoundingClientRect();
|
|
73
|
+
tooltipElement.style.left = "0px";
|
|
74
|
+
tooltipElement.style.top = "0px";
|
|
75
|
+
|
|
76
|
+
var tooltipRect = tooltipElement.getBoundingClientRect();
|
|
77
|
+
var viewportWidth = document.documentElement.clientWidth || window.innerWidth;
|
|
78
|
+
var viewportHeight = document.documentElement.clientHeight || window.innerHeight;
|
|
79
|
+
var top = targetRect.top - tooltipRect.height - OFFSET;
|
|
80
|
+
var placement = "top";
|
|
81
|
+
|
|
82
|
+
if (top < EDGE_GAP) {
|
|
83
|
+
top = targetRect.bottom + OFFSET;
|
|
84
|
+
placement = "bottom";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
top = clamp(top, EDGE_GAP, Math.max(EDGE_GAP, viewportHeight - tooltipRect.height - EDGE_GAP));
|
|
88
|
+
|
|
89
|
+
var left = targetRect.left + (targetRect.width / 2) - (tooltipRect.width / 2);
|
|
90
|
+
left = clamp(left, EDGE_GAP, Math.max(EDGE_GAP, viewportWidth - tooltipRect.width - EDGE_GAP));
|
|
91
|
+
|
|
92
|
+
var arrowMax = Math.max(10, tooltipRect.width - 10);
|
|
93
|
+
var arrowLeft = clamp(targetRect.left + (targetRect.width / 2) - left - 4, 10, arrowMax);
|
|
94
|
+
|
|
95
|
+
tooltipElement.style.left = Math.round(left) + "px";
|
|
96
|
+
tooltipElement.style.top = Math.round(top) + "px";
|
|
97
|
+
tooltipElement.style.setProperty("--admin-tooltip-arrow-left", Math.round(arrowLeft) + "px");
|
|
98
|
+
tooltipElement.setAttribute("data-admin-tooltip-placement", placement);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function showTooltip(trigger) {
|
|
102
|
+
var content = tooltipContent(trigger);
|
|
103
|
+
if (!content.html && !content.text) return;
|
|
104
|
+
|
|
105
|
+
if (activeTrigger && activeTrigger !== trigger) {
|
|
106
|
+
hideTooltip();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
activeTrigger = trigger;
|
|
110
|
+
tooltipElement = getTooltipElement();
|
|
111
|
+
if (content.html) {
|
|
112
|
+
tooltipElement.innerHTML = content.html;
|
|
113
|
+
} else {
|
|
114
|
+
tooltipElement.textContent = content.text;
|
|
115
|
+
}
|
|
116
|
+
tooltipElement.classList.add(VISIBLE_CLASS);
|
|
117
|
+
setTriggerState(trigger, true);
|
|
118
|
+
|
|
119
|
+
if (window.requestAnimationFrame) {
|
|
120
|
+
window.requestAnimationFrame(positionTooltip);
|
|
121
|
+
} else {
|
|
122
|
+
positionTooltip();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function hideTooltip(trigger) {
|
|
127
|
+
if (trigger && activeTrigger !== trigger) return;
|
|
128
|
+
|
|
129
|
+
setTriggerState(activeTrigger, false);
|
|
130
|
+
|
|
131
|
+
if (tooltipElement) {
|
|
132
|
+
tooltipElement.classList.remove(VISIBLE_CLASS);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
activeTrigger = null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function toggleTooltip(trigger) {
|
|
139
|
+
if (activeTrigger === trigger && tooltipElement && tooltipElement.classList.contains(VISIBLE_CLASS)) {
|
|
140
|
+
hideTooltip(trigger);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
showTooltip(trigger);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
document.addEventListener("mouseover", function(event) {
|
|
148
|
+
var trigger = closestTrigger(event.target);
|
|
149
|
+
if (!trigger || isMobile() || (event.relatedTarget && trigger.contains(event.relatedTarget))) return;
|
|
150
|
+
|
|
151
|
+
hoveredTrigger = trigger;
|
|
152
|
+
showTooltip(trigger);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
document.addEventListener("mouseout", function(event) {
|
|
156
|
+
var trigger = closestTrigger(event.target);
|
|
157
|
+
if (!trigger || isMobile() || (event.relatedTarget && trigger.contains(event.relatedTarget))) return;
|
|
158
|
+
|
|
159
|
+
if (hoveredTrigger === trigger) {
|
|
160
|
+
hoveredTrigger = null;
|
|
161
|
+
}
|
|
162
|
+
if (focusedTrigger === trigger) return;
|
|
163
|
+
|
|
164
|
+
hideTooltip(trigger);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
document.addEventListener("focusin", function(event) {
|
|
168
|
+
var trigger = closestTrigger(event.target);
|
|
169
|
+
if (!trigger || isMobile()) return;
|
|
170
|
+
|
|
171
|
+
focusedTrigger = trigger;
|
|
172
|
+
showTooltip(trigger);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
document.addEventListener("focusout", function(event) {
|
|
176
|
+
var trigger = closestTrigger(event.target);
|
|
177
|
+
if (!trigger || isMobile()) return;
|
|
178
|
+
|
|
179
|
+
if (focusedTrigger === trigger) {
|
|
180
|
+
focusedTrigger = null;
|
|
181
|
+
}
|
|
182
|
+
if (hoveredTrigger === trigger) return;
|
|
183
|
+
|
|
184
|
+
hideTooltip(trigger);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
document.addEventListener("click", function(event) {
|
|
188
|
+
var trigger = closestTrigger(event.target);
|
|
189
|
+
|
|
190
|
+
if (trigger) {
|
|
191
|
+
if (!isMobile()) return;
|
|
192
|
+
|
|
193
|
+
event.preventDefault();
|
|
194
|
+
event.stopPropagation();
|
|
195
|
+
toggleTooltip(trigger);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (activeTrigger && isMobile()) {
|
|
200
|
+
hideTooltip();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
document.addEventListener("keydown", function(event) {
|
|
205
|
+
if (event.key !== "Escape") return;
|
|
206
|
+
|
|
207
|
+
hideTooltip();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
window.addEventListener("scroll", positionTooltip, true);
|
|
211
|
+
window.addEventListener("resize", function() {
|
|
212
|
+
hideTooltip();
|
|
213
|
+
});
|
|
214
|
+
})();
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
.admin-tooltip-trigger {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
width: 1.25rem;
|
|
6
|
+
min-width: 1.25rem;
|
|
7
|
+
height: 1.25rem;
|
|
8
|
+
margin: 0 0 0 0.25rem;
|
|
9
|
+
padding: 0;
|
|
10
|
+
border: 1px solid #7a8594;
|
|
11
|
+
border-radius: 50%;
|
|
12
|
+
background: #fff;
|
|
13
|
+
color: #4b5563;
|
|
14
|
+
cursor: help;
|
|
15
|
+
font-size: 0.75rem;
|
|
16
|
+
font-weight: 700;
|
|
17
|
+
line-height: 1;
|
|
18
|
+
vertical-align: middle;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.admin-tooltip-trigger:hover,
|
|
22
|
+
.admin-tooltip-trigger:focus-visible,
|
|
23
|
+
.admin-tooltip-trigger[aria-expanded="true"] {
|
|
24
|
+
border-color: #0d6efd;
|
|
25
|
+
background: #f8fbff;
|
|
26
|
+
color: #0d6efd;
|
|
27
|
+
box-shadow: none;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.admin-tooltip-trigger__icon {
|
|
31
|
+
pointer-events: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.admin-tooltip {
|
|
35
|
+
position: fixed;
|
|
36
|
+
z-index: 1100;
|
|
37
|
+
max-width: 280px;
|
|
38
|
+
padding: 8px 10px;
|
|
39
|
+
border-radius: 4px;
|
|
40
|
+
background: #1f2933;
|
|
41
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
|
42
|
+
color: #fff;
|
|
43
|
+
font-size: 0.82rem;
|
|
44
|
+
line-height: 1.45;
|
|
45
|
+
opacity: 0;
|
|
46
|
+
overflow-wrap: anywhere;
|
|
47
|
+
pointer-events: none;
|
|
48
|
+
transform: translateY(2px);
|
|
49
|
+
transition: opacity 0.12s ease, transform 0.12s ease;
|
|
50
|
+
white-space: normal;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.admin-tooltip--visible {
|
|
54
|
+
opacity: 1;
|
|
55
|
+
transform: translateY(0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.admin-tooltip::before {
|
|
59
|
+
content: "";
|
|
60
|
+
position: absolute;
|
|
61
|
+
left: var(--admin-tooltip-arrow-left, 50%);
|
|
62
|
+
width: 8px;
|
|
63
|
+
height: 8px;
|
|
64
|
+
background: #1f2933;
|
|
65
|
+
transform: rotate(45deg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.admin-tooltip[data-admin-tooltip-placement="top"]::before {
|
|
69
|
+
bottom: -4px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.admin-tooltip[data-admin-tooltip-placement="bottom"]::before {
|
|
73
|
+
top: -4px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@media screen and (max-width: 767px) {
|
|
77
|
+
.admin-tooltip-trigger {
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.admin-tooltip {
|
|
82
|
+
max-width: calc(100vw - 24px);
|
|
83
|
+
font-size: 0.85rem;
|
|
84
|
+
}
|
|
85
|
+
}
|