diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b999cb..904e932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Changed: Improve docs UI - Changed: Make Product Hunt Badge smaller on footer - Changed: Some UI changes on showcase section +- Changed: button attributes now as a prop - Fixed: Width issue on tabs component ## 2024-10-05 diff --git a/assets/css/output.css b/assets/css/output.css index 6585cc5..d288391 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -662,6 +662,10 @@ body { bottom: 0px; } +.bottom-4 { + bottom: 1rem; +} + .left-0 { left: 0px; } @@ -674,6 +678,10 @@ body { right: 0.5rem; } +.right-4 { + right: 1rem; +} + .top-0 { top: 0px; } @@ -682,14 +690,6 @@ body { top: 0.5rem; } -.bottom-4 { - bottom: 1rem; -} - -.right-4 { - right: 1rem; -} - .z-10 { z-index: 10; } @@ -707,11 +707,6 @@ body { margin-right: auto; } -.my-8 { - margin-top: 2rem; - margin-bottom: 2rem; -} - .mb-12 { margin-bottom: 3rem; } @@ -752,6 +747,10 @@ body { margin-right: 0.5rem; } +.mt-16 { + margin-top: 4rem; +} + .mt-2 { margin-top: 0.5rem; } @@ -764,10 +763,6 @@ body { display: block; } -.inline-block { - display: inline-block; -} - .flex { display: flex; } @@ -776,6 +771,10 @@ body { display: inline-flex; } +.table { + display: table; +} + .hidden { display: none; } @@ -856,14 +855,14 @@ body { width: 16rem; } -.w-full { - width: 100%; -} - .w-\[350px\] { width: 350px; } +.w-full { + width: 100%; +} + .max-w-3xl { max-width: 48rem; } @@ -880,6 +879,15 @@ body { flex: 1 1 0%; } +.border-collapse { + border-collapse: collapse; +} + +.-translate-x-1\/4 { + --tw-translate-x: -25%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .-translate-x-full { --tw-translate-x: -100%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -895,11 +903,6 @@ body { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.translate-x-1\/4 { - --tw-translate-x: 25%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .translate-x-full { --tw-translate-x: 100%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -920,11 +923,6 @@ body { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.-translate-x-1\/4 { - --tw-translate-x: -25%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .transform { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } @@ -1047,10 +1045,6 @@ body { border-radius: calc(var(--radius) - 2px); } -.rounded-full { - border-radius: 9999px; -} - .border { border-width: 1px; } @@ -1076,6 +1070,11 @@ body { border-color: hsl(var(--border) / var(--tw-border-opacity)); } +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + .border-input { --tw-border-opacity: 1; border-color: hsl(var(--input) / var(--tw-border-opacity)); @@ -1100,6 +1099,11 @@ body { background-color: hsl(var(--destructive) / var(--tw-bg-opacity)); } +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + .bg-gray-700 { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); @@ -1133,22 +1137,12 @@ body { background-image: linear-gradient(to bottom right, var(--tw-gradient-stops)); } -.from-gray-900 { - --tw-gradient-from: #111827 var(--tw-gradient-from-position); - --tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} - .from-gray-100 { --tw-gradient-from: #f3f4f6 var(--tw-gradient-from-position); --tw-gradient-to: rgb(243 244 246 / 0) var(--tw-gradient-to-position); --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); } -.to-black { - --tw-gradient-to: #000 var(--tw-gradient-to-position); -} - .to-white { --tw-gradient-to: #fff var(--tw-gradient-to-position); } @@ -1182,10 +1176,6 @@ body { padding: 1.5rem; } -.p-8 { - padding: 2rem; -} - .px-2 { padding-left: 0.5rem; padding-right: 0.5rem; @@ -1201,11 +1191,6 @@ body { padding-right: 1rem; } -.px-6 { - padding-left: 1.5rem; - padding-right: 1.5rem; -} - .px-8 { padding-left: 2rem; padding-right: 2rem; @@ -1221,6 +1206,11 @@ body { padding-bottom: 3rem; } +.py-16 { + padding-top: 4rem; + padding-bottom: 4rem; +} + .py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; @@ -1246,15 +1236,14 @@ body { padding-bottom: 2rem; } -.py-16 { - padding-top: 4rem; - padding-bottom: 4rem; -} - .pb-4 { padding-bottom: 1rem; } +.pb-8 { + padding-bottom: 2rem; +} + .pl-6 { padding-left: 1.5rem; } @@ -1263,12 +1252,8 @@ body { padding-top: 0px; } -.pb-2 { - padding-bottom: 0.5rem; -} - -.pb-8 { - padding-bottom: 2rem; +.text-left { + text-align: left; } .text-center { @@ -1363,11 +1348,6 @@ body { color: hsl(var(--foreground) / var(--tw-text-opacity)); } -.text-gray-300 { - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); -} - .text-gray-400 { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); @@ -1383,6 +1363,11 @@ body { color: rgb(55 65 81 / var(--tw-text-opacity)); } +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + .text-muted-foreground { --tw-text-opacity: 1; color: hsl(var(--muted-foreground) / var(--tw-text-opacity)); @@ -1408,11 +1393,6 @@ body { color: rgb(255 255 255 / var(--tw-text-opacity)); } -.text-gray-900 { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity)); -} - .underline { text-decoration-line: underline; } @@ -1526,11 +1506,6 @@ body { background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } -.hover\:bg-gray-200:hover { - --tw-bg-opacity: 1; - background-color: rgb(229 231 235 / var(--tw-bg-opacity)); -} - .hover\:bg-gray-600:hover { --tw-bg-opacity: 1; background-color: rgb(75 85 99 / var(--tw-bg-opacity)); @@ -1726,16 +1701,6 @@ body { padding-right: 1.5rem; } - .sm\:px-8 { - padding-left: 2rem; - padding-right: 2rem; - } - - .sm\:py-3 { - padding-top: 0.75rem; - padding-bottom: 0.75rem; - } - .sm\:text-2xl { font-size: 1.5rem; line-height: 2rem; @@ -1753,14 +1718,6 @@ body { } @media (min-width: 768px) { - .md\:block { - display: block; - } - - .md\:inline { - display: inline; - } - .md\:flex { display: flex; } diff --git a/internals/ui/components/button.templ b/internals/ui/components/button.templ index 376df8b..4439e4a 100644 --- a/internals/ui/components/button.templ +++ b/internals/ui/components/button.templ @@ -1,30 +1,66 @@ package components +// ButtonVariant represents the visual style of the button. type ButtonVariant string + +// ButtonSize represents the size of the button. type ButtonSize string +// Constants for button variants and sizes. const ( + Default ButtonVariant = "default" Destructive ButtonVariant = "destructive" Outline ButtonVariant = "outline" Secondary ButtonVariant = "secondary" Ghost ButtonVariant = "ghost" Link ButtonVariant = "link" + Md ButtonSize = "md" Sm ButtonSize = "sm" Lg ButtonSize = "lg" Icon ButtonSize = "icon" ) +// ButtonProps defines the properties for the Button component. type ButtonProps struct { - Class string - Text string - Variant ButtonVariant - Size ButtonSize + // Class specifies additional CSS classes to apply to the button. + // Default: "" (empty string) + Class string + + // Text is the content of the button. + // Default: "" (empty string) + Text string + + // Variant determines the visual style of the button. + // Default: Default + Variant ButtonVariant + + // Size sets the size of the button. + // Default: Md + Size ButtonSize + + // FullWidth determines whether the button should take up the full width of its container. + // Default: false FullWidth bool - Href string - Target string + + // Href, if provided, renders the button as an anchor tag with this URL. + // Default: "" (empty string) + Href string + + // Target specifies the target attribute for the anchor tag (only used when Href is provided). + // Default: "" (empty string) + Target string + + // Disabled specifies whether the button is disabled. + // Default: "false" + Disabled string + + // Attributes allows passing additional HTML attributes to the button or anchor element. + // Default: nil + Attributes templ.Attributes } +// getVariantClasses returns the CSS classes for the given button variant. func getVariantClasses(variant ButtonVariant) string { switch variant { case Destructive: @@ -42,6 +78,7 @@ func getVariantClasses(variant ButtonVariant) string { } } +// getSizeClasses returns the CSS classes for the given button size. func getSizeClasses(size ButtonSize) string { switch size { case Sm: @@ -55,10 +92,35 @@ func getSizeClasses(size ButtonSize) string { } } -templ Button(props ButtonProps, attrs map[string]any) { +// Button renders a button or anchor component based on the provided props. +// It can be customized with various visual styles, sizes, and behaviors. +// +// Usage: +// +// @components.Button(components.ButtonProps{ +// Text: "Click me", +// Variant: components.Primary, +// Size: components.Md, +// FullWidth: false, +// Attributes: templ.Attributes{ +// "aria-label": "Click this button", +// "data-testid": "main-button", +// }, +// }) +// +// Props: +// - Class: Additional CSS classes to apply to the button. Default: "" (empty string) +// - Text: The text content of the button. Default: "" (empty string) +// - Variant: The visual style of the button (e.g., Default, Destructive, Outline). Default: Default +// - Size: The size of the button (Md, Sm, Lg, Icon). Default: Md +// - FullWidth: Whether the button should take up the full width of its container. Default: false +// - Href: If provided, renders the button as an anchor tag with this URL. Default: "" (empty string) +// - Target: The target attribute for the anchor tag (only used when Href is provided). Default: "" (empty string) +// - Disabled: Whether the button is disabled. Default: "false" +// - Attributes: Additional HTML attributes to apply to the button or anchor element. Default: nil +templ Button(props ButtonProps) { if props.Href != "" { { props.Text } { children... } } else {