Skip to content

Commit 721c941

Browse files
feat(ui): redesign empty document state
1 parent e5efe4a commit 721c941

6 files changed

Lines changed: 530 additions & 38 deletions

File tree

desktop-app/resources/index.html

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,11 +1196,52 @@ <h2 class="about-title">Markdown Viewer</h2>
11961196
</div>
11971197

11981198
<main class="content-container">
1199-
<div id="no-open-document" class="no-open-document" role="status" hidden>
1200-
<i class="lucide lucide-file-text" aria-hidden="true"></i>
1201-
<p class="no-open-document-title">No file open</p>
1202-
<p class="no-open-document-copy">Choose a file from the sidebar or create a new Markdown file.</p>
1203-
<button id="no-open-document-new" class="reset-modal-btn reset-modal-confirm" type="button"><i class="lucide lucide-file-plus-2" aria-hidden="true"></i> New file</button>
1199+
<div id="no-open-document" class="no-open-document" role="region" aria-labelledby="no-open-document-title" hidden>
1200+
<div class="no-open-document-layout">
1201+
<section class="no-open-document-identity" aria-label="Markdown Viewer">
1202+
<img class="no-open-document-logo" src="assets/icon.jpg" width="112" height="112" alt="">
1203+
<p class="no-open-document-app-name">Markdown Viewer</p>
1204+
<h2 id="no-open-document-title" class="no-open-document-title">No file open</h2>
1205+
<p class="no-open-document-session">You don&rsquo;t have any recent files in this browser session.</p>
1206+
<p class="no-open-document-copy">Create a new Markdown file or open one from your device to get started.</p>
1207+
</section>
1208+
1209+
<section class="no-open-document-start" aria-labelledby="no-open-document-start-title">
1210+
<h3 id="no-open-document-start-title">Get Started</h3>
1211+
<div class="no-open-document-actions">
1212+
<button id="no-open-document-new" class="no-open-document-action" type="button">
1213+
<i class="lucide lucide-file-plus-2" aria-hidden="true"></i>
1214+
<span>New Markdown File</span>
1215+
<i class="lucide lucide-chevron-right no-open-document-action-arrow" aria-hidden="true"></i>
1216+
</button>
1217+
<button id="no-open-document-open-file" class="no-open-document-action" type="button">
1218+
<i class="lucide lucide-upload" aria-hidden="true"></i>
1219+
<span>Open File</span>
1220+
<i class="lucide lucide-chevron-right no-open-document-action-arrow" aria-hidden="true"></i>
1221+
</button>
1222+
<button id="no-open-document-open-workspace" class="no-open-document-action" type="button">
1223+
<i class="lucide lucide-folder-open" aria-hidden="true"></i>
1224+
<span>Open Folder / Workspace</span>
1225+
<i class="lucide lucide-chevron-right no-open-document-action-arrow" aria-hidden="true"></i>
1226+
</button>
1227+
<button id="no-open-document-open-recent" class="no-open-document-action" type="button">
1228+
<i class="lucide lucide-history" aria-hidden="true"></i>
1229+
<span>Open Recent</span>
1230+
<i class="lucide lucide-chevron-right no-open-document-action-arrow" aria-hidden="true"></i>
1231+
</button>
1232+
<button id="no-open-document-welcome" class="no-open-document-action" type="button">
1233+
<i class="lucide lucide-panels-top-left" aria-hidden="true"></i>
1234+
<span>Use Welcome Template</span>
1235+
<i class="lucide lucide-chevron-right no-open-document-action-arrow" aria-hidden="true"></i>
1236+
</button>
1237+
<button id="no-open-document-github" class="no-open-document-action" type="button">
1238+
<i class="bi bi-github" aria-hidden="true"></i>
1239+
<span>Import from GitHub</span>
1240+
<i class="lucide lucide-chevron-right no-open-document-action-arrow" aria-hidden="true"></i>
1241+
</button>
1242+
</div>
1243+
</section>
1244+
</div>
12041245
</div>
12051246
<div class="editor-pane is-loading">
12061247
<div id="line-numbers" class="line-numbers" aria-hidden="true" inert></div>

