diff --git a/README.md b/README.md index 715c8e5..7baa9a4 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ * GitHub releases * Repository overview * Site monitor +* Search box #### Themeable ![multiple color schemes example](docs/images/themes-example.png) diff --git a/docs/configuration.md b/docs/configuration.md index e698fdd..40938a6 100644 --- a/docs/configuration.md +++ b/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. diff --git a/docs/images/search-widget-preview.png b/docs/images/search-widget-preview.png new file mode 100644 index 0000000..c058401 Binary files /dev/null and b/docs/images/search-widget-preview.png differ diff --git a/internal/assets/static/main.css b/internal/assets/static/main.css index 1e64def..a5b8acb 100644 --- a/internal/assets/static/main.css +++ b/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); +} diff --git a/internal/assets/templates.go b/internal/assets/templates.go index b8aa6ae..1a70ac1 100644 --- a/internal/assets/templates.go +++ b/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{ diff --git a/internal/assets/templates/search.html b/internal/assets/templates/search.html new file mode 100644 index 0000000..be70575 --- /dev/null +++ b/internal/assets/templates/search.html @@ -0,0 +1,18 @@ +{{ template "widget-base.html" . }} + +{{ define "widget-content" }} +
+
+ + +
+
+{{ end }} diff --git a/internal/widget/search.go b/internal/widget/search.go new file mode 100644 index 0000000..1786ee1 --- /dev/null +++ b/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) +} diff --git a/internal/widget/widget.go b/internal/widget/widget.go index 3707b7e..17b4f87 100644 --- a/internal/widget/widget.go +++ b/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) }