♻️ Migrated to new UI
This commit is contained in:
28
app/app.vue
28
app/app.vue
@@ -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
29
app/assets/css/main.css
Normal 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
13
app/auto-imports.d.ts
vendored
Normal 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
30
app/components.d.ts
vendored
Normal 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']
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
54
app/pages/products/index.vue
Normal file
54
app/pages/products/index.vue
Normal 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>
|
||||
Reference in New Issue
Block a user