♻️ 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>

View File

@@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -1,52 +1,86 @@
import tailwindcss from "@tailwindcss/vite";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { NaiveUiResolver } from "unplugin-vue-components/resolvers";
import { generateTailwindColorThemes } from "@bg-dev/nuxt-naiveui/utils";
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: "2025-07-15",
devtools: { enabled: true },
ssr: false,
css: ["~/assets/css/main.css"],
app: {
pageTransition: { name: "page", mode: "out-in" },
head: {
title: "Solsynth",
titleTemplate: "%s - Solsynth",
link: [{ rel: "icon", type: "image/png", href: "/favicon.png" }],
},
},
scripts: {
globals: {
umami: {
src: "https://cloud.umami.is/script.js",
"data-website-id": "eef151fb-07e2-461b-8b7f-2547aab735d4",
defer: true,
},
},
},
nitro: {
preset: "cloudflare_module",
cloudflare: {
deployConfig: true,
wrangler: {
d1_databases: [
{
binding: "DB",
database_name: "capital-content",
database_id: "73d65123-3c42-4dc9-b540-8e89678962a2",
},
],
},
},
},
content: {
database: {
type: "d1",
bindingName: "DB",
},
},
nitro: {},
modules: [
"@nuxt/content",
"@nuxt/eslint",
"@nuxt/image",
"@nuxt/scripts",
"@nuxtjs/tailwindcss",
"nuxtjs-naive-ui",
"@vueuse/nuxt",
"@eschricht/nuxt-color-mode",
"@bg-dev/nuxt-naiveui",
],
vite: {
plugins: [
tailwindcss(),
AutoImport({
imports: [
{
"naive-ui": [
"useDialog",
"useMessage",
"useNotification",
"useLoadingBar",
],
},
],
}),
Components({
resolvers: [NaiveUiResolver()],
}),
],
},
naiveui: {
colorModePreference: "system",
colorModePreferenceCookieName: "fi-ColorMode",
themeConfig: {
...generateTailwindColorThemes(),
shared: {
common: {
fontFamily:
"Nunito Variable, v-sans, ui-system, -apple-system, sans-serif",
primaryColor: "#3F51B5FF",
primaryColorHover: "#5767C1FF",
primaryColorPressed: "#3546A4FF",
primaryColorSuppl: "#4C5EC5FF",
borderRadius: "16px",
borderRadiusSmall: "8px",
},
Input: {
borderRadius: "8px",
},
Select: {
borderRadius: "8px",
},
Dropdown: {
borderRadius: "8px",
},
Button: {
borderRadius: "8px",
borderRadiusLarge: "12px",
borderRadiusMedium: "8px",
borderRadiusSmall: "4px",
},
},
light: {},
dark: {},
},
},
});

View File

@@ -10,28 +10,31 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@eschricht/nuxt-color-mode": "1.2.0",
"@fontsource-variable/nunito": "^5.2.6",
"@bg-dev/nuxt-naiveui": "^2.0.0",
"@fontsource-variable/nunito": "^5.2.7",
"@nuxt/content": "3.6.3",
"@nuxt/eslint": "1.7.1",
"@nuxt/image": "1.10.0",
"@nuxt/scripts": "0.11.10",
"@nuxtjs/tailwindcss": "6.14.0",
"@octokit/rest": "^22.0.0",
"@unhead/vue": "^2.0.3",
"@vueuse/core": "^13.6.0",
"@octokit/rest": "^22.0.1",
"@unhead/vue": "^2.0.19",
"@vueuse/core": "^13.9.0",
"@vueuse/nuxt": "13.6.0",
"better-sqlite3": "^12.2.0",
"eslint": "^9.0.0",
"nuxt": "^4.0.1",
"better-sqlite3": "^12.5.0",
"eslint": "^9.39.1",
"nuxt": "^4.2.1",
"nuxtjs-naive-ui": "1.0.2",
"typed.js": "^2.1.0",
"vue": "^3.5.18",
"vue-router": "^4.5.1",
"wrangler": "^4.26.1"
"vue": "^3.5.25",
"vue-router": "^4.6.3",
"wrangler": "^4.51.0"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.16",
"@vicons/material": "^0.13.0"
"@tailwindcss/typography": "^0.5.19",
"@vicons/material": "^0.13.0",
"daisyui": "^5.5.5",
"naive-ui": "^2.43.2",
"unplugin-auto-import": "^20.3.0",
"unplugin-vue-components": "^30.0.0"
}
}