Explorar el Código

Add dynamic columns style for bookmarks, stocks & monitor sites

Svilen Markov hace 1 año
padre
commit
714e1b6d29

+ 13 - 1
docs/configuration.md

@@ -734,7 +734,11 @@ You can hover over the "ERROR" text to view more information.
 
 | Name | Type | Required |
 | ---- | ---- | -------- |
-| sites | array | yes |  |
+| sites | array | yes |
+| style | string | no |
+
+##### `style`
+To make the widget scale appropriately in a `full` size column, set the style to the experimental `dynamic-columns-experimental` option.
 
 ##### `sites`
 
@@ -908,10 +912,14 @@ Preview:
 | Name | Type | Required |
 | ---- | ---- | -------- |
 | groups | array | yes |
+| style | string | no |
 
 ##### `groups`
 An array of groups which can optionally have a title and a custom color.
 
+##### `style`
+To make the widget scale appropriately in a `full` size column, set the style to the experimental `dynamic-columns-experimental` option.
+
 ###### Properties for each group
 | Name | Type | Required | Default |
 | ---- | ---- | -------- | ------- |
@@ -997,6 +1005,7 @@ Preview:
 | ---- | ---- | -------- |
 | stocks | array | yes |
 | sort-by | string | no |
+| style | string | no |
 
 ##### `stocks`
 An array of stocks for which to display information about.
@@ -1004,6 +1013,9 @@ An array of stocks for which to display information about.
 ##### `sort-by`
 By default the stocks are displayed in the order they were defined. You can customize their ordering by setting the `sort-by` property to `absolute-change` for descending order based on the stock's absolute price change.
 
+##### `style`
+To make the widget scale appropriately in a `full` size column, set the style to the experimental `dynamic-columns-experimental` option.
+
 ###### Properties for each stock
 | Name | Type | Required |
 | ---- | ---- | -------- |

+ 41 - 0
internal/assets/static/main.css

@@ -333,6 +333,44 @@ body {
     padding: 0 var(--content-bounds-padding);
 }
 
+.dynamic-columns {
+    gap: calc(var(--widget-content-vertical-padding) / 2);
+    display: grid;
+    grid-template-columns: repeat(var(--columns-per-row), 1fr);
+    margin: calc(0px - var(--widget-content-vertical-padding) / 2) calc(0px - var(--widget-content-horizontal-padding) / 2);
+}
+
+.dynamic-columns > * {
+    padding: calc(var(--widget-content-vertical-padding) / 2) calc(var(--widget-content-horizontal-padding) / 1.5);
+    background-color: var(--color-background);
+    border-radius: var(--border-radius);
+}
+
+.dynamic-columns:has(> :nth-child(1)) { --columns-per-row: 1; }
+.dynamic-columns:has(> :nth-child(2)) { --columns-per-row: 2; }
+.dynamic-columns:has(> :nth-child(3)) { --columns-per-row: 3; }
+.dynamic-columns:has(> :nth-child(4)) { --columns-per-row: 4; }
+.dynamic-columns:has(> :nth-child(5)) { --columns-per-row: 5; }
+
+@container widget (max-width: 1500px) {
+    .dynamic-columns:has(> :nth-child(1)) { --columns-per-row: 1; }
+    .dynamic-columns:has(> :nth-child(2)) { --columns-per-row: 2; }
+    .dynamic-columns:has(> :nth-child(3)) { --columns-per-row: 3; }
+    .dynamic-columns:has(> :nth-child(4)) { --columns-per-row: 4; }
+}
+@container widget (max-width: 1250px) {
+    .dynamic-columns:has(> :nth-child(1)) { --columns-per-row: 1; }
+    .dynamic-columns:has(> :nth-child(2)) { --columns-per-row: 2; }
+    .dynamic-columns:has(> :nth-child(3)) { --columns-per-row: 3; }
+}
+@container widget (max-width: 850px) {
+    .dynamic-columns:has(> :nth-child(1)) { --columns-per-row: 1; }
+    .dynamic-columns:has(> :nth-child(2)) { --columns-per-row: 2; }
+}
+@container widget (max-width: 550px) {
+    .dynamic-columns:has(> :nth-child(1)) { --columns-per-row: 1; }
+}
+
 .cards-vertical {
     flex-direction: column;
 }
