From c07da125bc5b0bb65f58c4edce912874e46f6ed8 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Fri, 15 May 2026 21:09:56 +0700 Subject: feat: subheader for blog pages with medley-related ones fix: inline shadow now sticks to scrolling feat: multitone backgrounds implementation refactor: convert color vars into oklch --- internal/router/handlers/api-v1-blog-search.go | 57 +++++++++----- internal/router/handlers/lang-blog-title.go | 2 + static/input.css | 68 ++++++++++------ views/layouts/general-page.html | 103 ++++++++++++++++++++++++- views/pages/blog-catalogue.html | 11 --- views/pages/blog-page.html | 49 ++++++++---- views/partials/catalogue-blog-cards.html | 14 +++- 7 files changed, 232 insertions(+), 72 deletions(-) diff --git a/internal/router/handlers/api-v1-blog-search.go b/internal/router/handlers/api-v1-blog-search.go index 38004a1..c48b40a 100644 --- a/internal/router/handlers/api-v1-blog-search.go +++ b/internal/router/handlers/api-v1-blog-search.go @@ -1,6 +1,7 @@ package handlers import ( + "cmp" "encoding/json" "fmt" "log/slog" @@ -51,6 +52,15 @@ func (r *BlogSearchHandler) RateLimiter() *fiber.Handler { func (r *BlogSearchHandler) Render(c *fiber.Ctx, supplements *router.Supplements, lang string, templateMap fiber.Map) (statusCode int, err error) { sort := c.Query("sort") tz := c.Query("tz") + medley := c.Query("medley") + referer := c.Get("Referer") + refererParts := strings.Split(referer, "/") + refererPage := "" + if len(refererParts) >= 1 { + refererPage = refererParts[len(refererParts)-1] + } + hideTags := c.QueryBool("hideTags", false) + hidePublishedTime := c.QueryBool("hidePublishedTime", false) loc, err := time.LoadLocation(tz) if err != nil { @@ -85,21 +95,26 @@ func (r *BlogSearchHandler) Render(c *fiber.Ctx, supplements *router.Supplements for _, page := range pages { for _, tag := range page.Metadata.Tags { if len(tags) == 0 || slices.Contains(tags, tag) { - pageMeta = append(pageMeta, fiber.Map{ - "Link": page.Link, - "ArticleLink": "/" + lang + "/blog/" + page.FileName, - "Title": page.Metadata.Title, - "PublishedTime": page.Metadata.PublishedTime.In(loc).Format("2006-01-02 15:04:05 -07:00"), - "ActionDate": page.Metadata.ActionDate, - "ShortDescription": page.Metadata.ShortDescription, - "Thumbnail": page.Metadata.Thumbnail, - "Tags": page.Metadata.Tags, - "LikeCount": supplements.ClientCache.GetLikeCount(page.FileName), - "Liked": supplements.ClientCache.GetLikeStatus(c.IP(), page.FileName), - "ViewCount": supplements.ClientCache.GetViewCount(page.FileName), - "Viewed": supplements.ClientCache.GetViewStatus(c.IP(), page.FileName), - }) - break + if medley == "" || medley == page.Metadata.Medley { + pageMeta = append(pageMeta, fiber.Map{ + "Link": page.Link, + "ArticleLink": "/" + lang + "/blog/" + page.FileName, + "Title": page.Metadata.Title, + "PublishedTime": page.Metadata.PublishedTime.In(loc).Format("2006-01-02 15:04:05 -07:00"), + "ActionDate": page.Metadata.ActionDate, + "ShortDescription": page.Metadata.ShortDescription, + "Thumbnail": page.Metadata.Thumbnail, + "Tags": page.Metadata.Tags, + "LikeCount": supplements.ClientCache.GetLikeCount(page.FileName), + "Liked": supplements.ClientCache.GetLikeStatus(c.IP(), page.FileName), + "ViewCount": supplements.ClientCache.GetViewCount(page.FileName), + "Viewed": supplements.ClientCache.GetViewStatus(c.IP(), page.FileName), + "Medley": page.Metadata.Medley, + "MedleyPart": page.Metadata.MedleyPart, + "ToHighlight": page.FileName == refererPage, + }) + break + } } } } @@ -107,13 +122,13 @@ func (r *BlogSearchHandler) Render(c *fiber.Ctx, supplements *router.Supplements slices.SortFunc(pageMeta, func(a, b fiber.Map) int { switch sort { case "titleAsc": - return strings.Compare(a["Title"].(string), b["Title"].(string)) + return cmp.Compare(a["Title"].(string), b["Title"].(string)) case "titleDesc": - return strings.Compare(b["Title"].(string), a["Title"].(string)) + return cmp.Compare(b["Title"].(string), a["Title"].(string)) case "actionDateAsc": - return strings.Compare(a["ActionDate"].(string), b["ActionDate"].(string)) + return cmp.Compare(a["ActionDate"].(string), b["ActionDate"].(string)) case "actionDateDesc": - return strings.Compare(b["ActionDate"].(string), a["ActionDate"].(string)) + return cmp.Compare(b["ActionDate"].(string), a["ActionDate"].(string)) case "publicationDateAsc": publishedTimeA, _ := time.Parse("2006-01-02 15:04:05 -07:00", a["PublishedTime"].(string)) publishedTimeB, _ := time.Parse("2006-01-02 15:04:05 -07:00", b["PublishedTime"].(string)) @@ -122,11 +137,15 @@ func (r *BlogSearchHandler) Render(c *fiber.Ctx, supplements *router.Supplements publishedTimeA, _ := time.Parse("2006-01-02 15:04:05 -07:00", a["PublishedTime"].(string)) publishedTimeB, _ := time.Parse("2006-01-02 15:04:05 -07:00", b["PublishedTime"].(string)) return publishedTimeB.Compare(publishedTimeA) + case "medley": + return cmp.Compare(a["MedleyPart"].(int), b["MedleyPart"].(int)) } return 0 }) templateMap["BlogPages"] = pageMeta + templateMap["HideTags"] = hideTags + templateMap["HidePublishedTime"] = hidePublishedTime return fiber.StatusOK, nil } diff --git a/internal/router/handlers/lang-blog-title.go b/internal/router/handlers/lang-blog-title.go index 49744c1..f7cd019 100644 --- a/internal/router/handlers/lang-blog-title.go +++ b/internal/router/handlers/lang-blog-title.go @@ -126,6 +126,8 @@ func (r *BlogPageHandler) RenderBody(c *fiber.Ctx, supplements *router.Supplemen templateMap["PublishedDate"] = metadata.PublishedTime.Format("2006-01-02 15:04:05 -07:00") templateMap["ActionDate"] = metadata.ActionDate templateMap["ShortDescription"] = metadata.ShortDescription + templateMap["Thumbnail"] = metadata.Thumbnail + templateMap["Medley"] = metadata.Medley go supplements.ClientCache.View(c.IP(), pathParts[2]) diff --git a/static/input.css b/static/input.css index e1ba37d..8b71614 100644 --- a/static/input.css +++ b/static/input.css @@ -104,12 +104,12 @@ body { [data-theme="olive"] { --color-accent-light: var(--color-lime-300); --color-accent-deep: var(--color-lime-600); - --color-main-dark-hard: #4b513a; - --color-main-dark-medium: #8a9d8a; - --color-main-dark-soft: #a5b8a5; - --color-main-light-soft: #ffffdd; + --color-main-dark-hard: oklch(42.269% 0.03716 119.926); + --color-main-dark-medium: oklch(67.552% 0.03493 145.278); + --color-main-dark-soft: oklch(76.256% 0.03392 145.352); + --color-main-light-soft: oklch(99.13% 0.04397 107.223); --color-main-light-medium: var(--color-main-light-soft); - --color-main-light-hard: #fffff0; + --color-main-light-hard: oklch(99.598% 0.01951 106.845); --color-main: var(--color-main-dark-hard); --color-main-hard: var(--color-main-dark-hard); --color-main-medium: var(--color-main-dark-medium); @@ -136,12 +136,12 @@ body { [data-theme="lettuce"] { --color-accent-light: var(--color-lime-300); --color-accent-deep: var(--color-lime-600); - --color-main-dark-hard: #384a0c; - --color-main-dark-medium: #617c1f; - --color-main-dark-soft: #9bb665; - --color-main-light-soft: #f5eee2; + --color-main-dark-hard: oklch(38.049% 0.087 124.935); + --color-main-dark-medium: oklch(54.648% 0.12144 124.626); + --color-main-dark-soft: oklch(73.722% 0.11138 124.213); + --color-main-light-soft: oklch(95.132% 0.01754 81.278); --color-main-light-medium: var(--color-main-light-soft); - --color-main-light-hard: #fff9ef; + --color-main-light-hard: oklch(98.403% 0.01457 80.636); --color-main: var(--color-main-dark-hard); --color-main-hard: var(--color-main-dark-hard); --color-main-medium: var(--color-main-dark-medium); @@ -173,9 +173,9 @@ body { --color-main-light-hard: var(--color-sky-100); --color-main-light-medium: var(--color-sky-200); --color-main-light-soft: var(--color-sky-300); - --color-main-dark-hard: #13131b; + --color-main-dark-hard: oklch(19.064% 0.01614 284.757); --color-main-dark-medium: var(--color-main-dark-hard); - --color-main-dark-soft: #222230; + --color-main-dark-soft: oklch(25.846% 0.02619 284.414); --color-main: var(--color-main-light-hard); --color-main-hard: var(--color-main-light-hard); --color-main-medium: var(--color-main-light-medium); @@ -239,12 +239,12 @@ body { [data-theme="ram"] { --color-accent-light: var(--color-orange-800); --color-accent-deep: var(--color-orange-300); - --color-main-light-hard: #fefad8; - --color-main-light-medium: #f6e4c5; - --color-main-light-soft: #e8d4b8; - --color-main-dark-hard: #413b34; - --color-main-dark-medium: #62584f; - --color-main-dark-soft: #6d6258; + --color-main-light-hard: oklch(97.95% 0.0443 101.66); + --color-main-light-medium: oklch(92.541% 0.04519 81.305); + --color-main-light-soft: oklch(87.909% 0.04338 76.287); + --color-main-dark-hard: oklch(35.615% 0.01442 71.558); + --color-main-dark-medium: oklch(46.724% 0.01927 64.275); + --color-main-dark-soft: oklch(50.352% 0.02092 64.558); --color-main: var(--color-main-light-hard); --color-main-hard: var(--color-main-light-hard); --color-main-medium: var(--color-main-light-medium); @@ -271,12 +271,12 @@ body { [data-theme="lilac"] { --color-accent-light: var(--color-indigo-300); --color-accent-deep: var(--color-indigo-800); - --color-main-dark-hard: #343b58; - --color-main-dark-medium: #414868; - --color-main-dark-soft: #6c6e75; - --color-main-light-hard: #e3e6ff; - --color-main-light-medium: #d1d6ff; - --color-main-light-soft: #c3caff; + --color-main-dark-hard: oklch(35.926% 0.05132 273.187); + --color-main-dark-medium: oklch(40.944% 0.05461 274.279); + --color-main-dark-soft: oklch(53.885% 0.01118 273.226); + --color-main-light-hard: oklch(93.022% 0.03408 280.254); + --color-main-light-medium: oklch(88.545% 0.05677 279.69); + --color-main-light-soft: oklch(85.154% 0.07433 278.817); --color-main: var(--color-main-dark-hard); --color-main-hard: var(--color-main-dark-hard); --color-main-medium: var(--color-main-dark-medium); @@ -348,6 +348,26 @@ form.crossable.htmx-request input { filter: grayscale(1); } +.multitone { + position: relative; + z-index: 1; +} + +.multitone::before { + filter: url(#multitone); + background-image: var(--multitone-bg); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -1; +} + .bg-interlocked-hexagons { background-image: var(--interlocked-hexagons-background); background-repeat: var(--interlocked-hexagons-background-repeat); diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html index 4230a57..2d125ae 100644 --- a/views/layouts/general-page.html +++ b/views/layouts/general-page.html @@ -109,6 +109,17 @@ + + + + + + + + + + + +{{- end }} +{{- end }} -- cgit v1.3.1+13 From 551295ecacebbb94019def022f70397f74c44775 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Sat, 16 May 2026 02:06:12 +0700 Subject: fix: font in like button on smartphone screens feat: some margin-left for medley title refactor: explicit highlight query for blog search api --- internal/router/handlers/api-v1-blog-search.go | 10 ++-------- internal/router/handlers/lang-blog-title.go | 8 +++++--- views/pages/blog-page.html | 4 ++-- views/partials/blog-page-like-button.html | 4 ++-- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/internal/router/handlers/api-v1-blog-search.go b/internal/router/handlers/api-v1-blog-search.go index c48b40a..b59f09a 100644 --- a/internal/router/handlers/api-v1-blog-search.go +++ b/internal/router/handlers/api-v1-blog-search.go @@ -8,7 +8,6 @@ import ( "net/url" "regexp" "slices" - "strings" "time" "github.com/SayaAndy/saya-today-web/internal/blog" @@ -53,12 +52,7 @@ func (r *BlogSearchHandler) Render(c *fiber.Ctx, supplements *router.Supplements sort := c.Query("sort") tz := c.Query("tz") medley := c.Query("medley") - referer := c.Get("Referer") - refererParts := strings.Split(referer, "/") - refererPage := "" - if len(refererParts) >= 1 { - refererPage = refererParts[len(refererParts)-1] - } + highlight := c.Query("highlight") hideTags := c.QueryBool("hideTags", false) hidePublishedTime := c.QueryBool("hidePublishedTime", false) @@ -111,7 +105,7 @@ func (r *BlogSearchHandler) Render(c *fiber.Ctx, supplements *router.Supplements "Viewed": supplements.ClientCache.GetViewStatus(c.IP(), page.FileName), "Medley": page.Metadata.Medley, "MedleyPart": page.Metadata.MedleyPart, - "ToHighlight": page.FileName == refererPage, + "ToHighlight": page.FileName == highlight, }) break } diff --git a/internal/router/handlers/lang-blog-title.go b/internal/router/handlers/lang-blog-title.go index f7cd019..eac317a 100644 --- a/internal/router/handlers/lang-blog-title.go +++ b/internal/router/handlers/lang-blog-title.go @@ -102,10 +102,11 @@ func (r *BlogPageHandler) RenderBody(c *fiber.Ctx, supplements *router.Supplemen if err != nil { return fiber.StatusBadRequest, fmt.Errorf("failed to get path from referer: %w", err) } + title := pathParts[2] - metadata, parsedMarkdown, err := readBlogPost(supplements.MarkdownRenderer, supplements.BlogClient, lang+"/"+pathParts[2]) + metadata, parsedMarkdown, err := readBlogPost(supplements.MarkdownRenderer, supplements.BlogClient, lang+"/"+title) if err != nil { - return fiber.StatusNotFound, fmt.Errorf("failed to find '%s' post: %w", pathParts[2], err) + return fiber.StatusNotFound, fmt.Errorf("failed to find '%s' post: %w", title, err) } geolocationParts := strings.Split(metadata.Geolocation, " ") @@ -122,6 +123,7 @@ func (r *BlogPageHandler) RenderBody(c *fiber.Ctx, supplements *router.Supplemen templateMap["MapLocationY"] = y templateMap["MapLocationAreaMeters"] = areaError templateMap["Title"] = metadata.Title + templateMap["Codename"] = title templateMap["ParsedMarkdown"] = template.HTML(parsedMarkdown) templateMap["PublishedDate"] = metadata.PublishedTime.Format("2006-01-02 15:04:05 -07:00") templateMap["ActionDate"] = metadata.ActionDate @@ -129,7 +131,7 @@ func (r *BlogPageHandler) RenderBody(c *fiber.Ctx, supplements *router.Supplemen templateMap["Thumbnail"] = metadata.Thumbnail templateMap["Medley"] = metadata.Medley - go supplements.ClientCache.View(c.IP(), pathParts[2]) + go supplements.ClientCache.View(c.IP(), title) return fiber.StatusOK, nil } diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html index dd716fb..2a1d5d4 100644 --- a/views/pages/blog-page.html +++ b/views/pages/blog-page.html @@ -23,11 +23,11 @@
{{- if .Medley }}
-

+

{{ .Medley }}


-
Loading...
diff --git a/views/partials/blog-page-like-button.html b/views/partials/blog-page-like-button.html index 54b2914..af668e6 100644 --- a/views/partials/blog-page-like-button.html +++ b/views/partials/blog-page-like-button.html @@ -12,7 +12,7 @@ -
{{ .LikedCount }}
+
{{ .LikedCount }}
{{ else }} @@ -23,6 +23,6 @@ -
{{ .LikedCount }}
+
{{ .LikedCount }}
{{ end }} -- cgit v1.3.1+13 From 44b72cbc80fb89788470bda75eeb9c0bb3dee2f5 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Sat, 16 May 2026 13:18:08 +0700 Subject: feat: all color themes now have light & dark variations depending on preference feat: color all leaflet elements depending on color theme & scheme feat: change font to m-plus for short description fix: theme wheel position on different dpi screens in global map --- static/input.css | 266 ++++++++++++++++++++++--------- views/layouts/general-page.html | 13 +- views/pages/global-map.html | 2 +- views/partials/catalogue-blog-cards.html | 2 +- 4 files changed, 202 insertions(+), 81 deletions(-) diff --git a/static/input.css b/static/input.css index 8b71614..8b18579 100644 --- a/static/input.css +++ b/static/input.css @@ -42,10 +42,6 @@ html { font-size: 12px; --crossed-out: url("data:image/svg+xml,"); --bg-paper: url(data:image/webp;base64,UklGRi4BAABXRUJQVlA4ICIBAABQCQCdASqAAIAAPm02lUmkIqIkIImIgA2JaW3rMFmGDAOKLAoJtP591ByFR74Tun2DP+Lygpfsz5FH7+cKgxi2Islfd03i5AJdXUfU0SDc8SXYAAD++hlzeYAJWQEF8ZdkJdlcA+5btZg0FMGaso8SHoBph0qAOQysElJ5C5SJFNoKIV1J550UyL7Y9Gh0/c/uzLnBmr8lvz7k1WeA81H4S5ViU/wBqa7aM1m8D9rDtrk8cSTqx+xWF6MS8UfZGSsks6CT/igtgv6syFN9uNA3LjnjiCJKYOvFcMkX+jB2578GWVo3nyLaM1QNPYCxn3TiUbnf7U0MdD2NsBpg1+Jd1wu6yW/U+goN+IQS6Nt4RMWltVcZHlxrneKJi0SobO0AAA==); - --split-left-background: unset; - --split-left-repeat: no-repeat; - --split-left-size: cover; - --split-left-position: left; --split-right-background: unset; --split-right-repeat: no-repeat; --split-right-size: cover; @@ -133,6 +129,22 @@ body { --squares-and-triangles-background-height-coef: 10; } +@media (prefers-color-scheme: dark) { + [data-theme="olive"] { + --color-accent-light: var(--color-lime-600); + --color-accent-deep: var(--color-lime-300); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-hard); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-light-hard); + } +} + [data-theme="lettuce"] { --color-accent-light: var(--color-lime-300); --color-accent-deep: var(--color-lime-600); @@ -167,66 +179,76 @@ body { --squares-and-triangles-background-height-coef: 10; } +@media (prefers-color-scheme: dark) { + [data-theme="lettuce"] { + --color-accent-light: var(--color-lime-600); + --color-accent-deep: var(--color-lime-300); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-hard); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-light-hard); + } +} + [data-theme="night"] { - --color-accent-light: var(--color-indigo-900); - --color-accent-deep: var(--color-indigo-500); - --color-main-light-hard: var(--color-sky-100); - --color-main-light-medium: var(--color-sky-200); - --color-main-light-soft: var(--color-sky-300); + --color-accent-light: var(--color-indigo-500); + --color-accent-deep: var(--color-indigo-800); + --color-main-light-hard: var(--color-indigo-300); + --color-main-light-medium: var(--color-indigo-200); + --color-main-light-soft: var(--color-indigo-200); --color-main-dark-hard: oklch(19.064% 0.01614 284.757); --color-main-dark-medium: var(--color-main-dark-hard); --color-main-dark-soft: oklch(25.846% 0.02619 284.414); - --color-main: var(--color-main-light-hard); - --color-main-hard: var(--color-main-light-hard); - --color-main-medium: var(--color-main-light-medium); - --color-main-soft: var(--color-main-light-soft); - --color-background: var(--color-main-dark-soft); - --color-background-dark: var(--color-main-dark-hard); - --color-background-medium: var(--color-main-dark-medium); - --color-background-light: var(--color-main-dark-soft); + --color-main: var(--color-main-dark-hard); + --color-main-hard: var(--color-main-dark-hard); + --color-main-medium: var(--color-main-dark-medium); + --color-main-soft: var(--color-main-dark-soft); + --color-background: var(--color-main-light-soft); + --color-background-dark: var(--color-main-light-hard); + --color-background-medium: var(--color-main-light-medium); + --color-background-light: var(--color-main-light-soft); --color-sidebar-text: var(--color-main-hard); - --color-sidebar-stroke: var(--color-main-light-soft); + --color-sidebar-stroke: var(--color-main-dark-soft); --color-secondary: var(--color-main-soft); --color-leaflet-text: var(--color-background-dark); --color-leaflet-link: var(--color-background-dark); --color-leaflet-link-hover: var(--color-background-light); --interlocked-hexagons-background: - radial-gradient( - 33.5% 25% at 100% 82%, - rgba(190, 227, 248, 0.2) 0%, - rgba(197, 179, 246, 0.13) 33.33%, - rgba(255, 0, 0, 0) 100% - ), - radial-gradient( - 54% 25% at 55% 100%, - rgba(190, 227, 248, 0.2) 0%, - rgba(197, 179, 246, 0.13) 33.33%, - rgba(255, 0, 0, 0) 100% - ), - radial-gradient( - 37% 19.5% at 20% 100%, - rgba(176, 220, 248, 0.3) 0%, - rgba(197, 172, 247, 0.2) 33.33%, - rgba(255, 0, 0, 0) 100% + linear-gradient( + 180deg, + #4c51bf 0%, + rgba(89, 108, 214, 0.75) 12%, + rgba(107, 136, 231, 0.5) 24%, + rgba(163, 191, 250, 0) 48% ), radial-gradient( - 63% 34.5% at 66% 77%, - rgba(190, 227, 248, 0.15) 0%, - rgba(197, 179, 246, 0.1) 33.33%, - rgba(255, 0, 0, 0) 100% + 100% 37.5% at 50% 100%, + #f687b3 0%, + rgba(245, 151, 227, 0.75) 25%, + rgba(217, 182, 245, 0.5) 50%, + rgba(190, 227, 248, 0) 100% + ), + linear-gradient( + 360deg, + #f6ad55 0%, + rgba(247, 183, 98, 0.75) 14%, + rgba(249, 192, 112, 0.5) 28%, + rgba(251, 211, 141, 0) 56% ), linear-gradient( - 0deg, - #2f5883 0%, - #2f4e7a 4.75%, - #2e4472 9.5%, - #2a3065 19%, - #272e57 26.5%, - #242b4b 34%, - #1f2437 49%, - #1c2030 57.75%, - #1a1b29 66.5%, - #13131b 84% + 90deg, + #bee3f8 0%, + #b7e0f7 14.29%, + #b1ddf7 28.57%, + #aadaf6 42.86%, + #a4d7f6 57.14%, + #9dd3f5 71.43%, + #90cdf4 100% ); --interlocked-hexagons-background-repeat: no-repeat; --interlocked-hexagons-background-size: 100dvw 100dvh; @@ -236,25 +258,79 @@ body { --squares-and-triangles-background-height-coef: 5; } +@media (prefers-color-scheme: dark) { + [data-theme="night"] { + --color-accent-light: var(--color-indigo-900); + --color-accent-deep: var(--color-indigo-500); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-soft); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-light-soft); + --interlocked-hexagons-background: + radial-gradient( + 33.5% 25% at 100% 82%, + rgba(190, 227, 248, 0.2) 0%, + rgba(197, 179, 246, 0.13) 33.33%, + rgba(255, 0, 0, 0) 100% + ), + radial-gradient( + 54% 25% at 55% 100%, + rgba(190, 227, 248, 0.2) 0%, + rgba(197, 179, 246, 0.13) 33.33%, + rgba(255, 0, 0, 0) 100% + ), + radial-gradient( + 37% 19.5% at 20% 100%, + rgba(176, 220, 248, 0.3) 0%, + rgba(197, 172, 247, 0.2) 33.33%, + rgba(255, 0, 0, 0) 100% + ), + radial-gradient( + 63% 34.5% at 66% 77%, + rgba(190, 227, 248, 0.15) 0%, + rgba(197, 179, 246, 0.1) 33.33%, + rgba(255, 0, 0, 0) 100% + ), + linear-gradient( + 0deg, + #2f5883 0%, + #2f4e7a 4.75%, + #2e4472 9.5%, + #2a3065 19%, + #272e57 26.5%, + #242b4b 34%, + #1f2437 49%, + #1c2030 57.75%, + #1a1b29 66.5%, + #13131b 84% + ); + } +} + [data-theme="ram"] { - --color-accent-light: var(--color-orange-800); - --color-accent-deep: var(--color-orange-300); + --color-accent-light: var(--color-orange-300); + --color-accent-deep: var(--color-orange-800); --color-main-light-hard: oklch(97.95% 0.0443 101.66); --color-main-light-medium: oklch(92.541% 0.04519 81.305); --color-main-light-soft: oklch(87.909% 0.04338 76.287); --color-main-dark-hard: oklch(35.615% 0.01442 71.558); --color-main-dark-medium: oklch(46.724% 0.01927 64.275); --color-main-dark-soft: oklch(50.352% 0.02092 64.558); - --color-main: var(--color-main-light-hard); - --color-main-hard: var(--color-main-light-hard); - --color-main-medium: var(--color-main-light-medium); - --color-main-soft: var(--color-main-light-soft); - --color-background: var(--color-main-dark-soft); - --color-background-dark: var(--color-main-dark-hard); - --color-background-medium: var(--color-main-dark-medium); - --color-background-light: var(--color-main-dark-soft); + --color-main: var(--color-main-dark-hard); + --color-main-hard: var(--color-main-dark-hard); + --color-main-medium: var(--color-main-dark-medium); + --color-main-soft: var(--color-main-dark-soft); + --color-background: var(--color-main-light-hard); + --color-background-dark: var(--color-main-light-hard); + --color-background-medium: var(--color-main-light-medium); + --color-background-light: var(--color-main-light-soft); --color-sidebar-text: var(--color-main-hard); - --color-sidebar-stroke: var(--color-main-light-soft); + --color-sidebar-stroke: var(--color-main-dark-soft); --color-secondary: var(--color-main-soft); --color-leaflet-text: var(--color-background-dark); --color-leaflet-link: var(--color-background-dark); @@ -268,6 +344,22 @@ body { --squares-and-triangles-background-height-coef: 15; } +@media (prefers-color-scheme: dark) { + [data-theme="ram"] { + --color-accent-light: var(--color-orange-800); + --color-accent-deep: var(--color-orange-300); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-soft); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-light-soft); + } +} + [data-theme="lilac"] { --color-accent-light: var(--color-indigo-300); --color-accent-deep: var(--color-indigo-800); @@ -298,8 +390,24 @@ body { --squares-and-triangles-background-repeat: repeat; --squares-and-triangles-background-width-coef: 5; --squares-and-triangles-background-height-coef: 5; - --split-left-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-left.webp"); - --split-right-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-right.webp"); + --split-right-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-right-light.webp"); +} + +@media (prefers-color-scheme: dark) { + [data-theme="lilac"] { + --color-accent-light: var(--color-indigo-800); + --color-accent-deep: var(--color-indigo-300); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-hard); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-dark-hard); + --split-right-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-right-dark.webp"); + } } a, @@ -314,16 +422,16 @@ a:hover, } #map-container { - color: var(--color-leaflet-text) !important; + color: var(--color-main-hard) !important; } #map-container a { - color: var(--color-leaflet-link) !important; + color: var(--color-main-medium) !important; text-decoration: underline; } #map-container a:hover { - color: var(--color-leaflet-link-hover) !important; + color: var(--color-main-soft) !important; text-decoration: underline; } @@ -379,13 +487,6 @@ form.crossable.htmx-request input { background-repeat: var(--squares-and-triangles-background-repeat); } -.bg-split-left { - background-image: var(--split-left-background); - background-repeat: var(--split-left-repeat); - background-size: var(--split-left-size); - background-position: var(--split-left-position); -} - .bg-split-right { background-image: var(--split-right-background); background-repeat: var(--split-right-repeat); @@ -738,9 +839,22 @@ form.crossable.htmx-request input { height: 100% !important; } -body[data-theme~="night"] .leaflet-tile, -body[data-theme~="ram"] .leaflet-tile { - filter: invert(1) hue-rotate(190deg) contrast(1.1) brightness(1.2) !important; +.leaflet-container .leaflet-control-attribution { + background: color-mix(in oklch, var(--color-background-medium) 80%, transparent) !important; +} + +.leaflet-popup-content-wrapper, .leaflet-popup-tip { + background: var(--color-background-medium) !important; +} + +.leaflet-bar a { + background-color: var(--color-background-medium) !important; +} + +@media (prefers-color-scheme: dark) { + .leaflet-tile { + filter: invert(1) hue-rotate(190deg) contrast(1.1) brightness(1.2) !important; + } } .home-page-heart { diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html index 2d125ae..491c652 100644 --- a/views/layouts/general-page.html +++ b/views/layouts/general-page.html @@ -401,15 +401,22 @@ localStorage.setItem("theme", theme); document.body.setAttribute("data-theme", theme); switchThemeDecor(theme); - if (theme == "ram" || theme == "night") { + } + + const savedTheme = localStorage.getItem("theme") || "lilac"; + switchTheme(savedTheme); + + function switchColorScheme(isNightMode) { + if (isNightMode) { makeMultitoneOklch('multitone', 4, '--color-background-dark', '--color-accent-light', '--color-background-light'); } else { makeMultitoneOklch('multitone', 4, '--color-background-light', '--color-accent-light', '--color-background-dark'); } } - const savedTheme = localStorage.getItem("theme") || "lilac"; - switchTheme(savedTheme); + const mq = matchMedia('(prefers-color-scheme: dark)'); + switchColorScheme(mq.matches); + mq.addEventListener('change', (e) => switchColorScheme(e.matches)); diff --git a/views/pages/global-map.html b/views/pages/global-map.html index a6dc006..788eac9 100644 --- a/views/pages/global-map.html +++ b/views/pages/global-map.html @@ -229,7 +229,6 @@ const themeWheel = document.getElementById("theme-wheel"); const themeButton = document.getElementById("sidebar-theme-button"); const themeIcons = document.querySelectorAll(".theme-icon"); - const themeWheelRadius = convertRemToPixels(6); const THUMB_BASE = "{{ .ThumbnailBaseUrl }}"; themeIcons.forEach((icon) => { @@ -294,6 +293,7 @@ const buttonRect = themeButton.getBoundingClientRect(); const buttonCenterX = buttonRect.left + buttonRect.width / 2; const buttonCenterY = buttonRect.top + buttonRect.height / 2; + const themeWheelRadius = convertRemToPixels(6); const margin = 0; diff --git a/views/partials/catalogue-blog-cards.html b/views/partials/catalogue-blog-cards.html index 3eebd58..799955f 100644 --- a/views/partials/catalogue-blog-cards.html +++ b/views/partials/catalogue-blog-cards.html @@ -24,7 +24,7 @@

{{ .PublishedTime }}

{{- end }}
-

{{ .ShortDescription }}

+

{{ .ShortDescription }}

{{- if not $.HideTags }}

{{ $.L.TagsLabel }} {{ template "catalogue-blog-card-tags.html" . }}

{{- end }} -- cgit v1.3.1+13 From ed476a1f0d3f970f977626688ac316f8b251d3a0 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Sat, 16 May 2026 14:01:14 +0700 Subject: feat: highlight the blog page visited earlier in blog catalogue --- internal/router/handlers/lang-blog.go | 7 +++---- internal/router/router.go | 3 ++- views/layouts/general-page.html | 1 + views/pages/blog-catalogue.html | 2 +- views/pages/blog-page.html | 1 + views/partials/general-page-body.html | 1 + 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/internal/router/handlers/lang-blog.go b/internal/router/handlers/lang-blog.go index 79ec9f3..9f7947b 100644 --- a/internal/router/handlers/lang-blog.go +++ b/internal/router/handlers/lang-blog.go @@ -65,10 +65,8 @@ func (r *CatalogueHandler) AddMeta(c *fiber.Ctx, supplements *router.Supplements } func (r *CatalogueHandler) RenderBody(c *fiber.Ctx, supplements *router.Supplements, lang string, templateMap fiber.Map) (statusCode int, err error) { - querySort := c.Query("sort") - if querySort == "" { - querySort = "publicationDateDesc" - } + querySort := c.Query("sort", "publicationDateDesc") + previousBlogPage := c.Query("codename") encodedQuery := c.Request().URI().QueryString() decodedQuery, _ := url.QueryUnescape(string(encodedQuery)) @@ -88,6 +86,7 @@ func (r *CatalogueHandler) RenderBody(c *fiber.Ctx, supplements *router.Suppleme templateMap["QuerySort"] = querySort templateMap["QueryTags"] = strings.Join(queryTags, ",") templateMap["Title"] = supplements.Localization[lang].BlogSearch.Header + templateMap["PreviousBlogPage"] = previousBlogPage return fiber.StatusOK, nil } diff --git a/internal/router/router.go b/internal/router/router.go index 7f3511a..a1208e0 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -576,11 +576,12 @@ func (r *Router) generalPageSegment(c *fiber.Ctx, part string) error { cacheKey := "" trimmedPath := strings.Trim(path, "/") + requestQuery := string(c.Request().URI().QueryString()) switch route.ToCache() { case ByUrlOnly: cacheKey = fmt.Sprintf("%s.%s.%s", method, part, trimmedPath) case ByUrlAndQuery: - cacheKey = fmt.Sprintf("%s.%s.%s.%s", method, part, trimmedPath, queryString) + cacheKey = fmt.Sprintf("%s.%s.%s.%s.%s", method, part, trimmedPath, queryString, requestQuery) } if route.ToCache() != Disabled { diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html index 491c652..3392ff7 100644 --- a/views/layouts/general-page.html +++ b/views/layouts/general-page.html @@ -659,6 +659,7 @@ hx-trigger="popstate from:window" hx-target="#general-page-body" hx-swap="innerHTML" + hx-include="#general-page-body .htmx-exit-trigger" >