Skip to content

Commit

Permalink
Doroudi/issue93 (#119)
Browse files Browse the repository at this point in the history
❇️ Implement Theme Support
* Fixed Layout support
Fixes #114

* reorganize nav bar
add theme customize component

* add theme customize component

* Implement Theme Support
Fixes #93

* fix linting issues
  • Loading branch information
doroudi authored Dec 6, 2024
1 parent c8d26f5 commit 012b44c
Show file tree
Hide file tree
Showing 15 changed files with 205 additions and 19 deletions.
6 changes: 6 additions & 0 deletions locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,9 @@ not-found: Not found

notifications:
empty: No notifications

customize:
title: Customize
theme: Theme
color: Color
layout: Layout
6 changes: 6 additions & 0 deletions locales/fa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,9 @@ userMenu:

notifications:
empty: هیچ اعلانی وجود ندارد

customize:
title: سفارشی سازی
theme: پوسته
color: رنگ
layout: چیدمان
9 changes: 8 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const rtlStyles = [
tagRtl,
]
const customTheme = ref({ ...themeOverrides })
watch(() => layout.activeLanguage, () => {
const body = document.querySelector('body') as HTMLElement
if (layout.isRtl)
Expand All @@ -38,11 +40,16 @@ watch(() => layout.isDark, (newValue) => {
else
document.documentElement.classList.remove('dark')
}, { immediate: true })
watch(() => layout.themeColor, (newValue) => {
if (customTheme.value.common && newValue !== '')
customTheme.value.common.primaryColor = newValue
}, { immediate: true })
</script>

<template>
<n-config-provider
:theme="layout.isDark ? darkTheme : lightTheme" :theme-overrides="themeOverrides"
:theme="layout.isDark ? darkTheme : lightTheme" :theme-overrides="customTheme"
:rtl="layout.isRtl ? rtlStyles : []" :preflight-style-disabled="false"
>
<n-notification-provider placement="bottom-right">
Expand Down
16 changes: 11 additions & 5 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ declare module 'vue' {
CreateColor: typeof import('./components/Color/CreateColor.vue')['default']
CreateProduct: typeof import('./components/Products/CreateProduct.vue')['default']
CustomerManagement: typeof import('./components/Customers/CustomerManagement.vue')['default']
CustomizeDialog: typeof import('./components/CustomizeDialog/CustomizeDialog.vue')['default']
DashboardCard: typeof import('./components/DashboardCard.vue')['default']
DashboardPage: typeof import('./components/Dahboard/DashboardPage.vue')['default']
DonutChart: typeof import('./components/DonutChart.vue')['default']
Editor: typeof import('./components/Editor.vue')['default']
EnglandIcon: typeof import('./components/CountryIcons/EnglandIcon.vue')['default']
GermanyIcon: typeof import('./components/CountryIcons/GermanyIcon.vue')['default']
GithubButton: typeof import('./components/GithubButton.vue')['default']
LanguageSelect: typeof import('./components/LanguageSelect.vue')['default']
LanguageSelect: typeof import('./components/Navbar/LanguageSelect.vue')['default']
LineChart: typeof import('./components/LineChart.vue')['default']
Navbar: typeof import('./components/Navbar.vue')['default']
Navbar: typeof import('./components/Navbar/Navbar.vue')['default']
NBadge: typeof import('naive-ui')['NBadge']
NBreadcrumb: typeof import('naive-ui')['NBreadcrumb']
NBreadcrumbItem: typeof import('naive-ui')['NBreadcrumbItem']
Expand All @@ -51,10 +52,14 @@ declare module 'vue' {
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NModal: typeof import('naive-ui')['NModal']
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
Notifications: typeof import('./components/Notifications.vue')['default']
Notifications: typeof import('./components/Navbar/Notifications.vue')['default']
NPageHeader: typeof import('naive-ui')['NPageHeader']
NPopselect: typeof import('naive-ui')['NPopselect']
NRadioButton: typeof import('naive-ui')['NRadioButton']
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
NSpace: typeof import('naive-ui')['NSpace']
NSwitch: typeof import('naive-ui')['NSwitch']
NTag: typeof import('naive-ui')['NTag']
NTooltip: typeof import('naive-ui')['NTooltip']
NTreeSelect: typeof import('naive-ui')['NTreeSelect']
NUpload: typeof import('naive-ui')['NUpload']
Expand All @@ -67,9 +72,10 @@ declare module 'vue' {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Sidebar: typeof import('./components/Sidebar.vue')['default']
ThemeSwitch: typeof import('./components/ThemeSwitch.vue')['default']
ThemeCustomize: typeof import('./components/Navbar/ThemeCustomize.vue')['default']
ThemeSwitch: typeof import('./components/Navbar/ThemeSwitch.vue')['default']
TrendingProducts: typeof import('./components/Dahboard/TrendingProducts.vue')['default']
TurkishIcon: typeof import('./components/CountryIcons/TurkishIcon.vue')['default']
UserProfile: typeof import('./components/UserProfile.vue')['default']
UserProfile: typeof import('./components/Navbar/UserProfile.vue')['default']
}
}
6 changes: 5 additions & 1 deletion src/components/BarChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const chartOptions = ref({
dataLabels: {
enabled: false,
},
colors: ['#3db9af', '#37938d', '#276e6b', '#7fcdca'],
colors: buildThemeSeries(),
plotOptions: {
bar: {
columnWidth: '17%',
Expand Down Expand Up @@ -71,6 +71,10 @@ const series = ref([
data: [3, 4, 15, 5, 4, 60, 10],
},
])
function buildThemeSeries() {
return ['#3db9af', '#37938d', '#276e6b', '#7fcdca']
}
</script>

<template>
Expand Down
101 changes: 101 additions & 0 deletions src/components/CustomizeDialog/CustomizeDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<script setup>
import {
Checkmark48Filled as CheckIcon,
WeatherMoon48Regular as MoonIcon,
WeatherSunny48Regular as SunIcon,
} from '@vicons/fluent'
import { storeToRefs } from 'pinia'
const { t } = useI18n()
const layout = useLayoutStore()
const { isRtl } = storeToRefs(layout)
function setLight() {
if (layout.isDark)
layout.toggleTheme()
}
function setDark() {
if (!layout.isDark)
layout.toggleTheme()
}
const colors = [
'#00ad4c', '#ef4848', '#FC0', '#FF8000', '#22d3ee',
]
const selectedColorIndex = ref(0)
function setColor(index) {
selectedColorIndex.value = index
layout.setThemeColor(colors[index])
}
onMounted(() => {
selectedColorIndex.value = colors.findIndex(x => x === layout.themeColor)
})
</script>

<template>
<div class="section">
<NTag type="primary" :bordered="false" size="small" class="mb-3 font-bold">
{{ t('customize.theme') }}
</NTag>

<n-space justify="center" size="large">
<NButton ghost class="p-7" :type="layout.isDark === false ? 'primary' : 'default'" size="large" @click="setLight">
<template #icon>
<NIcon>
<SunIcon />
</NIcon>
</template>
</NButton>

<NButton ghost class="w-full p-7" :type="layout.isDark ? 'primary' : 'default'" size="large" @click="setDark">
<template #icon>
<NIcon>
<MoonIcon />
</NIcon>
</template>
</NButton>
</n-space>
</div>
<div class="section">
<NTag type="primary" :bordered="false" size="small" class="mb-3 font-bold">
{{ t('customize.color') }}
</NTag>

<div>
<NButton
v-for="(color, index) of colors" :key="index" :color="color" size="medium" circle icon="CheckIcon"
class="mx-1" @click="setColor(index)"
>
<template #icon>
<CheckIcon v-if="selectedColorIndex === index" />
<span v-else />
</template>
</NButton>
</div>
</div>
<div class="section">
<NTag type="primary" :bordered="false" size="small" class="mb-3 font-bold">
{{ t('customize.layout') }}
</NTag>

<div>
<n-switch v-model:value="isRtl" />
RTL Layout
</div>
</div>
</template>

<style lang="scss" scoped>
.section {
margin-bottom: 1rem;
padding: 1rem 0;
.section-title {
font-weight: 500;
padding: 0.2rem 0;
border-bottom: solid 1px #CCC;
margin-bottom:1rem;
}
}
</style>
7 changes: 2 additions & 5 deletions src/components/GithubButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@
<n-tooltip placement="top" trigger="hover">
<template #trigger>
<a href="https://github.com/doroudi/yummyadmin" block target="_blank">
<n-button strong round type="primary" class="pulse-animated" flex space-between py-5 px-3>
<n-button strong round color="#36ad6a" class="pulse-animated" flex space-between py-5 px-3>
<NIcon size="1.6rem" class="mr-2">
<svg
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 32 32"
>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
<path
d="M16 2a14 14 0 0 0-4.43 27.28c.7.13 1-.3 1-.67v-2.38c-3.89.84-4.71-1.88-4.71-1.88a3.71 3.71 0 0 0-1.62-2.05c-1.27-.86.1-.85.1-.85a2.94 2.94 0 0 1 2.14 1.45a3 3 0 0 0 4.08 1.16a2.93 2.93 0 0 1 .88-1.87c-3.1-.36-6.37-1.56-6.37-6.92a5.4 5.4 0 0 1 1.44-3.76a5 5 0 0 1 .14-3.7s1.17-.38 3.85 1.43a13.3 13.3 0 0 1 7 0c2.67-1.81 3.84-1.43 3.84-1.43a5 5 0 0 1 .14 3.7a5.4 5.4 0 0 1 1.44 3.76c0 5.38-3.27 6.56-6.39 6.91a3.33 3.33 0 0 1 .95 2.59v3.84c0 .46.25.81 1 .67A14 14 0 0 0 16 2z"
fill-rule="evenodd" fill="currentColor"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
import { storeToRefs } from 'pinia'
import { Translate16Regular as TranslateIcon } from '@vicons/fluent'
import { NIcon } from 'naive-ui/es/icon'
import EnglandIcon from './CountryIcons/EnglandIcon.vue'
import GermanyIcon from './CountryIcons/GermanyIcon.vue'
import ChineseIcon from './CountryIcons/ChineseIcon.vue'
import ArabicIcon from './CountryIcons/ArabicIcon.vue'
import TurkishIcon from './CountryIcons/TurkishIcon.vue'
import EnglandIcon from '../CountryIcons/EnglandIcon.vue'
import GermanyIcon from '../CountryIcons/GermanyIcon.vue'
import ChineseIcon from '../CountryIcons/ChineseIcon.vue'
import ArabicIcon from '../CountryIcons/ArabicIcon.vue'
import TurkishIcon from '../CountryIcons/TurkishIcon.vue'
import PersianIcon from './CountryIcons/PersianIcon.vue'
import PersianIcon from '../CountryIcons/PersianIcon.vue'
const { t } = useI18n()
const layoutStore = useLayoutStore()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const { t } = useI18n()
</template>
<template #extra>
<div class="flex items-center">
<ThemeCustomize />
<ThemeSwitch class="mx-1" />
<LanguageSelect class="mx-1" />
<Notifications class="mx-1" />
Expand Down
File renamed without changes.
32 changes: 32 additions & 0 deletions src/components/Navbar/ThemeCustomize.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script setup lang='ts'>
import {
Settings48Regular as CustomizeIcon,
} from '@vicons/fluent'
const showCustomizeDialog = ref(false)
const { t } = useI18n()
function toggleDialog() {
showCustomizeDialog.value = !showCustomizeDialog.value
}
</script>

<template>
<div v-bind="$attrs">
<n-button quaternary circle @click="toggleDialog()">
<template #icon>
<NIcon size="1.4rem">
<CustomizeIcon class="rotate-animated" />
</NIcon>
</template>
</n-button>
</div>

<n-drawer v-model:show="showCustomizeDialog" :width="400" placement="right">
<n-drawer-content closable :title="t('customize.title')">
<CustomizeDialog @close="showCustomizeDialog = false" />
</n-drawer-content>
</n-drawer>
</template>

<style scoped lang='scss'></style>
File renamed without changes.
File renamed without changes.
8 changes: 7 additions & 1 deletion src/store/layout.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const useLayoutStore = defineStore('layout', () => {
const activeLanguage = ref('en')
const isRtl = ref(false)
const { t, locale } = useI18n()

const themeColor = ref('')
const isDark = ref(false)

watch(() => useWindowSize().width.value, (newValue: number) => {
Expand All @@ -28,6 +28,10 @@ export const useLayoutStore = defineStore('layout', () => {
isRtl.value = (dir !== null && dir === 'rtl')
}

function setThemeColor(color: string) {
themeColor.value = color
}

return {
collapsed,
toggleSidebar,
Expand All @@ -37,6 +41,8 @@ export const useLayoutStore = defineStore('layout', () => {
changeLanguage,
forceCollapsed,
isDark,
setThemeColor,
themeColor,
}
}, { persist: true })

Expand Down
20 changes: 20 additions & 0 deletions src/styles/utils/_animations.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
.rotate-animated {
-webkit-animation: rotate 4s linear infinite;
-moz-animation: rotate 4s linear infinite;
animation: rotate 4s linear infinite;
}

@keyframes rotate {
0% {
transform: rotate(0);
}

50% {
transform: rotate(180deg);
}

100% {
transform: rotate(360deg);
}
}

.shake-item {
-webkit-animation: bell-shake 40s ease infinite;
-moz-animation: bell-shake 40s ease infinite;
Expand Down

0 comments on commit 012b44c

Please sign in to comment.