Skip to content

Commit cdfd8ab

Browse files
committed
Add view mode toggle and UI improvements
- Add Source/Split/Rendered view toggle button group - Default to rendered view when opening files, split when no file - Add 10% side margins in full-width (non-split) modes - Hide empty state placeholder in rendered-only view - Update title to 'mkdedit' - Change tauri:build to skip bundling for faster local builds - Bump version to 1.1.0
1 parent eff904d commit cdfd8ab

10 files changed

Lines changed: 123 additions & 22 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"name": "mkdedit",
3-
"version": "1.0.5",
3+
"version": "1.1.0",
44
"type": "module",
55
"scripts": {
66
"dev": "vite",
77
"build": "vite build",
88
"preview": "vite preview",
99
"tauri": "tauri",
1010
"tauri:dev": "tauri dev",
11-
"tauri:build": "tauri build",
11+
"tauri:build": "tauri build --no-bundle",
1212
"tauri:build:win": "tauri build --bundles nsis,msi",
1313
"tauri:build:mac": "tauri build --bundles dmg,app",
1414
"tauri:build:linux": "tauri build --bundles deb,appimage",

sample-markdown.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ This demonstrates Markdown's features.
1818

1919
```javascript
2020
function hello() {
21-
return "Hello from Nuemark!"
21+
return "Hello from Markdown!"
2222
}
2323
```
2424

src-tauri/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mkdedit"
3-
version = "1.0.5"
3+
version = "1.1.0"
44
description = "A Markdown editor with live preview"
55
authors = ["Appurist Software Inc."]
66
license = "MIT"

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
33
"productName": "mkdedit",
4-
"version": "1.0.5",
4+
"version": "1.1.0",
55
"identifier": "com.appurist.mkdedit",
66
"build": {
77
"frontendDist": "../dist",

src/App.jsx

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Preview from './components/Preview'
1010
export default function App() {
1111
const [content, setContent] = createSignal('')
1212
const [editorWidth, setEditorWidth] = createSignal(50)
13+
const [viewMode, setViewMode] = createSignal('rendered') // 'source', 'split', 'rendered'
1314

1415
const fileSystem = useFileSystem()
1516
const { parse } = useMarkdown()
@@ -19,11 +20,20 @@ export default function App() {
1920
const file = fileSystem.currentFile()
2021
const dirty = fileSystem.isDirty()
2122
const title = file
22-
? `${file}${dirty ? ' *' : ''} - Markdown Editor`
23-
: 'Markdown Editor'
23+
? `${file}${dirty ? ' *' : ''} - mkdedit`
24+
: 'mkdedit'
2425
document.title = title
2526
})
2627

28+
// Switch to split view if no file is loaded after startup
29+
onMount(() => {
30+
setTimeout(() => {
31+
if (!fileSystem.currentFile() && !content()) {
32+
setViewMode('split')
33+
}
34+
}, 1200) // Wait for CLI/Open With file to load
35+
})
36+
2737
// Keyboard shortcut: Ctrl+S to save
2838
onMount(() => {
2939
const handleKeyDown = (e) => {
@@ -41,6 +51,7 @@ export default function App() {
4151
const { path, content: fileContent } = event.payload
4252
fileSystem.setOpenFile(path)
4353
setContent(fileContent)
54+
setViewMode('rendered')
4455
})
4556
onCleanup(() => unlisten())
4657
}
@@ -55,12 +66,14 @@ export default function App() {
5566
function handleNew() {
5667
setContent('')
5768
fileSystem.newFile()
69+
setViewMode('split')
5870
}
5971

6072
async function handleOpen() {
6173
const fileContent = await fileSystem.openFile()
6274
if (fileContent !== null) {
6375
setContent(fileContent)
76+
setViewMode('rendered')
6477
}
6578
}
6679

@@ -78,22 +91,32 @@ export default function App() {
7891
currentFile={fileSystem.currentFile}
7992
isDirty={fileSystem.isDirty}
8093
supportsFileSystemAccess={fileSystem.supportsFileSystemAccess}
94+
viewMode={viewMode}
95+
onViewModeChange={setViewMode}
8196
onNew={handleNew}
8297
onOpen={handleOpen}
8398
onSave={handleSave}
8499
onSaveAs={handleSaveAs}
85100
/>
86101
<main class="editor-container">
87-
<Editor
88-
content={content}
89-
onInput={handleContentChange}
90-
width={editorWidth}
91-
/>
92-
<Splitter onResize={setEditorWidth} />
93-
<Preview
94-
html={() => parse(content())}
95-
width={() => 100 - editorWidth()}
96-
/>
102+
{(viewMode() === 'source' || viewMode() === 'split') && (
103+
<Editor
104+
content={content}
105+
onInput={handleContentChange}
106+
width={() => viewMode() === 'split' ? editorWidth() : 100}
107+
viewMode={viewMode}
108+
/>
109+
)}
110+
{viewMode() === 'split' && (
111+
<Splitter onResize={setEditorWidth} />
112+
)}
113+
{(viewMode() === 'rendered' || viewMode() === 'split') && (
114+
<Preview
115+
html={() => parse(content())}
116+
width={() => viewMode() === 'split' ? 100 - editorWidth() : 100}
117+
viewMode={viewMode}
118+
/>
119+
)}
97120
</main>
98121
</div>
99122
)

src/components/Editor.jsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
export default function Editor(props) {
2+
const isFullWidth = () => props.viewMode && props.viewMode() === 'source'
3+
24
return (
3-
<div class="editor-pane" style={{ flex: `0 0 ${props.width()}%` }}>
5+
<div
6+
class={`editor-pane ${isFullWidth() ? 'editor-full' : ''}`}
7+
style={{ flex: `0 0 ${props.width()}%` }}
8+
>
49
<textarea
510
id="editor"
611
placeholder="Start typing your markdown here..."

src/components/Preview.jsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import { Show } from 'solid-js'
22

33
export default function Preview(props) {
4+
const isFullWidth = () => props.viewMode && props.viewMode() === 'rendered'
5+
46
return (
5-
<div class="preview-pane" style={{ flex: `0 0 ${props.width()}%` }}>
7+
<div
8+
class={`preview-pane ${isFullWidth() ? 'preview-full' : ''}`}
9+
style={{ flex: `0 0 ${props.width()}%` }}
10+
>
611
<div class="preview-content">
712
<Show
813
when={props.html()}
9-
fallback={<p class="empty-state">Start typing markdown to see the preview...</p>}
14+
fallback={!isFullWidth() && <p class="empty-state">Start typing markdown to see the preview...</p>}
1015
>
1116
<div innerHTML={props.html()} />
1217
</Show>

src/components/Toolbar.jsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,27 @@ export default function Toolbar(props) {
1010

1111
return (
1212
<header class="toolbar">
13-
<h1>Markdown Editor</h1>
13+
<h1>mkdedit</h1>
14+
<div class="view-toggle">
15+
<button
16+
class={`btn-toggle ${props.viewMode() === 'source' ? 'active' : ''}`}
17+
onClick={() => props.onViewModeChange('source')}
18+
>
19+
Source
20+
</button>
21+
<button
22+
class={`btn-toggle ${props.viewMode() === 'split' ? 'active' : ''}`}
23+
onClick={() => props.onViewModeChange('split')}
24+
>
25+
Split
26+
</button>
27+
<button
28+
class={`btn-toggle ${props.viewMode() === 'rendered' ? 'active' : ''}`}
29+
onClick={() => props.onViewModeChange('rendered')}
30+
>
31+
Rendered
32+
</button>
33+
</div>
1434
<div class="file-controls">
1535
<span class="current-file">{displayName()}</span>
1636
<button class="btn" onClick={props.onOpen}>Open</button>

src/styles/index.css

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,46 @@ body {
7878
background: #005a9e;
7979
}
8080

81+
.view-toggle {
82+
display: flex;
83+
margin-left: 1.5rem;
84+
}
85+
86+
.btn-toggle {
87+
padding: 0.4rem 0.75rem;
88+
border: 1px solid #ccc;
89+
background: white;
90+
cursor: pointer;
91+
font-size: 0.8rem;
92+
transition: background-color 0.15s, color 0.15s;
93+
}
94+
95+
.btn-toggle:first-child {
96+
border-radius: 4px 0 0 4px;
97+
}
98+
99+
.btn-toggle:last-child {
100+
border-radius: 0 4px 4px 0;
101+
}
102+
103+
.btn-toggle:not(:first-child) {
104+
border-left: none;
105+
}
106+
107+
.btn-toggle:hover {
108+
background: #f0f0f0;
109+
}
110+
111+
.btn-toggle.active {
112+
background: #007acc;
113+
color: white;
114+
border-color: #007acc;
115+
}
116+
117+
.btn-toggle.active + .btn-toggle {
118+
border-left-color: #007acc;
119+
}
120+
81121
.editor-container {
82122
display: flex;
83123
flex: 1;
@@ -90,6 +130,10 @@ body {
90130
flex-direction: column;
91131
}
92132

133+
.editor-pane.editor-full {
134+
padding: 0 10%;
135+
}
136+
93137
#editor {
94138
flex: 1;
95139
border: none;
@@ -131,6 +175,10 @@ body {
131175
background: white;
132176
}
133177

178+
.preview-pane.preview-full .preview-content {
179+
margin: 0 10%;
180+
}
181+
134182
.preview-content {
135183
padding: 1rem;
136184
max-width: none;

0 commit comments

Comments
 (0)