mirror of
https://github.com/axzilla/templui.git
synced 2025-02-22 03:12:52 +00:00
feat: add avatar component
This commit is contained in:
parent
4b175edac6
commit
1df0a9bc58
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## 2024-10-07
|
## 2024-10-07
|
||||||
|
|
||||||
|
- Added: Avatar component
|
||||||
|
|
||||||
|
## 2024-10-07
|
||||||
|
|
||||||
- Added: Input component
|
- Added: Input component
|
||||||
- Added: Modal component
|
- Added: Modal component
|
||||||
- Added: Alert component
|
- Added: Alert component
|
||||||
|
@ -871,6 +871,14 @@ body {
|
|||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-12 {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-16 {
|
||||||
|
height: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
.\!max-h-\[501px\] {
|
.\!max-h-\[501px\] {
|
||||||
max-height: 501px !important;
|
max-height: 501px !important;
|
||||||
}
|
}
|
||||||
@ -931,6 +939,18 @@ body {
|
|||||||
width: 1.25rem;
|
width: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-12 {
|
||||||
|
width: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-16 {
|
||||||
|
width: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-8 {
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.max-w-3xl {
|
.max-w-3xl {
|
||||||
max-width: 48rem;
|
max-width: 48rem;
|
||||||
}
|
}
|
||||||
@ -1166,6 +1186,10 @@ body {
|
|||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-2 {
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.border-b {
|
.border-b {
|
||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
}
|
}
|
||||||
@ -1210,6 +1234,11 @@ body {
|
|||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-blue-500 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-background {
|
.bg-background {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: hsl(var(--background) / var(--tw-bg-opacity));
|
background-color: hsl(var(--background) / var(--tw-bg-opacity));
|
||||||
@ -1308,6 +1337,11 @@ body {
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.object-cover {
|
||||||
|
-o-object-fit: cover;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
.p-1 {
|
.p-1 {
|
||||||
padding: 0.25rem;
|
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/getting-started", http.RedirectHandler("/docs/introduction", http.StatusSeeOther))
|
||||||
mux.Handle("GET /docs/introduction", templ.Handler(pages.Introduction()))
|
mux.Handle("GET /docs/introduction", templ.Handler(pages.Introduction()))
|
||||||
mux.Handle("GET /docs/how-to-use", templ.Handler(pages.HowToUse()))
|
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/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/sheet", templ.Handler(pages.Sheet()))
|
||||||
mux.Handle("GET /docs/components/tabs", templ.Handler(pages.Tabs()))
|
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")
|
fmt.Println("Server is running on http://localhost:8090")
|
||||||
http.ListenAndServe(":8090", mux)
|
http.ListenAndServe(":8090", mux)
|
||||||
|
@ -37,6 +37,10 @@ var Sections = []Section{
|
|||||||
Text: "Alert",
|
Text: "Alert",
|
||||||
Href: "/docs/components/alert",
|
Href: "/docs/components/alert",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Text: "Avatar",
|
||||||
|
Href: "/docs/components/avatar",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Text: "Button",
|
Text: "Button",
|
||||||
Href: "/docs/components/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