Skip to content

Commit

Permalink
made code simplifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Kahera committed Aug 25, 2024
1 parent 493117a commit 36bda02
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 107 deletions.
15 changes: 15 additions & 0 deletions src/assets/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@
@tailwind components;
@tailwind utilities;

@layer base {
*:focus-visible {
@apply focus-outline;
}
}

@layer utilities {
.focus-outline {
@apply rounded-md outline outline-2 outline-offset-4 outline-primary-dark dark:outline-primary-light;
}

.bg-gradient {
@apply bg-gradient-to-tl from-primary-lightest to-secondary-light via-accent-lightest dark:from-accent-darkest dark:to-primary-darkest;
}
Expand All @@ -25,6 +35,10 @@
@apply text-primary dark:text-primary/80 hover:text-primary-dark dark:hover:text-primary group-hover:text-primary-dark dark:group-hover:text-primary transition-colors duration-200;
}

.primary-higher-contrast-hover-text {
@apply text-primary-darkest dark:text-primary-lightest hover:text-primary-darker dark:hover:text-primary-light transition-colors duration-200;
}

.secondary-hover-text {
@apply text-secondary-darker dark:text-secondary-darker hover:text-secondary-darkest dark:hover:text-secondary-dark transition-colors duration-200;
}
Expand All @@ -36,6 +50,7 @@
.secondary-hover-bg {
@apply bg-secondary-darker dark:bg-secondary-darker hover:bg-secondary-darkest dark:hover:bg-secondary-dark transition-colors duration-200;
}

}

