templicons

package module
v0.0.0-...-92f3b7e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 16, 2023 License: MIT Imports: 8 Imported by: 0

README

Templicons

This package implements Icon components for the Templ templating language by using the Iconify API, which are pretty similar to the Iconify React, Vue, and other frameworks components, except that retrieved icons are cached on your Go application, which means that only one request per icon is needed and no javascript is required.

Usage

Singleton

Once you import this package, a cache singleton will be created, making usage pretty straightforward:

package foobar

import i "github.com/callsamu/templicons"

templ FooComponent() {
    <!-- A Simple Home Icon -->
    @i.Icon("mdi:home", nil)
    <!-- The Same Icon, But With Width and Height Set -->
    @i.Icon("mdi:home", i.Params().SetDimensions(20, 20))
    <!-- The Same Icon, But With Color Set to Blue -->
    @i.Icon("mdi:home", i.Params().SetColor("#FF0000"))
    <!-- Or Just Ignore Any Setters -->
    @i.Icon("mdi:home", &i.Parameters{Width: 20, Height: 20, Color: "#FF0000"})
}

Currently, the "Width", "Height" and "Color" are the only supported parameters. Also, keep in mind that an invalid icon format will result in a panic.

Instantiating The Cache

However, if you would like to avoid global state, you can manually create a cache instance, which supports all of the singleton functions, and pass it to your components. This approach is a little bit more manual, and requires some configuration.

package main

import "github.com/callsamu/templicons"

templ FooComponent(c *templicons.Cache) {
    @c.Icon("mdi:home", nil)
}
package main

import (
    "os"
    "context"

    "github.com/callsamu/templicons"
)

func main() {
    // The Iconify Instance You Would Like to Use
    instance := "https://api.iconify.design"
    // The Client
    client := templicons.NewIconifyClient(instance)
    // The Fallback Component (we will come back to this later)
    fallback := templicons.DefaultFallback

    // Your cache instance
    cache := templicons.NewCache(client, fallback)

    component := FooComponent(cache)
    err := component.Render(context.Background(), os.Stdout)
    if err != nil {
        panic(err)
    }
}
Fallbacks

A major problem with the Icon (function/method), is that it is blocking: it will directly attempt to fetch the icon from the API. This may not be acceptable, even if all of the results are cached. To solve this, you can use the IconWithFallback (function or method, it depends if you are using the singleton or not). Instead of waiting for the expensive API call, it renders a Fallback Component, which can be easily customized.

package foobar

import i "github.com/callsamu/templicons"

templ MyFallback(text string, url string) {
    <span> { text } </span>
}

templ FooComponent() {
    <!-- It requires an additional parameter -->
    <!-- which is a placeholder for using on -->
    <!-- the fallback component -->
    @i.IconWithFallback("mdi:home", "home", nil)
}
package main

import (
    "os"
    "log"
    "context"

    "github.com/callsamu/templicons"
)

func main() {
    templicons.SetFallback(MyFallback)

    // Of course you can always use the select statement
    go func() {
        for err := templicons.Errors() {
            log.Error(err)
        }
    }

    component := FooComponent()
    err := component.Render(context.Background(), os.Stdout)
    if err != nil {
        panic(err)
    }
}

There are two things to note:

  1. Each call of IconWithFallback invokes a goroutine which makes a API call whose errors are communicated via a channel, which be listened.

  2. A new fallback component is created and set, overriding the default. A fallback component is just any function that takes a text and icon url strings as input and returns a templ component.

A nice thing about customizing fallback components is that you can use the url parameter and a javascript library like HTMX to achieve something like this:

package foobar

import i "github.com/callsamu/templicons"

templ HTMXFallback(text string, url string) {
	<span 
		hx-get={ url }
		hx-disinherit="*"
		hx-target="this" 
		hx-swap="outerHTML" 
		hx-confirm="unset"
		hx-trigger="load"
		hx-on="htmx:configRequest: event.detail.headers=''">
        { text } 
    </span>
}

This fallback component will make a client side call to the Iconify API and replace itself by the response, thus rendering the icon on the page even if it wasn't yet retrieved, while the default fallback would just render a span containing the text parameters value and left the url untouched.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultFallback

func DefaultFallback(span, iconURL string) templ.Component

func Errors

func Errors() chan error

func Icon

func Icon(name string, p *Parameters) templ.Component

func IconWithFallback

func IconWithFallback(name string, fallback string, p *Parameters) templ.Component

func SetFallback

func SetFallback(fallback Fallback)

func SetInstances

func SetInstances(urls ...string)

Types

type Cache

type Cache struct {
	Errors chan error

	Fallback Fallback
	// contains filtered or unexported fields
}

func NewCache

func NewCache(client Client, fallback Fallback) *Cache

func (*Cache) Icon

func (c *Cache) Icon(name string, p *Parameters) templ.Component

func (*Cache) IconWithFallback

func (c *Cache) IconWithFallback(name string, fallback string, p *Parameters) templ.Component

type Client

type Client interface {
	Fetch(path string) ([]byte, error)
	SetInstances(instances ...string)
}

type Fallback

type Fallback func(span, iconURL string) templ.Component

type IconifyClient

type IconifyClient struct {
	*http.Client

	Instances []string
}

func NewIconifyClient

func NewIconifyClient(instances ...string) *IconifyClient

func (IconifyClient) Fetch

func (c IconifyClient) Fetch(path string) ([]byte, error)

func (*IconifyClient) SetInstances

func (c *IconifyClient) SetInstances(instances ...string)

type Parameters

type Parameters struct {
	Width  int
	Height int
	Color  string
}

func Params

func Params() *Parameters

func (*Parameters) SetColor

func (p *Parameters) SetColor(color string) *Parameters

func (*Parameters) SetDimensions

func (p *Parameters) SetDimensions(width, height int) *Parameters

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL