diff --git a/CHANGELOG.md b/CHANGELOG.md index eb61704..b6425c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 2024-10-07 +- Added: Avatar component + +## 2024-10-07 + - Added: Input component - Added: Modal component - Added: Alert component diff --git a/assets/css/output.css b/assets/css/output.css index 4afc82a..5650457 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -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; } diff --git a/cmd/server/main.go b/cmd/server/main.go index d3d8571..ffbe1af 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -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) diff --git a/internals/shared/menudata.go b/internals/shared/menudata.go index 9a0c364..c1e8303 100644 --- a/internals/shared/menudata.go +++ b/internals/shared/menudata.go @@ -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", diff --git a/internals/ui/components/avatar.templ b/internals/ui/components/avatar.templ new file mode 100644 index 0000000..806fbcf --- /dev/null +++ b/internals/ui/components/avatar.templ @@ -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) { +
An image element with a fallback for representing the user.
+