Avatar
Visual representation of a user through images or initials.
TailwindCSS
package showcase
import "github.com/axzilla/templui/components"
templ AvatarDefault() {
@components.Avatar() {
@components.AvatarImage(components.AvatarImageProps{
Src: "https://avatars.githubusercontent.com/u/26936893?v=4",
})
}
}
package components
import (
"fmt"
"github.com/axzilla/templui/utils"
"strings"
)
type AvatarSize string
type AvatarGroupSpacing string
const (
AvatarSizeSmall AvatarSize = "small"
AvatarSizeMedium AvatarSize = "medium"
AvatarSizeLarge AvatarSize = "large"
)
const (
AvatarGroupSpacingSmall AvatarGroupSpacing = "small"
AvatarGroupSpacingMedium AvatarGroupSpacing = "medium"
AvatarGroupSpacingLarge AvatarGroupSpacing = "large"
)
type AvatarProps struct {
ID string
Class string
Attributes templ.Attributes
Size AvatarSize
InGroup bool
}
type AvatarImageProps struct {
ID string
Class string
Attributes templ.Attributes
Alt string
Src string
}
type AvatarFallbackProps struct {
ID string
Class string
Attributes templ.Attributes
}
type AvatarGroupProps struct {
ID string
Class string
Attributes templ.Attributes
Spacing AvatarGroupSpacing
}
templ Avatar(props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted",
utils.If(p.InGroup, "ring-2 ring-background"),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarImage(props ...AvatarImageProps) {
{{ var p AvatarImageProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<img
if p.ID != "" {
id={ p.ID }
}
if p.Src != "" {
src={ p.Src }
}
if p.Alt != "" {
alt={ p.Alt }
}
class={
utils.TwMerge(
"w-full h-full",
"rounded-full object-cover",
p.Class,
),
}
{ p.Attributes... }
/>
}
templ AvatarFallback(props ...AvatarFallbackProps) {
{{ var p AvatarFallbackProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<span
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"font-medium text-muted-foreground",
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</span>
}
templ AvatarGroup(props ...AvatarGroupProps) {
{{ var p AvatarGroupProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"flex items-center -space-x-3",
avatarGroupSpacingClasses(p.Spacing),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarGroupOverflow(count int, props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted ring-2 ring-background",
p.Class,
),
}
{ p.Attributes... }
>
<span class="text-xs font-medium">+{ fmt.Sprint(count) }</span>
</div>
}
func avatarSizeClasses(size AvatarSize) string {
switch size {
case AvatarSizeSmall:
return "w-8 h-8 text-xs"
case AvatarSizeLarge:
return "w-16 h-16 text-xl"
default:
return "w-12 h-12 text-base"
}
}
func AvatarInitials(name string) string {
parts := strings.Fields(name)
initials := ""
for i, part := range parts {
if i > 1 {
break
}
if len(part) > 0 {
initials += string(part[0])
}
}
return strings.ToUpper(initials)
}
func avatarGroupSpacingClasses(spacing AvatarGroupSpacing) string {
switch spacing {
case AvatarGroupSpacingSmall:
return "-space-x-1"
case AvatarGroupSpacingLarge:
return "-space-x-4"
default:
return "-space-x-2"
}
}
Usage
@components.Avatar(components.AvatarProps{...})
Examples
Fallback
JD
package showcase
import "github.com/axzilla/templui/components"
templ AvatarFallback() {
@components.Avatar() {
@components.AvatarFallback() {
{ components.AvatarInitials("John Doe") }
}
}
}
package components
import (
"fmt"
"github.com/axzilla/templui/utils"
"strings"
)
type AvatarSize string
type AvatarGroupSpacing string
const (
AvatarSizeSmall AvatarSize = "small"
AvatarSizeMedium AvatarSize = "medium"
AvatarSizeLarge AvatarSize = "large"
)
const (
AvatarGroupSpacingSmall AvatarGroupSpacing = "small"
AvatarGroupSpacingMedium AvatarGroupSpacing = "medium"
AvatarGroupSpacingLarge AvatarGroupSpacing = "large"
)
type AvatarProps struct {
ID string
Class string
Attributes templ.Attributes
Size AvatarSize
InGroup bool
}
type AvatarImageProps struct {
ID string
Class string
Attributes templ.Attributes
Alt string
Src string
}
type AvatarFallbackProps struct {
ID string
Class string
Attributes templ.Attributes
}
type AvatarGroupProps struct {
ID string
Class string
Attributes templ.Attributes
Spacing AvatarGroupSpacing
}
templ Avatar(props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted",
utils.If(p.InGroup, "ring-2 ring-background"),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarImage(props ...AvatarImageProps) {
{{ var p AvatarImageProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<img
if p.ID != "" {
id={ p.ID }
}
if p.Src != "" {
src={ p.Src }
}
if p.Alt != "" {
alt={ p.Alt }
}
class={
utils.TwMerge(
"w-full h-full",
"rounded-full object-cover",
p.Class,
),
}
{ p.Attributes... }
/>
}
templ AvatarFallback(props ...AvatarFallbackProps) {
{{ var p AvatarFallbackProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<span
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"font-medium text-muted-foreground",
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</span>
}
templ AvatarGroup(props ...AvatarGroupProps) {
{{ var p AvatarGroupProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"flex items-center -space-x-3",
avatarGroupSpacingClasses(p.Spacing),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarGroupOverflow(count int, props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted ring-2 ring-background",
p.Class,
),
}
{ p.Attributes... }
>
<span class="text-xs font-medium">+{ fmt.Sprint(count) }</span>
</div>
}
func avatarSizeClasses(size AvatarSize) string {
switch size {
case AvatarSizeSmall:
return "w-8 h-8 text-xs"
case AvatarSizeLarge:
return "w-16 h-16 text-xl"
default:
return "w-12 h-12 text-base"
}
}
func AvatarInitials(name string) string {
parts := strings.Fields(name)
initials := ""
for i, part := range parts {
if i > 1 {
break
}
if len(part) > 0 {
initials += string(part[0])
}
}
return strings.ToUpper(initials)
}
func avatarGroupSpacingClasses(spacing AvatarGroupSpacing) string {
switch spacing {
case AvatarGroupSpacingSmall:
return "-space-x-1"
case AvatarGroupSpacingLarge:
return "-space-x-4"
default:
return "-space-x-2"
}
}
Sizes
package showcase
import "github.com/axzilla/templui/components"
templ AvatarSizes() {
<div class="flex flex-wrap gap-2">
@components.Avatar(components.AvatarProps{
Size: components.AvatarSizeSmall,
}) {
@components.AvatarImage(components.AvatarImageProps{
Src: "https://avatars.githubusercontent.com/u/26936893?v=4",
})
}
@components.Avatar() {
@components.AvatarImage(components.AvatarImageProps{
Src: "https://avatars.githubusercontent.com/u/26936893?v=4",
})
}
@components.Avatar(components.AvatarProps{
Size: components.AvatarSizeLarge,
}) {
@components.AvatarImage(components.AvatarImageProps{
Src: "https://avatars.githubusercontent.com/u/26936893?v=4",
})
}
</div>
}
package components
import (
"fmt"
"github.com/axzilla/templui/utils"
"strings"
)
type AvatarSize string
type AvatarGroupSpacing string
const (
AvatarSizeSmall AvatarSize = "small"
AvatarSizeMedium AvatarSize = "medium"
AvatarSizeLarge AvatarSize = "large"
)
const (
AvatarGroupSpacingSmall AvatarGroupSpacing = "small"
AvatarGroupSpacingMedium AvatarGroupSpacing = "medium"
AvatarGroupSpacingLarge AvatarGroupSpacing = "large"
)
type AvatarProps struct {
ID string
Class string
Attributes templ.Attributes
Size AvatarSize
InGroup bool
}
type AvatarImageProps struct {
ID string
Class string
Attributes templ.Attributes
Alt string
Src string
}
type AvatarFallbackProps struct {
ID string
Class string
Attributes templ.Attributes
}
type AvatarGroupProps struct {
ID string
Class string
Attributes templ.Attributes
Spacing AvatarGroupSpacing
}
templ Avatar(props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted",
utils.If(p.InGroup, "ring-2 ring-background"),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarImage(props ...AvatarImageProps) {
{{ var p AvatarImageProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<img
if p.ID != "" {
id={ p.ID }
}
if p.Src != "" {
src={ p.Src }
}
if p.Alt != "" {
alt={ p.Alt }
}
class={
utils.TwMerge(
"w-full h-full",
"rounded-full object-cover",
p.Class,
),
}
{ p.Attributes... }
/>
}
templ AvatarFallback(props ...AvatarFallbackProps) {
{{ var p AvatarFallbackProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<span
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"font-medium text-muted-foreground",
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</span>
}
templ AvatarGroup(props ...AvatarGroupProps) {
{{ var p AvatarGroupProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"flex items-center -space-x-3",
avatarGroupSpacingClasses(p.Spacing),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarGroupOverflow(count int, props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted ring-2 ring-background",
p.Class,
),
}
{ p.Attributes... }
>
<span class="text-xs font-medium">+{ fmt.Sprint(count) }</span>
</div>
}
func avatarSizeClasses(size AvatarSize) string {
switch size {
case AvatarSizeSmall:
return "w-8 h-8 text-xs"
case AvatarSizeLarge:
return "w-16 h-16 text-xl"
default:
return "w-12 h-12 text-base"
}
}
func AvatarInitials(name string) string {
parts := strings.Fields(name)
initials := ""
for i, part := range parts {
if i > 1 {
break
}
if len(part) > 0 {
initials += string(part[0])
}
}
return strings.ToUpper(initials)
}
func avatarGroupSpacingClasses(spacing AvatarGroupSpacing) string {
switch spacing {
case AvatarGroupSpacingSmall:
return "-space-x-1"
case AvatarGroupSpacingLarge:
return "-space-x-4"
default:
return "-space-x-2"
}
}
With Icon
package showcase
import "github.com/axzilla/templui/components"
import "github.com/axzilla/templui/icons"
templ AvatarWithIcon() {
@components.Avatar(components.AvatarProps{
Class: "bg-purple-300",
}) {
@icons.Camera(icons.IconProps{
Size: 22,
Color: "white",
})
}
}
package components
import (
"fmt"
"github.com/axzilla/templui/utils"
"strings"
)
type AvatarSize string
type AvatarGroupSpacing string
const (
AvatarSizeSmall AvatarSize = "small"
AvatarSizeMedium AvatarSize = "medium"
AvatarSizeLarge AvatarSize = "large"
)
const (
AvatarGroupSpacingSmall AvatarGroupSpacing = "small"
AvatarGroupSpacingMedium AvatarGroupSpacing = "medium"
AvatarGroupSpacingLarge AvatarGroupSpacing = "large"
)
type AvatarProps struct {
ID string
Class string
Attributes templ.Attributes
Size AvatarSize
InGroup bool
}
type AvatarImageProps struct {
ID string
Class string
Attributes templ.Attributes
Alt string
Src string
}
type AvatarFallbackProps struct {
ID string
Class string
Attributes templ.Attributes
}
type AvatarGroupProps struct {
ID string
Class string
Attributes templ.Attributes
Spacing AvatarGroupSpacing
}
templ Avatar(props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted",
utils.If(p.InGroup, "ring-2 ring-background"),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarImage(props ...AvatarImageProps) {
{{ var p AvatarImageProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<img
if p.ID != "" {
id={ p.ID }
}
if p.Src != "" {
src={ p.Src }
}
if p.Alt != "" {
alt={ p.Alt }
}
class={
utils.TwMerge(
"w-full h-full",
"rounded-full object-cover",
p.Class,
),
}
{ p.Attributes... }
/>
}
templ AvatarFallback(props ...AvatarFallbackProps) {
{{ var p AvatarFallbackProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<span
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"font-medium text-muted-foreground",
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</span>
}
templ AvatarGroup(props ...AvatarGroupProps) {
{{ var p AvatarGroupProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"flex items-center -space-x-3",
avatarGroupSpacingClasses(p.Spacing),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarGroupOverflow(count int, props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted ring-2 ring-background",
p.Class,
),
}
{ p.Attributes... }
>
<span class="text-xs font-medium">+{ fmt.Sprint(count) }</span>
</div>
}
func avatarSizeClasses(size AvatarSize) string {
switch size {
case AvatarSizeSmall:
return "w-8 h-8 text-xs"
case AvatarSizeLarge:
return "w-16 h-16 text-xl"
default:
return "w-12 h-12 text-base"
}
}
func AvatarInitials(name string) string {
parts := strings.Fields(name)
initials := ""
for i, part := range parts {
if i > 1 {
break
}
if len(part) > 0 {
initials += string(part[0])
}
}
return strings.ToUpper(initials)
}
func avatarGroupSpacingClasses(spacing AvatarGroupSpacing) string {
switch spacing {
case AvatarGroupSpacingSmall:
return "-space-x-1"
case AvatarGroupSpacingLarge:
return "-space-x-4"
default:
return "-space-x-2"
}
}
Group
+2
package showcase
import "github.com/axzilla/templui/components"
templ AvatarGroup() {
@components.AvatarGroup(components.AvatarGroupProps{
Spacing: components.AvatarGroupSpacingLarge,
}) {
@components.Avatar(components.AvatarProps{
InGroup: true,
}) {
@components.AvatarImage(components.AvatarImageProps{
Src: "https://avatars.githubusercontent.com/u/26936893?v=4",
})
}
@components.Avatar(components.AvatarProps{
InGroup: true,
}) {
@components.AvatarImage(components.AvatarImageProps{
Src: "https://avatars.githubusercontent.com/u/26936893?v=4",
})
}
@components.Avatar(components.AvatarProps{
InGroup: true,
}) {
@components.AvatarImage(components.AvatarImageProps{
Src: "https://avatars.githubusercontent.com/u/26936893?v=4",
})
}
@components.AvatarGroupOverflow(2, components.AvatarProps{
InGroup: true,
}) {
@components.AvatarImage(components.AvatarImageProps{
Src: "https://avatars.githubusercontent.com/u/26936893?v=4",
})
}
}
}
package components
import (
"fmt"
"github.com/axzilla/templui/utils"
"strings"
)
type AvatarSize string
type AvatarGroupSpacing string
const (
AvatarSizeSmall AvatarSize = "small"
AvatarSizeMedium AvatarSize = "medium"
AvatarSizeLarge AvatarSize = "large"
)
const (
AvatarGroupSpacingSmall AvatarGroupSpacing = "small"
AvatarGroupSpacingMedium AvatarGroupSpacing = "medium"
AvatarGroupSpacingLarge AvatarGroupSpacing = "large"
)
type AvatarProps struct {
ID string
Class string
Attributes templ.Attributes
Size AvatarSize
InGroup bool
}
type AvatarImageProps struct {
ID string
Class string
Attributes templ.Attributes
Alt string
Src string
}
type AvatarFallbackProps struct {
ID string
Class string
Attributes templ.Attributes
}
type AvatarGroupProps struct {
ID string
Class string
Attributes templ.Attributes
Spacing AvatarGroupSpacing
}
templ Avatar(props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted",
utils.If(p.InGroup, "ring-2 ring-background"),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarImage(props ...AvatarImageProps) {
{{ var p AvatarImageProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<img
if p.ID != "" {
id={ p.ID }
}
if p.Src != "" {
src={ p.Src }
}
if p.Alt != "" {
alt={ p.Alt }
}
class={
utils.TwMerge(
"w-full h-full",
"rounded-full object-cover",
p.Class,
),
}
{ p.Attributes... }
/>
}
templ AvatarFallback(props ...AvatarFallbackProps) {
{{ var p AvatarFallbackProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<span
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"font-medium text-muted-foreground",
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</span>
}
templ AvatarGroup(props ...AvatarGroupProps) {
{{ var p AvatarGroupProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"flex items-center -space-x-3",
avatarGroupSpacingClasses(p.Spacing),
p.Class,
),
}
{ p.Attributes... }
>
{ children... }
</div>
}
templ AvatarGroupOverflow(count int, props ...AvatarProps) {
{{ var p AvatarProps }}
if len(props) > 0 {
{{ p = props[0] }}
}
<div
if p.ID != "" {
id={ p.ID }
}
class={
utils.TwMerge(
"inline-flex items-center justify-center",
avatarSizeClasses(p.Size),
"rounded-full bg-muted ring-2 ring-background",
p.Class,
),
}
{ p.Attributes... }
>
<span class="text-xs font-medium">+{ fmt.Sprint(count) }</span>
</div>
}
func avatarSizeClasses(size AvatarSize) string {
switch size {
case AvatarSizeSmall:
return "w-8 h-8 text-xs"
case AvatarSizeLarge:
return "w-16 h-16 text-xl"
default:
return "w-12 h-12 text-base"
}
}
func AvatarInitials(name string) string {
parts := strings.Fields(name)
initials := ""
for i, part := range parts {
if i > 1 {
break
}
if len(part) > 0 {
initials += string(part[0])
}
}
return strings.ToUpper(initials)
}
func avatarGroupSpacingClasses(spacing AvatarGroupSpacing) string {
switch spacing {
case AvatarGroupSpacingSmall:
return "-space-x-1"
case AvatarGroupSpacingLarge:
return "-space-x-4"
default:
return "-space-x-2"
}
}