.font-icon {
Expand Down
42 changes: 19 additions & 23 deletions src/components/DropdownComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ defineProps({
buttonType: {
type: String as PropType<'outline' | 'solid'>,
default: 'outline'
},
buttonSize: {
type: String as PropType<'sm' | 'md' | 'lg'>,
default: 'md'
}
});
const dropdownOpen = ref(false);
},
buttonSize: {
type: String as PropType<'sm' | 'md' | 'lg'>,
default: 'md'
},
backgroundColorClasses: {
type: String as PropType<string>,
default: 'bg-accent-lightest dark:bg-accent-darker shadow shadow-accent-light dark:shadow-accent-dark'
}
});
const dropdownOpen = ref(false);
function toggleDropdown(closeDropdown: boolean = false) {
if (closeDropdown) dropdownOpen.value = false;
Expand All @@ -26,7 +29,7 @@ function toggleDropdown(closeDropdown: boolean = false) {
// Close dropdown when clicking outside of it
const handleOutsideClick = (e: MouseEvent) => {
if (!(e.target as HTMLElement).closest('.dropdown-btn')) {
if (!(e.target as HTMLElement).closest('#dropdown-btn')) {
toggleDropdown(true);
}
};
Expand All @@ -41,8 +44,8 @@ onUnmounted(() => {
<template>
<div class="relative min-w-fit">
<Button
class="dropdown-btn"
:type="'solid'"
id="dropdown-btn"
:type="buttonType"
:size="buttonSize"
:icon="dropdownOpen ? 'close' : 'menu'"
@click="toggleDropdown()"
Expand All @@ -53,8 +56,11 @@ onUnmounted(() => {
>
<div
v-if="dropdownOpen"
class="dropdown-parent absolute z-10 top-14 mb-2 min-w-[10rem] rounded-lg"
:class="{ 'right-0': position == 'right', 'left-0': position == 'left' }"
class="absolute flex flex-col gap-2 top-14 p-4 min-w-[10rem] rounded-md *:primary-higher-contrast-hover-text"
:class="[
position == 'right' ? 'right-0' : 'left-0',
backgroundColorClasses
]"
>
<slot />
</div>
Expand All @@ -63,16 +69,6 @@ onUnmounted(() => {
</template>

<style scoped>
:slotted(.dropdown-parent > *) {
@apply px-4 py-2 block text-center
text-primary-darkest bg-primary-lighter hover:bg-primary-light
transition-colors duration-200;
.dark & { /* For some reason, the tailwind dark-prefix don't work on the slotted elements */
@apply text-primary-lighter bg-accent-darker hover:bg-accent-darkest;
}
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.15s ease;
Expand Down
102 changes: 43 additions & 59 deletions src/components/LanguageSelector.vue
Original file line number Diff line number Diff line change
@@ -1,68 +1,52 @@
<script setup lang="ts">
import { onMounted } from 'vue';
import { nextTick, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import type { PropType } from 'vue';
const { locale } = useI18n();
const labelRef = ref<HTMLElement | null>(null);
const cssVariables = ref<Record<string, string>>({ '--width': '0px' });
onMounted(() => updateWidth());
watch(locale, async() => updateWidth());
defineProps({
colorScheme: {
type: String as PropType<'primary' | 'secondary'>,
default: 'primary'
}
});
const updateWidth = async () => {
await nextTick();
cssVariables.value['--width'] = `${labelRef.value ? labelRef.value.offsetWidth + 18 : 0}px`;
// First string = text or border, second string = color scheme
const colorOptions: Record<string, Record<string, string>> = {
text: {
primary: 'primary-hover-text',
secondary: 'secondary-hover-text'
},
border: {
primary: 'primary-hover-border',
secondary: 'secondary-hover-border'
}
}
</script>

<template>
<div>
<!-- Wrapper to avoid the padding from the outside of this element to affect the insets -->
<div class="relative group">
<label
ref="labelRef"
for="locale"
:style="cssVariables"
class="absolute text-sm -mt-2.5 left-3 floating-label-position primary-hover-text group-text-color"
<fieldset
:class="colorOptions.border[colorScheme]"
class="group border rounded-md px-2 pb-3 -mt-2 has-[:focus-within]:focus-outline"
>
<legend
class="px-1 text-sm"
:class="colorOptions.text[colorScheme]"
>
{{ $t('locale.select') }}
</legend>
<select
id="locale"
v-model="$i18n.locale"
class="w-full bg-transparent focus-visible:outline-none text-primary-darkest dark:text-primary-lighter"
@click="$event.stopPropagation()"
>
<option
v-for="(loc, index) in $i18n.availableLocales"
:key="`locale-${loc}`"
:data-index="index"
:value="loc"
class="bg-primary-lightest dark:bg-accent-darker"
>
{{ $t('locale.select') }}
</label>
<div class="hide-border-top relative overflow-clip rounded-md text-primary-darkest dark:text-primary-lighter">
<div
class="absolute top-0 left-0 w-2 border-t border-x-0 primary-hover-border group-border-color rounded-tl-md"
/>
<div
:style="cssVariables"
class="absolute top-0 right-0 border-t border-x-0 primary-hover-border group-border-color top-border-right"
/>
<select
id="locale"
v-model="$i18n.locale"
class="block h-12 py-0 px-6 w-full bg-transparent rounded-md border primary-hover-border group-border-color hide-border-top focus-visible:border-2 focus-visible:outline-0 focus-visible:outline-transparent appearance-none"
@click="$event.stopPropagation()"
>
<option
v-for="(loc, index) in $i18n.availableLocales"
:key="`locale-${loc}`"
:data-index="index"
:value="loc"
class="bg-primary-lightest dark:bg-accent-darker"
>
{{ $t('locale.' + loc) }}
</option>
</select>
</div>
</div>
</div>
{{ $t('locale.' + loc) }}
</option>
</select>
</fieldset>
</template>

<style scoped>
.hide-border-top {
border-top: none;
}
.top-border-right {
width: calc(100% - var(--width));
}
</style>
47 changes: 22 additions & 25 deletions src/components/NavbarComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,9 @@ import { useDarkModeStore } from '@/stores/darkMode';
import Dropdown from '@/components/DropdownComponent.vue';
import Button from '@/components/ButtonComponent.vue';
import LanguageSelector from './LanguageSelector.vue';
import { onUnmounted, ref } from 'vue';
// Variables
const darkModeStore = useDarkModeStore();
// Screen size variable
const isSmallScreen = ref(false);
checkWindowSize();
function checkWindowSize() {
isSmallScreen.value = window.matchMedia('(max-width: 768px)').matches;
}
window.addEventListener('resize', () => checkWindowSize());
function getNavIcon(name: string | undefined) {
switch (name) {
case 'about':
Expand All @@ -33,30 +23,27 @@ function getNavIcon(name: string | undefined) {
return 'email';
}
}
// Destroy event listener on unmount
onUnmounted(() => window.removeEventListener('resize', () => checkWindowSize()));
</script>

<template>
<header class="flex items-center space-x-4 md:space-x-8 mx-4 md:mx-6 my-3 md:my-4">
<header class="flex items-center gap-4 md:gap-8 mx-4 md:mx-6 my-3 md:my-4">
<!-- Logo home-link -->
<RouterLink
to="/"
class="flex space-x-4 md:space-x-6 max-md:grow"
class="flex gap-4 md:gap-6 max-md:grow"
>
<img
alt="{{ $t('common.JuneIcon') }}"
src="@/assets/images/Kahera.webp"
class="max-h-12 max-xs:hidden"
>
<h1 class="text-center my-auto text-xl xxs:text-2xl md:text-3xl lg:text-4xl primary-hover-text">
<h1 class="text-center my-auto brand-header primary-hover-text">
{{ $t('common.JuneHansen') }}
</h1>
</RouterLink>

<!-- In header navigation on larger screens -->
<nav class="max-md:hidden flex justify-center space-x-6 m-auto grow">
<nav class="max-md:hidden flex justify-center gap-6 m-auto grow">
<RouterLink
v-for="route in $router.getRoutes().filter(x => x.name != 'home')"
:key="route.path"
Expand All @@ -69,8 +56,7 @@ onUnmounted(() => window.removeEventListener('resize', () => checkWindowSize()))
<!-- Using if here to ensure new component is generated on resize,
in case of language change between size changes -->
<LanguageSelector
v-if="!isSmallScreen"
class="w-28"
class="w-28 max-md:hidden"
/>

<!-- Dark/light mode for larger screens -->
Expand All @@ -79,12 +65,12 @@ onUnmounted(() => window.removeEventListener('resize', () => checkWindowSize()))
:type="'outline'"
:size="'lg'"
:icon="darkModeStore.darkMode ? 'light_mode' : 'dark_mode'"
class="max-md:hidden focus:outline-1 focus:outline-primary-light"
class="max-md:hidden"
@click="darkModeStore.toggle()"
/>

<!-- Dropdown navigation for smaller screens, see v-if explanation above LanguageSelector -->
<nav v-if="isSmallScreen">
<!-- Dropdown on small screens, link list on larger -->
<nav class="md:hidden">
<Dropdown
:position="'right'"
:button-type="'outline'"
Expand All @@ -93,7 +79,7 @@ onUnmounted(() => window.removeEventListener('resize', () => checkWindowSize()))
<RouterLink
v-for="route in $router.getRoutes().filter(x => x.name != 'home')"
:key="route.path"
class="flex space-x-2"
class="flex gap-2"
:to="route.path"
>
<span class="font-icon align-bottom">{{ getNavIcon(route.name?.toString()) }}</span>
Expand All @@ -103,14 +89,25 @@ onUnmounted(() => window.removeEventListener('resize', () => checkWindowSize()))
class="w-full"
@click="darkModeStore.toggle()"
>
<div class="flex space-x-2 whitespace-nowrap">
<div class="flex gap-2 whitespace-nowrap w-">
<span class="font-icon">{{ darkModeStore.darkMode ? 'light_mode' : 'dark_mode' }}</span>
<span>{{ $t('ui.swapTo', {mode: darkModeStore.darkMode ? $t('ui.lightMode').toLocaleLowerCase() : $t('ui.darkMode').toLocaleLowerCase()}) }}</span>
</div>
</button>

<LanguageSelector />
<LanguageSelector
class="-mt-1"
:color-scheme="'secondary'"
/>
</Dropdown>
</nav>
</header>
</template>

<style scoped>
.brand-header {
/* Magic numbers from the website fluid.style */
--preferred: 1.15rem + 2vw;
font-size: clamp(1.5rem, 1.16rem + 2vw, 2.5rem);
}
</style>

0 comments on commit 36bda02

Please sign in to comment.