added htmx swapping and url history features
This commit is contained in:
parent
7b9a760e67
commit
f97b31093c
7 changed files with 184 additions and 36 deletions
12
web/dashboard.templ
Normal file
12
web/dashboard.templ
Normal file
|
@ -0,0 +1,12 @@
|
|||
package web
|
||||
|
||||
templ dashboard() {
|
||||
<title>Home</title>
|
||||
<h1>Hello World!</h1>
|
||||
<button hx-get="/hello" hx-trigger="click" hx-target="#hello" hx-swap="outerHtml">Hello you!</button>
|
||||
|
||||
<div id="hello">
|
||||
|
||||
</div>
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package web
|
||||
|
||||
templ hello(name string) {
|
||||
<title>Hello</title>
|
||||
<div>Hello { name } </div>
|
||||
<h1>SUPRISE!!!</h1>
|
||||
}
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const TemplateDir = "./web/templates/"
|
||||
|
||||
type IndexData struct {
|
||||
Title string
|
||||
type TemplateState struct {
|
||||
InnerHtml template.HTML
|
||||
ActivePage string
|
||||
}
|
||||
|
||||
const TemplateDir = "./web/templates/"
|
||||
|
||||
func SetLogLevel(level zerolog.Level) {
|
||||
zerolog.SetGlobalLevel(level)
|
||||
}
|
||||
|
@ -29,7 +32,23 @@ func WebRouter() http.Handler {
|
|||
return r
|
||||
}
|
||||
|
||||
func getIndex(w http.ResponseWriter, req *http.Request) {
|
||||
//for name, values := range req.Header {
|
||||
// Loop over all values for the name.
|
||||
// for _, value := range values {
|
||||
// log.Debug().Msg(name + " " + value);
|
||||
// }
|
||||
// }
|
||||
|
||||
func renderFullPage(w http.ResponseWriter, c templ.Component, pageName string) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
// Render the provided templ component
|
||||
err := c.Render(context.Background(), &buf)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Fatal error reading hello template");
|
||||
}
|
||||
|
||||
// get the index template
|
||||
index, err := template.ParseFiles(TemplateDir + "index.html")
|
||||
if err != nil {
|
||||
log.Fatal().
|
||||
|
@ -37,11 +56,40 @@ func getIndex(w http.ResponseWriter, req *http.Request) {
|
|||
Msg("Fatal error reading index template")
|
||||
}
|
||||
|
||||
err = index.Execute(w, IndexData{Title: "thetitle"})
|
||||
// Inject the templ component html into the index template
|
||||
err = index.Execute(w,
|
||||
TemplateState{
|
||||
InnerHtml: template.HTML(buf.String()),
|
||||
ActivePage: pageName,
|
||||
});
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Fatal error reading hello template");
|
||||
}
|
||||
}
|
||||
|
||||
func getIndex(w http.ResponseWriter, req *http.Request) {
|
||||
component := dashboard();
|
||||
|
||||
_, ok := req.Header["Hx-Request"]
|
||||
if ok {
|
||||
err := component.Render(context.Background(), w);
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Couldn't render dashboard templ template");
|
||||
}
|
||||
} else {
|
||||
renderFullPage(w, component, "index");
|
||||
}
|
||||
}
|
||||
|
||||
func getHello(w http.ResponseWriter, req *http.Request) {
|
||||
log.Debug().Msg("Got index")
|
||||
component := hello("Nick")
|
||||
component.Render(context.Background(), w)
|
||||
_, ok := req.Header["Hx-Request"]
|
||||
if ok {
|
||||
err := component.Render(context.Background(), w);
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Couldn't render dashboard templ template");
|
||||
}
|
||||
}else {
|
||||
renderFullPage(w, component, "hello");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,42 @@
|
|||
header {
|
||||
background-color: $nav-bg;
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
nav {
|
||||
background-color: $nav-bg;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
li { display: inline-block; }
|
||||
|
||||
button.title {
|
||||
color: $green;
|
||||
li {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
button.active {
|
||||
a.active {
|
||||
pointer-events: none;
|
||||
background-color: $nav-active-bg;
|
||||
color: $nav-active-color;
|
||||
}
|
||||
button {
|
||||
a {
|
||||
transition: background-color $hl-trn-spd ease-in, color $hl-trn-spd ease-in;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
padding: 12px 0px;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
color: $nav-color;
|
||||
display: block;
|
||||
padding: 12px 24px;
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
@include button_link;
|
||||
}
|
||||
button:hover {
|
||||
a:hover {
|
||||
background-color: $nav-hover;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
@import 'catpuccin';
|
||||
|
||||
// highlight transition speed
|
||||
$hl-trn-spd: 0.2s;
|
||||
|
||||
$bg: $latte-base;
|
||||
$nav-bg: $latte-crust;
|
||||
$nav-color: $latte-text;
|
||||
|
@ -21,3 +24,31 @@ body.dark-mode {
|
|||
$nav-bg: $macchiato-crust;
|
||||
$green: $macchiato-green;
|
||||
}
|
||||
|
||||
div#below-header {
|
||||
display:flex;
|
||||
}
|
||||
|
||||
div#left-col {
|
||||
width: 15vw;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
div#main-body-content {
|
||||
width: 70vw;
|
||||
padding: 10px;
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s ease-out;
|
||||
}
|
||||
div#main-body-content.htmx-swapping {
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease-out;
|
||||
}
|
||||
div#main-body-content.htmx-added {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
div#right-col {
|
||||
width: 15vw;
|
||||
padding: 10px;
|
||||
}
|
||||
|
|
|
@ -3,4 +3,20 @@ function say_hello() {
|
|||
console.log("Hello World");
|
||||
}
|
||||
|
||||
export {say_hello};
|
||||
function register_nav_links() {
|
||||
var navAnchors = document.querySelectorAll("nav a");
|
||||
|
||||
navAnchors.forEach(function (a_el) {
|
||||
a_el.addEventListener("click", nav_a_click);
|
||||
});
|
||||
}
|
||||
|
||||
function nav_a_click(event) {
|
||||
var active_anchor = document.querySelector("nav a.active");
|
||||
active_anchor.classList.remove("active");
|
||||
|
||||
var clicked = event.target;
|
||||
clicked.classList.add("active");
|
||||
}
|
||||
|
||||
export {say_hello, register_nav_links};
|
||||
|
|
|
@ -5,30 +5,58 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/static/site.css">
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<title>{{.Title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
|
||||
</header>
|
||||
<div id="below-header">
|
||||
|
||||
<div id="left-col">
|
||||
<nav>
|
||||
<button class="title" href="/">Recount!</button>
|
||||
<ul>
|
||||
<li><button hx-boost="true" class="active" href="/home">Home!</button></li>
|
||||
<li><button href="/nohome">Not home!</button></li>
|
||||
<li>
|
||||
<a
|
||||
hx-get="/"
|
||||
hx-swap="innerHtml swap:0.2s settle:0.2s"
|
||||
hx-push-url="true"
|
||||
hx-boost="true"
|
||||
hx-target="#main-body-content"
|
||||
{{ if (eq .ActivePage "index") }}
|
||||
class="active"
|
||||
{{ end }}
|
||||
>
|
||||
Home!
|
||||
</a>
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
hx-get="/hello"
|
||||
hx-swap="innerHtml swap:0.2s settle:0.2s"
|
||||
hx-push-url="true"
|
||||
hx-boost="true"
|
||||
hx-target="#main-body-content"
|
||||
{{ if (eq .ActivePage "hello") }}
|
||||
class="active"
|
||||
{{ end }}
|
||||
>
|
||||
Not home!
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
</div>
|
||||
<div id="main-body-content">
|
||||
<h1>Hello World!</h1>
|
||||
<button hx-get="/hello" hx-trigger="click" hx-target="#hello" hx-swap="outerHtml">Hello you!</button>
|
||||
|
||||
<div id="hello">
|
||||
|
||||
{{.InnerHtml}}
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/static/index.js"></script>
|
||||
<script type="module">
|
||||
import {say_hello} from "/static/index.js";
|
||||
import {say_hello, register_nav_links} from "/static/index.js";
|
||||
say_hello();
|
||||
register_nav_links();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue