♻️ Migrated to new UI

This commit is contained in:
2025-11-30 03:10:12 +08:00
parent a06e0cb76a
commit 2598f6c112
10 changed files with 349 additions and 120 deletions

View File

@@ -1,8 +1,5 @@
<template>
<n-config-provider
:theme-overrides="themeOverrides"
:theme="theme.value === 'dark' ? darkTheme : lightTheme"
>
<naive-config>
<n-global-style />
<n-loading-bar-provider>
<n-dialog-provider>
@@ -13,33 +10,18 @@
</n-message-provider>
</n-dialog-provider>
</n-loading-bar-provider>
</n-config-provider>
</naive-config>
</template>
<script setup lang="ts">
import {
darkTheme,
lightTheme,
NConfigProvider,
NGlobalStyle,
NLoadingBarProvider,
NDialogProvider,
NMessageProvider,
} from "naive-ui";
import '@fontsource-variable/nunito';
const themeOverrides = {
common: {
fontFamily: "Nunito Variable, v-sans, ui-system, -apple-system, sans-serif",
primaryColor: "#7D80BAFF",
primaryColorHover: "#9294C5FF",
primaryColorPressed: "#575B9DFF",
primaryColorSuppl: "#6B6FC1FF",
},
};
const theme = useColorMode();
import "@fontsource-variable/nunito";
</script>
<style>
@@ -47,7 +29,9 @@ html,
body {
padding: 0;
margin: 0;
font-family: Nunito Variable, sans-serif;
font-family:
Nunito Variable,
sans-serif;
scroll-behavior: smooth;
}

29
app/assets/css/main.css Normal file
View File

@@ -0,0 +1,29 @@
@import "tailwindcss";
@plugin "daisyui";
@plugin "@tailwindcss/typography";
@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities);
@layer base {
:root {
--font-family: "Nunito Variable", "Helvatica", sans-serif;
}
html,
body {
font-family: var(--font-family);
}
}
.page-enter-active,
.page-leave-active {
transition: all 0.4s;
}
.page-enter-from,
.page-leave-to {
opacity: 0;
filter: blur(1rem);
}

13
app/auto-imports.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
const useDialog: typeof import('naive-ui').useDialog
const useLoadingBar: typeof import('naive-ui').useLoadingBar
const useMessage: typeof import('naive-ui').useMessage
const useNotification: typeof import('naive-ui').useNotification
}

30
app/components.d.ts vendored Normal file
View File

@@ -0,0 +1,30 @@
/* eslint-disable */
// @ts-nocheck
// biome-ignore lint: disable
// oxlint-disable
// ------
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
import { GlobalComponents } from 'vue'
export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
NAvatar: typeof import('naive-ui')['NAvatar']
NDropdown: typeof import('naive-ui')['NDropdown']
NMenu: typeof import('naive-ui')['NMenu']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
}
// For TSX support
declare global {
const NAvatar: typeof import('naive-ui')['NAvatar']
const NDropdown: typeof import('naive-ui')['NDropdown']
const NMenu: typeof import('naive-ui')['NMenu']
const RouterLink: typeof import('vue-router')['RouterLink']
const RouterView: typeof import('vue-router')['RouterView']
}

View File

