Skip to content

Commit 9bc1158

Browse files
staredclaude
andcommitted
feat: Improve mobile UI with collapsible color picker and compact layout
- Add MobileColorPicker component with dropdown for color scheme selection - Move color controls to mobile header between Equations and Code buttons - Reduce vertical spacing throughout mobile view for better space usage - Make buttons consistent with smaller font, proper icon-text spacing - Center equation on mobile, reduce margins on title/subtitle - Ensure font sizes match between description and definition popup - Hide desktop color switcher on mobile, show collapsible picker instead 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 1f63551 commit 9bc1158

File tree

7 files changed

+198
-22
lines changed

7 files changed

+198
-22
lines changed

src/App.vue

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<button class="mobile-menu-btn" @click="mobileMenuOpen = !mobileMenuOpen">
66
<span class="icon">☰</span> Equations
77
</button>
8+
<MobileColorPicker @change="colorScheme = $event" />
89
<button
910
class="mobile-menu-btn"
1011
@click="mobileEditorOpen = !mobileEditorOpen"
@@ -55,7 +56,7 @@
5556

5657
<!-- Main Content -->
5758
<main class="main-content">
58-
<ColorSchemeSwitcher @change="colorScheme = $event" />
59+
<ColorSchemeSwitcher class="desktop-color-switcher" @change="colorScheme = $event" />
5960
<CentralPanel
6061
v-if="parsedContent"
6162
:content="parsedContent"
@@ -122,6 +123,7 @@ import { parseContent } from "./utils/parser";
122123
import CentralPanel from "./components/CentralPanel.vue";
123124
import EquationSelector from "./components/controls/EquationSelector.vue";
124125
import ColorSchemeSwitcher from "./components/controls/ColorSchemeSwitcher.vue";
126+
import MobileColorPicker from "./components/controls/MobileColorPicker.vue";
125127
import ExportControls from "./components/controls/ExportControls.vue";
126128
import MarkdownEditor from "./components/MarkdownEditor.vue";
127129
@@ -357,31 +359,36 @@ body {
357359
/* Mobile Header */
358360
.mobile-header {
359361
display: none;
360-
height: 50px;
361-
background-color: var(--bg-secondary);
362-
border-bottom: 1px solid var(--border-color);
363-
padding: 0 1rem;
362+
height: 32px;
363+
background-color: var(--bg-primary);
364+
padding: 0.125rem 0.5rem;
364365
align-items: center;
365366
justify-content: space-between;
366367
position: fixed;
367368
top: 0;
368369
left: 0;
369370
right: 0;
370371
z-index: 40;
372+
gap: 0.5rem;
371373
}
372374
373375
.mobile-menu-btn {
374376
background: transparent;
375377
border: 1px solid var(--border-color);
376-
padding: 0.5rem 1rem;
377-
border-radius: 4px;
378+
padding: 0.25rem 0.5rem;
379+
border-radius: 3px;
378380
color: var(--text-primary);
379381
font-family: var(--font-ui);
380-
font-size: 0.875rem;
382+
font-size: 0.75rem;
381383
cursor: pointer;
382384
display: flex;
383385
align-items: center;
384-
gap: 0.5rem;
386+
gap: 0.25rem;
387+
flex-shrink: 0;
388+
}
389+
390+
.mobile-menu-btn .icon {
391+
font-size: 0.875rem;
385392
}
386393
387394
.mobile-close-header {
@@ -408,13 +415,17 @@ body {
408415
flex-direction: column;
409416
height: auto;
410417
overflow-y: auto;
411-
padding-top: 50px; /* Space for mobile header */
418+
padding-top: 34px; /* Space for mobile header */
412419
}
413420
414421
.mobile-header {
415422
display: flex;
416423
}
417424
425+
.desktop-color-switcher {
426+
display: none;
427+
}
428+
418429
.mobile-close-header {
419430
display: flex;
420431
}
@@ -429,6 +440,7 @@ body {
429440
z-index: 100;
430441
width: 100%;
431442
max-width: 100%;
443+
min-width: 100%;
432444
height: 100%;
433445
max-height: 100vh;
434446
transform: translateX(-100%);
@@ -451,8 +463,9 @@ body {
451463
}
452464
453465
.main-content {
454-
padding: 2rem 1rem;
466+
padding: 0 0.75rem;
455467
overflow: visible;
468+
justify-content: flex-start;
456469
}
457470
458471
.editor-sidebar {
@@ -461,6 +474,7 @@ body {
461474
z-index: 100;
462475
width: 100%;
463476
max-width: 100%;
477+
min-width: 100%;
464478
height: 100%;
465479
transform: translateY(100%);
466480
transition: transform 0.3s ease;
@@ -478,7 +492,7 @@ body {
478492
}
479493
480494
.editor-sidebar .editor-toolbar {
481-
padding: 0 1rem; /* Adjust padding for mobile */
495+
padding: 0 1rem;
482496
}
483497
}
484498
</style>

src/components/CentralPanel.vue

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ h1 {
107107
font-size: 2.5rem;
108108
font-weight: 400;
109109
color: var(--text-primary);
110+
margin-top: 0;
110111
margin-bottom: 0.5rem;
111112
text-align: center;
112113
letter-spacing: -0.02em;
@@ -122,13 +123,20 @@ h1 {
122123
}
123124
124125
@media (max-width: 768px) {
126+
.central-panel {
127+
padding-top: 0;
128+
}
129+
125130
h1 {
126-
font-size: 1.75rem;
131+
font-size: 1.4rem;
132+
margin-top: 0;
133+
margin-bottom: 0;
134+
line-height: 1.2;
127135
}
128136
129137
.subtitle {
130-
font-size: 0.875rem;
131-
margin-bottom: 1rem;
138+
font-size: 0.75rem;
139+
margin-bottom: 0.125rem;
132140
}
133141
}
134142
</style>

src/components/controls/ColorSchemeSwitcher.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,10 @@ onMounted(() => {
6969
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
7070
font-weight: 600;
7171
}
72+
73+
@media (max-width: 768px) {
74+
.color-scheme-switcher {
75+
display: none;
76+
}
77+
}
7278
</style>
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<template>
2+
<div class="mobile-color-picker" :class="{ open: isOpen }">
3+
<button class="picker-toggle" @click="isOpen = !isOpen">
4+
<span class="icon">⊞</span> Colors <span class="toggle-icon">{{ isOpen ? '▲' : '▼' }}</span>
5+
</button>
6+
<div class="picker-dropdown" v-show="isOpen">
7+
<button
8+
v-for="(scheme, key) in colorSchemes"
9+
:key="key"
10+
:class="{ active: key === currentKey }"
11+
@click="selectScheme(key)"
12+
>
13+
{{ scheme.name }}
14+
</button>
15+
</div>
16+
</div>
17+
</template>
18+
19+
<script setup lang="ts">
20+
import { ref, computed, onMounted, onUnmounted } from 'vue'
21+
import { colorSchemes, defaultScheme } from '../../utils/colorSchemes'
22+
import type { ColorScheme } from '../../export'
23+
24+
const emit = defineEmits<{
25+
change: [scheme: ColorScheme]
26+
}>()
27+
28+
const isOpen = ref(false)
29+
const currentKey = ref('vibrant')
30+
31+
const previewColor = computed(() => {
32+
const scheme = colorSchemes[currentKey.value]
33+
return scheme?.colors[0] ?? '#666'
34+
})
35+
36+
function selectScheme(key: string) {
37+
if (colorSchemes[key]) {
38+
currentKey.value = key
39+
emit('change', colorSchemes[key])
40+
isOpen.value = false
41+
}
42+
}
43+
44+
// Close on outside click
45+
function handleClickOutside(e: MouseEvent) {
46+
const target = e.target as HTMLElement
47+
if (!target.closest('.mobile-color-picker')) {
48+
isOpen.value = false
49+
}
50+
}
51+
52+
onMounted(() => {
53+
document.addEventListener('click', handleClickOutside)
54+
emit('change', defaultScheme)
55+
})
56+
57+
onUnmounted(() => {
58+
document.removeEventListener('click', handleClickOutside)
59+
})
60+
</script>
61+
62+
<style scoped>
63+
.mobile-color-picker {
64+
position: relative;
65+
}
66+
67+
.picker-toggle {
68+
display: flex;
69+
align-items: center;
70+
gap: 0.25rem;
71+
padding: 0.25rem 0.5rem;
72+
border: 1px solid var(--border-color);
73+
border-radius: 3px;
74+
background: transparent;
75+
cursor: pointer;
76+
font-family: var(--font-ui);
77+
font-size: 0.75rem;
78+
color: var(--text-primary);
79+
}
80+
81+
.icon {
82+
font-size: 0.875rem;
83+
}
84+
85+
.toggle-icon {
86+
font-size: 0.5rem;
87+
color: var(--text-secondary);
88+
}
89+
90+
.picker-dropdown {
91+
position: absolute;
92+
top: 100%;
93+
left: 50%;
94+
transform: translateX(-50%);
95+
margin-top: 0.25rem;
96+
background: var(--bg-primary);
97+
border: 1px solid var(--border-color);
98+
border-radius: 6px;
99+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
100+
z-index: 200;
101+
min-width: 120px;
102+
overflow: hidden;
103+
}
104+
105+
.picker-dropdown button {
106+
display: block;
107+
width: 100%;
108+
padding: 0.5rem 0.75rem;
109+
border: none;
110+
background: transparent;
111+
text-align: left;
112+
font-family: var(--font-ui);
113+
font-size: 0.8125rem;
114+
color: var(--text-secondary);
115+
cursor: pointer;
116+
}
117+
118+
.picker-dropdown button:hover {
119+
background: var(--bg-secondary);
120+
color: var(--text-primary);
121+
}
122+
123+
.picker-dropdown button.active {
124+
background: var(--accent-light);
125+
color: var(--accent-color);
126+
font-weight: 600;
127+
}
128+
</style>

src/components/equation/DefinitionPopup.vue

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ const renderedDefinition = computed(() => {
4444
min-height: 3rem;
4545
opacity: 0;
4646
transition: opacity 0.3s ease;
47-
font-size: 1rem;
48-
line-height: 1.6;
47+
font-size: 1.125rem;
48+
line-height: 1.7;
4949
color: var(--text-secondary);
5050
text-align: left;
51-
font-family: var(--font-ui);
51+
font-family: var(--font-math);
5252
margin: 1rem auto 0 auto;
5353
border: 1px solid var(--accent-color);
5454
background-color: #fff;
@@ -61,4 +61,14 @@ const renderedDefinition = computed(() => {
6161
.hover-explanation.visible {
6262
opacity: 1;
6363
}
64+
65+
@media (max-width: 768px) {
66+
.hover-explanation {
67+
font-size: 1rem;
68+
line-height: 1.5;
69+
padding: 0.75rem;
70+
margin-top: 0.5rem;
71+
min-height: 2rem;
72+
}
73+
}
6474
</style>

src/components/equation/DescriptionPanel.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,13 @@ onMounted(setupDescription)
8888
.static-description :deep(span.active) {
8989
background-color: var(--accent-light);
9090
}
91+
92+
@media (max-width: 768px) {
93+
.static-description {
94+
padding-top: 0.5rem;
95+
margin-bottom: 0.5rem;
96+
font-size: 1rem;
97+
line-height: 1.5;
98+
}
99+
}
91100
</style>

src/components/equation/EquationDisplay.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,15 +224,16 @@ onUnmounted(() => resizeObserver?.disconnect());
224224
225225
@media (max-width: 768px) {
226226
#equation-container {
227-
padding: 0.5rem 1rem;
227+
padding: 0.5rem;
228228
overflow-x: auto;
229-
justify-content: flex-start;
230-
/* Ensure container can scroll */
229+
justify-content: center;
231230
width: 100%;
231+
min-height: 60px;
232+
margin: 0.25rem 0 0.5rem 0;
232233
}
233234
234235
#equation-container :deep(.katex) {
235-
font-size: 1.5rem;
236+
font-size: 1.25rem;
236237
}
237238
}
238239
</style>

0 commit comments

Comments
 (0)