瀏覽代碼

Add search box

chand1012 1 年之前
父節點
當前提交
0f01a8eda5

+ 1 - 0
README.md

@@ -18,6 +18,7 @@
 * GitHub releases
 * Repository overview
 * Site monitor
+* Search box
 
 #### Themeable
 ![multiple color schemes example](docs/images/themes-example.png)

+ 33 - 0
docs/configuration.md

@@ -21,6 +21,7 @@
   - [Twitch Channels](#twitch-channels)
   - [Twitch Top Games](#twitch-top-games)
   - [iframe](#iframe)
+  - [Search](#search)
 
 ## Intro
 Configuration is done via a single YAML file and a server restart is required in order for any changes to take effect. Trying to start the server with an invalid config file will result in an error.
@@ -1132,3 +1133,35 @@ The source of the iframe.
 
 ##### `height`
 The height of the iframe. The minimum allowed height is 50.
+
+### Search
+Display a search bar that can be used to search for specific terms on various search engines.
+
+Example:
+
+```yaml
+- type: search
+  search-url: https://www.google.com/search?q=
+  query: This is a default search
+```
+
+Preview:
+
+![](images/search-widget-preview.png)
+
+#### Properties
+| Name | Type | Required | Default |
+| ---- | ---- | -------- | ------- |
+| search-url | string | no | https://duckduckgo.com/?q= |
+| query | string | no | |
+
+##### `search-url`
+The URL to use for the search. The query will be appended to the end of the URL. Some common examples:
+- Google: `https://www.google.com/search?q=`
+- DuckDuckGo: `https://duckduckgo.com/?q=`
+- Bing: `https://www.bing.com/search?q=`
+- Perplexity AI: `https://perplexity.ai/search?q=`
+- ChatGPT (requires ChatGPT Plus subscription): `https://chatgpt.com/?model=gpt-4o&oai-dm=1&q=`
+
+##### `query`
+The default query to show in the search bar. If left blank the search bar will be empty.

二進制
docs/images/search-widget-preview.png


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

@@ -1201,3 +1201,59 @@ body {
 .margin-bottom-10   { margin-bottom: 1rem; }
 .margin-bottom-15   { margin-bottom: 1.5rem; }
 .margin-bottom-auto { margin-bottom: auto; }
+
+.search-form {
+    margin: 0;
+    padding: var(--widget-content-padding);
+    background-color: var(--color-background);
+    border-radius: 20px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    width: 100%;
+    display: flex;
+    align-items: center;
+}
+
+.search-input-container {
+    position: relative;
+    width: 100%;
+}
+
+.search-input {
+    width: 100%;
+    padding: 10px 40px 10px 10px;
+    font-size: var(--font-size-h3);
+    border: 1px solid var(--color-widget-content-border);
+    border-radius: 20px;
+    color: white;
+    background: var(--color-background);
+    transition: border-color 0.15s ease;
+}
+
+.search-input:focus {
+    outline: none;
+    border-color: var(--color-primary);
+}
+
+.search-button {
+    position: absolute;
+    right: 10px;
+    top: 50%;
+    transform: translateY(-50%);
+    background: none;
+    border: none;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0;
+}
+
+.search-button svg {
+    width: 24px;
+    height: 24px;
+    color: white;
+}
+
+.search-button:hover svg {
+    color: var(--color-text-highlight);
+}

+ 1 - 0
internal/assets/templates.go

@@ -32,6 +32,7 @@ var (
 	TwitchGamesListTemplate       = compileTemplate("twitch-games-list.html", "widget-base.html")
 	TwitchChannelsTemplate        = compileTemplate("twitch-channels.html", "widget-base.html")
 	RepositoryTemplate            = compileTemplate("repository.html", "widget-base.html")
+	SearchTemplate                = compileTemplate("search.html", "widget-base.html")
 )
 
 var globalTemplateFunctions = template.FuncMap{

+ 18 - 0
internal/assets/templates/search.html

@@ -0,0 +1,18 @@
+{{ template "widget-base.html" . }}
+<!-- Search box  -->
+{{ define "widget-content" }}
+    <form class="search-form" action="{{ .SearchURL }}" method="get">
+      <div class="search-input-container">
+        <input type="text" class="search-input" value name="q" placeholder="Search...">
+        <button type="submit" class="search-button">
+          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
+            class="icon icon-tabler icons-tabler-outline icon-tabler-search">
+            <path stroke="none" d="M0 0h24v24H0z" fill="none" />
+            <path d="M10 10m-7 0a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" />
+            <path d="M21 21l-6 -6" />
+          </svg>
+        </button>
+      </div>
+    </form>
+{{ end }}

+ 30 - 0
internal/widget/search.go

@@ -0,0 +1,30 @@
+package widget
+
+import (
+	"html/template"
+
+	"github.com/glanceapp/glance/internal/assets"
+)
+
+type Search struct {
+	widgetBase `yaml:",inline"`
+	SearchURL  string `yaml:"search-url"`
+	Query      string `yaml:"query"`
+}
+
+func (widget *Search) Initialize() error {
+	widget.withTitle("Search").withError(nil)
+
+	if widget.SearchURL == "" {
+		// set to the duckduckgo search engine
+		widget.SearchURL = "https://duckduckgo.com/?q="
+	}
+
+	// if no query is provided, leave an empty string
+
+	return nil
+}
+
+func (widget *Search) Render() template.HTML {
+	return widget.render(widget, assets.SearchTemplate)
+}

+ 2 - 0
internal/widget/widget.go

@@ -45,6 +45,8 @@ func New(widgetType string) (Widget, error) {
 		return &TwitchChannels{}, nil
 	case "repository":
 		return &Repository{}, nil
+	case "search":
+		return &Search{}, nil
 	default:
 		return nil, fmt.Errorf("unknown widget type: %s", widgetType)
 	}