mirror of
https://github.com/axzilla/templui.git
synced 2025-02-21 01:32:45 +00:00
feat: add avatar component
This commit is contained in:
parent
4b175edac6
commit
1df0a9bc58
@ -2,6 +2,10 @@
|
||||
|
||||
## 2024-10-07
|
||||
|
||||
- Added: Avatar component
|
||||
|
||||
## 2024-10-07
|
||||
|
||||
- Added: Input component
|
||||
- Added: Modal component
|
||||
- Added: Alert component
|
||||
|
@ -871,6 +871,14 @@ body {
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.h-12 {
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
.h-16 {
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
.\!max-h-\[501px\] {
|
||||
max-height: 501px !important;
|
||||
}
|
||||
@ -931,6 +939,18 @@ body {
|
||||
width: 1.25rem;
|
||||
}
|
||||
|
||||
.w-12 {
|
||||
width: 3rem;
|
||||
}
|
||||
|
||||
.w-16 {
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.w-8 {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.max-w-3xl {
|
||||
max-width: 48rem;
|
||||
}
|
||||
@ -1166,6 +1186,10 @@ body {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.border-2 {
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.border-b {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
@ -1210,6 +1234,11 @@ body {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.border-blue-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.bg-background {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: hsl(var(--background) / var(--tw-bg-opacity));
|
||||
@ -1308,6 +1337,11 @@ body {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.object-cover {
|
||||
-o-object-fit: cover;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.p-1 {
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
@ -21,15 +21,17 @@ func main() {
|
||||
mux.Handle("GET /docs/getting-started", http.RedirectHandler("/docs/introduction", http.StatusSeeOther))
|
||||
mux.Handle("GET /docs/introduction", templ.Handler(pages.Introduction()))
|
||||
mux.Handle("GET /docs/how-to-use", templ.Handler(pages.HowToUse()))
|
||||
// Components
|
||||
mux.Handle("GET /docs/components/accordion", templ.Handler(pages.Accordion()))
|
||||
mux.Handle("GET /docs/components/alert", templ.Handler(pages.Alert()))
|
||||
mux.Handle("GET /docs/components/avatar", templ.Handler(pages.Avatar()))
|
||||
mux.Handle("GET /docs/components/button", templ.Handler(pages.Button()))
|
||||
mux.Handle("GET /docs/components/card", templ.Handler(pages.Card()))
|
||||
mux.Handle("GET /docs/components/datepicker", templ.Handler(pages.Datepicker()))
|
||||
mux.Handle("GET /docs/components/input", templ.Handler(pages.Input()))
|
||||
mux.Handle("GET /docs/components/modal", templ.Handler(pages.Modal()))
|
||||
mux.Handle("GET /docs/components/sheet", templ.Handler(pages.Sheet()))
|
||||
mux.Handle("GET /docs/components/tabs", templ.Handler(pages.Tabs()))
|
||||
mux.Handle("GET /docs/components/card", templ.Handler(pages.Card()))
|
||||
mux.Handle("GET /docs/components/input", templ.Handler(pages.Input()))
|
||||
mux.Handle("GET /docs/components/accordion", templ.Handler(pages.Accordion()))
|
||||
mux.Handle("GET /docs/components/datepicker", templ.Handler(pages.Datepicker()))
|
||||
mux.Handle("GET /docs/components/alert", templ.Handler(pages.Alert()))
|
||||
mux.Handle("GET /docs/components/modal", templ.Handler(pages.Modal()))
|
||||
|
||||
fmt.Println("Server is running on http://localhost:8090")
|
||||
http.ListenAndServe(":8090", mux)
|
||||
|
@ -37,6 +37,10 @@ var Sections = []Section{
|
||||
Text: "Alert",
|
||||
Href: "/docs/components/alert",
|
||||
},
|
||||
{
|
||||
Text: "Avatar",
|
||||
Href: "/docs/components/avatar",
|
||||
},
|
||||
{
|
||||
Text: "Button",
|
||||
Href: "/docs/components/button",
|
||||
|
103
internals/ui/components/avatar.templ
Normal file
103
internals/ui/components/avatar.templ
Normal file
@ -0,0 +1,103 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AvatarSize represents the size of the avatar.
|
||||
type AvatarSize string
|
||||
|
||||
const (
|
||||
AvatarSizeSmall AvatarSize = "small"
|
||||
AvatarSizeMedium AvatarSize = "medium"
|
||||
AvatarSizeLarge AvatarSize = "large"
|
||||
)
|
||||
|
||||
// AvatarProps defines the properties for the Avatar component.
|
||||
type AvatarProps struct {
|
||||
// ImageSrc is the URL of the avatar image.
|
||||
// If empty, initials will be used.
|
||||
ImageSrc string
|
||||
|
||||
// Name is used to generate initials if ImageSrc is empty.
|
||||
Name string
|
||||
|
||||
// Size determines the size of the avatar.
|
||||
// Default: AvatarSizeMedium
|
||||
Size AvatarSize
|
||||
|
||||
// Class specifies additional CSS classes to apply to the avatar.
|
||||
Class string
|
||||
|
||||
// Attributes allows passing additional HTML attributes to the avatar element.
|
||||
Attributes templ.Attributes
|
||||
}
|
||||
|
||||
// getInitials generates initials from the given name.
|
||||
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)
|
||||
}
|
||||
|
||||
// getSizeClasses returns the CSS classes for the given avatar size.
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
// Avatar renders an avatar component based on the provided props.
|
||||
// It displays an image if ImageSrc is provided, otherwise it shows initials.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// @components.Avatar(components.AvatarProps{
|
||||
// ImageSrc: "https://example.com/avatar.jpg",
|
||||
// Name: "John Doe",
|
||||
// Size: components.AvatarSizeMedium,
|
||||
// Class: "border-2 border-blue-500",
|
||||
// })
|
||||
//
|
||||
// Props:
|
||||
// - ImageSrc: The URL of the avatar image. Default: "" (empty string)
|
||||
// - Name: The name used to generate initials if ImageSrc is empty. Default: "" (empty string)
|
||||
// - Size: The size of the avatar (AvatarSizeSmall, AvatarSizeMedium, AvatarSizeLarge). Default: AvatarSizeMedium
|
||||
// - Class: Additional CSS classes to apply to the avatar. Default: "" (empty string)
|
||||
// - Attributes: Additional HTML attributes to apply to the avatar element. Default: nil
|
||||
templ Avatar(props AvatarProps) {
|
||||
<div
|
||||
class={
|
||||
"inline-flex items-center justify-center rounded-full bg-muted",
|
||||
AvatarSizeClasses(props.Size),
|
||||
props.Class,
|
||||
}
|
||||
{ props.Attributes... }
|
||||
>
|
||||
if props.ImageSrc != "" {
|
||||
<img
|
||||
src={ props.ImageSrc }
|
||||
alt={ fmt.Sprintf("%s's avatar", props.Name) }
|
||||
class="w-full h-full object-cover rounded-full"
|
||||
/>
|
||||
} else {
|
||||
<span class="font-medium text-muted-foreground">
|
||||
{ AvatarInitials(props.Name) }
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
}
|
39
internals/ui/pages/avatar.templ
Normal file
39
internals/ui/pages/avatar.templ
Normal file
@ -0,0 +1,39 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"github.com/axzilla/goilerplate/internals/ui/components"
|
||||
"github.com/axzilla/goilerplate/internals/ui/layouts"
|
||||
"github.com/axzilla/goilerplate/internals/ui/showcase"
|
||||
)
|
||||
|
||||
templ Avatar() {
|
||||
@layouts.DocsLayout() {
|
||||
<div>
|
||||
<div class="mb-16">
|
||||
<h1 class="text-3xl font-bold mb-2">Avatar</h1>
|
||||
<p class="mb-4 text-muted-foreground">An image element with a fallback for representing the user.</p>
|
||||
</div>
|
||||
@components.Tabs(components.TabsProps{
|
||||
Tabs: []components.Tab{
|
||||
{
|
||||
ID: "preview",
|
||||
Title: "Preview",
|
||||
Content: showcase.AvatarShowcase(),
|
||||
},
|
||||
{
|
||||
ID: "code",
|
||||
Title: "Code",
|
||||
Content: CodeSnippetFromEmbedded("avatar.templ", "go", showcase.TemplFiles),
|
||||
},
|
||||
{
|
||||
ID: "component",
|
||||
Title: "Component",
|
||||
Content: CodeSnippetFromEmbedded("avatar.templ", "go", components.TemplFiles),
|
||||
},
|
||||
},
|
||||
TabsContainerClass: "md:w-1/2",
|
||||
ContentContainerClass: "w-full",
|
||||
})
|
||||
</div>
|
||||
}
|
||||
}
|
52
internals/ui/showcase/avatar.templ
Normal file
52
internals/ui/showcase/avatar.templ
Normal file
@ -0,0 +1,52 @@
|
||||
package showcase
|
||||
|
||||
import (
|
||||
"github.com/axzilla/goilerplate/internals/ui/components"
|
||||
)
|
||||
|
||||
templ AvatarShowcase() {
|
||||
<div class="flex justify-center items-center border rounded-md py-16 px-4">
|
||||
<div>
|
||||
<div class="mb-8">
|
||||
<h2 class="font-semibold mb-2">With Image</h2>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@components.Avatar(components.AvatarProps{
|
||||
ImageSrc: "https://avatars.githubusercontent.com/u/26936893?v=4",
|
||||
Name: "John Doe",
|
||||
Class: "border-2 border-border",
|
||||
})
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<h2 class="font-semibold mb-2">With Placeholder</h2>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@components.Avatar(components.AvatarProps{
|
||||
Name: "The Dude",
|
||||
})
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<h2 class="font-semibold mb-2">With Sizes</h2>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@components.Avatar(components.AvatarProps{
|
||||
ImageSrc: "https://avatars.githubusercontent.com/u/26936893?v=4",
|
||||
Name: "John Doe",
|
||||
Size: components.AvatarSizeSmall,
|
||||
Class: "border-2 border-border",
|
||||
})
|
||||
@components.Avatar(components.AvatarProps{
|
||||
ImageSrc: "https://avatars.githubusercontent.com/u/26936893?v=4",
|
||||
Name: "John Doe",
|
||||
Class: "border-2 border-border",
|
||||
})
|
||||
@components.Avatar(components.AvatarProps{
|
||||
ImageSrc: "https://avatars.githubusercontent.com/u/26936893?v=4",
|
||||
Name: "John Doe",
|
||||
Size: components.AvatarSizeLarge,
|
||||
Class: "border-2 border-border",
|
||||
})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user