refactor: centralize UI config and inject CSS variables dynamically

This commit is contained in:
2026-02-28 04:18:53 +00:00
parent d5d3d37804
commit 70d7c8873e
8 changed files with 29 additions and 22 deletions

View File

@@ -6,6 +6,7 @@ import Footer from './components/Footer.vue'
import Sidebar from './components/Sidebar.vue'
import InstallPrompt from './components/InstallPrompt.vue'
import ReloadPrompt from './components/ReloadPrompt.vue'
import { UI_CONFIG } from './config/ui'
const isSidebarOpen = ref(window.innerWidth >= 768)
const router = useRouter()
@@ -31,6 +32,11 @@ const handleResize = () => {
}
onMounted(() => {
// Set global CSS variables from config
document.documentElement.style.setProperty('--header-height', `${UI_CONFIG.headerHeight}px`)
document.documentElement.style.setProperty('--footer-height', `${UI_CONFIG.footerHeight}px`)
document.documentElement.style.setProperty('--page-padding', `${UI_CONFIG.pagePadding}px`)
window.addEventListener('resize', handleResize)
})
@@ -70,14 +76,14 @@ onUnmounted(() => {
padding: 1rem;
width: 100%;
max-width: 100%;
/* Space for fixed footer on mobile + extra margin (match top padding 2rem + footer height ~40px) */
padding-bottom: calc(1rem + 40px + env(safe-area-inset-bottom));
/* Space for fixed footer on mobile + extra margin */
padding-bottom: calc(1rem + var(--footer-height) + env(safe-area-inset-bottom));
}
@media (max-width: 640px) {
.main-content {
padding: 0.5rem;
padding-bottom: calc(0.5rem + 40px + env(safe-area-inset-bottom));
padding-bottom: calc(0.5rem + var(--footer-height) + env(safe-area-inset-bottom));
}
}

View File

@@ -14,7 +14,8 @@ const version = __APP_VERSION__;
<style scoped>
.app-footer {
width: 100%;
padding: 0.5rem;
height: var(--footer-height);
padding: 0 0.5rem;
/* Background handled by glass-panel */
border-left: none;
border-right: none;
@@ -24,12 +25,9 @@ const version = __APP_VERSION__;
align-items: center;
justify-content: center;
z-index: 10;
/* Remove fixed height to allow content to dictate size */
/* height: 30px; */
position: fixed;
bottom: 0;
left: 0;
padding-bottom: max(0.5rem, env(safe-area-inset-bottom));
}
@media (min-width: 768px) {

View File

@@ -65,7 +65,10 @@ onMounted(() => {
/* Remove hardcoded colors and use theme variables */
background: var(--header-bg);
color: var(--text-color);
padding: 1rem;
height: var(--header-height);
padding: 0 1rem;
display: flex;
align-items: center;
/* box-shadow handled by glass-panel class */
position: sticky;
top: 0;
@@ -77,7 +80,7 @@ onMounted(() => {
}
.header-content {
max-width: 100%;
width: 100%;
padding: 0;
margin: 0 auto;
display: flex;

View File

@@ -16,7 +16,7 @@ const {
stopListening
} = useExtension()
const { height: textareaHeight } = useFillHeight(textareaRef, 120)
const { height: textareaHeight } = useFillHeight(textareaRef, 40)
// Watch for clipboard updates from extension
watch(lastClipboardText, (newText) => {

View File

@@ -142,7 +142,6 @@ const generatePasswords = () => {
class="tool-textarea"
v-model="result"
placeholder="Generated passwords will appear here..."
readonly
></textarea>
</div>
</div>

View File

@@ -12,7 +12,7 @@ const format = useLocalStorage('format', 'png', 'qr-code')
const svgContent = ref('')
const previewRef = ref(null)
const { height: previewHeight } = useFillHeight(previewRef, 40) // 40px margin bottom
const { height: previewHeight } = useFillHeight(previewRef, 40) // 40px extra margin
const generateQR = async () => {
if (!text.value) {

View File

@@ -1,6 +1,7 @@
import { onMounted, onUnmounted, ref, nextTick } from 'vue'
import { UI_CONFIG } from '../config/ui'
export function useFillHeight(elementRef, marginBottom = 20) {
export function useFillHeight(elementRef, extraMargin = 0) {
const height = ref('auto')
const updateHeight = () => {
@@ -8,16 +9,10 @@ export function useFillHeight(elementRef, marginBottom = 20) {
const rect = elementRef.value.getBoundingClientRect()
const windowHeight = window.innerHeight
// Calculate available space: window height - element top position - margin bottom
// We also need to account for the footer height if it's fixed or layout related
// The user mentioned "margin bottom from footer".
// If footer is in the flow, we might just want to fill the parent container?
// But user asked for JS resizing.
// Let's assume we want to fill down to (windowHeight - marginBottom).
// This assumes the element should stretch to the bottom of the viewport.
const availableHeight = windowHeight - rect.top - marginBottom
// Calculate available space: window height - element top position - footer height - padding - extra margin
const bottomOffset = UI_CONFIG.footerHeight + UI_CONFIG.pagePadding + extraMargin
const availableHeight = windowHeight - rect.top - bottomOffset
// Ensure minimum height
if (availableHeight > 100) {

6
src/config/ui.js Normal file
View File

@@ -0,0 +1,6 @@
export const UI_CONFIG = {
headerHeight: 64,
footerHeight: 50,
pagePadding: 16 // Single side padding (1rem)
}