@@ -820,6 +858,7 @@ body {
 }
 
 .monitor-site-status-icon {
+    flex-shrink: 0;
     margin-left: auto;
     width: 2rem;
     height: 2rem;
@@ -1082,6 +1121,8 @@ body {
         --content-bounds-padding: 10px;
     }
 
+    .dynamic-columns:has(> :nth-child(1)) { --columns-per-row: 1; }
+
     .forum-post-list-item {
         flex-flow: row-reverse;
     }

+ 27 - 13
internal/assets/templates/bookmarks.html

@@ -1,23 +1,37 @@
 {{ template "widget-base.html" . }}
 
 {{ define "widget-content" }}
+{{ if ne .Style "dynamic-columns-experimental" }}
 <ul class="list list-gap-24 list-with-separator">
     {{ range .Groups }}
     <li class="bookmarks-group"{{ if .Color }} style="--bookmarks-group-color: {{ .Color.AsCSSValue }}"{{ end }}>
-        {{ if ne .Title "" }}<div class="bookmarks-group-title size-h3 margin-bottom-3">{{ .Title }}</div>{{ end }}
-        <ul class="list list-gap-2">
-        {{ range .Links }}
-            <li class="flex items-center gap-10">
-                {{ if ne "" .Icon }}
-                <div class="bookmarks-icon-container">
-                    <img class="bookmarks-icon{{ if .IsSimpleIcon }} simple-icon{{ end }}" src="{{ .Icon }}" alt="" loading="lazy">
-                </div>
-                {{ end }}
-                <a href="{{ .URL }}" class="bookmarks-link {{ if .HideArrow }}bookmarks-link-no-arrow {{ end }}color-highlight size-h4" {{ if not .SameTab }}target="_blank"{{ end }} rel="noreferrer">{{ .Title }}</a>
-            </li>
-        {{ end }}
-        </ul>
+        {{ template "group" . }}
     </li>
     {{ end }}
 </ul>
+{{ else }}
+<div class="dynamic-columns">
+    {{ range .Groups }}
+    <div class="bookmarks-group"{{ if .Color }} style="--bookmarks-group-color: {{ .Color.AsCSSValue }}"{{ end }}>
+        {{ template "group" . }}
+    </div>
+    {{ end }}
+</div>
+{{ end }}
+{{ end }}
+
+{{ define "group" }}
+{{ if ne .Title "" }}<div class="bookmarks-group-title size-h3 margin-bottom-3">{{ .Title }}</div>{{ end }}
+<ul class="list list-gap-2">
+{{ range .Links }}
+<li class="flex items-center gap-10">
+    {{ if ne "" .Icon }}
+    <div class="bookmarks-icon-container">
+        <img class="bookmarks-icon{{ if .IsSimpleIcon }} simple-icon{{ end }}" src="{{ .Icon }}" alt="" loading="lazy">
+    </div>
+    {{ end }}
+    <a href="{{ .URL }}" class="bookmarks-link {{ if .HideArrow }}bookmarks-link-no-arrow {{ end }}color-highlight size-h4" {{ if not .SameTab }}target="_blank"{{ end }} rel="noreferrer">{{ .Title }}</a>
+</li>
+{{ end }}
+</ul>
 {{ end }}

+ 43 - 29
internal/assets/templates/monitor.html

@@ -1,39 +1,53 @@
 {{ template "widget-base.html" . }}
 
 {{ define "widget-content" }}
+{{ if ne .Style "dynamic-columns-experimental" }}
 <ul class="list list-gap-20 list-with-separator">
     {{ range .Sites }}
     <li class="monitor-site flex items-center gap-15">
-        {{ if .IconUrl }}
-        <img class="monitor-site-icon" src="{{ .IconUrl }}" alt="" loading="lazy">
-        {{ end }}
-        <div>
-            <a class="size-h3 color-highlight" href="{{ .Url }}" {{ if not .SameTab }}target="_blank"{{ end }} rel="noreferrer">{{ .Title }}</a>
-            <ul class="list-horizontal-text">
-                {{ if not .Status.Error }}
-                <li>{{ .StatusText }}</li>
-                <li>{{ .Status.ResponseTime.Milliseconds | formatNumber }}ms</li>
-                {{ else if .Status.TimedOut }}
-                <li class="color-negative">Timed Out</li>
-                {{ else }}
-                <li class="color-negative" title="{{ .Status.Error }}">ERROR</li>
-                {{ end }}
-            </ul>
-        </div>
-        {{ if eq .StatusStyle "good" }}
-        <div class="monitor-site-status-icon">
-            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="var(--color-positive)">
-                <path fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z" clip-rule="evenodd" />
-            </svg>
-        </div>
-        {{ else }}
-        <div class="monitor-site-status-icon">
-            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="var(--color-negative)">
-                <path fill-rule="evenodd" d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003ZM12 8.25a.75.75 0 0 1 .75.75v3.75a.75.75 0 0 1-1.5 0V9a.75.75 0 0 1 .75-.75Zm0 8.25a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z" clip-rule="evenodd" />
-            </svg>
-        </div>
-        {{ end }}
+        {{ template "site" . }}
     </li>
     {{ end }}
 </ul>
+{{ else }}
+<ul class="dynamic-columns">
+    {{ range .Sites }}
+    <div class="flex items-center gap-15">
+        {{ template "site" . }}
+    </div>
+    {{ end }}
+</ul>
+{{ end }}
+{{ end }}
+
+{{ define "site" }}
+{{ if .IconUrl }}
+<img class="monitor-site-icon" src="{{ .IconUrl }}" alt="" loading="lazy">
+{{ end }}
+<div>
+    <a class="size-h3 color-highlight" href="{{ .Url }}" {{ if not .SameTab }}target="_blank"{{ end }} rel="noreferrer">{{ .Title }}</a>
+    <ul class="list-horizontal-text">
+        {{ if not .Status.Error }}
+        <li>{{ .StatusText }}</li>
+        <li>{{ .Status.ResponseTime.Milliseconds | formatNumber }}ms</li>
+        {{ else if .Status.TimedOut }}
+        <li class="color-negative">Timed Out</li>
+        {{ else }}
+        <li class="color-negative" title="{{ .Status.Error }}">ERROR</li>
+        {{ end }}
+    </ul>
+</div>
+{{ if eq .StatusStyle "good" }}
+<div class="monitor-site-status-icon">
+    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="var(--color-positive)">
+        <path fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z" clip-rule="evenodd" />
+    </svg>
+</div>
+{{ else }}
+<div class="monitor-site-status-icon">
+    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="var(--color-negative)">
+        <path fill-rule="evenodd" d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003ZM12 8.25a.75.75 0 0 1 .75.75v3.75a.75.75 0 0 1-1.5 0V9a.75.75 0 0 1 .75-.75Zm0 8.25a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z" clip-rule="evenodd" />
+    </svg>
+</div>
+{{ end }}
 {{ end }}

+ 29 - 15
internal/assets/templates/stocks.html

@@ -1,25 +1,39 @@
 {{ template "widget-base.html" . }}
 
 {{ define "widget-content" }}
+{{ if ne .Style "dynamic-columns-experimental" }}
 <ul class="list list-gap-20 list-with-separator">
     {{ range .Stocks }}
     <li class="flex items-center gap-15">
-        <div class="shrink min-width-0">
-            <a{{ if ne "" .SymbolLink }} href="{{ .SymbolLink }}" target="_blank" rel="noreferrer"{{ end }} class="color-highlight size-h3 block text-truncate">{{ .Symbol }}</a>
-            <div class="text-truncate">{{ .Name }}</div>
-        </div>
-
-        <a class="stock-chart" {{ if ne "" .ChartLink }} href="{{ .ChartLink }}" target="_blank" rel="noreferrer"{{ end }}>
-            <svg class="stock-chart shrink-0" viewBox="0 0 100 50">
-                <polyline fill="none" stroke="var(--color-text-subdue)" stroke-width="1.5px" points="{{ .SvgChartPoints }}" vector-effect="non-scaling-stroke"></polyline>
-            </svg>
-        </a>
-
-        <div class="stock-values shrink-0">
-            <div class="size-h3 text-right {{ if eq .PercentChange 0.0 }}{{ else if gt .PercentChange 0.0 }}color-positive{{ else }}color-negative{{ end }}">{{ printf "%+.2f" .PercentChange }}%</div>
-            <div class="text-right">{{ .Currency }}{{ .Price | formatPrice }}</div>
-        </div>
+        {{ template "stock" . }}
     </li>
     {{ end }}
 </ul>
+{{ else }}
+<div class="dynamic-columns">
+    {{ range .Stocks }}
+    <div class="flex items-center gap-15">
+        {{ template "stock" . }}
+    </div>
+    {{ end }}
+</div>
+{{ end }}
+{{ end }}
+
+{{ define "stock" }}
+<div class="shrink min-width-0">
+    <a{{ if ne "" .SymbolLink }} href="{{ .SymbolLink }}" target="_blank" rel="noreferrer"{{ end }} class="color-highlight size-h3 block text-truncate">{{ .Symbol }}</a>
+    <div class="text-truncate">{{ .Name }}</div>
+</div>
+
+<a class="stock-chart" {{ if ne "" .ChartLink }} href="{{ .ChartLink }}" target="_blank" rel="noreferrer"{{ end }}>
+    <svg class="stock-chart shrink-0" viewBox="0 0 100 50">
+        <polyline fill="none" stroke="var(--color-text-subdue)" stroke-width="1.5px" points="{{ .SvgChartPoints }}" vector-effect="non-scaling-stroke"></polyline>
+    </svg>
+</a>
+
+<div class="stock-values shrink-0">
+    <div class="size-h3 text-right {{ if eq .PercentChange 0.0 }}{{ else if gt .PercentChange 0.0 }}color-positive{{ else }}color-negative{{ end }}">{{ printf "%+.2f" .PercentChange }}%</div>
+    <div class="text-right">{{ .Currency }}{{ .Price | formatPrice }}</div>
+</div>
 {{ end }}

+ 1 - 0
internal/widget/bookmarks.go

@@ -22,6 +22,7 @@ type Bookmarks struct {
 			HideArrow    bool   `yaml:"hide-arrow"`
 		} `yaml:"links"`
 	} `yaml:"groups"`
+	Style string `yaml:"style"`
 }
 
 func (widget *Bookmarks) Initialize() error {

+ 1 - 0
internal/widget/monitor.go

@@ -54,6 +54,7 @@ type Monitor struct {
 		StatusText  string            `yaml:"-"`
 		StatusStyle string            `yaml:"-"`
 	} `yaml:"sites"`
+	Style string `yaml:"style"`
 }
 
 func (widget *Monitor) Initialize() error {

+ 1 - 0
internal/widget/stocks.go

@@ -14,6 +14,7 @@ type Stocks struct {
 	widgetBase `yaml:",inline"`
 	Stocks     feed.Stocks `yaml:"stocks"`
 	Sort       string      `yaml:"sort-by"`
+	Style      string      `yaml:"style"`
 }
 
 func (widget *Stocks) Initialize() error {