feat: mobile scale improvements, workflow

This commit is contained in:
Luka Dekanozishvili 2026-02-01 13:14:03 +01:00
parent 2f1a928aa3
commit f14604f219
8 changed files with 117 additions and 67 deletions

View file

@ -9,24 +9,19 @@
<div class="hidden sm:block"></div>
<aside>
<svg class="size-14" viewBox="-2 -2 139 157"><path style="fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:11px" d="M130.887 54.969 67.444 78.214 4 54.969l13.51-35.9L67.444 4l49.934 15.069zm-5.273 39.517-58.17 22.969-58.17-22.969h-.01m111.93 33.229-53.75 21.68-53.75-21.68m-.001 0L4.004 54.967m126.88 0-9.689 72.748M67.444 78.214v71.182"/></svg>
<p>
© 2025-{year} HexName
<br/>
Focus on what truly matters.
</p>
<p>© 2025-{year} HexName</p>
<p>Focus on what truly matters.</p>
</aside>
<nav>
<p class="footer-title">Services</p>
<!-- <div> -->
<a class="link link-hover" href="/register">Register</a>
<a class="link link-hover" href="/login">Log in</a>
<!-- </div> -->
<a class="link link-hover" href="/register">Register</a>
<a class="link link-hover" href="/login">Log in</a>
{#if auth.isAuthenticated}
<a class="link link-hover" href="/dashboard/register-domain">Register a domain</a>
{:else}
<a class="link link-hover" href="/#search-for-your-domain">Search for a domain</a>
{/if}
<a class="link link-hover" href="/#contact">Contact us!</a>
<a class="link link-hover" href="/#contact">Contact us</a>
</nav>
<nav>
<p class="footer-title">Pages</p>

View file

@ -1,44 +1,45 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { PUBLIC_BACKEND_API_HOST } from "$env/static/public";
import { auth, setUserLoggedOut } from "./auth.svelte";
// import { goto } from "$app/navigation";
// import { PUBLIC_BACKEND_API_HOST } from "$env/static/public";
// import { auth, setUserLoggedOut } from "./auth.svelte";
import { auth } from "./auth.svelte";
async function toggleMfa() {
try {
const res = await fetch(`${PUBLIC_BACKEND_API_HOST}/api/v1/user/update-mfa`, {
credentials: "include",
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ enable_mfa: auth.isMfaEnabled }),
});
// async function toggleMfa() {
// try {
// const res = await fetch(`${PUBLIC_BACKEND_API_HOST}/api/v1/user/update-mfa`, {
// credentials: "include",
// method: "PATCH",
// headers: { "Content-Type": "application/json" },
// body: JSON.stringify({ enable_mfa: auth.isMfaEnabled }),
// });
if (res.status === 401 || res.status === 500) {
setUserLoggedOut();
goto('/login');
throw new Error('Unauthorized');
} else if (res.status !== 204) {
let msg = await res.text();
throw new Error(`Failed updating MFA: ${msg}`);
}
} catch (err) {
// TODO: show error to user
console.error(err);
auth.isMfaEnabled = !auth.isMfaEnabled;
}
}
// if (res.status === 401 || res.status === 500) {
// setUserLoggedOut();
// goto('/login');
// throw new Error('Unauthorized');
// } else if (res.status !== 204) {
// let msg = await res.text();
// throw new Error(`Failed updating MFA: ${msg}`);
// }
// } catch (err) {
// // TODO: show error to user
// console.error(err);
// auth.isMfaEnabled = !auth.isMfaEnabled;
// }
// }
let { sideMenuOpen = $bindable() } = $props()
let innerWidth: number | null | undefined = $state();
let isMobile: boolean = $derived.by(() =>{
if (!innerWidth) return false;
return innerWidth < 768;
if (!innerWidth) return false;
return innerWidth < 768;
});
let isXs: boolean = $derived.by(() =>{
if (!innerWidth) return false;
return innerWidth < 480;
let isXxs: boolean = $derived.by(() =>{
if (!innerWidth) return false;
return innerWidth < 360;
});
</script>
@ -103,7 +104,7 @@
</div>
{:else}
<div class="xs:gap-4 flex">
{#if isXs}
{#if isXxs}
<a href="/register"><button style="box-shadow: 0 0 10px rgba(0,0,0,0.6)" class="btn btn-primary break-keep whitespace-nowrap rounded-lg">Register</button></a>
{:else}
<a href="/register"><button style="box-shadow: 0 0 10px rgba(0,0,0,0.6)" class="btn btn-primary break-keep whitespace-nowrap rounded-lg">Create an account</button></a>
@ -113,4 +114,4 @@
{/if}
</div>
</div>
<div class="divider bg-primary-content/20 fixed mt-[63px] z-41 h-0.25 w-screen"></div>
<div class="divider bg-primary-content/20 fixed mt-[63px] z-41 h-0.25 w-full"></div>

View file

@ -20,7 +20,7 @@
z-31
`}
>
<ul class="menu bg-white/6 h-[calc(100vh-65px)] z-9 w-60 block min-h-0 overflow-y-auto">
<ul class="menu bg-white/6 h-[calc(135vh-65px)] z-9 w-60 block min-h-0 overflow-y-auto">
{#if isDashboard}
<li class="bg-base-300 opacity-0 lg:opacity-100 h-screen fixed -z-1 w-60 top-0 left-0 m-0"></li>
{/if}
@ -62,5 +62,5 @@
<li class="bg-error rounded"><a class="text-error-content" href="/logout">Loading your domains failed. Please refresh the page or try logging out and back in</a></li>
{/if}
</ul>
<div class="divider divider-vertical bg-primary-content/35 fixed w-0.25 h-[calc(100vh-65px)] top-0 z-10 m-0 ml-60">&nbsp;</div>
<div class="divider divider-vertical bg-primary-content/35 fixed w-0.25 h-[calc(135vh-65px)] top-0 z-10 m-0 ml-60">&nbsp;</div>
</aside>

View file

@ -35,8 +35,16 @@
afterNavigate(() => {
sideMenuOpen = isDashboard && window.matchMedia('(min-width: 1024px)').matches;
})
let innerWidth: number | null | undefined = $state();
let isXs: boolean = $derived.by(() =>{
if (!innerWidth) return false;
return innerWidth < 480;
});
</script>
<svelte:window bind:innerWidth/>
<svelte:head>
<link rel="icon" href={favicon}/>
<link rel="apple-touch-icon" href={favicon}>
@ -48,13 +56,18 @@
</svelte:head>
<main class="bg-base-300">
<main class={
isXs ?
"bg-base-300 not-sm:overflow-auto not-sm:overflow-x-hidden [zoom:0.75]"
: "bg-base-300 not-sm:overflow-auto not-sm:overflow-x-hidden"
}
>
<MainNavbar bind:sideMenuOpen/>
<div class="flex flex-row min-h-0 flex-grow">
<div class={sideMenuOpen && isDashboard ? "w-0 lg:w-60" : "w-0"}>
<SideMenu bind:sideMenuOpen={sideMenuOpen} {isDashboard}/>
</div>
<div class="flex-grow mt-16 bg-base-300 not-sm:overflow-auto not-sm:overflow-x-hidden">
<div class="flex-grow mt-16 bg-base-300">
{@render children()}
<Footer/>
</div>

View file

@ -4,6 +4,7 @@
import { domains } from "$lib/domains.svelte";
import ErrorPopup from "$lib/ErrorPopup.svelte";
import Phone from "$lib/Phone.svelte";
import { auth } from "$lib/auth.svelte";
let errorMessage: string | null = $state(null);
let subdomain = $state("");
@ -81,7 +82,7 @@
<div class="flex flex-col items-center m-auto">
<div class="relative w-full overflow-x-clip">
<svg class="absolute left-1/2 -translate-x-1/2 w-[1624px] -translate-y-16" width="1440" height="676" viewBox="0 0 1440 676" fill="none">
<svg class="absolute left-1/2 -translate-x-1/2 w-406 -translate-y-16" width="1440" height="676" viewBox="0 0 1440 676" fill="none">
<rect x="-92" y="-948" width="1624" height="1624" rx="812" fill="url(#a)"></rect>
<defs>
<radialGradient id="a" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="rotate(90 428 292)scale(812)">
@ -92,20 +93,36 @@
</svg>
</div>
<section class="flex flex-col items-center -mt-38 z-1">
<a href="/register" class="flex items-center z-1 mt-48 gap-2 border border-2 border-font text-font/90 rounded-full px-4 py-2" style="opacity: 1; transform: none;">
<div class="size-2.5 bg-success rounded-full animate-pulse"></div>
<span>Start using today!</span>
</a>
{#if auth.isAuthenticated}
<a href="/dashboard" class="flex items-center z-1 mt-48 gap-2 border border-2 border-font text-font/90 rounded-full px-4 py-2" style="opacity: 1; transform: none;">
<div class="size-2.5 bg-success rounded-full animate-pulse"></div>
<span>Start using today!</span>
</a>
{:else}
<a href="/register" class="flex items-center z-1 mt-48 gap-2 border border-2 border-font text-font/90 rounded-full px-4 py-2" style="opacity: 1; transform: none;">
<div class="size-2.5 bg-success rounded-full animate-pulse"></div>
<span>Start using today!</span>
</a>
{/if}
<h1 class="text-center leading-[55px] lg:leading-[70px] z-1 text-5xl lg:text-6xl mx-2 mt-4 font-semibold max-w-3xl" style="opacity: 1; transform: none;">Let's manage the backbone of every website - DNS</h1>
<p class="text-center text-base max-w-lg mt-6 z-1 mx-2" style="opacity: 1; transform: none;">Our platform helps you manage DNS and DynDNS - so you can focus on what truly matters.</p>
<div class="flex items-center gap-4 mt-16 z-1" style="opacity: 1; transform: none;">
<a href="/register"><button style="box-shadow: 0 0 10px rgba(0,0,0,0.6)" class="btn btn-lg btn-primary rounded-lg max-w-50">
Get started
<svg viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="size-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"/>
</svg>
</button></a>
<button style="box-shadow: 0 0 10px rgba(0,0,0,0.6)" class="btn btn-lg btn-outline btn-secondary rounded-lg border-2 max-w-50"><a href="/#contact">Contact us</a></button>
{#if auth.isAuthenticated}
<a href="/dashboard"><button style="box-shadow: 0 0 10px rgba(0,0,0,0.6)" class="btn btn-lg btn-primary rounded-lg max-w-50">
Get started
<svg viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="size-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"/>
</svg>
</button></a>
{:else}
<a href="/register"><button style="box-shadow: 0 0 10px rgba(0,0,0,0.6)" class="btn btn-lg btn-primary rounded-lg max-w-50">
Get started
<svg viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="size-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"/>
</svg>
</button></a>
{/if}
<a href="/#contact"><button style="box-shadow: 0 0 10px rgba(0,0,0,0.6)" class="btn btn-lg btn-outline btn-secondary rounded-lg border-2 max-w-50">Contact us</button></a>
</div>
<div class="grid grid-cols-1 lg:grid-cols-[1fr_auto_1fr] overflow-none -mt-4 lg:my-8 justify-items-center items-center not-lg:max-w-120 max-w-full justify-items-stretch">
@ -275,11 +292,35 @@
&nbsp
{/if}
</p>
<a href="/register" class="flex max-w-full h-full items-center justify-center">
<!-- <a href="/register" class="flex max-w-full h-full items-center justify-center">
<button class="btn btn-primary w-full p-0" disabled={!available || loadingCheck}>
{loadingCheck ? "Checking..." : "Register"}
</button>
</a>
</a> -->
{#if !available || loadingCheck}
<div class="flex max-w-full h-full items-center justify-center">
<button class="btn btn-primary w-full p-0" disabled={!available || loadingCheck}>
{loadingCheck ? "Checking..." : "Register"}
</button>
</div>
{:else}
{#if auth.isAuthenticated}
<a href="/dashboard/register-domain" class="flex max-w-full h-full items-center justify-center">
<button class="btn btn-primary w-full p-0" disabled={!available || loadingCheck}>
{loadingCheck ? "Checking..." : "Register"}
</button>
</a>
{:else}
<a href="/register" class="flex max-w-full h-full items-center justify-center">
<button class="btn btn-primary w-full p-0" disabled={!available || loadingCheck}>
{loadingCheck ? "Checking..." : "Register"}
</button>
</a>
{/if}
{/if}
</div>
<div class="mt-3 h-12 flex items-center">

View file

@ -70,7 +70,7 @@
His most important goal while guiding the company is ensuring that useful products are made that people are going to use.
His leadership style emphasizes responsibility, clarity, and actually getting things done fast.
</p>
<button class="btn btn-primary not-sm:w-full"><a rel="nofollow" href="https://www.linkedin.com/in/lukadeka">Get in touch!</a></button>
<a rel="nofollow" href="https://www.linkedin.com/in/lukadeka"><button class="btn btn-primary not-sm:w-full">Get in touch!</button></a>
</div>
</div>
</div>
@ -93,7 +93,7 @@
With numerous years of experience building and leading projects, Mr. Dekanozishvili is an expert at backend as well as frontend development.
He specializes in scalability, maintainability, as well as ensuring a high-quality product.
</p>
<button class="btn btn-primary not-sm:w-full"><a rel="nofollow" href="https://www.linkedin.com/in/lukadeka">Get in touch!</a></button>
<a rel="nofollow" href="https://www.linkedin.com/in/lukadeka"><button class="btn btn-primary not-sm:w-full">Get in touch!</button></a>
</div>
</div>
</div>
@ -116,7 +116,7 @@
With extensive hands-on experience deploying, monitoring, and maintaining production systems, Luka single-handedly designed the entire deployment infrastructure.
He specializes in automating everything that can be automated, keeping systems reliable, simple, and rapidly fixing issues to ensure a high uptime.
</p>
<button class="btn btn-primary not-sm:w-full"><a rel="nofollow" href="https://www.linkedin.com/in/lukadeka">Get in touch!</a></button>
<a rel="nofollow" href="https://www.linkedin.com/in/lukadeka"><button class="btn btn-primary not-sm:w-full">Get in touch!</button></a>
</div>
</div>
</div>
@ -140,7 +140,7 @@
He excels in Search Engine Optimization, and helped build up the reputation of HexName from the ground up.
With years of experience, he also authors and redacts our blogs aimed for learning/understanding our technologies.
</p>
<button class="btn btn-primary not-sm:w-full"><a rel="nofollow" href="https://www.linkedin.com/in/lukadeka">Get in touch!</a></button>
<a rel="nofollow" href="https://www.linkedin.com/in/lukadeka"><button class="btn btn-primary not-sm:w-full">Get in touch!</button></a>
</div>
</div>
</div>
@ -164,7 +164,7 @@
He is responsible for layout decisions, color schemes, accessibility considerations, and ensuring the product is maximally intuitive, and dead simple.
He ensures this by paying attention to every detail, and weighing the pros and cons of every design choice beforehand.
</p>
<button class="btn btn-primary not-sm:w-full"><a rel="nofollow" href="https://www.linkedin.com/in/lukadeka">Get in touch!</a></button>
<a rel="nofollow" href="https://www.linkedin.com/in/lukadeka"><button class="btn btn-primary not-sm:w-full">Get in touch!</button></a>
</div>
</div>
</div>

View file

@ -57,7 +57,7 @@
</div>
<div class="flex flex-col items-center sm:flex-row w-full">
<p class="list-col-wrap sm:mr-4">{post.description}</p>
<button class="btn btn-primary not-sm:mt-4 w-full ml-auto sm:w-35"><a href="/blog/{post.slug}">Read more...</a></button>
<a href="/blog/{post.slug}"><button class="btn btn-primary not-sm:mt-4 w-full ml-auto sm:w-35">Read more...</button></a>
</div>
</li>
{/each}

View file

@ -39,7 +39,7 @@
}
@theme {
--breakpoint-xs: 390px;
--breakpoint-xs: 290px;
--animate-fadeInDown: fadeInDown 1s ease-in;
@keyframes fadeInDown {