desktop-app/resources/js/script.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,11 @@ document.addEventListener("DOMContentLoaded", async function () {
383383
const documentSplitPreview = document.getElementById('document-split-preview');
384384
const noOpenDocument = document.getElementById('no-open-document');
385385
const noOpenDocumentNew = document.getElementById('no-open-document-new');
386+
const noOpenDocumentOpenFile = document.getElementById('no-open-document-open-file');
387+
const noOpenDocumentOpenWorkspace = document.getElementById('no-open-document-open-workspace');
388+
const noOpenDocumentOpenRecent = document.getElementById('no-open-document-open-recent');
389+
const noOpenDocumentWelcome = document.getElementById('no-open-document-welcome');
390+
const noOpenDocumentGithub = document.getElementById('no-open-document-github');
386391

387392
// Mobile View Mode Elements - Story 1.4
388393
const mobileViewModeButtons = document.querySelectorAll(".mobile-view-mode-btn");
@@ -6060,11 +6065,31 @@ document.addEventListener("DOMContentLoaded", async function () {
60606065
});
60616066
}
60626067

6068+
function getRecentClosedDocument() {
6069+
return tabs.filter(function(tab) {
6070+
if (!tab || isTabOpen(tab) || isTemporaryDocument(tab)) return false;
6071+
return tab.workspaceId !== SECRET_WORKSPACE_ID || isSecretWorkspaceUnlocked();
6072+
}).sort(function(a, b) {
6073+
return getDocumentActivityTimestamp(b) - getDocumentActivityTimestamp(a);
6074+
})[0] || null;
6075+
}
6076+
6077+
function updateNoOpenDocumentActions() {
6078+
if (!noOpenDocumentOpenRecent) return;
6079+
const recentDocument = getRecentClosedDocument();
6080+
noOpenDocumentOpenRecent.disabled = !recentDocument;
6081+
noOpenDocumentOpenRecent.setAttribute('aria-disabled', recentDocument ? 'false' : 'true');
6082+
noOpenDocumentOpenRecent.title = recentDocument
6083+
? 'Reopen ' + (recentDocument.title || 'recent document')
6084+
: 'No recent documents available';
6085+
}
6086+
60636087
function updateNoOpenDocumentState() {
60646088
const activeTab = tabs.find(function(tab) { return tab.id === activeTabId && isTabOpen(tab); });
60656089
const hasActiveTab = Boolean(activeTab);
60666090
if (contentContainer) contentContainer.classList.toggle('no-active-document', !hasActiveTab);
60676091
if (noOpenDocument) noOpenDocument.hidden = hasActiveTab;
6092+
updateNoOpenDocumentActions();
60686093
if (!hasActiveTab) {
60696094
markdownEditor.value = '';
60706095
if (secondarySplitTabId) closeDocumentSplitView({ silent: true, renderTabs: false });
@@ -7362,6 +7387,36 @@ document.addEventListener("DOMContentLoaded", async function () {
73627387
if (noOpenDocumentNew) {
73637388
noOpenDocumentNew.onclick = function() { newTab(); };
73647389
}
7390+
if (noOpenDocumentOpenFile) {
7391+
noOpenDocumentOpenFile.onclick = function() {
7392+
if (importFromFileButton) importFromFileButton.click();
7393+
else fileInput.click();
7394+
};
7395+
}
7396+
if (noOpenDocumentOpenWorkspace) {
7397+
noOpenDocumentOpenWorkspace.onclick = function() { openDocumentSidebar(); };
7398+
}
7399+
if (noOpenDocumentOpenRecent) {
7400+
noOpenDocumentOpenRecent.onclick = function() {
7401+
const recentDocument = getRecentClosedDocument();
7402+
if (recentDocument) switchTab(recentDocument.id);
7403+
};
7404+
}
7405+
if (noOpenDocumentWelcome) {
7406+
noOpenDocumentWelcome.onclick = function() {
7407+
const welcome = tabs.find(function(tab) {
7408+
return !isTabOpen(tab) && tab.title === 'Welcome to Markdown' && tab.workspaceId !== SECRET_WORKSPACE_ID;
7409+
});
7410+
if (welcome) switchTab(welcome.id);
7411+
else newTab(sampleMarkdown, 'Welcome to Markdown');
7412+
};
7413+
}
7414+
if (noOpenDocumentGithub) {
7415+
noOpenDocumentGithub.onclick = function() {
7416+
if (importFromGithubButton) importFromGithubButton.click();
7417+
else openGitHubImportModal();
7418+
};
7419+
}
73657420
}
73667421

73677422
// Late-load callback hook for Neutralino command-line files

desktop-app/resources/styles.css

Lines changed: 164 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,7 @@ body.document-sidebar-collapsed .document-sidebar {
11291129
}
11301130

11311131
.content-container {
1132+
position: relative;
11321133
display: flex;
11331134
flex: 1;
11341135
overflow: hidden;
@@ -1138,38 +1139,187 @@ body.document-sidebar-collapsed .document-sidebar {
11381139
position: absolute;
11391140
inset: 0;
11401141
z-index: 30;
1141-
display: flex;
1142-
align-items: center;
1143-
justify-content: center;
1144-
flex-direction: column;
1145-
padding: 32px;
1146-
text-align: center;
1142+
display: grid;
1143+
place-items: center;
1144+
padding: clamp(32px, 6vw, 72px);
1145+
overflow: auto;
11471146
background: var(--bg-color);
11481147
}
11491148

11501149
.no-open-document[hidden] {
11511150
display: none;
11521151
}
11531152

1154-
.no-open-document > i {
1155-
margin-bottom: 12px;
1153+
.no-open-document-layout {
1154+
display: grid;
1155+
width: min(100%, 900px);
1156+
grid-template-columns: minmax(0, 1fr) minmax(300px, 0.82fr);
1157+
align-items: center;
1158+
gap: clamp(48px, 8vw, 96px);
1159+
}
1160+
1161+
.no-open-document-identity {
1162+
min-width: 0;
1163+
text-align: center;
1164+
}
1165+
1166+
.no-open-document-logo {
1167+
display: block;
1168+
width: clamp(88px, 10vw, 112px);
1169+
height: clamp(88px, 10vw, 112px);
1170+
margin: 0 auto 14px;
1171+
border-radius: 22px;
1172+
object-fit: cover;
1173+
opacity: 0.08;
1174+
filter: invert(1);
1175+
mix-blend-mode: multiply;
1176+
}
1177+
1178+
html[data-theme="dark"] .no-open-document-logo {
1179+
opacity: 0.12;
1180+
filter: none;
1181+
mix-blend-mode: screen;
1182+
}
1183+
1184+
.no-open-document-app-name {
1185+
margin: 0 0 11px;
11561186
color: var(--text-secondary);
1157-
font-size: 34px;
1187+
font-size: 14px;
1188+
font-weight: 500;
11581189
}
11591190

11601191
.no-open-document-title {
11611192
margin: 0;
11621193
color: var(--text-color);
1163-
font-size: 16px;
1164-
font-weight: 600;
1194+
font-size: clamp(22px, 2.5vw, 27px);
1195+
font-weight: 650;
1196+
line-height: 1.25;
1197+
letter-spacing: -0.025em;
11651198
}
11661199

1200+
.no-open-document-session,
11671201
.no-open-document-copy {
1168-
max-width: 360px;
1169-
margin: 6px 0 16px;
1202+
margin-inline: auto;
11701203
color: var(--text-secondary);
11711204
font-size: 12px;
1172-
line-height: 1.5;
1205+
line-height: 1.55;
1206+
}
1207+
1208+
.no-open-document-session {
1209+
margin-block: 18px 0;
1210+
}
1211+
1212+
.no-open-document-copy {
1213+
max-width: 410px;
1214+
margin-block: 6px 0;
1215+
}
1216+
1217+
.no-open-document-start {
1218+
width: 100%;
1219+
max-width: 360px;
1220+
padding-inline-start: clamp(26px, 4vw, 54px);
1221+
border-inline-start: 1px solid color-mix(in srgb, var(--border-color) 74%, transparent);
1222+
}
1223+
1224+
.no-open-document-start h3 {
1225+
margin: 0 0 14px;
1226+
color: var(--text-color);
1227+
font-size: 14px;
1228+
font-weight: 650;
1229+
}
1230+
1231+
.no-open-document-actions {
1232+
display: flex;
1233+
flex-direction: column;
1234+
gap: 7px;
1235+
}
1236+
1237+
.no-open-document-action {
1238+
display: grid;
1239+
width: 100%;
1240+
min-height: 44px;
1241+
grid-template-columns: 20px minmax(0, 1fr) 16px;
1242+
align-items: center;
1243+
gap: 11px;
1244+
padding: 9px 11px;
1245+
border: 1px solid var(--border-color);
1246+
border-radius: 8px;
1247+
color: var(--accent-color);
1248+
background: color-mix(in srgb, var(--bg-color) 92%, var(--button-bg));
1249+
font: inherit;
1250+
font-size: 12px;
1251+
font-weight: 600;
1252+
text-align: start;
1253+
cursor: pointer;
1254+
touch-action: manipulation;
1255+
transition: border-color 0.16s ease, background-color 0.16s ease, box-shadow 0.16s ease;
1256+
}
1257+
1258+
.no-open-document-action > i:first-child {
1259+
color: currentColor;
1260+
font-size: 17px;
1261+
}
1262+
1263+
.no-open-document-action:hover:not(:disabled) {
1264+
border-color: color-mix(in srgb, var(--accent-color) 36%, var(--border-color));
1265+
background: color-mix(in srgb, var(--accent-color) 7%, var(--bg-color));
1266+
}
1267+
1268+
.no-open-document-action:active:not(:disabled) {
1269+
background: color-mix(in srgb, var(--accent-color) 11%, var(--bg-color));
1270+
}
1271+
1272+
.no-open-document-action:focus-visible {
1273+
outline: 2px solid var(--accent-color);
1274+
outline-offset: 2px;
1275+
}
1276+
1277+
.no-open-document-action:disabled {
1278+
color: var(--text-secondary);
1279+
cursor: not-allowed;
1280+
opacity: 0.48;
1281+
}
1282+
1283+
.no-open-document-action-arrow {
1284+
justify-self: end;
1285+
color: var(--text-secondary);
1286+
font-size: 14px;
1287+
}
1288+
1289+
[dir="rtl"] .no-open-document-action-arrow {
1290+
transform: rotate(180deg);
1291+
}
1292+
1293+
@media (max-width: 767.98px) {
1294+
.no-open-document {
1295+
place-items: start center;
1296+
padding: 30px clamp(16px, 6vw, 36px) 40px;
1297+
}
1298+
1299+
.no-open-document-layout {
1300+
width: min(100%, 520px);
1301+
grid-template-columns: 1fr;
1302+
gap: 32px;
1303+
}
1304+
1305+
.no-open-document-logo {
1306+
width: 82px;
1307+
height: 82px;
1308+
border-radius: 18px;
1309+
}
1310+
1311+
.no-open-document-start {
1312+
max-width: none;
1313+
padding: 26px 0 0;
1314+
border-inline-start: 0;
1315+
border-top: 1px solid color-mix(in srgb, var(--border-color) 74%, transparent);
1316+
}
1317+
}
1318+
1319+
@media (prefers-reduced-motion: reduce) {
1320+
.no-open-document-action {
1321+
transition: none;
1322+
}
11731323
}
11741324

11751325
.editor-pane,

0 commit comments

Comments
 (0)