Add grid style for bookmarks widget #600 #611

Co-authored-by: Vishal kadam <107353260+vishalkadam47@users.noreply.github.com>
Co-authored-by: Tomás Gutiiérrez L. <tgutierrezlet@gmail.com>
pull/697/head^2
Svilen Markov 2025-08-11 06:00:47 +07:00
parent e0c15c7782
commit df9b886bd0
4 changed files with 70 additions and 18 deletions

@ -512,6 +512,8 @@ details[open] .summary::after {
.color-positive { color: var(--color-positive); }
.color-primary { color: var(--color-primary); }
.bg-highlight { background-color: var(--color-widget-background-highlight); }
.color-primary-if-not-visited:not(:visited) {
color: var(--color-primary);
}
@ -587,6 +589,7 @@ details[open] .summary::after {
.shrink { flex-shrink: 1; }
.shrink-0 { flex-shrink: 0; }
.min-width-0 { min-width: 0; }
.width-max-content { width: max-content; }
.max-width-100 { max-width: 100%; }
.block { display: block; }
.inline-block { display: inline-block; }
@ -622,6 +625,7 @@ details[open] .summary::after {
.gap-50 { gap: 5rem; }
.gap-55 { gap: 5.5rem; }
.margin-left-auto { margin-left: auto; }
.margin-inline-auto { margin-inline: auto; }
.margin-top-3 { margin-top: 0.3rem; }
.margin-top-5 { margin-top: 0.5rem; }
.margin-top-7 { margin-top: 0.7rem; }
@ -648,9 +652,11 @@ details[open] .summary::after {
.padding-widget { padding: var(--widget-content-padding); }
.padding-block-widget { padding-block: var(--widget-content-vertical-padding); }
.padding-inline-widget { padding-inline: var(--widget-content-horizontal-padding); }
.padding-inline-10 { padding-inline: 1rem; }
.pointer-events-none { pointer-events: none; }
.select-none { user-select: none; }
.padding-block-5 { padding-block: 0.5rem; }
.padding-10 { padding: 1rem; }
.scale-half { transform: scale(0.5); }
.list { --list-half-gap: 0rem; }
.list-gap-2 { --list-half-gap: 0.1rem; }

@ -22,3 +22,9 @@
padding: 0.5rem;
flex-shrink: 0;
}
.bookmarks-grid {
display: grid;
gap: 2.5rem 0;
grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}

@ -0,0 +1,21 @@
{{ template "widget-base.html" . }}
{{ define "widget-content" }}
<ul class="bookmarks-grid">
{{- range .Links }}
<li class="icon-parent text-center padding-inline-10">
<a href="{{ .URL | safeURL }}" class="block" {{ if .Target }}target="{{ .Target }}"{{ end }} rel="noreferrer">
{{- if ne "" .Icon.URL }}
<div class="padding-10 rounded bg-highlight width-max-content margin-inline-auto">
{{ .Icon.ElemWithClass "square-40" }}
</div>
{{- end }}
<p class="margin-top-7 block text-truncate color-highlight size-h4">{{ .Title }}</p>
</a>
{{- if .Description }}
<div class="margin-top-5 text-truncate-2-lines text-compact">{{ .Description }}</div>
{{- end }}
</li>
{{- end }}
</ul>
{{ end }}

@ -1,42 +1,52 @@
package glance
import (
"errors"
"html/template"
)
var bookmarksWidgetTemplate = mustParseTemplate("bookmarks.html", "widget-base.html")
var bookmarksGridWidgetTemplate = mustParseTemplate("bookmarks-grid.html", "widget-base.html")
type bookmarkLinks []struct {
Title string `yaml:"title"`
URL string `yaml:"url"`
Description string `yaml:"description"`
Icon customIconField `yaml:"icon"`
// we need a pointer to bool to know whether a value was provided,
// however there's no way to dereference a pointer in a template so
// {{ if not .SameTab }} would return true for any non-nil pointer
// which leaves us with no way of checking if the value is true or
// false, hence the duplicated fields below
SameTabRaw *bool `yaml:"same-tab"`
SameTab bool `yaml:"-"`
HideArrowRaw *bool `yaml:"hide-arrow"`
HideArrow bool `yaml:"-"`
Target string `yaml:"target"`
}
type bookmarksWidget struct {
widgetBase `yaml:",inline"`
cachedHTML template.HTML `yaml:"-"`
cachedHTML template.HTML `yaml:"-"`
Style string `yaml:"style"`
Links *bookmarkLinks `yaml:"-"`
Groups []struct {
Title string `yaml:"title"`
Color *hslColorField `yaml:"color"`
SameTab bool `yaml:"same-tab"`
HideArrow bool `yaml:"hide-arrow"`
Target string `yaml:"target"`
Links []struct {
Title string `yaml:"title"`
URL string `yaml:"url"`
Description string `yaml:"description"`
Icon customIconField `yaml:"icon"`
// we need a pointer to bool to know whether a value was provided,
// however there's no way to dereference a pointer in a template so
// {{ if not .SameTab }} would return true for any non-nil pointer
// which leaves us with no way of checking if the value is true or
// false, hence the duplicated fields below
SameTabRaw *bool `yaml:"same-tab"`
SameTab bool `yaml:"-"`
HideArrowRaw *bool `yaml:"hide-arrow"`
HideArrow bool `yaml:"-"`
Target string `yaml:"target"`
} `yaml:"links"`
Links bookmarkLinks `yaml:"links"`
} `yaml:"groups"`
}
func (widget *bookmarksWidget) initialize() error {
widget.withTitle("Bookmarks").withError(nil)
if len(widget.Groups) == 0 {
return errors.New("must have at least one group")
}
for g := range widget.Groups {
group := &widget.Groups[g]
for l := range group.Links {
@ -67,7 +77,16 @@ func (widget *bookmarksWidget) initialize() error {
}
}
widget.cachedHTML = widget.renderTemplate(widget, bookmarksWidgetTemplate)
if widget.Style == "grid" {
if len(widget.Groups) != 1 {
return errors.New("grid style can only be used with a single group")
}
widget.Links = &widget.Groups[0].Links
widget.cachedHTML = widget.renderTemplate(widget, bookmarksGridWidgetTemplate)
} else {
widget.cachedHTML = widget.renderTemplate(widget, bookmarksWidgetTemplate)
}
return nil
}