feat: resolve linter warnings, optimize tables scroll behavior with top scroll sync, and extract reusable table macros
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro modal(id, title, content, close_label="Close") %}
|
||||
<div id="{{ id }}" class="modal-dialog fixed inset-0 z-50 flex items-center justify-center hidden" role="dialog" aria-modal="true">
|
||||
<div id="{{ id }}" class="modal-dialog fixed inset-0 z-50 items-center justify-center hidden" role="dialog" aria-modal="true">
|
||||
<div class="modal-backdrop fixed inset-0 bg-[#07090e]/80 backdrop-blur-sm transition-opacity duration-300"></div>
|
||||
<div class="modal-content relative z-10 w-full max-w-sm scale-95 opacity-0 transition-all duration-300 border border-border bg-popover/95 backdrop-blur-xl p-6 shadow-2xl rounded-3xl text-center">
|
||||
<div class="mx-auto flex h-10 w-10 items-center justify-center rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 mb-3">
|
||||
@@ -80,7 +80,7 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro modal_open(id, title) %}
|
||||
<div id="{{ id }}" class="modal-dialog fixed inset-0 z-50 flex items-center justify-center hidden" role="dialog" aria-modal="true">
|
||||
<div id="{{ id }}" class="modal-dialog fixed inset-0 z-50 items-center justify-center hidden" role="dialog" aria-modal="true">
|
||||
<div class="modal-backdrop fixed inset-0 bg-[#07090e]/80 backdrop-blur-sm transition-opacity duration-300"></div>
|
||||
<div class="modal-content relative z-10 w-full max-w-sm scale-95 opacity-0 transition-all duration-300 border border-border bg-popover/95 backdrop-blur-xl p-6 shadow-2xl rounded-3xl text-center">
|
||||
<div class="mx-auto flex h-10 w-10 items-center justify-center rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 mb-3">
|
||||
@@ -234,7 +234,7 @@
|
||||
{% endif %}
|
||||
<label class="relative inline-flex items-center cursor-pointer">
|
||||
<input type="checkbox" name="{{ name }}" class="sr-only peer" {% if checked %}checked{% endif %}>
|
||||
<div class="w-9 h-5 bg-secondary rounded-full border border-border peer-checked:bg-indigo-600 peer-checked:border-indigo-500 transition-all duration-300 relative after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-slate-400 after:rounded-full after:h-[14px] after:w-[14px] after:transition-all peer-checked:after:translate-x-4 peer-checked:after:bg-white"></div>
|
||||
<div class="w-9 h-5 bg-secondary rounded-full border border-border peer-checked:bg-indigo-600 peer-checked:border-indigo-500 transition-all duration-300 relative after:content-[''] after:absolute after:top-0.5 after:left-0.5 after:bg-slate-400 after:rounded-full after:h-3.5 after:w-3.5 after:transition-all peer-checked:after:translate-x-4 peer-checked:after:bg-white"></div>
|
||||
</label>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -279,7 +279,7 @@
|
||||
</span>
|
||||
<svg class="h-4 w-4 text-slate-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg>
|
||||
</button>
|
||||
<div class="datepicker-popover absolute left-0 z-20 mt-2 w-[270px] p-3 rounded-2xl border border-border bg-popover shadow-2xl animate-in fade-in slide-in-from-top-2 duration-200 hidden">
|
||||
<div class="datepicker-popover absolute left-0 z-20 mt-2 w-67.5 p-3 rounded-2xl border border-border bg-popover shadow-2xl animate-in fade-in slide-in-from-top-2 duration-200 hidden">
|
||||
<div class="flex items-center justify-between mb-3.5">
|
||||
<button type="button" class="datepicker-prev p-1.5 rounded-lg hover:bg-secondary text-muted-foreground/90 hover:text-white transition">
|
||||
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><polyline points="15 18 9 12 15 6"/></svg>
|
||||
@@ -315,7 +315,7 @@
|
||||
</span>
|
||||
<svg class="h-4 w-4 text-slate-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg>
|
||||
</button>
|
||||
<div class="timepicker-popover absolute right-0 sm:left-0 z-20 mt-2 w-[230px] p-3 rounded-2xl border border-border bg-popover shadow-2xl animate-in fade-in slide-in-from-top-2 duration-200 hidden">
|
||||
<div class="timepicker-popover absolute right-0 sm:left-0 z-20 mt-2 w-57.5 p-3 rounded-2xl border border-border bg-popover shadow-2xl animate-in fade-in slide-in-from-top-2 duration-200 hidden">
|
||||
<div class="flex gap-2 justify-center items-center">
|
||||
<div class="flex flex-col items-center">
|
||||
<span class="text-[9px] font-bold text-slate-500 mb-1.5 uppercase tracking-wider">Hr</span>
|
||||
@@ -360,7 +360,7 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro tabs_content_open() %}
|
||||
<div class="p-4 bg-card/50 rounded-xl border border-border text-xs text-muted-foreground min-h-[5rem]">
|
||||
<div class="p-4 bg-card/50 rounded-xl border border-border text-xs text-muted-foreground min-h-20">
|
||||
{% endmacro %}
|
||||
|
||||
{% macro tab_pane_open(group, id, is_active=true) %}
|
||||
@@ -388,3 +388,54 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro table_container_open(id, has_top_scroll=true, max_height="68vh") %}
|
||||
{% if has_top_scroll %}
|
||||
<!-- Top Horizontal Scrollbar (Synced) -->
|
||||
<div id="{{ id }}-scrollbar-top" class="overflow-x-auto w-full scrollbar-thin mb-3 bg-[#1e293b]/20 border border-slate-900/50 rounded-xl py-1 px-2">
|
||||
<div id="{{ id }}-scrollbar-top-inner" style="height: 1px;"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Table Container -->
|
||||
<div class="bg-[#1e293b]/40 backdrop-blur-xl border border-slate-900 rounded-3xl shadow-2xl mb-8 overflow-hidden">
|
||||
<div id="{{ id }}-container" class="overflow-auto scrollbar-thin rounded-[22px]" style="max-height: {{ max_height }};">
|
||||
{% endmacro %}
|
||||
|
||||
{% macro table_container_close(id, has_top_scroll=true) %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if has_top_scroll %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const topScroll = document.getElementById('{{ id }}-scrollbar-top');
|
||||
const tableContainer = document.getElementById('{{ id }}-container');
|
||||
const topScrollInner = document.getElementById('{{ id }}-scrollbar-top-inner');
|
||||
const table = tableContainer ? tableContainer.querySelector('table') : null;
|
||||
|
||||
if (topScroll && tableContainer && topScrollInner && table) {
|
||||
const updateWidth = () => {
|
||||
topScrollInner.style.width = table.scrollWidth + 'px';
|
||||
};
|
||||
|
||||
// Initialize width mapping
|
||||
updateWidth();
|
||||
|
||||
// Observe both resizing of the table and changes to table layout
|
||||
const resizeObserver = new ResizeObserver(() => updateWidth());
|
||||
resizeObserver.observe(table);
|
||||
|
||||
// Sync scroll positions
|
||||
topScroll.addEventListener('scroll', () => {
|
||||
tableContainer.scrollLeft = topScroll.scrollLeft;
|
||||
});
|
||||
tableContainer.addEventListener('scroll', () => {
|
||||
topScroll.scrollLeft = tableContainer.scrollLeft;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user