@@ -1,53 +1,138 @@
<template>
<n-layout class="h-screen">
<n-layout-header class="app-bar-blur">
<div class="flex justify-between items-center container mx-auto">
<router-link to="/" class="text-lg font-bold"> Solsynth </router-link>
<div class="flex gap-3">
<router-link to="/terms" class="text-md font-bold">
Legal
<div class="flex flex-col min-h-screen">
<header
class="navbar bg-transparent shadow-lg fixed top-0 left-0 right-0 backdrop-blur-2xl z-1000 h-[64px]"
>
<div class="container mx-auto flex items-center justify-between px-5">
<div class="flex gap-2 items-center">
<router-link to="/">
<nuxt-img src="/favicon.png" alt="Solsynth" class="w-10 h-8" />
</router-link>
</div>
</div>
</n-layout-header>
<n-layout-content>
<n-menu
v-model:value="activeKey"
mode="horizontal"
:options="menuOptions"
/>
</div>
<n-dropdown :options="dropdownOptions" @select="handleDropdownSelect">
<n-avatar :size="32">
<n-icon :component="PersonIcon" :size="20" />
</n-avatar>
</n-dropdown>
</div>
</header>
<main class="grow mt-[64px]">
<slot />
</n-layout-content>
</n-layout>
</main>
<footer
class="footer sm:footer-horizontal bg-base-200 text-base-content p-10"
>
<aside>
<nuxt-img src="/favicon.png" alt="Solsynth" class="w-12 h-12" />
<p>
Solsynth
<br />
Making software, hardware and experiences since 2024
</p>
</aside>
<nav>
<h6 class="footer-title">Products</h6>
<router-link to="/products" class="link link-hover"
>Our Products</router-link
>
<router-link to="/#about" class="link link-hover">About Us</router-link>
</nav>
<nav>
<h6 class="footer-title">Company</h6>
<a
href="https://github.com/Solsynth"
target="_blank"
class="link link-hover"
>GitHub</a
>
<router-link to="/#about" class="link link-hover">Team</router-link>
</nav>
<nav>
<h6 class="footer-title">Legal</h6>
<router-link to="/terms/user-agreement" class="link link-hover"
>Terms of Service</router-link
>
<router-link to="/terms/privacy-policy" class="link link-hover"
>Privacy Policy</router-link
>
<router-link to="/terms/refund-policy" class="link link-hover"
>Refund Policy</router-link
>
<router-link to="/terms" class="link link-hover"
>All Documents</router-link
>
</nav>
</footer>
</div>
</template>
<script setup lang="ts">
import { NLayout, NLayoutHeader, NLayoutContent } from "naive-ui";
<script lang="ts" setup>
import type { MenuOption } from "naive-ui";
import { NIcon, NAvatar, NMenu, NDropdown } from "naive-ui";
import { computed, h } from "vue";
import { useRouter, useRoute, RouterLink } from "vue-router";
import {
ExploreOutlined,
DashboardOutlined,
LogInOutlined,
PersonAddOutlined,
PersonOutlined,
} from "@vicons/material";
const router = useRouter();
const route = useRoute();
const PersonIcon = PersonOutlined;
const activeKey = computed(() => {
// Map route paths to menu keys
if (route.path === "/") return "explore";
return null;
});
function renderIcon(icon: any) {
return () => h(NIcon, null, { default: () => h(icon) });
}
function renderLabel(label: string, route: string) {
return () => h(RouterLink, { to: route }, { default: () => label });
}
const menuOptions: MenuOption[] = [
{
label: renderLabel("Explore", "/"),
key: "explore",
icon: renderIcon(ExploreOutlined),
},
];
const dropdownOptions = computed(() => {
// For now, show login/signup options
// TODO: Add user authentication state check
return [
{
label: "Login",
key: "/auth/login",
icon: renderIcon(LogInOutlined),
},
{
label: "Create Account",
key: "/auth/create-account",
icon: renderIcon(PersonAddOutlined),
},
];
});
function handleDropdownSelect(key: string) {
router.push(key);
}
</script>
<style scoped>
.n-layout-header {
padding: 8px 24px;
border-color: var(--n-border-color);
height: 57px; /* Fixed height */
display: flex;
align-items: center;
}
.n-layout-content {
height: calc(100vh - 57px); /* Adjust based on header height */
}
.app-bar-blur {
-webkit-mask-image: linear-gradient(
to bottom,
rgba(0, 0, 0, 1) 40%,
rgba(0, 0, 0, 0.5) 65%,
rgba(0, 0, 0, 0) 100%
);
mask-image: linear-gradient(
to bottom,
rgba(0, 0, 0, 1) 40%,
rgba(0, 0, 0, 0.5) 65%,
rgba(0, 0, 0, 0) 100%
);
mask-repeat: no-repeat;
mask-size: 100%;
}
</style>

View File

@@ -25,7 +25,7 @@
show-arrow
autoplay
dot-type="line"
class="rounded-xl w-full max-h-[360px] aspect-video flex-shrink-1"
class="rounded-xl w-full max-h-[360px] aspect-video shrink"
>
<n-carousel-item
v-for="product in products"
@@ -114,7 +114,7 @@
<n-grid cols="1 m:2 l:2" responsive="screen" x-gap="32" y-gap="16">
<n-gi>
<div
class="flex justify-center text-left h-full py-8 px-4 flex flex-col"
class="justify-center text-left h-full py-8 px-4 flex flex-col"
>
<h2 class="text-3xl font-bold mb-3">About us</h2>
<p class="text-lg mb-1">

View File

@@ -0,0 +1,54 @@
<template>
<div class="container max-w-xl mx-auto my-16 px-8">
<h1 class="text-4xl font-bold mb-8">Our Products</h1>
<nuxt-link
v-for="product in products"
:key="product.url"
:to="product.url"
class="no-underline block mb-4"
>
<n-card hoverable>
<template #cover>
<div class="h-48 overflow-hidden relative">
<img :src="product.background" class="w-full h-full object-cover" />
<div
class="absolute bottom-0 left-0 p-4 bg-linear-to-t from-black/80 to-transparent w-full flex items-center gap-3"
>
<img
:src="product.icon"
class="aspect-square h-10 rounded-full bg-white/10 p-1"
style="width: auto"
/>
<span class="text-white font-bold text-lg grow">{{
product.name
}}</span>
</div>
</div>
</template>
<p class="line-clamp-3 pt-4">{{ product.description }}</p>
<template #footer>
<div class="flex justify-between items-center text-xs opacity-75">
<span>v{{ product.version }}</span>
<span>
Released:
{{ new Date(product.releasedDate ?? "").toLocaleDateString() }}
</span>
</div>
</template>
</n-card>
</nuxt-link>
</div>
</template>
<script setup lang="ts">
import { NCard } from "naive-ui";
const { data: products } = await useAsyncData("products", () =>
queryCollection("products").all()
);
useHead({
title: "Products",
});
</script>