Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor UI dark/bright mode #2590

Merged
merged 16 commits into from
Nov 1, 2023
Merged
10 changes: 7 additions & 3 deletions web/src/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
"password": "Password",
"url": "URL",
"back": "Back",
"color_scheme_light": "Switch to dark mode",
"color_scheme_dark": "Switch to light mode",
"unknown_error": "An unknown error occurred",
"documentation_for": "Documentation for \"{topic}\"",
"pipeline_feed": "Pipeline feed",
Expand Down Expand Up @@ -453,7 +451,13 @@
"settings": "User Settings",
"general": {
"general": "General",
"language": "Language"
"language": "Language",
"theme": {
"theme": "Theme",
"light": "Light",
"dark": "Dark",
"auto": "Auto"
}
},
"secrets": {
"secrets": "Secrets",
Expand Down
3 changes: 2 additions & 1 deletion web/src/components/layout/Panel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ import Icon from '~/components/atomic/Icon.vue';
const props = defineProps<{
title?: string;
collapsable?: boolean;
collapsedByDefault?: boolean;
}>();

/**
* _collapsed is used to store the internal state of the panel, but is
* ignored if the panel is not collapsable.
*/
const _collapsed = ref(false);
const _collapsed = ref(props.collapsedByDefault || false);

const collapsed = computed(() => props.collapsable && _collapsed.value);
</script>
9 changes: 0 additions & 9 deletions web/src/components/layout/header/Navbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@
</div>
<!-- Right Icons Box -->
<div class="flex ml-auto -m-1.5 items-center space-x-2">
<!-- Dark Mode Toggle -->
<IconButton
:icon="darkMode ? 'dark' : 'light'"
:title="$t(darkMode ? 'color_scheme_dark' : 'color_scheme_light')"
class="navbar-icon"
@click="darkMode = !darkMode"
/>
anbraten marked this conversation as resolved.
Show resolved Hide resolved
<!-- Admin Settings -->
<IconButton
v-if="user?.admin"
Expand Down Expand Up @@ -62,15 +55,13 @@ import Button from '~/components/atomic/Button.vue';
import IconButton from '~/components/atomic/IconButton.vue';
import useAuthentication from '~/compositions/useAuthentication';
import useConfig from '~/compositions/useConfig';
import { useDarkMode } from '~/compositions/useDarkMode';

import ActivePipelines from './ActivePipelines.vue';

const config = useConfig();
const route = useRoute();
const authentication = useAuthentication();
const { user } = authentication;
const { darkMode } = useDarkMode();
const apiUrl = `${config.rootPath ?? ''}/swagger/index.html`;

function doLogin() {
Expand Down
12 changes: 12 additions & 0 deletions web/src/components/user/UserGeneralTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
<InputField :label="$t('user.settings.general.language')">
<SelectField v-model="selectedLocale" :options="localeOptions" />
</InputField>
<InputField :label="$t('user.settings.general.theme.theme')">
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
<SelectField
v-model="storeTheme"
:options="[
{ value: 'auto', text: $t('user.settings.general.theme.auto') },
{ value: 'light', text: $t('user.settings.general.theme.light') },
{ value: 'dark', text: $t('user.settings.general.theme.dark') },
]"
/>
</InputField>
</Settings>
</template>

Expand All @@ -17,8 +27,10 @@ import { useI18n } from 'vue-i18n';
import SelectField from '~/components/form/SelectField.vue';
import Settings from '~/components/layout/Settings.vue';
import { setI18nLanguage } from '~/compositions/useI18n';
import { useTheme } from '~/compositions/useTheme';

const { locale } = useI18n();
const { storeTheme } = useTheme();

const localeOptions = computed(() =>
SUPPORTED_LOCALES.map((supportedLocale) => ({
Expand Down
47 changes: 0 additions & 47 deletions web/src/compositions/useDarkMode.ts

This file was deleted.

5 changes: 3 additions & 2 deletions web/src/compositions/useFavicon.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { computed, ref, watch } from 'vue';

import useConfig from '~/compositions/useConfig';
import { useDarkMode } from '~/compositions/useDarkMode';
import { useTheme } from '~/compositions/useTheme';
import { PipelineStatus } from '~/lib/api/types';

const darkMode = computed(() => (useDarkMode().darkMode.value ? 'dark' : 'light'));
const { theme } = useTheme();
const darkMode = computed(() => theme.value);

type Status = 'default' | 'success' | 'pending' | 'error';
const faviconStatus = ref<Status>('default');
Expand Down
31 changes: 31 additions & 0 deletions web/src/compositions/useTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useColorMode } from '@vueuse/core';
import { watch } from 'vue';

const { store: storeTheme, state: resolvedTheme } = useColorMode({
storageKey: 'woodpecker:theme',
});

function updateTheme() {
if (resolvedTheme.value === 'dark') {
document.documentElement.classList.remove('light');
document.documentElement.classList.add('dark');
document.documentElement.setAttribute('data-theme', 'dark');
document.querySelector('meta[name=theme-color]')?.setAttribute('content', '#2A2E3A'); // internal-wp-secondary-600 (see windi.config.ts)
} else {
document.documentElement.classList.remove('dark');
document.documentElement.classList.add('light');
document.documentElement.setAttribute('data-theme', 'light');
document.querySelector('meta[name=theme-color]')?.setAttribute('content', '#369943'); // internal-wp-primary-400
}
}

watch(storeTheme, updateTheme);

updateTheme();

export function useTheme() {
return {
theme: resolvedTheme,
storeTheme,
};
}
1 change: 1 addition & 0 deletions web/src/views/repo/pipeline/PipelineConfig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
v-for="pipelineConfig in pipelineConfigs || []"
:key="pipelineConfig.hash"
collapsable
collapsed-by-default
:title="pipelineConfig.name"
>
<SyntaxHighlight class="font-mono whitespace-pre overflow-auto" language="yaml" :code="pipelineConfig.data" />
Expand Down