Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions app/assets/css/main.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
body {
background:
radial-gradient(
circle at top left,
rgba(232, 83, 73, 0.08),
transparent 28%
),
radial-gradient(
circle at top right,
rgba(48, 111, 255, 0.08),
transparent 32%
),
linear-gradient(
180deg,
var(--color-bg-1) 0%,
var(--color-neutral-2) 46%,
var(--color-bg-1) 100%
);
background-color: var(--color-neutral-2);
background-attachment: fixed;
color: var(--color-text-2);
--border-radius-small: 4px;
--border-radius-medium: 6px;
Expand All @@ -10,6 +28,38 @@ body {
@apply flex min-h-screen flex-col gap-4;
}

a,
button,
.arco-btn,
.arco-card,
.arco-menu-item,
.arco-link {
transition:
transform 0.25s ease,
box-shadow 0.25s ease,
border-color 0.25s ease,
background-color 0.25s ease,
color 0.25s ease;
}

/* .arco-card,
.arco-collapse,
.arco-collapse-item,
.arco-collapse-item-header,
.arco-collapse-item-content,
.arco-menu,
.arco-menu-inner,
.arco-menu-light,
.arco-layout-sider,
.arco-layout-sider-light,
.arco-layout-sider-children,
.arco-menu-inline-header,
.arco-menu-inline-content,
.arco-menu-item,
.arco-menu-item-inner {
background-color: transparent !important;
} */

.arco-drawer-body {
padding: 0;
}
Expand Down
32 changes: 26 additions & 6 deletions app/components/AppFooter.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<script lang="ts" setup>
import { motion } from 'motion-v'

const { t } = useI18n()

const { hidden, hoverLift, press, viewport, visible } = useMotionPresets()
</script>

<template>
Expand All @@ -8,24 +12,40 @@ const { t } = useI18n()
class="mx-auto flex min-h-14 max-w-full flex-col items-center justify-center gap-1 py-3 text-center text-sm md:flex-row md:gap-0 md:py-0"
>
<ASpace wrap class="justify-center">
<div>
<motion.div
:initial="hidden(14)"
:whileInView="visible()"
:inViewOptions="viewport"
:whileHover="hoverLift(3, 1.01)"
>
Copyright &copy; {{ new Date().getFullYear() }}
<ALink target="_blank" href="https://github.com/ikxin/kms-tools">
KMS Tools
</ALink>
</div>
<div>
</motion.div>
<motion.div
:initial="hidden(14)"
:whileInView="visible(0.05)"
:inViewOptions="viewport"
:whileHover="hoverLift(3, 1.01)"
>
Running on
<ALink target="_blank" href="https://www.asiayun.com/aff/TVXVRALM">
AsiaYun
</ALink>
</div>
<div>
</motion.div>
<motion.div
:initial="hidden(14)"
:whileInView="visible(0.1)"
:inViewOptions="viewport"
:whileHover="hoverLift(3, 1.01)"
:whilePress="press"
>
Code with by
<ALink target="_blank" href="https://blog.ikxin.com">
{{ t('label.author') }}
</ALink>
</div>
</motion.div>
</ASpace>
</div>
</ALayoutFooter>
Expand Down
114 changes: 80 additions & 34 deletions app/components/AppHeader.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
<script setup lang="ts">
import { motion } from 'motion-v'
import logoUrl from '~/assets/icons/kms-tools.svg'

const route = useRoute()

const { locales, t, setLocale } = useI18n()

const { hidden, hoverLift, press, visible } = useMotionPresets()

const localePath = useLocalePath()

const path = computed(() => route.path.slice(1).split('/'))

const activeSection = computed(() => path.value[0] || '')

const drawerVisible = ref(false)

const navItems = computed(() => [
Expand Down Expand Up @@ -50,45 +57,63 @@ function handleNavClick(name: string) {

<template>
<ALayoutHeader
class="sticky top-0 z-[100] flex h-20 select-none items-center bg-[--color-bg-2] px-4 shadow-md"
class="sticky top-0 z-[100] flex h-20 select-none items-center border-b border-white/10 bg-[--color-bg-2]/80 px-4 shadow-md backdrop-blur-xl"
>
<div class="mx-auto flex w-[72rem] max-w-full items-center justify-between">
<img
src="/assets/icons/kms-tools.svg"
<motion.img
:src="logoUrl"
alt="KMS Tools"
class="h-14 w-auto cursor-pointer"
:initial="hidden(10)"
:animate="visible(0.02)"
:whileHover="{ scale: 1.04, rotate: -2 }"
:whilePress="press"
@click="navigateTo(localePath('/'))"
/>

<!-- Desktop Menu -->
<AMenu
:selected-keys="path"
mode="horizontal"
class="hidden grow md:flex [&_.arco-menu-overflow-wrap]:text-end [&_.arco-menu-selected-label]:left-4"
>
<AMenuItem
<nav class="hidden grow items-center justify-center gap-2 md:flex">
<motion.button
v-for="item in navItems"
:key="item.name"
class="!inline-flex items-center gap-1"
type="button"
class="relative flex items-center gap-2 overflow-hidden rounded-full px-4 py-2 text-sm font-medium text-[var(--color-text-2)] transition-colors hover:text-[var(--color-text-1)]"
:initial="hidden(10)"
:animate="visible(navItems.findIndex(nav => nav.name === item.name) * 0.05 + 0.08)"
:whileHover="hoverLift(4, 1.02)"
:whilePress="press"
@click="handleNavClick(item.name)"
>
<Icon :name="item.icon" />
<span>{{ item.label }}</span>
</AMenuItem>
</AMenu>
<motion.span
v-if="activeSection === item.name"
layoutId="header-nav-pill"
class="absolute inset-0 rounded-full bg-[rgb(var(--primary-6))]/14 ring-1 ring-[rgb(var(--primary-6))]/20"
/>
<span class="relative z-[1] inline-flex items-center gap-2">
<Icon :name="item.icon" />
<span>{{ item.label }}</span>
</span>
</motion.button>
</nav>

<ASpace>
<ADropdown>
<AButton size="small" type="secondary">
<template #icon>
<ClientOnly>
<Icon :name="`icons:${$colorMode.preference}-mode`" />
<template #fallback>
<Icon :name="`icons:system-mode`" />
</template>
</ClientOnly>
</template>
</AButton>
<motion.div
:initial="hidden(10)"
:animate="visible(0.14)"
:whileHover="hoverLift(3, 1.04)"
:whilePress="press"
>
<AButton size="small" type="secondary">
<template #icon>
<ClientOnly>
<Icon :name="`icons:${$colorMode.preference}-mode`" />
<template #fallback>
<Icon :name="`icons:system-mode`" />
</template>
</ClientOnly>
</template>
</AButton>
</motion.div>
<template #content>
<ADoption
v-for="item in themeItems"
Expand All @@ -103,9 +128,16 @@ function handleNavClick(name: string) {
</template>
</ADropdown>
<ADropdown>
<AButton size="small" type="secondary">
<template #icon><Icon name="icons:languages" /></template>
</AButton>
<motion.div
:initial="hidden(10)"
:animate="visible(0.18)"
:whileHover="hoverLift(3, 1.04)"
:whilePress="press"
>
<AButton size="small" type="secondary">
<template #icon><Icon name="icons:languages" /></template>
</AButton>
</motion.div>
<template #content>
<ADoption
v-for="locale in locales"
Expand All @@ -120,16 +152,30 @@ function handleNavClick(name: string) {
</template>
</ADropdown>
<a target="_blank" href="https://github.com/ikxin/kms-tools">
<AButton size="small" type="secondary">
<template #icon><Icon name="icons:github" /></template>
</AButton>
<motion.div
:initial="hidden(10)"
:animate="visible(0.22)"
:whileHover="hoverLift(3, 1.04)"
:whilePress="press"
>
<AButton size="small" type="secondary">
<template #icon><Icon name="icons:github" /></template>
</AButton>
</motion.div>
</a>

<!-- Mobile Hamburger -->
<div class="md:hidden">
<AButton size="small" type="secondary" @click="drawerVisible = true">
<template #icon><Icon name="material-symbols:menu" /></template>
</AButton>
<motion.div
:initial="hidden(10)"
:animate="visible(0.24)"
:whileHover="hoverLift(3, 1.04)"
:whilePress="press"
>
<AButton size="small" type="secondary" @click="drawerVisible = true">
<template #icon><Icon name="material-symbols:menu" /></template>
</AButton>
</motion.div>
</div>
</ASpace>
</div>
Expand Down
Loading
Loading