Add dark mode
This commit is contained in:
parent
a5562e7fa4
commit
7ab85991db
6 changed files with 113 additions and 0 deletions
|
@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
### Added
|
||||
|
||||
- Define CSS variables for color theme.
|
||||
- Added dark mode.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
32
src/App.vue
32
src/App.vue
|
@ -59,6 +59,38 @@ watch($$(currentUser), () => {
|
|||
--shadow-color: #{$shadow-color};
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--background-color: #{$dark-background-color};
|
||||
--text-color: #{$dark-text-color};
|
||||
--text-colorizer: #{$dark-text-colorizer};
|
||||
--secondary-text-color: #{$dark-secondary-text-color};
|
||||
--secondary-text-colorizer: #{$dark-secondary-text-colorizer};
|
||||
--secondary-text-hover-color: #{$dark-secondary-text-hover-color};
|
||||
--secondary-text-hover-colorizer: #{$dark-secondary-text-hover-colorizer};
|
||||
--link-color: #{$dark-link-color};
|
||||
--link-colorizer: #{$dark-link-colorizer};
|
||||
--link-hover-color: #{$dark-link-hover-color};
|
||||
--link-hover-colorizer: #{$dark-link-hover-colorizer};
|
||||
--btn-background-color: #{$dark-btn-background-color};
|
||||
--btn-background-hover-color: #{$dark-btn-background-hover-color};
|
||||
--btn-text-color: #{$dark-btn-text-color};
|
||||
--btn-text-colorizer: #{$dark-btn-text-colorizer};
|
||||
--btn-text-hover-color: #{$dark-btn-text-hover-color};
|
||||
--btn-text-hover-colorizer: #{$dark-btn-text-hover-colorizer};
|
||||
--btn-secondary-background-color: #{$dark-btn-secondary-background-color};
|
||||
--btn-secondary-text-color: #{$dark-btn-secondary-text-color};
|
||||
--btn-disabled-background-color: #{$dark-btn-disabled-background-color};
|
||||
--btn-disabled-text-color: #{$dark-btn-disabled-text-color};
|
||||
--block-background-color: #{$dark-block-background-color};
|
||||
--block-link-color: #{$dark-block-link-color};
|
||||
--block-link-hover-color: #{$dark-block-link-hover-color};
|
||||
--separator-color: #{$dark-separator-color};
|
||||
--widget-background-color: #{$dark-widget-background-color};
|
||||
--highlight-color: #{$dark-highlight-color};
|
||||
--loader-color: #{$dark-loader-color};
|
||||
--shadow-color: #{$dark-shadow-color};
|
||||
}
|
||||
|
||||
html {
|
||||
background: var(--background-color);
|
||||
color: var(--text-color);
|
||||
|
|
|
@ -44,6 +44,7 @@ import { $, $computed } from "vue/macros"
|
|||
import { useRouter } from "vue-router"
|
||||
|
||||
import { Permissions } from "@/api/users"
|
||||
import { useTheme } from "@/composables/theme"
|
||||
import { useNotifications } from "@/store/notifications"
|
||||
import { useCurrentUser } from "@/store/user"
|
||||
import { useInstanceInfo } from "@/store/instance"
|
||||
|
@ -56,9 +57,11 @@ const {
|
|||
} = $(useCurrentUser())
|
||||
const { instance } = $(useInstanceInfo())
|
||||
const { loadNotifications, getUnreadNotificationCount } = $(useNotifications())
|
||||
const { loadTheme } = useTheme()
|
||||
|
||||
onMounted(async () => {
|
||||
if (isUserAuthenticated()) {
|
||||
loadTheme()
|
||||
// TODO: reload notifications periodically
|
||||
await loadNotifications(ensureAuthToken())
|
||||
}
|
||||
|
|
37
src/composables/theme.ts
Normal file
37
src/composables/theme.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { ref } from "vue"
|
||||
|
||||
const THEME_STORAGE_KEY = "theme"
|
||||
|
||||
enum Theme {
|
||||
Light = "light",
|
||||
Dark = "dark",
|
||||
}
|
||||
|
||||
const currentTheme = ref(Theme.Light)
|
||||
|
||||
export function useTheme() {
|
||||
|
||||
function setTheme(theme: Theme) {
|
||||
document.documentElement.setAttribute("data-theme", theme)
|
||||
currentTheme.value = theme
|
||||
localStorage.setItem(THEME_STORAGE_KEY, theme)
|
||||
}
|
||||
|
||||
function loadTheme() {
|
||||
const theme = localStorage.getItem(THEME_STORAGE_KEY) || Theme.Light
|
||||
setTheme(theme as Theme)
|
||||
}
|
||||
|
||||
function toggleDarkMode() {
|
||||
if (currentTheme.value === Theme.Light) {
|
||||
setTheme(Theme.Dark)
|
||||
} else {
|
||||
setTheme(Theme.Light)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
loadTheme,
|
||||
toggleDarkMode,
|
||||
}
|
||||
}
|
|
@ -40,3 +40,38 @@ $shadow-color: #B7B5B5;
|
|||
|
||||
$gem-color: #9678c3;
|
||||
$gem-colorizer: invert(51%) sepia(48%) saturate(437%) hue-rotate(222deg) brightness(92%) contrast(84%);
|
||||
|
||||
/* Dark theme */
|
||||
|
||||
$dark-background-color: #12110C;
|
||||
|
||||
$dark-text-color: #cccccc;
|
||||
$dark-text-colorizer: invert(94%) sepia(14%) saturate(0%) hue-rotate(228deg) brightness(83%) contrast(96%);
|
||||
$dark-secondary-text-color: #8C8C8C;
|
||||
$dark-secondary-text-colorizer: invert(62%) sepia(0%) saturate(610%) hue-rotate(189deg) brightness(90%) contrast(86%);
|
||||
$dark-secondary-text-hover-color: #B3B3B3;
|
||||
$dark-secondary-text-hover-colorizer: invert(73%) sepia(1%) saturate(0%) hue-rotate(210deg) brightness(100%) contrast(89%);
|
||||
$dark-link-color: #b7b8b8;
|
||||
$dark-link-colorizer: invert(80%) sepia(4%) saturate(52%) hue-rotate(131deg) brightness(94%) contrast(85%);
|
||||
$dark-link-hover-color: #fff;
|
||||
$dark-link-hover-colorizer: invert(100%) sepia(0%) saturate(7500%) hue-rotate(199deg) brightness(109%) contrast(105%);
|
||||
|
||||
$dark-btn-background-color: $dark-text-color;
|
||||
$dark-btn-background-hover-color: #4D4D4D;
|
||||
$dark-btn-text-color: #000;
|
||||
$dark-btn-text-colorizer: invert(0%) sepia(100%) saturate(0%) hue-rotate(21deg) brightness(97%) contrast(103%);
|
||||
$dark-btn-text-hover-color: $dark-text-color;
|
||||
$dark-btn-text-hover-colorizer: $dark-text-colorizer;
|
||||
$dark-btn-secondary-background-color: #333;
|
||||
$dark-btn-secondary-text-color: $dark-text-color;
|
||||
$dark-btn-disabled-background-color: #222222;
|
||||
$dark-btn-disabled-text-color: #666666;
|
||||
|
||||
$dark-block-background-color: #262626;
|
||||
$dark-block-link-color: #E3C093;
|
||||
$dark-block-link-hover-color: #F2E2CD;
|
||||
$dark-separator-color: $dark-background-color;
|
||||
$dark-widget-background-color: #1A1A1A;
|
||||
$dark-highlight-color: #B37400;
|
||||
$dark-loader-color: #666666;
|
||||
$dark-shadow-color: #666;
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
<router-link class="btn" :to="{ name: 'move-followers' }">
|
||||
Move followers
|
||||
</router-link>
|
||||
<button class="btn" @click="toggleDarkMode()">
|
||||
Toggle dark mode
|
||||
</button>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
|
@ -76,9 +79,11 @@ import { $, $ref } from "vue/macros"
|
|||
|
||||
import { changePassword, exportFollowers, exportFollows } from "@/api/settings"
|
||||
import SidebarLayout from "@/components/SidebarLayout.vue"
|
||||
import { useTheme } from "@/composables/theme"
|
||||
import { useCurrentUser } from "@/store/user"
|
||||
|
||||
const { currentUser, ensureAuthToken, setCurrentUser } = $(useCurrentUser())
|
||||
const { toggleDarkMode } = useTheme()
|
||||
let newPassword = $ref("")
|
||||
let newPasswordConfirmation = $ref("")
|
||||
let passwordFormMessage = $ref<string | null>(null)
|
||||
|
|
Loading…
Reference in a new issue