Skip to content

Commit dd5c2e0

Browse files
authored
Merge pull request #103 from bocan/feature/move-folder-and-deps
Implement folder move functionality and enhance responsive design
2 parents 6f51dcc + b213a45 commit dd5c2e0

21 files changed

Lines changed: 666 additions & 103 deletions

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"diff": "^8.0.3",
1717
"github-slugger": "^2.0.0",
1818
"html-docx-js-typescript": "^0.1.5",
19-
"lucide-react": "^0.575.0",
19+
"lucide-react": "^0.577.0",
2020
"mermaid": "^11.4.1",
2121
"react": "^19.2.4",
2222
"react-dom": "^19.2.4",

client/src/App.css

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,9 @@ body {
237237
background: rgba(255, 255, 255, 0.2);
238238
border: 1px solid rgba(255, 255, 255, 0.3);
239239
color: white;
240-
font-size: 24px;
241-
width: 48px;
242-
height: 48px;
240+
font-size: 18px;
241+
width: 34px;
242+
height: 34px;
243243
border-radius: 50%;
244244
cursor: pointer;
245245
transition: all 0.2s;
@@ -273,11 +273,11 @@ body {
273273
background: rgba(255, 255, 255, 0.2);
274274
border: 1px solid rgba(255, 255, 255, 0.3);
275275
color: white;
276-
width: 36px;
277-
height: 36px;
276+
width: 34px;
277+
height: 34px;
278278
border-radius: 50%;
279279
cursor: pointer;
280-
font-size: 18px;
280+
font-size: 16px;
281281
font-weight: bold;
282282
transition: all 0.2s;
283283
display: flex;
@@ -742,6 +742,11 @@ body {
742742
.logout-button {
743743
padding: 8px 12px;
744744
}
745+
746+
/* Drop the keyboard shortcut badge from the search button */
747+
.search-shortcut {
748+
display: none;
749+
}
745750
}
746751

747752
/* Tablet portrait (≤768px) - auto-collapse preview */
@@ -763,9 +768,9 @@ body {
763768
}
764769

765770
.theme-toggle {
766-
width: 40px;
767-
height: 40px;
768-
font-size: 20px;
771+
width: 34px;
772+
height: 34px;
773+
font-size: 18px;
769774
}
770775

771776
/* Hide resize handles on touch devices */
@@ -780,6 +785,16 @@ body {
780785
height: 48px;
781786
font-size: 14px;
782787
}
788+
789+
/* Collapse search trigger to icon-only */
790+
.search-hint {
791+
display: none;
792+
}
793+
794+
.search-trigger {
795+
padding: 0 8px;
796+
width: 34px;
797+
}
783798
}
784799

785800
/* Large phones (≤600px) - auto-collapse sidebar */
@@ -797,8 +812,8 @@ body {
797812
}
798813

799814
.theme-toggle {
800-
width: 36px;
801-
height: 36px;
815+
width: 34px;
816+
height: 34px;
802817
font-size: 18px;
803818
}
804819

@@ -851,12 +866,6 @@ body {
851866
font-size: 16px;
852867
}
853868

854-
.theme-toggle {
855-
width: 32px;
856-
height: 32px;
857-
font-size: 16px;
858-
}
859-
860869
.logout-button {
861870
padding: 4px 8px;
862871
font-size: 14px;

client/src/App.tsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,23 +87,40 @@ function App() {
8787
const isResizingRight = useRef(false);
8888
const isResizingFolderTree = useRef(false);
8989
const leftPaneRef = useRef<HTMLDivElement>(null);
90-
const hasAutoCollapsed = useRef(false); // Track if we've auto-collapsed to avoid repeated triggers
90+
const lastBreakpointRef = useRef<string | null>(null); // Track breakpoint changes for responsive collapse
9191

9292
// Responsive: auto-collapse panes based on screen size
9393
useEffect(() => {
9494
const handleResize = () => {
9595
const width = window.innerWidth;
9696
setIsMobile(width <= MOBILE_BREAKPOINT);
9797

98-
// Only auto-collapse once on initial load or when crossing breakpoints
99-
if (!hasAutoCollapsed.current) {
100-
if (width <= MOBILE_BREAKPOINT) {
98+
// Determine current breakpoint bucket
99+
const breakpoint =
100+
width <= MOBILE_BREAKPOINT ? 'mobile' :
101+
width <= TABLET_BREAKPOINT ? 'tablet' :
102+
'desktop';
103+
104+
// Only act when crossing a breakpoint boundary (including initial mount)
105+
if (breakpoint !== lastBreakpointRef.current) {
106+
const prev = lastBreakpointRef.current;
107+
lastBreakpointRef.current = breakpoint;
108+
109+
if (breakpoint === 'mobile') {
101110
setLeftPaneCollapsed(true);
102111
setRightPaneCollapsed(true);
103-
} else if (width <= TABLET_BREAKPOINT) {
112+
} else if (breakpoint === 'tablet') {
104113
setRightPaneCollapsed(true);
114+
if (prev === 'mobile') setLeftPaneCollapsed(false);
115+
} else {
116+
// Desktop: restore panes that were auto-collapsed
117+
if (prev === 'mobile') {
118+
setLeftPaneCollapsed(false);
119+
setRightPaneCollapsed(false);
120+
} else if (prev === 'tablet') {
121+
setRightPaneCollapsed(false);
122+
}
105123
}
106-
hasAutoCollapsed.current = true;
107124
}
108125
};
109126

client/src/components/Attachments.css

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
.btn-delete {
168168
background: transparent;
169169
border: 1px solid var(--border-color);
170+
color: var(--text-secondary);
170171
width: 32px;
171172
height: 32px;
172173
border-radius: 4px;
@@ -182,11 +183,13 @@
182183
.btn-download:hover {
183184
background: var(--bg-tertiary);
184185
border-color: var(--accent-color);
186+
color: var(--text-primary);
185187
}
186188

187189
.btn-delete:hover {
188-
background: #fee;
189-
border-color: #f44;
190+
background: rgba(220, 38, 38, 0.12);
191+
border-color: var(--error-color);
192+
color: var(--error-color);
190193
}
191194

192195
.spinner {

client/src/components/Attachments.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,13 @@ export const Attachments: React.FC<AttachmentsProps> = ({
219219
<span className="file-icon" aria-hidden="true">
220220
{getFileIcon(file.name)}
221221
</span>
222-
<div className="file-info">
222+
<div
223+
className="file-info"
224+
title={`${file.name}\nModified: ${new Date(file.modified).toLocaleString()}`}
225+
>
223226
<div className="file-name">{file.name}</div>
224227
<div className="file-meta">
225-
{formatFileSize(file.size)}
228+
{formatFileSize(file.size)} · {new Date(file.modified).toLocaleDateString()}
226229
</div>
227230
</div>
228231
<div className="file-actions">

client/src/components/Editor.css

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,43 @@
300300
background: var(--border-color);
301301
margin: 0 var(--space-2);
302302
}
303+
304+
/* =====================================================
305+
RESPONSIVE: EDITOR HEADER & TOOLBAR
306+
===================================================== */
307+
308+
/* Tablet and below: allow the header row to wrap so
309+
action buttons spill to a second row instead of
310+
being pushed off-screen */
311+
@media (max-width: 900px) {
312+
.editor-header {
313+
flex-wrap: wrap;
314+
padding: var(--space-2) var(--space-3);
315+
}
316+
317+
.editor-actions {
318+
flex-wrap: wrap;
319+
gap: var(--space-1);
320+
}
321+
}
322+
323+
/* Tablet portrait (≤768px): force actions onto their
324+
own full-width row below the title */
325+
@media (max-width: 768px) {
326+
.editor-actions {
327+
flex: 0 0 100%;
328+
}
329+
}
330+
331+
/* Mobile (≤480px): tighter button padding so more
332+
buttons fit per row; hide verbose save status */
333+
@media (max-width: 480px) {
334+
.editor-actions button {
335+
padding: var(--space-1) var(--space-2);
336+
font-size: var(--text-xs);
337+
}
338+
339+
.save-status {
340+
display: none;
341+
}
342+
}

client/src/components/FolderTree.css

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,136 @@
133133
color: var(--text-secondary);
134134
font-style: italic;
135135
}
136+
137+
/* Move folder modal */
138+
.move-modal-overlay {
139+
position: fixed;
140+
inset: 0;
141+
background: rgba(0, 0, 0, 0.5);
142+
display: flex;
143+
align-items: center;
144+
justify-content: center;
145+
z-index: 2000;
146+
}
147+
148+
.move-modal {
149+
background: var(--bg-primary);
150+
border: 1px solid var(--border-color);
151+
border-radius: var(--radius-lg);
152+
padding: 20px;
153+
width: 320px;
154+
max-width: 90vw;
155+
box-shadow: 0 8px 32px var(--shadow-lg);
156+
display: flex;
157+
flex-direction: column;
158+
gap: 12px;
159+
}
160+
161+
.move-modal-title {
162+
margin: 0;
163+
font-size: var(--text-base);
164+
font-weight: 600;
165+
color: var(--text-primary);
166+
}
167+
168+
.move-modal-subtitle {
169+
margin: 0;
170+
font-size: var(--text-sm);
171+
color: var(--text-secondary);
172+
}
173+
174+
.move-picker {
175+
border: 1px solid var(--border-color);
176+
border-radius: var(--radius-md);
177+
max-height: 240px;
178+
overflow-y: auto;
179+
display: flex;
180+
flex-direction: column;
181+
}
182+
183+
.move-picker-item {
184+
display: flex;
185+
align-items: center;
186+
gap: 6px;
187+
padding: 7px 8px;
188+
border: none;
189+
border-bottom: 1px solid var(--border-color);
190+
background: none;
191+
text-align: left;
192+
cursor: pointer;
193+
font-size: var(--text-sm);
194+
color: var(--text-primary);
195+
transition: background var(--transition-fast);
196+
}
197+
198+
.move-picker-item:last-child {
199+
border-bottom: none;
200+
}
201+
202+
.move-picker-item:hover {
203+
background: var(--bg-hover);
204+
}
205+
206+
.move-picker-item.selected {
207+
background: var(--accent-bg);
208+
color: var(--accent-color);
209+
font-weight: 500;
210+
}
211+
212+
.move-picker-root {
213+
font-style: italic;
214+
color: var(--text-secondary);
215+
}
216+
217+
.move-picker-root.selected {
218+
color: var(--accent-color);
219+
}
220+
221+
.move-modal-error {
222+
margin: 0;
223+
font-size: var(--text-sm);
224+
color: var(--error-color);
225+
}
226+
227+
.move-modal-actions {
228+
display: flex;
229+
gap: 8px;
230+
justify-content: flex-end;
231+
}
232+
233+
.move-modal-cancel {
234+
padding: 6px 14px;
235+
border: 1px solid var(--border-color);
236+
border-radius: var(--radius-md);
237+
background: none;
238+
color: var(--text-secondary);
239+
cursor: pointer;
240+
font-size: var(--text-sm);
241+
transition: background var(--transition-fast);
242+
}
243+
244+
.move-modal-cancel:hover:not(:disabled) {
245+
background: var(--bg-hover);
246+
}
247+
248+
.move-modal-confirm {
249+
padding: 6px 14px;
250+
border: none;
251+
border-radius: var(--radius-md);
252+
background: var(--accent-color);
253+
color: var(--accent-text);
254+
cursor: pointer;
255+
font-size: var(--text-sm);
256+
font-weight: 500;
257+
transition: background var(--transition-fast);
258+
}
259+
260+
.move-modal-confirm:hover:not(:disabled) {
261+
background: var(--accent-hover);
262+
}
263+
264+
.move-modal-cancel:disabled,
265+
.move-modal-confirm:disabled {
266+
opacity: 0.5;
267+
cursor: not-allowed;
268+
}

0 commit comments

Comments
 (0)