2024-11-23 01:28:58 -05:00
|
|
|
package ui
|
2024-10-07 20:14:46 -04:00
|
|
|
|
2024-10-18 13:07:52 -04:00
|
|
|
// Variant is a component that has attributes
|
2024-10-07 20:14:46 -04:00
|
|
|
type Variant interface {
|
|
|
|
|
Attributes() templ.Attributes
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-18 13:07:52 -04:00
|
|
|
// ╭───────────────────────────────────────────────────────────╮
|
|
|
|
|
// │ General Layout Components │
|
|
|
|
|
// ╰───────────────────────────────────────────────────────────╯
|
2024-10-07 20:14:46 -04:00
|
|
|
|
2024-10-18 13:07:52 -04:00
|
|
|
// Columns is a component that renders a flex container with a gap of 3 and a max width of 100%
|
2024-10-07 20:14:46 -04:00
|
|
|
templ Columns() {
|
|
|
|
|
<div class="flex flex-col h-full w-full gap-3 md:gap-6 md:flex-row">
|
|
|
|
|
{ children... }
|
|
|
|
|
</div>
|
|
|
|
|
}
|
2024-10-07 20:13:38 -04:00
|
|
|
|
2024-10-18 13:07:52 -04:00
|
|
|
// Layout is a component that renders the general layout of the application
|
2024-09-29 14:40:36 -04:00
|
|
|
templ Layout(title string, remote bool) {
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
2024-10-09 14:16:53 -04:00
|
|
|
@Styles()
|
|
|
|
|
@Htmx()
|
|
|
|
|
@Alpine()
|
2024-11-23 01:28:58 -05:00
|
|
|
@WebAwesome()
|
2024-09-29 14:40:36 -04:00
|
|
|
<meta charset="UTF-8"/>
|
|
|
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
|
|
|
<title>{ title }</title>
|
|
|
|
|
<!-- Sets the status bar style to transparent -->
|
|
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
|
|
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
|
2024-10-01 19:36:15 -04:00
|
|
|
<link rel="icon" type="image/png" href="https://cdn.sonr.id/favicon.png"/>
|
2024-09-29 14:40:36 -04:00
|
|
|
</head>
|
|
|
|
|
<body class="flex items-center justify-center h-full bg-neutral-50 lg:p-24 md:16 p-4">
|
2024-10-15 14:31:19 -04:00
|
|
|
@Toaster() {
|
|
|
|
|
<main class="flex-row items-center justify-center mx-auto w-fit max-w-screen-sm gap-y-3">
|
|
|
|
|
{ children... }
|
|
|
|
|
</main>
|
|
|
|
|
}
|
2024-09-29 14:40:36 -04:00
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-18 13:07:52 -04:00
|
|
|
// LayoutNoBody is a component that renders the general layout of the application without the body tag
|
2024-09-29 14:40:36 -04:00
|
|
|
templ LayoutNoBody(title string, remote bool) {
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
2024-10-09 14:16:53 -04:00
|
|
|
@Styles()
|
|
|
|
|
@Htmx()
|
|
|
|
|
@Alpine()
|
2024-11-23 01:28:58 -05:00
|
|
|
@WebAwesome()
|
2024-09-29 14:40:36 -04:00
|
|
|
<meta charset="UTF-8"/>
|
|
|
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
|
|
|
<title>{ title }</title>
|
2024-10-01 19:36:15 -04:00
|
|
|
<link rel="icon" type="image/png" href="https://cdn.sonr.id/favicon.png"/>
|
2024-09-29 14:40:36 -04:00
|
|
|
<!-- Sets the status bar style to transparent -->
|
|
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
|
|
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
|
|
|
|
|
</head>
|
|
|
|
|
<main class="grow">
|
2024-09-29 21:42:46 -04:00
|
|
|
<body class="font-inter antialiased bg-white text-zinc-900 tracking-tight">
|
2024-10-15 14:31:19 -04:00
|
|
|
@Toaster() {
|
|
|
|
|
<div class="flex flex-col min-h-screen overflow-hidden supports-[overflow:clip]:overflow-clip">
|
|
|
|
|
{ children... }
|
|
|
|
|
</div>
|
|
|
|
|
}
|
2024-09-29 21:42:46 -04:00
|
|
|
</body>
|
2024-09-29 14:40:36 -04:00
|
|
|
</main>
|
|
|
|
|
</html>
|
|
|
|
|
}
|
2024-10-07 10:39:50 -04:00
|
|
|
|
2024-10-18 13:07:52 -04:00
|
|
|
// OpenModal is a component that renders a modal with a title and description
|
2024-10-07 13:59:29 -04:00
|
|
|
templ OpenModal(title, description string) {
|
2024-10-07 10:39:50 -04:00
|
|
|
<div
|
|
|
|
|
x-data="{ modalOpen: true }"
|
|
|
|
|
@keydown.escape="modalOpen=false"
|
|
|
|
|
:class="{ 'z-40': modalOpen }"
|
|
|
|
|
class="relative w-auto h-auto"
|
|
|
|
|
>
|
|
|
|
|
<template x-teleport="body">
|
|
|
|
|
<div x-show="modalOpen" class="fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen" x-cloak>
|
|
|
|
|
<div
|
|
|
|
|
x-show="modalOpen"
|
|
|
|
|
x-transition:enter="ease-out duration-300"
|
|
|
|
|
x-transition:enter-start="opacity-0"
|
|
|
|
|
x-transition:enter-end="opacity-100"
|
|
|
|
|
x-transition:leave="ease-in duration-300"
|
|
|
|
|
x-transition:leave-start="opacity-100"
|
|
|
|
|
x-transition:leave-end="opacity-0"
|
|
|
|
|
@click="modalOpen=false"
|
2024-10-07 13:59:29 -04:00
|
|
|
class="absolute inset-0 w-full h-full bg-zinc-900 bg-opacity-90 backdrop-blur-sm"
|
2024-10-07 10:39:50 -04:00
|
|
|
></div>
|
|
|
|
|
<div
|
|
|
|
|
x-show="modalOpen"
|
|
|
|
|
x-trap.inert.noscroll="modalOpen"
|
|
|
|
|
x-transition:enter="ease-out duration-300"
|
|
|
|
|
x-transition:enter-start="opacity-0 scale-90"
|
|
|
|
|
x-transition:enter-end="opacity-100 scale-100"
|
|
|
|
|
x-transition:leave="ease-in duration-200"
|
|
|
|
|
x-transition:leave-start="opacity-100 scale-100"
|
|
|
|
|
x-transition:leave-end="opacity-0 scale-90"
|
|
|
|
|
class="relative w-full py-6 bg-white shadow-md px-7 bg-opacity-90 drop-shadow-md backdrop-blur-sm sm:max-w-lg sm:rounded-lg"
|
|
|
|
|
>
|
|
|
|
|
<div class="flex items-center justify-between pb-3">
|
|
|
|
|
<h3 class="text-lg font-semibold">{ title }</h3>
|
|
|
|
|
<button @click="modalOpen=false" class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-zinc-600 rounded-full hover:text-zinc-800 hover:bg-zinc-50">
|
|
|
|
|
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path></svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="relative w-auto pb-8">
|
|
|
|
|
<p>{ description }</p>
|
|
|
|
|
</div>
|
|
|
|
|
{ children... }
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
2024-10-18 13:07:52 -04:00
|
|
|
|
2024-11-23 01:28:58 -05:00
|
|
|
templ FullScreenModal() {
|
|
|
|
|
<div
|
|
|
|
|
x-data="{ fullscreenModal: true }"
|
|
|
|
|
x-init="
|
|
|
|
|
$watch('fullscreenModal', function(value){
|
|
|
|
|
if(value === true){
|
|
|
|
|
document.body.classList.add('overflow-hidden');
|
|
|
|
|
}else{
|
|
|
|
|
document.body.classList.remove('overflow-hidden');
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
"
|
|
|
|
|
@keydown.escape="fullscreenModal=false"
|
|
|
|
|
>
|
|
|
|
|
<template x-teleport="body">
|
|
|
|
|
<div
|
|
|
|
|
x-show="fullscreenModal"
|
|
|
|
|
x-transition:enter="transition ease-out duration-150"
|
|
|
|
|
x-transition:enter-start="opacity-0"
|
|
|
|
|
x-transition:enter-end="opacity-100"
|
|
|
|
|
x-transition:leave="transition ease-in duration-150"
|
|
|
|
|
x-transition:leave-start="opacity-100"
|
|
|
|
|
x-transition:leave-end="opacity-0"
|
|
|
|
|
class="flex fixed inset-0 z-[99] w-screen h-screen bg-white"
|
|
|
|
|
>
|
|
|
|
|
<button @click="fullscreenModal=false" class="absolute top-0 right-0 z-30 flex items-center justify-center px-3 py-3 mt-5 mr-3 space-x-1 text-xs font-medium uppercase rounded-full text-zinc-500 hover:bg-zinc-200">
|
|
|
|
|
<svg class="w-8 h-8" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path></svg>
|
|
|
|
|
</button>
|
|
|
|
|
<div class="relative top-0 bottom-0 right-0 flex-shrink-0 hidden w-1/3 overflow-hidden bg-cover lg:block">
|
|
|
|
|
<a href="#_" class="absolute bottom-0 left-0 z-30 inline-flex items-end mb-4 ml-3 font-sans text-2xl font-extrabold text-left text-white no-underline bg-transparent cursor-pointer group focus:no-underline">
|
|
|
|
|
<svg class="w-auto h-4 text-white fill-current lg:h-5" viewBox="0 0 355 99" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M119.1 87V66.4h19.8c34.3 0 34.2-49.5 0-49.5-11 0-22 .1-33 .1v70h13.2zm19.8-32.7h-19.8V29.5h19.8c16.8 0 16.9 24.8 0 24.8zm32.6-30.5c0 9.5 14.4 9.5 14.4 0s-14.4-9.5-14.4 0zM184.8 87V37.5h-12.2V87h12.2zm22.8 0V61.8c0-7.5 5.1-13.8 12.6-13.8 7.8 0 11.9 5.7 11.9 13.2V87h12.2V61.1c0-15.5-9.3-24.2-20.9-24.2-6.2 0-11.2 2.5-16.2 7.4l-.8-6.7h-10.9V87h12.1zm72.1 1.3c7.5 0 16-2.6 21.2-8l-7.8-7.7c-2.8 2.9-8.7 4.6-13.2 4.6-8.6 0-13.9-4.4-14.7-10.5h38.5c1.9-20.3-8.4-30.5-24.9-30.5-16 0-26.2 10.8-26.2 25.8 0 15.8 10.1 26.3 27.1 26.3zM292 56.6h-26.6c1.8-6.4 7.2-9.6 13.8-9.6 7 0 12 3.2 12.8 9.6zm41.2 32.1c14.1 0 21.2-7.5 21.2-16.2 0-13.1-11.8-15.2-21.1-15.8-6.3-.4-9.2-2.2-9.2-5.4 0-3.1 3.2-4.9 9-4.9 4.7 0 8.7 1.1 12.2 4.4l6.8-8c-5.7-5-11.5-6.5-19.2-6.5-9 0-20.8 4-20.8 15.4 0 11.2 11.1 14.6 20.4 15.3 7 .4 9.8 1.8 9.8 5.2 0 3.6-4.3 6-8.9 5.9-5.5-.1-13.5-3-17-6.9l-6 8.7c7.2 7.5 15 8.8 22.8 8.8z" id="a"></path></defs><g fill="none" fill-rule="evenodd"><g fill="currentColor"><path d="M19.742 49h28.516L68 83H0l19.742-34z"></path><path d="M26 69h14v30H26V69zM4 50L33.127 0 63 50H4z"></path></g><g fill-rule="nonzero"><use fill="currentColor" xlink:href="#a"></use><use fill="currentColor" xlink:href="#a"></use></g></g></svg>
|
|
|
|
|
<span class="flex opacity-90 group-hover:scale-150 group-hover:opacity-100 items-center h-full group-hover:-rotate-6 ease-out duration-500 px-0.5 py-px ml-2 -translate-x-px text-[0.6rem] font-bold leading-none border-[2px] rounded border-white -translate-y-px">UI</span>
|
|
|
|
|
</a>
|
|
|
|
|
<div class="absolute inset-0 z-20 w-full h-full opacity-70 bg-gradient-to-t from-black"></div>
|
|
|
|
|
<img src="https://cdn.devdojo.com/images/may2023/pines-bg-1.png" class="z-10 object-cover w-full h-full"/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
|
|
|
|
{ children... }
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-18 13:07:52 -04:00
|
|
|
// Rows is a component that renders a flex container with a gap of 2 and a max width of 100%
|
|
|
|
|
templ Rows() {
|
|
|
|
|
<div class="flex flex-row w-full gap-2 md:gap-4">
|
|
|
|
|
{ children... }
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Spacer is a component that renders a <br/> tag
|
|
|
|
|
templ Spacer() {
|
|
|
|
|
<br/>
|
|
|
|
|
}
|
2024-11-23 01:28:58 -05:00
|
|
|
|
|
|
|
|
templ Separator(text string) {
|
|
|
|
|
<div class="relative py-6">
|
|
|
|
|
<div class="absolute inset-0 flex items-center"><span class="w-full border-t"></span></div>
|
|
|
|
|
<div class="relative flex justify-center text-xs uppercase">
|
|
|
|
|
<span class="px-2 bg-white text-neutral-500">{ text }</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
}
|