theme switcher

This commit is contained in:
nicwands
2026-03-10 11:11:22 -04:00
parent 23054d4981
commit 77b8ad2dcd
21 changed files with 88962 additions and 92 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,768 @@
@charset "UTF-8";
:root {
--black: #181818;
--white: #D5D5D5;
--grey-100: #747474;
--green: #87FF5B;
--blue: #5B92FF;
}
:root .theme-light {
--theme-bg: #D5D5D5;
--theme-fg: #181818;
--theme-accent: #87FF5B;
--theme-link: #5B92FF;
}
:root .theme-dark {
--theme-bg: #181818;
--theme-fg: #D5D5D5;
--theme-accent: #87FF5B;
--theme-link: #5B92FF;
}
:root {
--ease-in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53);
--ease-in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19);
--ease-in-quart: cubic-bezier(0.895, 0.03, 0.685, 0.22);
--ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06);
--ease-in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035);
--ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335);
--ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);
--ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
--ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
--ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
--ease-out-circ: cubic-bezier(0.075, 0.82, 0.165, 1);
--ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
--ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1);
--ease-in-out-quart: cubic-bezier(0.77, 0, 0.175, 1);
--ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1);
--ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
--ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86);
--ease-custom: cubic-bezier(0.315, 0.365, 0.23, 0.985);
}
/***
The new CSS reset - version 1.9 (last updated 19.6.2023)
GitHub page: https://github.com/elad2412/the-new-css-reset
***/
/*
Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property
- The "symbol *" part is to solve Firefox SVG sprite bug
- The "html" element is excluded, otherwise a bug in Chrome breaks the CSS hyphens property (https://github.com/elad2412/the-new-css-reset/issues/36)
*/
*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {
all: unset;
display: revert;
}
/* Preferred box-sizing value */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Reapply the pointer cursor for anchor tags */
a,
button {
cursor: revert;
}
/* For images to not be able to exceed their container */
img {
max-inline-size: 100%;
max-block-size: 100%;
}
/* removes spacing between cells in tables */
table {
border-collapse: collapse;
}
/* Safari - solving issue when using user-select:none on the <body> text input doesn't working */
input,
textarea {
-webkit-user-select: auto;
}
/* revert the 'white-space' property for textarea elements on Safari */
textarea {
white-space: revert;
}
/* minimum style to allow to style meter element */
meter {
-webkit-appearance: revert;
appearance: revert;
}
/* preformatted text - use only for this feature */
:where(pre) {
all: revert;
}
/* reset default text opacity of input placeholder */
::placeholder {
color: unset;
}
/* remove default dot (•) sign */
::marker {
content: initial;
}
/* fix the feature of 'hidden' attribute.
display:revert; revert to element instead of attribute */
:where([hidden]) {
display: none;
}
/* revert for bug in Chromium browsers
- fix for the content editable attribute will work properly.
- webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element*/
:where([contenteditable]:not([contenteditable=false])) {
-moz-user-modify: read-write;
-webkit-user-modify: read-write;
overflow-wrap: break-word;
-webkit-line-break: after-white-space;
-webkit-user-select: auto;
}
/* apply back the draggable feature - exist only in Chromium and Safari */
:where([draggable=true]) {
-webkit-user-drag: element;
}
/* Revert Modal native behavior */
:where(dialog:modal) {
all: revert;
}
.menu {
z-index: 10;
}
.full-width {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
.overflow-hidden {
overflow: hidden;
}
.relative {
position: relative;
}
html:not(.has-scroll-smooth) .hide-on-native-scroll {
display: none;
}
/*
Font Weights:
100 - Thin
200 - Extra Light (Ultra Light)
300 - Light
400 - Normal
500 - Medium
600 - Semi Bold (Demi Bold)
700 - Bold
800 - Extra Bold (Ultra Bold)
900 - Black (Heavy)
*/
/* Leibniz Fraktur */
@font-face {
font-family: "Leibniz Fraktur";
font-style: normal;
font-weight: 400;
src: url("./neuefraktur-A4S1ACH2.woff2") format("woff2"), url("./neuefraktur-CwjUIZ0G.woff") format("woff");
}
/* Geist Mono */
@font-face {
font-family: "Geist Mono";
font-style: normal;
font-weight: 700;
src: url("./geist-mono-bold-CTLtpKvJ.woff2") format("woff2"), url("./geist-mono-bold-Bz_UliG4.woff") format("woff");
}
@font-face {
font-family: "Geist Mono";
font-style: normal;
font-weight: 400;
src: url("./geist-mono-BzrJhchg.woff2") format("woff2"), url("./geist-mono-OFKGen7b.woff") format("woff");
}
:root {
--font-display: 'Leibniz Fraktur', serif;
--font-mono: 'Geist Mono', monospace;
}
:root {
--layout-column-count: 6;
--layout-column-gap: 10px;
--layout-margin: 20px;
--layout-width: calc(100vw - (2 * var(--layout-margin)));
--layout-column-width: calc(
(
var(--layout-width) -
(
(var(--layout-column-count) - 1) *
var(--layout-column-gap)
)
) /
var(--layout-column-count)
);
}
.layout-block, .layout-grid {
padding-left: var(--layout-margin);
padding-right: var(--layout-margin);
width: 100%;
}
.layout-grid {
display: grid;
grid-template-columns: repeat(var(--layout-column-count), minmax(0, 1fr));
grid-gap: var(--layout-column-gap);
}
html,
html * {
scrollbar-width: none !important;
-ms-overflow-style: none !important;
}
html::-webkit-scrollbar,
html *::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 400ms;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.quick-fade-enter-active,
.quick-fade-leave-active {
transition: opacity 100ms;
}
.quick-fade-enter-from,
.quick-fade-leave-to {
opacity: 0;
}
.slow-fade-enter-active,
.slow-fade-leave-active {
transition: opacity 600ms;
}
.slow-fade-enter-from,
.slow-fade-leave-to {
opacity: 0;
}
.slide-up-enter-active,
.slide-up-leave-active {
transition: transform 400ms var(--ease-out-quad);
}
.slide-up-enter-from,
.slide-up-leave-to {
transform: translateY(-100%);
}
.slide-left-enter-active,
.slide-left-leave-active {
transition: transform 400ms var(--ease-out-quad);
}
.slide-left-enter-from,
.slide-left-leave-to {
transform: translateX(-100%);
}
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
background: var(--black);
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
margin: 0;
min-height: 100vh;
}
.h1,
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-display);
font-weight: 400;
letter-spacing: -0.02em;
line-height: 1.3;
font-size: 30px;
}
.h1.mono,
h1.mono,
h2.mono,
h3.mono,
h4.mono,
h5.mono,
h6.mono {
font-family: var(--font-mono);
font-weight: 400;
line-height: 1;
font-size: 22px;
}
.p,
p,
a,
button,
input,
pre {
font-family: var(--font-mono);
font-weight: 400;
line-height: 1;
font-size: 12px;
}
.bold {
font-weight: 700;
}
#app {
min-height: 100vh;
}
button {
cursor: pointer;
}
::selection {
color: var(--theme-bg);
background: var(--theme-fg);
}
::-moz-selection {
color: var(--theme-bg);
background: var(--theme-fg);
}.nav {
padding-top: 9px;
color: var(--grey-100);
}.menu {
position: fixed;
top: 0;
left: 0;
right: 0;
background: var(--theme-bg);
border-bottom: 1px solid var(--grey-100);
}
.menu .menu-wrap {
display: flex;
flex-direction: column;
padding-top: 3px;
padding-bottom: 10px;
}
.menu .menu-wrap .menu-item {
display: block;
padding: 16px 0;
text-align: center;
}
.menu .menu-wrap .menu-item:not(:last-child) {
border-bottom: 1px dashed currentColor;
}
.menu .menu-wrap .menu-item:hover {
color: var(--theme-accent);
}
.menu.menu-enter-active, .menu.menu-leave-active {
transition: transform 300ms var(--ease-out-expo);
}
.menu.menu-enter-from, .menu.menu-leave-to {
transform: translateY(-100%);
}.scroll-bar {
position: fixed;
top: 0;
right: 0;
bottom: 0;
width: 8px;
will-change: transform;
border-left: 1px solid var(--grey-100);
}
.scroll-bar .inner {
height: 100%;
position: relative;
}
.scroll-bar .inner .handle {
width: 100%;
height: 388px;
background: var(--grey-100);
border-radius: 20px;
position: absolute;
right: 0;
will-change: transform;
}.container {
min-height: calc(100 * var(--vh));
max-width: 100vw;
overflow-x: clip;
background: var(--theme-bg);
color: var(--theme-fg);
transition: opacity 400ms;
}
.container:not(.fonts-ready) {
opacity: 0;
}.category-row {
display: grid;
grid-template-columns: 26px 1fr auto;
align-items: flex-start;
width: 100%;
position: relative;
padding: 8px 0 6px;
border-bottom: 1px dashed currentColor;
cursor: pointer;
}
.category-row .index {
margin-top: 19px;
font-family: var(--font-mono);
font-weight: 400;
line-height: 1;
font-size: 12px;
}
.category-row .title {
display: block;
width: 100%;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.category-row .category-input {
display: block;
width: 100%;
font-family: var(--font-display);
font-weight: 400;
letter-spacing: -0.02em;
line-height: 1.3;
font-size: 30px;
}
.category-row .category-input:focus {
outline: none;
}
.category-row .edit-button,
.category-row .save-button {
color: var(--grey-100);
cursor: pointer;
padding-right: 0.5em;
padding-left: 0.5em;
margin-top: 1.5em;
}
.category-row .edit-button {
opacity: 0;
pointer-events: none;
}
.category-row.editable:hover .edit-button {
opacity: 1;
pointer-events: auto;
}
.category-row.router-link-exact-active, .category-row.editable {
cursor: default;
}
.category-row:hover:not(.router-link-exact-active):not(.editable) {
color: var(--theme-accent);
}.note-row {
grid-template-columns: auto 1fr;
display: grid;
gap: 20px;
cursor: pointer;
}
.note-row .title {
width: calc(100% - 43.2px);
position: relative;
}
.note-row .title::after {
content: "(open)";
position: absolute;
bottom: 0;
right: 0;
transform: translateX(100%);
font-weight: 700;
opacity: 0;
}
.note-row:hover {
color: var(--theme-accent);
}
.note-row:hover .title::after {
opacity: 1;
}main.directory {
padding-top: 18px;
padding-bottom: 30px;
}
main.directory .label {
text-transform: uppercase;
margin: 17px 0 24px;
font-family: var(--font-mono);
font-weight: 400;
line-height: 1;
font-size: 12px;
}
main.directory .notes {
display: flex;
flex-direction: column;
gap: 14px;
}.note-menu {
display: flex;
gap: 5px;
border: 1px solid var(--grey-100);
color: var(--grey-100);
border-radius: 0.2em;
background: var(--theme-bg);
}
.note-menu button {
cursor: pointer;
padding: 0.2em;
border-radius: 0.2em;
}
.note-menu button:hover {
background: var(--grey-100);
color: var(--theme-bg);
}
.note-menu button.active {
background: var(--theme-fg);
color: var(--theme-bg);
}
.note-editor h1 {
font-weight: 700 !important;
font-family: var(--font-mono);
font-weight: 400;
line-height: 1;
font-size: 12px;
}
.note-editor h1:first-child {
font-family: var(--font-mono);
font-size: 12px;
font-weight: 400 !important;
}
.note-editor h1:first-child:first-child::first-letter {
font-family: var(--font-display);
font-size: 42px;
}
.note-editor h1.is-editor-empty:first-child::before {
color: var(--grey-100);
content: attr(data-placeholder);
pointer-events: none;
font-family: var(--font-mono);
font-size: 12px;
font-weight: 400 !important;
}
.note-editor h1.is-editor-empty:first-child::before:first-child::first-letter {
font-family: var(--font-display);
font-size: 42px;
}
.note-editor p strong {
font-weight: 700;
}
.note-editor p em {
font-style: italic;
}
.note-editor hr {
border: 1px dashed currentColor;
}
.note-editor ul {
list-style-type: disc;
}
.note-editor ul li {
display: list-item;
margin-left: 1em;
}
.note-editor ul li *:not(:last-child) {
margin-bottom: 0.5em;
}
.note-editor ol {
list-style-type: decimal;
}
.note-editor ol li {
display: list-item;
margin-left: 1.5em;
}
.note-editor ol li::marker {
font-family: var(--font-mono);
font-weight: 400;
line-height: 1;
font-size: 12px;
}
.note-editor li:not(:last-child) {
margin-bottom: 0.5em;
}
.note-editor a {
color: var(--theme-link);
cursor: pointer;
}
.note-editor code {
border: 1px solid var(--grey-100);
color: var(--theme-accent);
padding: 0 0.2em;
border-radius: 0.2em;
}
.note-editor pre code {
display: block;
color: inherit;
padding: 1em;
/* Code styling */
}
.note-editor pre code .hljs-comment,
.note-editor pre code .hljs-quote {
color: #616161;
}
.note-editor pre code .hljs-variable,
.note-editor pre code .hljs-template-variable,
.note-editor pre code .hljs-attribute,
.note-editor pre code .hljs-tag,
.note-editor pre code .hljs-name,
.note-editor pre code .hljs-regexp,
.note-editor pre code .hljs-link,
.note-editor pre code .hljs-name,
.note-editor pre code .hljs-selector-id,
.note-editor pre code .hljs-selector-class {
color: #f98181;
}
.note-editor pre code .hljs-number,
.note-editor pre code .hljs-meta,
.note-editor pre code .hljs-built_in,
.note-editor pre code .hljs-builtin-name,
.note-editor pre code .hljs-literal,
.note-editor pre code .hljs-type,
.note-editor pre code .hljs-params {
color: #fbbc88;
}
.note-editor pre code .hljs-string,
.note-editor pre code .hljs-symbol,
.note-editor pre code .hljs-bullet {
color: #b9f18d;
}
.note-editor pre code .hljs-title,
.note-editor pre code .hljs-section {
color: #faf594;
}
.note-editor pre code .hljs-keyword,
.note-editor pre code .hljs-selector-tag {
color: #70cff8;
}
.note-editor pre code .hljs-emphasis {
font-style: italic;
}
.note-editor pre code .hljs-strong {
font-weight: 700;
}
.note-editor blockquote {
border-left: 4px solid var(--grey-100);
padding-left: 0.5em;
}
.note-editor s {
position: relative;
}
.note-editor s::after {
content: " ";
display: block;
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background: currentColor;
}
.note-editor mark {
background: var(--theme-accent);
color: var(--theme-bg);
padding: 0 0.2em;
}
.note-editor ul[data-type=taskList] {
list-style: none;
margin-left: 0;
padding: 0;
}
.note-editor ul[data-type=taskList] li {
align-items: center;
display: flex;
margin-left: 0;
}
.note-editor ul[data-type=taskList] li > label {
flex: 0 0 auto;
margin-right: 0.5rem;
user-select: none;
margin-bottom: 0;
}
.note-editor ul[data-type=taskList] li > label input {
margin: 0;
}
.note-editor ul[data-type=taskList] li > div {
flex: 1 1 auto;
}
.note-editor ul[data-type=taskList] input[type=checkbox] {
cursor: pointer;
display: block;
width: 1.5em;
height: 1.5em;
border: 1px solid var(--grey-100);
border-radius: 0.2em;
}
.note-editor ul[data-type=taskList] input[type=checkbox]::after {
content: "✓";
font-size: 1.5em;
opacity: 0;
}
.note-editor ul[data-type=taskList] input[type=checkbox]:checked::after {
opacity: 1;
}
.note-editor ul[data-type=taskList] ul[data-type=taskList] {
margin: 0;
}
.note-editor .editor-wrap > div {
display: flex;
flex-direction: column;
gap: 20px;
}
.note-editor .editor-wrap > div:focus {
outline: none;
}main.note {
padding-top: 8px;
padding-bottom: 20px;
}main.category .back {
display: block;
opacity: 0.25;
margin-top: 9px;
}
main.category .category-row {
margin-top: 4px;
}
main.category .notes {
display: flex;
flex-direction: column;
gap: 14px;
margin-top: 9px;
}
main.category .new-note {
display: block;
margin: 50px auto 0;
}main.instructions .back-link {
opacity: 0.25;
display: block;
margin-top: 9px;
margin-bottom: 14px;
}

Binary file not shown.

Binary file not shown.

18
out/renderer/index.html Normal file
View File

@@ -0,0 +1,18 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Electron</title>
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
/>
<script type="module" crossorigin src="./assets/index-B9wwyKue.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-CiC_zCT0.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@@ -14,16 +14,20 @@
import { ref, computed, onMounted } from 'vue'
import loadFonts from '@fuzzco/font-loader'
import { useWindowSize } from '@vueuse/core'
import Menu from '@/components/menu/Index.vue'
import Menu from '@/components/Menu.vue'
import Nav from '@/components/Nav.vue'
import ScrollBar from './components/ScrollBar.vue'
import useState from '@/composables/useState'
import ScrollBar from '@/components/ScrollBar.vue'
const { height } = useWindowSize()
// Theme state
const { theme } = useState()
const classes = computed(() => [
'container',
{ 'fonts-ready': !fontsLoading.value },
'theme-dark',
`theme-${theme.value}`,
])
const fontsLoading = ref(true)

View File

@@ -8,7 +8,7 @@
<router-link class="menu-item" to="/category"
>+ New Capitulum</router-link
>
<button class="menu-item">Change Theme</button>
<theme-switcher class="menu-item" />
<router-link class="menu-item" to="/instructions"
>Instructio</router-link
>
@@ -21,9 +21,10 @@
<script setup>
import NewNote from '@/components/NewNote.vue'
import ThemeSwitcher from '@/components/ThemeSwitcher.vue'
import { onClickOutside } from '@vueuse/core'
import { ref, watch } from 'vue'
import Nav from '../Nav.vue'
import Nav from './Nav.vue'
import useMenu from '@/composables/useMenu'
import { useRoute } from 'vue-router'
@@ -64,7 +65,6 @@ const openNewCategory = () => {}
padding-bottom: 10px;
.menu-item {
display: block;
padding: 16px 0;
text-align: center;

View File

@@ -0,0 +1,48 @@
<template>
<div class="theme-switcher">
<span>Change Theme</span>
<button
v-for="(value, key) in themes"
:class="[`theme-${key}`, { active: theme === key }]"
@click="setTheme(key)"
/>
</div>
</template>
<script setup>
import { themes } from '@/libs/theme'
import useState from '@/composables/useState'
const { theme } = useState()
const setTheme = (value) => {
theme.value = value
}
</script>
<style lang="scss">
.theme-switcher {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
button {
background: var(--theme-bg);
display: block;
width: 14px;
height: 14px;
border-radius: 50%;
border: none;
cursor: pointer;
&.active {
border: 1px solid var(--theme-fg);
}
}
&:hover {
color: var(--theme-fg) !important;
}
}
</style>

View File

@@ -1,62 +1,40 @@
<template>
<main v-if="editor" class="editor layout-block">
<bubble-menu :editor="editor">
<div class="bubble-menu">
<button
@click="editor.chain().focus().toggleBold().run()"
:class="{ active: editor.isActive('bold') }"
>
Bold
</button>
<button
@click="editor.chain().focus().toggleItalic().run()"
:class="{ active: editor.isActive('italic') }"
>
Italic
</button>
<button
@click="editor.chain().focus().toggleHighlight().run()"
:class="{ active: editor.isActive('highlight') }"
>
Highlight
</button>
</div>
</bubble-menu>
<div v-if="editor" class="note-editor">
<editor-content :editor="editor" class="editor-wrap" />
</main>
<editor-menu :editor="editor" />
</div>
</template>
<script setup>
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
import { onBeforeUnmount, onMounted, shallowRef } from 'vue'
import { TaskList, TaskItem } from '@tiptap/extension-list'
import { Highlight } from '@tiptap/extension-highlight'
import { Editor, EditorContent } from '@tiptap/vue-3'
import Document from '@tiptap/extension-document'
import { Placeholder } from '@tiptap/extensions'
import StarterKit from '@tiptap/starter-kit'
import { TaskList, TaskItem } from '@tiptap/extension-list'
import { Highlight } from '@tiptap/extension-highlight'
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
import { BubbleMenu } from '@tiptap/vue-3/menus'
import { all, createLowlight } from 'lowlight'
import useNotes from '@/composables/useNotes'
import { useRoute } from 'vue-router'
import StarterKit from '@tiptap/starter-kit'
import _debounce from 'lodash/debounce'
import EditorMenu from './Menu.vue'
const route = useRoute()
const id = route.params.id
const { loadNote, updateNoteContent, updateNoteMetadata } = useNotes()
const CustomDocument = Document.extend({
content: 'heading block*',
const props = defineProps({
id: {
type: String,
required: true,
},
})
const editor = shallowRef()
const { loadNote, updateNoteContent, updateNoteMetadata } = useNotes()
const updateNote = _debounce(async ({ editor }) => {
const json = editor.getJSON()
await updateNoteContent(id, json)
await updateNoteContent(props.id, json)
updateTitle(editor)
}, 300)
@@ -74,16 +52,21 @@ const updateTitle = _debounce(async (editor) => {
if (newTitle === lastTitle) return
lastTitle = newTitle
await updateNoteMetadata(id, { title: newTitle })
await updateNoteMetadata(props.id, { title: newTitle })
}, 300)
onMounted(async () => {
const note = await loadNote(id)
const note = await loadNote(props.id)
lastTitle = note.title
// Lowlight setup
const lowlight = createLowlight(all)
// Force note format
const CustomDocument = Document.extend({
content: 'heading block*',
})
editor.value = new Editor({
extensions: [
CustomDocument,
@@ -119,10 +102,7 @@ onBeforeUnmount(() => {
</script>
<style lang="scss">
main.editor {
padding-top: 8px;
padding-bottom: 20px;
.note-editor {
h1 {
font-weight: 700 !important;
@include p;
@@ -143,9 +123,8 @@ main.editor {
p em {
font-style: italic;
}
hr::before {
content: '----------------------------------------';
@include p;
hr {
border: 1px dashed currentColor;
}
ul {
list-style-type: disc;
@@ -181,7 +160,7 @@ main.editor {
code {
border: 1px solid var(--grey-100);
color: var(--theme-accent);
padding: 0.2em;
padding: 0 0.2em;
border-radius: 0.2em;
}
pre code {
@@ -263,8 +242,7 @@ main.editor {
mark {
background: var(--theme-accent);
color: var(--theme-bg);
padding: 0.2em;
border-radius: 0.2em;
padding: 0 0.2em;
}
ul[data-type='taskList'] {
@@ -325,29 +303,5 @@ main.editor {
}
}
}
.bubble-menu {
display: flex;
gap: 5px;
border: 1px solid var(--grey-100);
color: var(--grey-100);
border-radius: 0.2em;
background: var(--theme-bg);
button {
cursor: pointer;
padding: 0.2em;
border-radius: 0.2em;
&:hover {
background: var(--grey-100);
color: var(--theme-bg);
}
&.active {
background: var(--theme-fg);
color: var(--theme-bg);
}
}
}
}
</style>

View File

@@ -0,0 +1,12 @@
<template>
<div class="note-find"></div>
</template>
<script setup>
const props = defineProps({})
</script>
<style lang="scss">
.note-find {
}
</style>

View File

@@ -0,0 +1,61 @@
<template>
<bubble-menu v-if="editor" :editor="editor">
<div class="note-menu">
<button
@click="editor.chain().focus().toggleBold().run()"
:class="{ active: editor.isActive('bold') }"
>
Bold
</button>
<button
@click="editor.chain().focus().toggleItalic().run()"
:class="{ active: editor.isActive('italic') }"
>
Italic
</button>
<button
@click="editor.chain().focus().toggleHighlight().run()"
:class="{ active: editor.isActive('highlight') }"
>
Highlight
</button>
</div>
</bubble-menu>
</template>
<script setup>
import { BubbleMenu } from '@tiptap/vue-3/menus'
const props = defineProps({
editor: {
type: Object,
required: true,
},
})
</script>
<style lang="scss">
.note-menu {
display: flex;
gap: 5px;
border: 1px solid var(--grey-100);
color: var(--grey-100);
border-radius: 0.2em;
background: var(--theme-bg);
button {
cursor: pointer;
padding: 0.2em;
border-radius: 0.2em;
&:hover {
background: var(--grey-100);
color: var(--theme-bg);
}
&.active {
background: var(--theme-fg);
color: var(--theme-bg);
}
}
}
</style>

View File

@@ -0,0 +1,7 @@
import { createGlobalState, useStorage } from '@vueuse/core'
export default createGlobalState(() => {
const theme = useStorage('app-theme', 'dark')
return { theme }
})

View File

@@ -0,0 +1,17 @@
# Instructions
This will be the instructions for the application.
---
## Getting Started
1. Install the application by running `npm install` in the project directory.
2. Start the application by running `npm start` in the project directory.
3. Open the application in your browser at `http://localhost:3000`.
## Usage
1. Create a new note by clicking the "New Note" button.
2. Edit an existing note by clicking on it.
3. Delete a note by clicking the "Delete" button.

View File

@@ -7,18 +7,18 @@ const colors = {
}
const themes = {
light: {
bg: colors.white,
fg: colors.black,
accent: colors.green,
link: colors.blue,
},
dark: {
bg: colors.black,
fg: colors.white,
accent: colors.green,
link: colors.blue,
},
light: {
bg: colors.white,
fg: colors.black,
accent: colors.green,
link: colors.blue,
},
}
export { colors, themes }

View File

@@ -1,14 +1,14 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import Directory from '@/views/Directory.vue'
import Editor from '@/views/Editor.vue'
import Note from '@/views/Note.vue'
import CreateCategory from '@/views/CreateCategory.vue'
import Category from '@/views/Category.vue'
import Instructions from '@/views/Instructions.vue'
const routes = [
{ path: '/', name: 'directory', component: Directory },
{ path: '/note/:id', name: 'note', component: Editor },
{ path: '/note/:id', name: 'note', component: Note },
{ path: '/category', name: 'create-category', component: CreateCategory },
{ path: '/category/:id', name: 'category', component: Category },
{ path: '/instructions', name: 'instructions', component: Instructions },

View File

@@ -46,7 +46,8 @@ p,
a,
button,
input,
pre {
pre,
span {
@include p;
}
.bold {
@@ -64,9 +65,9 @@ button {
// Text selection
::selection {
color: var(--theme-bg);
background: var(--theme-accent);
background: var(--theme-fg);
}
::-moz-selection {
color: var(--theme-bg);
background: var(--theme-accent);
background: var(--theme-fg);
}

View File

@@ -0,0 +1,29 @@
<template>
<main class="note layout-block">
<note-editor :id="id" />
</main>
</template>
<script setup>
import { watchEffect } from 'vue'
import { useMagicKeys } from '@vueuse/core'
import { useRoute } from 'vue-router'
import NoteEditor from '@/components/note/Editor.vue'
const route = useRoute()
const id = route.params.id
const { ctrl, f } = useMagicKeys()
watchEffect(() => {
if (ctrl.value && f.value) {
console.log('find')
}
})
</script>
<style lang="scss">
main.note {
padding-top: 8px;
padding-bottom: 20px;
}
</style>