Badge
A small label for a status or a count.
<badge.Badge>Badge</badge.Badge>Installation
Run the command in the app module.
gx add badgeThe command also installs icons.
The command writes these files.
| File | Path in the app |
|---|---|
Badge.gx |
ui/badge/Badge.gx |
Badge.fixtures.go |
ui/badge/Badge.fixtures.go |
styles.go |
ui/badge/styles.go |
Install icons first.
Copy each file to its path in the app. Change each import of a registry package to the path of that package in the app.
package badge
props {
// Variant sets the visual style: Default, Secondary, Destructive, Outline, Ghost or Link.
Variant Variant = Default
// Href is the URL of the link. A non-empty value renders the badge as an a element, not a span.
Href gx.URL = ""
// Class adds classes to the root element.
Class string = ""
// Children is the badge label.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
if p.Href != "" {
<a href={p.Href} data-slot="badge" data-variant={p.variant()} class={p.class()} {...p.Attrs}>{p.Children}</a>
} else {
<span data-slot="badge" data-variant={p.variant()} class={p.class()} {...p.Attrs}>{p.Children}</span>
}package badge
import (
"github.com/alternayte/gx"
"github.com/alternayte/gx/registry/icons"
)
var BadgeFixtures = gx.Fixtures[BadgeProps]{
"Default": {Children: gx.Text("Badge")},
"Secondary": {Variant: Secondary, Children: gx.Text("Secondary")},
"Destructive": {Variant: Destructive, Children: gx.Text("Destructive")},
"Outline": {Variant: Outline, Children: gx.Text("Outline")},
"Ghost": {Variant: Ghost, Children: gx.Text("Ghost")},
"Link": {Variant: Link, Href: gx.URL("/docs"), Children: gx.Text("Link")},
"WithIcon": {Variant: Secondary, Children: gx.Frag(icons.CircleCheck(icons.CircleCheckProps{}), gx.Text("Verified"))},
"Anchor": {Href: gx.URL("/docs"), Children: gx.Text("Docs")},
}package badge
import "github.com/alternayte/gx"
// Variant is the visual style of a badge.
type Variant string
// The variants of badge.Badge.
const (
Default Variant = "default"
Secondary Variant = "secondary"
Destructive Variant = "destructive"
Outline Variant = "outline"
Ghost Variant = "ghost"
Link Variant = "link"
)
var variantClass = gx.Enum[Variant]{
Default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
Secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
Destructive: "bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90",
Outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
Ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
Link: "text-primary underline-offset-4 [a&]:hover:underline",
}
// variant returns the data-variant value; a zero value is Default.
func (p BadgeProps) variant() string {
if p.Variant == "" {
return string(Default)
}
return string(p.Variant)
}
// class returns the classes of one badge.
func (p BadgeProps) class() string {
const base = "inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3"
return gx.Cx(base, variantClass[Variant(p.variant())], p.Class)
}The theme must define these tokens: --primary, --primary-foreground, --secondary, --secondary-foreground, --destructive, --accent, --accent-foreground, --border, --foreground, --ring.
Usage
<badge.Badge>New</badge.Badge>
<badge.Badge variant={badge.Outline}>Draft</badge.Badge>
<badge.Badge variant={badge.Secondary}><icons.CircleCheck />Verified</badge.Badge>
<badge.Badge variant={badge.Link} href={docsRoute}>Docs</badge.Badge>The variants are Default, Secondary, Destructive, Outline, Ghost and Link.
Set Href to render the badge as a link. A link badge has a hover state.
Examples
Default
<badge.Badge>Badge</badge.Badge>Secondary
<badge.Badge variant={badge.Secondary}>Secondary</badge.Badge>Destructive
<badge.Badge variant={badge.Destructive}>Destructive</badge.Badge>Outline
<badge.Badge variant={badge.Outline}>Outline</badge.Badge>Ghost
<badge.Badge variant={badge.Ghost}>Ghost</badge.Badge>Link
<badge.Badge variant={badge.Link} href={gx.URL("/docs")}>Link</badge.Badge>With icon
<badge.Badge variant={badge.Secondary}>
<icons.CircleCheck />
Verified
</badge.Badge>Anchor
<badge.Badge href={gx.URL("/docs")}>Docs</badge.Badge>API reference
A tag sets a prop by its name with a lower-case first letter: Class is class.
badge.Badge
| Prop | Type | Default | Description |
|---|---|---|---|
Variant |
Variant |
Default |
Variant sets the visual style: Default, Secondary, Destructive, Outline, Ghost or Link. |
Href |
gx.URL |
"" |
Href is the URL of the link. A non-empty value renders the badge as an a element, not a span. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the badge label. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
Do and do not
Do
- Keep the text to one or two words.
- Use
Destructiveonly for an error or a removal.
Don't
- Do not use a badge as a button. Use a button.
- Do not use colour as the only signal. Write the status in the text.
Keyboard
| Key | Action |
|---|---|
| Tab | Moves focus to a link badge. |
| Enter | Follows a link badge. |