diff --git a/website/resources/ts/@layouts/components/VerticalNav.vue b/website/resources/ts/@layouts/components/VerticalNav.vue deleted file mode 100644 index e0ebdaf..0000000 --- a/website/resources/ts/@layouts/components/VerticalNav.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - - - diff --git a/website/resources/ts/@layouts/components/VerticalNavGroup.vue b/website/resources/ts/@layouts/components/VerticalNavGroup.vue deleted file mode 100644 index 2fd4774..0000000 --- a/website/resources/ts/@layouts/components/VerticalNavGroup.vue +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - {{ item.title }} - - {{ item.badgeContent }} - - - - - - - - - - diff --git a/website/resources/ts/@layouts/components/VerticalNavLayout.vue b/website/resources/ts/@layouts/components/VerticalNavLayout.vue deleted file mode 100644 index 12621f4..0000000 --- a/website/resources/ts/@layouts/components/VerticalNavLayout.vue +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/website/resources/ts/@layouts/components/VerticalNavLink.vue b/website/resources/ts/@layouts/components/VerticalNavLink.vue deleted file mode 100644 index a1fc003..0000000 --- a/website/resources/ts/@layouts/components/VerticalNavLink.vue +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - {{ item.title }} - - {{ item.badgeContent }} - - - - diff --git a/website/resources/ts/@layouts/components/VerticalNavSectionTitle.vue b/website/resources/ts/@layouts/components/VerticalNavSectionTitle.vue deleted file mode 100644 index 5a8feab..0000000 --- a/website/resources/ts/@layouts/components/VerticalNavSectionTitle.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - {{ item.heading }} - - - - diff --git a/website/resources/ts/@layouts/styles/_mixins.scss b/website/resources/ts/@layouts/styles/_mixins.scss deleted file mode 100644 index ed35ae4..0000000 --- a/website/resources/ts/@layouts/styles/_mixins.scss +++ /dev/null @@ -1,30 +0,0 @@ -@use "placeholders"; -@use "@configured-variables" as variables; - -@mixin rtl { - @if variables.$enable-rtl-styles { - [dir="rtl"] & { - @content; - } - } -} - -@mixin boxed-content($nest-selector: false) { - & { - @extend %boxed-content-spacing; - - @at-root { - @if $nest-selector == false { - .layout-content-width-boxed#{&} { - @extend %boxed-content; - } - } - // stylelint-disable-next-line @stylistic/indentation - @else { - .layout-content-width-boxed & { - @extend %boxed-content; - } - } - } - } -} diff --git a/website/resources/ts/@layouts/styles/_placeholders.scss b/website/resources/ts/@layouts/styles/_placeholders.scss deleted file mode 100644 index 0ab9f5f..0000000 --- a/website/resources/ts/@layouts/styles/_placeholders.scss +++ /dev/null @@ -1,9 +0,0 @@ -// Stub β placeholders not used in our Inertia setup -%boxed-content { - max-inline-size: 1440px; - margin-inline: auto; -} - -%boxed-content-spacing { - padding-inline: 1.5rem; -} diff --git a/website/resources/ts/@layouts/styles/_variables.scss b/website/resources/ts/@layouts/styles/_variables.scss deleted file mode 100644 index 90d610c..0000000 --- a/website/resources/ts/@layouts/styles/_variables.scss +++ /dev/null @@ -1,29 +0,0 @@ -// @use "@styles/style.scss"; - -// π Vertical nav -$layout-vertical-nav-z-index: 12 !default; -$layout-vertical-nav-width: 260px !default; -$layout-vertical-nav-collapsed-width: 80px !default; -$selector-vertical-nav-mini: ".layout-vertical-nav-collapsed .layout-vertical-nav:not(:hover)"; - -// π Horizontal nav -$layout-horizontal-nav-z-index: 11 !default; -$layout-horizontal-nav-navbar-height: 64px !default; - -// π Navbar -$layout-vertical-nav-navbar-height: 64px !default; -$layout-vertical-nav-navbar-is-contained: true !default; -$layout-vertical-nav-layout-navbar-z-index: 11 !default; -$layout-horizontal-nav-layout-navbar-z-index: 11 !default; - -// π Main content -$layout-boxed-content-width: 1440px !default; - -// πFooter -$layout-vertical-nav-footer-height: 56px !default; - -// π Layout overlay -$layout-overlay-z-index: 11 !default; - -// π RTL -$enable-rtl-styles: true !default; diff --git a/website/resources/ts/@layouts/styles/_vertical-nav.scss b/website/resources/ts/@layouts/styles/_vertical-nav.scss deleted file mode 100644 index e8f7bc7..0000000 --- a/website/resources/ts/@layouts/styles/_vertical-nav.scss +++ /dev/null @@ -1,311 +0,0 @@ -@use "@configured-variables" as variables; -@use "variables" as layout-variables; - -// βββ Layout Wrapper βββ -.layout-wrapper.layout-nav-type-vertical { - display: flex; - min-block-size: 100vh; - flex: 1 1 auto; -} - -// βββ Vertical Nav (Sidebar) βββ -.layout-vertical-nav { - position: fixed; - inset-block: 0; - inset-inline-start: 0; - z-index: layout-variables.$layout-vertical-nav-z-index; - display: flex; - flex-direction: column; - inline-size: layout-variables.$layout-vertical-nav-width; - background-color: rgb(var(--v-theme-surface)); - border-inline-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity)); - transition: inline-size 0.25s ease-in-out, transform 0.25s ease-in-out, box-shadow 0.25s ease-in-out; - - // βββ Nav Header βββ - .nav-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 16px 8px; - min-block-size: layout-variables.$layout-vertical-nav-navbar-height; - } - - .nav-header-logo { - display: flex; - align-items: center; - gap: 10px; - text-decoration: none; - overflow: hidden; - } - - .nav-logo-img { - block-size: 28px; - inline-size: auto; - flex-shrink: 0; - } - - .nav-logo-title { - font-size: 1.125rem; - font-weight: 700; - letter-spacing: 0.5px; - color: rgb(var(--v-theme-on-surface)); - white-space: nowrap; - transition: opacity 0.15s ease; - } - - .nav-collapse-btn { - flex-shrink: 0; - } - - // βββ Nav Items List βββ - .nav-items { - list-style: none; - padding: 0; - margin: 0; - overflow-y: auto; - overflow-x: hidden; - flex-grow: 1; - padding-block: 4px; - padding-inline: 12px; - } - - // βββ Nav Link βββ - .nav-link { - margin-block: 2px; - - .nav-link-btn { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - border-radius: 6px; - text-decoration: none; - color: rgba(var(--v-theme-on-surface), 0.78); - transition: background-color 0.15s ease, color 0.15s ease; - white-space: nowrap; - overflow: hidden; - } - - .nav-item-icon { - flex-shrink: 0; - } - - .nav-item-title { - font-size: 0.9375rem; - line-height: 1.4; - flex-grow: 1; - overflow: hidden; - text-overflow: ellipsis; - } - - .nav-item-badge { - font-size: 0.75rem; - padding: 2px 6px; - border-radius: 4px; - background-color: rgb(var(--v-theme-error)); - color: rgb(var(--v-theme-on-error)); - line-height: 1; - flex-shrink: 0; - } - - &:not(.disabled) .nav-link-btn:hover { - background-color: rgba(var(--v-theme-on-surface), 0.06); - } - - &.active .nav-link-btn { - background: linear-gradient(270deg, rgb(var(--v-theme-primary)), rgba(var(--v-theme-primary), 0.7)); - color: rgb(var(--v-theme-on-primary)); - box-shadow: 0 2px 6px 0 rgba(var(--v-theme-primary), 0.4); - - .nav-item-icon { - color: inherit; - } - } - - &.disabled .nav-link-btn { - opacity: 0.4; - pointer-events: none; - } - } - - // βββ Nav Group βββ - .nav-group { - margin-block: 2px; - - .nav-group-label { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - border-radius: 6px; - cursor: pointer; - color: rgba(var(--v-theme-on-surface), 0.78); - transition: background-color 0.15s ease; - white-space: nowrap; - overflow: hidden; - user-select: none; - } - - .nav-group-label:hover { - background-color: rgba(var(--v-theme-on-surface), 0.06); - } - - &.active > .nav-group-label { - color: rgb(var(--v-theme-primary)); - } - - .nav-group-arrow { - margin-inline-start: auto; - transition: transform 0.25s ease-in-out; - flex-shrink: 0; - } - - &.open > .nav-group-label .nav-group-arrow { - transform: rotate(90deg); - } - - .nav-group-children { - list-style: none; - padding: 0; - margin: 0; - padding-inline-start: 12px; - } - - &.disabled > .nav-group-label { - opacity: 0.4; - pointer-events: none; - } - } - - // βββ Section Title βββ - .nav-section-title { - margin-block: 12px 4px; - padding-inline: 12px; - - .nav-section-title-text { - font-size: 0.6875rem; - font-weight: 600; - letter-spacing: 1px; - text-transform: uppercase; - color: rgba(var(--v-theme-on-surface), 0.38); - white-space: nowrap; - overflow: hidden; - } - - .nav-section-title-icon { - color: rgba(var(--v-theme-on-surface), 0.38); - margin-inline: auto; - } - - &:first-child { - margin-block-start: 0; - } - } -} - -// βββ Collapsed / Mini Mode βββ -.layout-vertical-nav-collapsed .layout-vertical-nav:not(:hover) { - inline-size: layout-variables.$layout-vertical-nav-collapsed-width; -} - -.layout-vertical-nav-collapsed .layout-vertical-nav:hover { - box-shadow: 0 4px 25px 0 rgba(0, 0, 0, 0.25); -} - -// βββ Content Wrapper βββ -.layout-content-wrapper { - display: flex; - flex-direction: column; - flex-grow: 1; - min-block-size: 100vh; - padding-inline-start: layout-variables.$layout-vertical-nav-width; - transition: padding-inline-start 0.25s ease-in-out; -} - -.layout-vertical-nav-collapsed .layout-content-wrapper { - padding-inline-start: layout-variables.$layout-vertical-nav-collapsed-width; -} - -// βββ Navbar βββ -.layout-navbar { - position: sticky; - inset-block-start: 0; - z-index: layout-variables.$layout-vertical-nav-layout-navbar-z-index; - background-color: rgb(var(--v-theme-surface)); - border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity)); - min-block-size: layout-variables.$layout-vertical-nav-navbar-height; - - .navbar-content { - block-size: 100%; - } -} - -// βββ Page Content βββ -.layout-page-content { - flex-grow: 1; - padding: 24px; -} - -// βββ Footer βββ -.layout-footer { - display: flex; - align-items: center; - justify-content: center; - min-block-size: layout-variables.$layout-vertical-nav-footer-height; - padding-inline: 24px; -} - -// βββ Overlay βββ -.layout-overlay { - position: fixed; - inset: 0; - z-index: layout-variables.$layout-overlay-z-index; - background-color: rgba(0, 0, 0, 0.5); - opacity: 0; - pointer-events: none; - transition: opacity 0.25s ease-in-out; - - &.visible { - opacity: 1; - pointer-events: auto; - } -} - -// βββ Responsive (Mobile Overlay) βββ -@media (max-width: 1279.98px) { - .layout-vertical-nav { - position: fixed; - transform: translateX(-100%); - - &.visible { - transform: translateX(0); - } - } - - .layout-content-wrapper { - padding-inline-start: 0 !important; - } - - .layout-vertical-nav-collapsed .layout-content-wrapper { - padding-inline-start: 0 !important; - } -} - -// βββ Transition for nav group expand/collapse βββ -.vertical-nav-group-enter-active, -.vertical-nav-group-leave-active { - overflow: hidden; - transition: max-height 0.3s ease-in-out, opacity 0.25s ease-in-out; -} - -.vertical-nav-group-enter-from, -.vertical-nav-group-leave-to { - max-height: 0; - opacity: 0; -} - -.vertical-nav-group-enter-to, -.vertical-nav-group-leave-from { - max-height: 500px; - opacity: 1; -} diff --git a/website/resources/ts/Components/AppSidebar.vue b/website/resources/ts/Components/AppSidebar.vue new file mode 100644 index 0000000..86d8d05 --- /dev/null +++ b/website/resources/ts/Components/AppSidebar.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/website/resources/ts/Components/AppTopNavbar.vue b/website/resources/ts/Components/AppTopNavbar.vue new file mode 100644 index 0000000..355ae43 --- /dev/null +++ b/website/resources/ts/Components/AppTopNavbar.vue @@ -0,0 +1,54 @@ + + + + + + + + + + + + + Search... + + βK + + + + + + + + + + + diff --git a/website/resources/ts/Components/Breadcrumbs.vue b/website/resources/ts/Components/Breadcrumbs.vue new file mode 100644 index 0000000..a2aba30 --- /dev/null +++ b/website/resources/ts/Components/Breadcrumbs.vue @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/website/resources/ts/Components/CommandPalette.vue b/website/resources/ts/Components/CommandPalette.vue new file mode 100644 index 0000000..0c9e223 --- /dev/null +++ b/website/resources/ts/Components/CommandPalette.vue @@ -0,0 +1,137 @@ + + + + + + + + + + ESC + + + + + + + + + + + {{ item.title }} + + + {{ item.section }} + + + + + + + No results found + + + + + + diff --git a/website/resources/ts/Components/EmptyState.vue b/website/resources/ts/Components/EmptyState.vue new file mode 100644 index 0000000..7b42618 --- /dev/null +++ b/website/resources/ts/Components/EmptyState.vue @@ -0,0 +1,38 @@ + + + + + + + + {{ title }} + + {{ description }} + + + {{ actionLabel }} + + + diff --git a/website/resources/ts/Components/NotificationPanel.vue b/website/resources/ts/Components/NotificationPanel.vue new file mode 100644 index 0000000..e20d346 --- /dev/null +++ b/website/resources/ts/Components/NotificationPanel.vue @@ -0,0 +1,141 @@ + + + + + + Notifications + + + Mark all read + + + + + + + + + + + + + + + + + + {{ notification.message }} + + + {{ notification.created_at }} + + + + + + + No notifications + + + diff --git a/website/resources/ts/Components/SkeletonLoader.vue b/website/resources/ts/Components/SkeletonLoader.vue new file mode 100644 index 0000000..ec34b5b --- /dev/null +++ b/website/resources/ts/Components/SkeletonLoader.vue @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/resources/ts/Components/ToastStack.vue b/website/resources/ts/Components/ToastStack.vue new file mode 100644 index 0000000..256f527 --- /dev/null +++ b/website/resources/ts/Components/ToastStack.vue @@ -0,0 +1,76 @@ + + + + + + + + + + + {{ toast.message }} + + + + + + + diff --git a/website/resources/ts/Layouts/AccountLayout.vue b/website/resources/ts/Layouts/AccountLayout.vue index 9e0c552..7fc1fea 100644 --- a/website/resources/ts/Layouts/AccountLayout.vue +++ b/website/resources/ts/Layouts/AccountLayout.vue @@ -1,11 +1,13 @@ - - - - - + + - - {{ user.name }} - - - - - - Log out - - - - - - - - - - Impersonation Active - + + + + + + + {{ user.name }} + + - + - Stop Impersonating + Log out - - - You are viewing the account as {{ user?.name }}. All actions will be attributed to this user. - - + - - - + + + + + + + Impersonation Active + + + + + Stop Impersonating + + + + + You are viewing the account as {{ user?.name }}. All actions will be attributed to this user. + + + + + + + + + + + + + + + + + diff --git a/website/resources/ts/Layouts/AdminLayout.vue b/website/resources/ts/Layouts/AdminLayout.vue index 48bb01c..5a2b5bf 100644 --- a/website/resources/ts/Layouts/AdminLayout.vue +++ b/website/resources/ts/Layouts/AdminLayout.vue @@ -1,11 +1,13 @@ - - - - Admin - + + - - - + - - - Customer View - - + + Admin + - - + + + + Customer View + + - - {{ user.name }} - + + + + - - - - Log out - - - + + {{ user.name }} + - - - + + + + Log out + + + + + + + + + + + + + + + + + + + + diff --git a/website/resources/ts/Layouts/AuthLayout.vue b/website/resources/ts/Layouts/AuthLayout.vue index 43287e3..402159a 100644 --- a/website/resources/ts/Layouts/AuthLayout.vue +++ b/website/resources/ts/Layouts/AuthLayout.vue @@ -1,7 +1,6 @@ - + - + - - - - - - - - - Deploy VPS, Dedicated Servers, Web Hosting, and Game Servers in minutes. - Enterprise-grade infrastructure made simple. - + + + + + + - - - 99.99% - Uptime - - - 50+ - Locations - - - 24/7 - Support - + + + + + + + + Deploy VPS, Dedicated Servers, Web Hosting, and Game Servers in minutes. + Enterprise-grade infrastructure made simple. + + + + + 99.99% + Uptime + + + 50+ + Locations + + + 24/7 + Support @@ -74,16 +61,8 @@ const isDark = computed(() => theme.global.current.value.dark) - - + + @@ -91,8 +70,35 @@ const isDark = computed(() => theme.global.current.value.dark) - diff --git a/website/resources/ts/Layouts/MarketingLayout.vue b/website/resources/ts/Layouts/MarketingLayout.vue index 3f13030..f68f4de 100644 --- a/website/resources/ts/Layouts/MarketingLayout.vue +++ b/website/resources/ts/Layouts/MarketingLayout.vue @@ -8,7 +8,6 @@ import logoWhite from '@images/ezscale_logo_white.png' const theme = useTheme() const isDark = computed(() => theme.global.current.value.dark) - const isScrolled = ref(false) function handleScroll(): void { @@ -25,20 +24,14 @@ onUnmounted(() => { }) const currentPath = computed(() => { - if (typeof window !== 'undefined') { - return window.location.pathname - } + if (typeof window !== 'undefined') return window.location.pathname return '/' }) -const newsletterForm = useForm({ - email: '', -}) - +const newsletterForm = useForm({ email: '' }) const newsletterSuccess = ref(false) function subscribeNewsletter(): void { - // For now, just show success state (no backend endpoint yet) if (newsletterForm.email) { newsletterSuccess.value = true setTimeout(() => { @@ -67,7 +60,6 @@ const footerLinks = { { title: 'About', href: '/about' }, { title: 'Pricing', href: '/pricing' }, { title: 'Contact', href: '/contact' }, - { title: 'Blog', href: '/blog' }, ], support: [ { title: 'Help Center', href: 'https://ezscale.support' }, @@ -84,32 +76,36 @@ const footerLinks = { const socialLinks = [ { title: 'twitter', icon: 'tabler-brand-twitter-filled', href: '#' }, - { title: 'facebook', icon: 'tabler-brand-facebook-filled', href: '#' }, - { title: 'github', icon: 'tabler-brand-github-filled', href: '#' }, { title: 'discord', icon: 'tabler-brand-discord-filled', href: '#' }, + { title: 'github', icon: 'tabler-brand-github-filled', href: '#' }, ] + +const mobileMenuOpen = ref(false) + - + + @@ -118,7 +114,6 @@ const socialLinks = [ - - - - Login - + + Login - - - Sign Up - + + Sign Up + + + + + + + + + + + + + + + {{ child.title }} + + + + {{ item.title }} + + + + + Login + + + Sign Up + + + + - -
+ {{ description }} +
- Deploy VPS, Dedicated Servers, Web Hosting, and Game Servers in minutes. - Enterprise-grade infrastructure made simple. -
+ Deploy VPS, Dedicated Servers, Web Hosting, and Game Servers in minutes. + Enterprise-grade infrastructure made simple. +