Skip to content

Commit 0ef560f

Browse files
committed
better toolbar and polishing
1 parent 177bb60 commit 0ef560f

File tree

6 files changed

+101
-47
lines changed

6 files changed

+101
-47
lines changed

src/components/button.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ button {
2424
}
2525
2626
button:hover {
27+
cursor: pointer;
2728
background: var(--surface);
2829
}
2930

src/components/menu-item.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ defineProps({
2424
padding-bottom: 8px;
2525
font-size: 12px;
2626
text-transform: uppercase;
27-
color:var(--subtle);
27+
color: var(--subtle);
2828
}
2929
3030
.item-wrapper:hover {
31+
cursor: pointer;
3132
background: var(--surface);
3233
}
3334

src/components/menu.vue

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
<template>
22
<div class="container">
3-
<Button @click="state.dropdownOpen = !state.dropdownOpen" class="trigger">
3+
<Button @click="state.dropdownOpen = !state.dropdownOpen" class="ghost trigger">
44
{{ triggerLabel }}
55
</Button>
66

7-
<div
8-
v-if="state.dropdownOpen"
9-
class="dropdown"
10-
@click="state.dropdownOpen = false"
11-
></div>
7+
<div v-if="state.dropdownOpen" class="dropdown" @click="state.dropdownOpen = false"></div>
128

139
<div v-if="state.dropdownOpen" class="dropdown-items">
1410
<slot></slot>
@@ -36,6 +32,7 @@ const state = reactive({ dropdownOpen: false });
3632
.trigger {
3733
position: relative;
3834
}
35+
3936
.dropdown {
4037
position: fixed;
4138
height: 100vh;
@@ -46,12 +43,13 @@ const state = reactive({ dropdownOpen: false });
4643
.dropdown-items {
4744
position: absolute;
4845
left: 0;
46+
bottom: calc(var(--toolbar-height) + 10px);
4947
margin-top: 8px;
5048
padding-top: 8px;
5149
padding-bottom: 8px;
52-
width: 30em;
50+
width: 15em;
5351
background: var(--overlay);
54-
color:var(--subtle);
52+
color: var(--subtle);
5553
border-radius: 12px;
5654
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
5755
z-index: 20;

src/components/toolbar.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<template>
2+
<div class="toolbar">
3+
<slot />
4+
</div>
5+
</template>
6+

src/pages/Home.vue

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,37 @@
22
<BaseLayout>
33
<Toast ref="toastRef" />
44
<div class="flex justify-between mb-2">
5-
<Menu triggerLabel="Menu">
6-
<MenuItem
7-
label="Toggle Preview"
8-
modifier="⌘ + k"
9-
@click="handlePreviewToggle"
10-
/>
11-
<MenuItem label="Copy as HTML" @click="handleCopyAsHTML" />
12-
<MenuItem label="Save File" modifier="⌘ + s" @click="handleSaveFile" />
13-
<MenuItem
14-
label="Save File as HTML"
15-
modifier="⌘ + ⇧ + s "
16-
@click="handleSaveAsHTML"
17-
/>
18-
<MenuItem label="Save File as PDF" @click="handleSaveAsPDF" />
19-
<MenuItem label="Save File as Image" @click="handleSaveAsImage" />
20-
</Menu>
21-
22-
<Button class="ghost" @click="handlePreviewToggle" title="Toggle preview state">
23-
<span
24-
class="preview-dot"
25-
v-bind:class="{ on: state.showPreview }"
26-
></span>
27-
</Button>
5+
<Toolbar>
6+
<Menu triggerLabel="Menu">
7+
<MenuItem label="Toggle Preview" modifier="⌘ + k" @click="handlePreviewToggle" />
8+
<MenuItem label="Copy as HTML" @click="handleCopyAsHTML" />
9+
<MenuItem label="Save File" modifier="⌘ + s" @click="handleSaveFile" />
10+
<MenuItem label="Save File as HTML" modifier="⌘ + ⇧ + s " @click="handleSaveAsHTML" />
11+
<MenuItem label="Save File as PDF" @click="handleSaveAsPDF" />
12+
<MenuItem label="Save File as Image" @click="handleSaveAsImage" />
13+
</Menu>
14+
<div class="flex align-center">
15+
<Button class="trigger ghost" v-bind:class="{ active: state.copied }" @click="handleCopyAsHTML">
16+
<svg v-if="!state.copied" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
17+
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
18+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
19+
<rect x="8" y="8" width="12" height="12" rx="2"></rect>
20+
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path>
21+
</svg>
22+
<svg v-if="state.copied" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
23+
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
24+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
25+
<circle cx="12" cy="12" r="9"></circle>
26+
<path d="M9 12l2 2l4 -4"></path>
27+
</svg>
28+
</Button>
29+
<Button class="ghost" @click="handlePreviewToggle">
30+
<span class="preview-dot" v-bind:class="{'on':state.showPreview}"></span>
31+
</Button>
32+
</div>
33+
</Toolbar>
2834
</div>
29-
<Editor
30-
v-if="!state.showPreview"
31-
class="mt-1"
32-
v-on:change="handleChange"
33-
v-bind:code="state.code"
34-
></Editor>
35+
<Editor v-if="!state.showPreview" class="mt-1" v-on:change="handleChange" v-bind:code="state.code"></Editor>
3536
<Preview v-if="state.showPreview" v-bind:code="marked(state.code)" />
3637
</BaseLayout>
3738
</template>
@@ -40,6 +41,7 @@
4041
import BaseLayout from "../components/base-layout.vue";
4142
import Menu from "../components/menu.vue";
4243
import MenuItem from "../components/menu-item.vue";
44+
import Toolbar from "../components/toolbar.vue";
4345
import Editor from "../components/editor.vue";
4446
import Button from "../components/button.vue";
4547
import Preview from "../components/preview.vue";
@@ -65,7 +67,11 @@ const getDefaultCode = () => {
6567
return defaultMarkdownText;
6668
};
6769
68-
const state = reactive({ code: getDefaultCode(), showPreview: false });
70+
const state = reactive({
71+
copied: false,
72+
code: getDefaultCode(),
73+
showPreview: false,
74+
});
6975
7076
onMounted(() => {
7177
document.addEventListener("keydown", shortcutListener.bind(this));
@@ -103,7 +109,10 @@ async function handleCopyAsHTML() {
103109
}
104110
const htmlValue = marked(state.code);
105111
await copy(htmlValue);
106-
toastRef.value.createSuccessToast("Copied!");
112+
state.copied = true;
113+
setTimeout(() => {
114+
state.copied = false;
115+
}, 2500);
107116
}
108117
109118
function handlePreviewToggle() {
@@ -194,4 +203,5 @@ function exportFile(filename, file, generateDataURI = true) {
194203
</script>
195204

196205
<style scoped>
206+
197207
</style>

src/styles/index.css

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33

44
:root {
55
--base-spacing: 4px;
6-
--base: #e9eaeb;
7-
--overlay: #d3d5d6;
8-
--surface: #bdbfc2;
6+
--base: #fff;
7+
--overlay: #f8f9fa;
8+
--surface: #f1f3f5;
99
--text: #030405;
1010
--subtle: #07090a;
11+
--warn: #e5c07b;
12+
--success: #98c379;
13+
--toolbar-height: 42px;
1114
}
1215

1316
@media (prefers-color-scheme: dark) {
@@ -40,14 +43,14 @@ a {
4043
}
4144

4245
.preview-dot {
43-
height: 12px;
44-
width: 12px;
46+
height: 10px;
47+
width: 10px;
4548
border-radius: 25px;
46-
background: #e5c07b;
49+
background: var(--warn);
4750
}
4851

4952
.preview-dot.on {
50-
background: #98c379;
53+
background: var(--success);
5154
}
5255

5356
.flex {
@@ -62,6 +65,10 @@ a {
6265
justify-content: space-between;
6366
}
6467

68+
.align-center {
69+
align-items: center;
70+
}
71+
6572
.p-5 {
6673
padding: calc(var(--base-spacing) * 5);
6774
}
@@ -89,3 +96,34 @@ a {
8996
.min-h-screen {
9097
min-height: 100vh;
9198
}
99+
100+
.toolbar {
101+
color: var(--subtle);
102+
height: var(--toolbar-height);
103+
align-items: center;
104+
justify-content: space-between;
105+
gap: 4px;
106+
padding-right: 10px;
107+
display: inline-flex;
108+
position: fixed;
109+
bottom: 20px;
110+
left: 50%;
111+
min-width: 350px;
112+
border-radius: 50px;
113+
transform: translateX(-50%);
114+
background: var(--overlay);
115+
box-shadow: 0px 2px 4px rgba(0,0,0,0.12);
116+
}
117+
118+
.trigger {
119+
min-width: 50px;
120+
max-width: 150px;
121+
border-radius: 0px !important;
122+
height: var(--toolbar-height);
123+
padding-left: 16px !important;
124+
padding-right: 16px !important;
125+
}
126+
127+
.trigger.active {
128+
color: var(--success);
129+
}

0 commit comments

Comments
 (0)