feat: Light/dark modes
All checks were successful
Build and Push App Image / build-and-push (push) Successful in 1m48s
All checks were successful
Build and Push App Image / build-and-push (push) Successful in 1m48s
This commit is contained in:
@@ -44,9 +44,20 @@
|
|||||||
|
|
||||||
<!-- Search -->
|
<!-- Search -->
|
||||||
<div class="search-box nav-search" v-if="!isAdminRoute">
|
<div class="search-box nav-search" v-if="!isAdminRoute">
|
||||||
<input type="text" class="form-control form-control-sm" placeholder="Search notes..." v-model="searchQuery" @keyup.enter="performSearch" />
|
<input type="text" class="form-control" placeholder="Search notes..." v-model="searchQuery" @keyup.enter="performSearch" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Theme Toggle -->
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-light theme-toggle"
|
||||||
|
type="button"
|
||||||
|
:aria-label="isDarkMode ? 'Switch to light mode' : 'Switch to dark mode'"
|
||||||
|
:title="isDarkMode ? 'Switch to light mode' : 'Switch to dark mode'"
|
||||||
|
@click="isDarkMode = !isDarkMode"
|
||||||
|
>
|
||||||
|
<i :class="isDarkMode ? 'mdi mdi-weather-sunny' : 'mdi mdi-weather-night'" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- User Menu -->
|
<!-- User Menu -->
|
||||||
<div ref="userDropdownRef" class="dropdown nav-user-menu" v-if="currentUser" @mouseleave="showUserMenu = false">
|
<div ref="userDropdownRef" class="dropdown nav-user-menu" v-if="currentUser" @mouseleave="showUserMenu = false">
|
||||||
<button class="btn btn-outline-light dropdown-toggle" type="button" @click="toggleUserMenu">
|
<button class="btn btn-outline-light dropdown-toggle" type="button" @click="toggleUserMenu">
|
||||||
@@ -322,6 +333,13 @@ const shareCopied = ref(false);
|
|||||||
const shareCopyTimeout = ref(null);
|
const shareCopyTimeout = ref(null);
|
||||||
const noteViewMode = ref(localStorage.getItem("noteViewMode") || "grid");
|
const noteViewMode = ref(localStorage.getItem("noteViewMode") || "grid");
|
||||||
watch(noteViewMode, (val) => localStorage.setItem("noteViewMode", val));
|
watch(noteViewMode, (val) => localStorage.setItem("noteViewMode", val));
|
||||||
|
const isDarkMode = ref(localStorage.getItem("theme") === "dark");
|
||||||
|
const applyTheme = (dark) => {
|
||||||
|
document.documentElement.setAttribute("data-bs-theme", dark ? "dark" : "light");
|
||||||
|
localStorage.setItem("theme", dark ? "dark" : "light");
|
||||||
|
};
|
||||||
|
watch(isDarkMode, applyTheme);
|
||||||
|
applyTheme(isDarkMode.value);
|
||||||
const showUnlockModal = ref(false);
|
const showUnlockModal = ref(false);
|
||||||
const unlockTargetNote = ref(null);
|
const unlockTargetNote = ref(null);
|
||||||
const unlockPassword = ref("");
|
const unlockPassword = ref("");
|
||||||
@@ -1191,4 +1209,21 @@ const logout = () => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .sidebar-header {
|
||||||
|
border-bottom-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .breadcrumb-title {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .breadcrumb-link {
|
||||||
|
color: #7aa2f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .breadcrumb-separator {
|
||||||
|
color: #4a5568;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -6,6 +6,75 @@
|
|||||||
--border-color: #dee2e6;
|
--border-color: #dee2e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] {
|
||||||
|
--text-color: #e2e8f0;
|
||||||
|
--bg-color: #1a1d23;
|
||||||
|
--border-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] body {
|
||||||
|
background-color: #1a1d23;
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .sidebar {
|
||||||
|
background-color: #21252e !important;
|
||||||
|
border-color: #3a3f4b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .toolbar {
|
||||||
|
background-color: #21252e;
|
||||||
|
border-color: #3a3f4b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .main-content {
|
||||||
|
background-color: #1a1d23;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .markdown-body table {
|
||||||
|
background: #21252e;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .markdown-body th {
|
||||||
|
background: #2a2f3a;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .markdown-body tr:nth-child(even) td {
|
||||||
|
background: #232830;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .markdown-body blockquote {
|
||||||
|
background: #1e2430;
|
||||||
|
color: #a0aec0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .markdown-body :not(pre) > code {
|
||||||
|
background: #2d3748;
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .markdown-body pre code {
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .markdown-body pre {
|
||||||
|
background: #2d3748;
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] ::-webkit-scrollbar-track {
|
||||||
|
background: #2d3748;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] ::-webkit-scrollbar-thumb {
|
||||||
|
background: #4a5568;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] ::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #718096;
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -70,7 +139,7 @@ body,
|
|||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
background: #111827;
|
background: #353943;
|
||||||
color: #f9fafb;
|
color: #f9fafb;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,4 +275,53 @@ const handleDeleteCategory = (category) => {
|
|||||||
.subcategories {
|
.subcategories {
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .category-header:hover {
|
||||||
|
background-color: #2d3748;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .menu-button {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .menu-button:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .menu-dropdown {
|
||||||
|
background: #2d3748;
|
||||||
|
border-color: #4a5568;
|
||||||
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .menu-item {
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .menu-item:hover {
|
||||||
|
background-color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-item:hover {
|
||||||
|
background-color: #2d3748;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-item.is-pinned {
|
||||||
|
background: #1a3a5c;
|
||||||
|
border-color: #2d6a9f;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-item.is-pinned:hover {
|
||||||
|
background: #1e4470;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-item.is-featured {
|
||||||
|
background: #3a2e0a;
|
||||||
|
border-color: #7a5a0a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-item.is-featured:hover {
|
||||||
|
background: #453710;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -328,4 +328,23 @@ watch(showNewFolderInput, async (v) => {
|
|||||||
.file-item:hover .btn-delete {
|
.file-item:hover .btn-delete {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .file-explorer {
|
||||||
|
background: #21252e;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .file-explorer-header {
|
||||||
|
background: #21252e;
|
||||||
|
border-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .file-item {
|
||||||
|
border-bottom-color: #3a3f4b;
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .file-item:hover {
|
||||||
|
background-color: #2d3748;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -262,4 +262,20 @@ onMounted(loadProviders);
|
|||||||
padding-right: 0.85rem;
|
padding-right: 0.85rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .modal-panel {
|
||||||
|
background: #21252e;
|
||||||
|
border-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .provider-modal-header {
|
||||||
|
background: linear-gradient(180deg, #2a2f3a 0%, #21252e 100%);
|
||||||
|
border-bottom-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .provider-section {
|
||||||
|
background: #2a2f3a;
|
||||||
|
border-color: #3a3f4b;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -346,4 +346,31 @@ onMounted(async () => {
|
|||||||
color: #7a2727;
|
color: #7a2727;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .editor-toolbar {
|
||||||
|
border-bottom-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .flag-check {
|
||||||
|
background: #2d3748;
|
||||||
|
border-color: #4a5568;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .preview-pane {
|
||||||
|
background-color: #21252e;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .danger-zone {
|
||||||
|
background: #2d1a1a;
|
||||||
|
border-color: #7a3030;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .danger-zone-title {
|
||||||
|
color: #fc8181;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .danger-zone-copy {
|
||||||
|
color: #fca5a5;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -180,6 +180,10 @@ const getDescription = (note) => {
|
|||||||
|
|
||||||
.note-list--list .note-card:hover {
|
.note-list--list .note-card:hover {
|
||||||
transform: none;
|
transform: none;
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: #eef2ff;
|
||||||
|
border-color: #667eea;
|
||||||
|
border-left: 3px solid #667eea;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-list--list .note-title {
|
.note-list--list .note-title {
|
||||||
@@ -218,4 +222,51 @@ const getDescription = (note) => {
|
|||||||
font-size: 1.45rem;
|
font-size: 1.45rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .empty-notes-state {
|
||||||
|
border-color: #3a3f4b;
|
||||||
|
background: linear-gradient(180deg, #1e2430 0%, #21252e 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .empty-notes-title {
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .empty-notes-message {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-card {
|
||||||
|
border-color: #3a3f4b;
|
||||||
|
background-color: #21252e;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-card:hover {
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-list--list .note-card:hover {
|
||||||
|
background-color: #2a2f3a;
|
||||||
|
border-color: #7aa2f7;
|
||||||
|
border-left-color: #7aa2f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-title {
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-preview {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-card.is-pinned {
|
||||||
|
background: #1a3a5c;
|
||||||
|
border-color: #2d6a9f;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .note-card.is-featured {
|
||||||
|
background: #3a2e0a;
|
||||||
|
border-color: #7a5a0a;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -161,8 +161,6 @@ const formatDateTime = (dateString) => new Date(dateString).toLocaleString();
|
|||||||
.markdown-body :deep(pre) {
|
.markdown-body :deep(pre) {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
background: #111827;
|
|
||||||
color: #f9fafb;
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,4 +174,49 @@ const formatDateTime = (dateString) => new Date(dateString).toLocaleString();
|
|||||||
border-left: 4px solid #748ffc;
|
border-left: 4px solid #748ffc;
|
||||||
background: #f8f9ff;
|
background: #f8f9ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .note-meta {
|
||||||
|
border-bottom-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .tag-chip {
|
||||||
|
background: #1e2d5f;
|
||||||
|
color: #93b4ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .pinned-chip {
|
||||||
|
color: #7dd3fc;
|
||||||
|
background: #1a3a5c;
|
||||||
|
border-color: #2d6a9f;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .featured-chip {
|
||||||
|
color: #fbbf24;
|
||||||
|
background: #3a2e0a;
|
||||||
|
border-color: #7a5a0a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .public-chip {
|
||||||
|
color: #67e8f9;
|
||||||
|
background: #0c2a3a;
|
||||||
|
border-color: #1d6a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .private-chip {
|
||||||
|
color: #c4b5fd;
|
||||||
|
background: #2d1f5e;
|
||||||
|
border-color: #5b3f9a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .protected-chip {
|
||||||
|
color: #fdba74;
|
||||||
|
background: #3a1f0a;
|
||||||
|
border-color: #7a4f1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .markdown-body :deep(blockquote) {
|
||||||
|
background: #1e2430;
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -151,4 +151,34 @@ const goToPage = (page) => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .search-results-header h2 {
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .search-meta {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .page-indicator {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .empty-state {
|
||||||
|
border-color: #3a3f4b;
|
||||||
|
background: radial-gradient(circle at 20% 20%, #1a2035 0%, #1e2430 70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .empty-state h3 {
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .empty-state p {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .empty-state-icon {
|
||||||
|
color: #4a6fa5;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -919,4 +919,36 @@ onMounted(async () => {
|
|||||||
gap: 0.65rem;
|
gap: 0.65rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode overrides */
|
||||||
|
:root[data-bs-theme="dark"] .admin-topbar {
|
||||||
|
border-bottom-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .admin-sidebar {
|
||||||
|
background: #21252e;
|
||||||
|
border-right-color: #3a3f4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .admin-nav .nav-link {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .admin-nav .nav-link:hover {
|
||||||
|
background: #2d3748;
|
||||||
|
color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .admin-nav .nav-link.active {
|
||||||
|
background: #e2e8f0;
|
||||||
|
color: #1a1d23;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .user-meta-value {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-bs-theme="dark"] .admin-section {
|
||||||
|
background-color: #21252e;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user