mirror of
https://github.com/axzilla/templui.git
synced 2025-02-21 00:32:58 +00:00
feat: add dropdown menu component
This commit is contained in:
parent
b4de2f5cb7
commit
6684f6bb45
@ -666,6 +666,10 @@ body {
|
||||
bottom: 1rem;
|
||||
}
|
||||
|
||||
.bottom-full {
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
.left-0 {
|
||||
left: 0px;
|
||||
}
|
||||
@ -690,6 +694,10 @@ body {
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
.top-full {
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
@ -711,6 +719,10 @@ body {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.-mr-1 {
|
||||
margin-right: -0.25rem;
|
||||
}
|
||||
|
||||
.mb-1 {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
@ -747,6 +759,10 @@ body {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.mr-2 {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
@ -887,6 +903,10 @@ body {
|
||||
width: 1.25rem;
|
||||
}
|
||||
|
||||
.w-56 {
|
||||
width: 14rem;
|
||||
}
|
||||
|
||||
.w-6 {
|
||||
width: 1.5rem;
|
||||
}
|
||||
@ -991,6 +1011,18 @@ 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));
|
||||
}
|
||||
|
||||
.scale-100 {
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
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));
|
||||
}
|
||||
|
||||
.scale-95 {
|
||||
--tw-scale-x: .95;
|
||||
--tw-scale-y: .95;
|
||||
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));
|
||||
}
|
||||
@ -1199,6 +1231,11 @@ body {
|
||||
border-color: hsl(var(--foreground) / 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));
|
||||
@ -1631,6 +1668,21 @@ body {
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
.ring-1 {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.ring-black {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.ring-opacity-5 {
|
||||
--tw-ring-opacity: 0.05;
|
||||
}
|
||||
|
||||
.ring-offset-background {
|
||||
--tw-ring-offset-color: hsl(var(--background) / 1);
|
||||
}
|
||||
@ -1687,6 +1739,10 @@ body {
|
||||
transition-duration: 300ms;
|
||||
}
|
||||
|
||||
.duration-75 {
|
||||
transition-duration: 75ms;
|
||||
}
|
||||
|
||||
.ease-in {
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
|
||||
}
|
||||
@ -1749,6 +1805,11 @@ body {
|
||||
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-50:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-600:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
|
||||
@ -1787,6 +1848,11 @@ body {
|
||||
color: rgb(107 114 128 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:text-gray-900:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:text-green-700:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(21 128 61 / var(--tw-text-opacity));
|
||||
@ -1824,6 +1890,10 @@ body {
|
||||
--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.focus\:ring-offset-2:focus {
|
||||
--tw-ring-offset-width: 2px;
|
||||
}
|
||||
|
||||
.focus-visible\:outline-none:focus-visible {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
@ -1878,6 +1948,16 @@ body {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.dark\:border-gray-600:is(.dark *) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(75 85 99 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-gray-800:is(.dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:from-gray-900:is(.dark *) {
|
||||
--tw-gradient-from: #111827 var(--tw-gradient-from-position);
|
||||
--tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position);
|
||||
@ -1908,6 +1988,11 @@ body {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:ring-gray-700:is(.dark *) {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(55 65 81 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.dark\:file\:text-foreground:is(.dark *)::file-selector-button {
|
||||
--tw-text-opacity: 1;
|
||||
color: hsl(var(--foreground) / var(--tw-text-opacity));
|
||||
@ -1918,6 +2003,16 @@ body {
|
||||
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:hover\:text-white:hover:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:focus\:ring-indigo-400:focus:is(.dark *) {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(129 140 248 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.sm\:my-8 {
|
||||
margin-top: 2rem;
|
||||
|
@ -28,6 +28,7 @@ func main() {
|
||||
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/dropdown-menu", templ.Handler(pages.DropdownMenu()))
|
||||
mux.Handle("GET /docs/components/icon", templ.Handler(pages.Icon()))
|
||||
mux.Handle("GET /docs/components/input", templ.Handler(pages.Input()))
|
||||
mux.Handle("GET /docs/components/modal", templ.Handler(pages.Modal()))
|
||||
|
@ -53,6 +53,10 @@ var Sections = []Section{
|
||||
Text: "Datepicker",
|
||||
Href: "/docs/components/datepicker",
|
||||
},
|
||||
{
|
||||
Text: "Dropdown Menu",
|
||||
Href: "/docs/components/dropdown-menu",
|
||||
},
|
||||
{
|
||||
Text: "Icon",
|
||||
Href: "/docs/components/icon",
|
||||
|
39
internals/ui/pages/dropdown_menu.templ
Normal file
39
internals/ui/pages/dropdown_menu.templ
Normal file
@ -0,0 +1,39 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"github.com/axzilla/goilerplate/pkg/components"
|
||||
"github.com/axzilla/goilerplate/internals/ui/layouts"
|
||||
"github.com/axzilla/goilerplate/internals/ui/showcase"
|
||||
)
|
||||
|
||||
templ DropdownMenu() {
|
||||
@layouts.DocsLayout() {
|
||||
<div>
|
||||
<div class="mb-16">
|
||||
<h1 class="text-3xl font-bold mb-2">Dropdown Menu</h1>
|
||||
<p class="mb-4 text-muted-foreground">The Dropdown Menu component provides a way to display a list of options in a compact form.</p>
|
||||
</div>
|
||||
@components.Tabs(components.TabsProps{
|
||||
Tabs: []components.Tab{
|
||||
{
|
||||
ID: "preview",
|
||||
Title: "Preview",
|
||||
Content: showcase.DropdownMenuShowcase(),
|
||||
},
|
||||
{
|
||||
ID: "code",
|
||||
Title: "Code",
|
||||
Content: CodeSnippetFromEmbedded("dropdown_menu.templ", "go", showcase.TemplFiles),
|
||||
},
|
||||
{
|
||||
ID: "component",
|
||||
Title: "Component",
|
||||
Content: CodeSnippetFromEmbedded("dropdown_menu.templ", "go", components.TemplFiles),
|
||||
},
|
||||
},
|
||||
TabsContainerClass: "md:w-1/2",
|
||||
ContentContainerClass: "w-full",
|
||||
})
|
||||
</div>
|
||||
}
|
||||
}
|
20
internals/ui/showcase/dropdown_menu.templ
Normal file
20
internals/ui/showcase/dropdown_menu.templ
Normal file
@ -0,0 +1,20 @@
|
||||
package showcase
|
||||
|
||||
import "github.com/axzilla/goilerplate/pkg/components"
|
||||
|
||||
templ DropdownMenuShowcase() {
|
||||
<div class="flex justify-center items-center border rounded-md py-16 px-4">
|
||||
<div class="flex gap-2 flex-wrap">
|
||||
@components.DropdownMenu(components.DropdownMenuProps{
|
||||
Label: "Click me",
|
||||
Position: "left",
|
||||
Items: []components.DropdownMenuItem{
|
||||
{Label: "Option 1", Value: "option1"},
|
||||
{Label: "Option 2", Value: "option2"},
|
||||
{Label: "Option 3", Value: "option3"},
|
||||
{Label: "With Link", Href: "https://github.com/axzilla/goilerplate", Target: "_blank"},
|
||||
},
|
||||
})
|
||||
</div>
|
||||
</div>
|
||||
}
|
134
pkg/components/dropdown_menu.templ
Normal file
134
pkg/components/dropdown_menu.templ
Normal file
@ -0,0 +1,134 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// DropdownMenuItem represents an item in the dropdown menu
|
||||
type DropdownMenuItem struct {
|
||||
Label string
|
||||
Value string
|
||||
Href string
|
||||
Target string
|
||||
}
|
||||
|
||||
// DropdownMenuProps defines the properties for the DropdownMenu component
|
||||
type DropdownMenuProps struct {
|
||||
Items []DropdownMenuItem
|
||||
Label string
|
||||
Class string
|
||||
Position string // "left" or "right", defaults to right if not specified
|
||||
}
|
||||
|
||||
// DropdownMenu renders a dropdown menu component.
|
||||
//
|
||||
// It provides a button that, when clicked, displays a list of options.
|
||||
// The menu can be positioned to the left or right of the button.
|
||||
// It supports both button and link items, with optional target attribute for links.
|
||||
//
|
||||
// Props:
|
||||
// - Items: Slice of DropdownMenuItem, defining the content of the dropdown
|
||||
// - Label: Text to display on the dropdown button
|
||||
// - Class: Additional CSS classes to apply to the root element
|
||||
// - Position: "left" or "right", determines the horizontal position of the dropdown
|
||||
//
|
||||
// DropdownMenuItem fields:
|
||||
// - Label: Text to display for the item
|
||||
// - Value: Value associated with the item (for button items)
|
||||
// - Href: URL for link items
|
||||
// - Target: Target attribute for link items (e.g., "_blank" for new tab)
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// @components.DropdownMenu(components.DropdownMenuProps{
|
||||
// Label: "Options",
|
||||
// Position: "right",
|
||||
// Items: []components.DropdownMenuItem{
|
||||
// {Label: "Option 1", Value: "opt1"},
|
||||
// {Label: "Option 2", Value: "opt2"},
|
||||
// {Label: "External Link", Href: "https://example.com", Target: "_blank"},
|
||||
// },
|
||||
// })
|
||||
//
|
||||
// The component uses Alpine.js for interactivity and Tailwind CSS for styling.
|
||||
// It includes dark mode support and responsive positioning.
|
||||
templ DropdownMenu(props DropdownMenuProps) {
|
||||
<div
|
||||
class={ "relative inline-block text-left", props.Class }
|
||||
x-data="{
|
||||
open: false,
|
||||
position: $el.dataset.position,
|
||||
verticalPosition: 'bottom',
|
||||
updatePosition() {
|
||||
const menu = this.$refs.menu;
|
||||
const rect = menu.getBoundingClientRect();
|
||||
const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
|
||||
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
||||
|
||||
if (this.position === 'left' && rect.left < 0) {
|
||||
this.position = 'right';
|
||||
} else if (this.position !== 'left' && rect.right > viewportWidth) {
|
||||
this.position = 'left';
|
||||
}
|
||||
|
||||
if (this.verticalPosition === 'bottom' && rect.bottom > viewportHeight) {
|
||||
this.verticalPosition = 'top';
|
||||
} else if (this.verticalPosition === 'top' && rect.top < 0) {
|
||||
this.verticalPosition = 'bottom';
|
||||
}
|
||||
}
|
||||
}"
|
||||
@resize.window="if (open) updatePosition()"
|
||||
data-position={ props.Position }
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex justify-center w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-800 text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-indigo-400"
|
||||
id="dropdown-menu-button"
|
||||
@click="open = !open; if (open) $nextTick(() => updatePosition())"
|
||||
>
|
||||
{ props.Label }
|
||||
<svg class="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div
|
||||
x-ref="menu"
|
||||
x-show="open"
|
||||
@click.away="open = false"
|
||||
x-transition:enter="transition ease-out duration-100"
|
||||
x-transition:enter-start="transform opacity-0 scale-95"
|
||||
x-transition:enter-end="transform opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-75"
|
||||
x-transition:leave-start="transform opacity-100 scale-100"
|
||||
x-transition:leave-end="transform opacity-0 scale-95"
|
||||
:class="{
|
||||
'right-0': position === 'left',
|
||||
'left-0': position !== 'left',
|
||||
'bottom-full mb-2': verticalPosition === 'top',
|
||||
'top-full mt-2': verticalPosition === 'bottom'
|
||||
}"
|
||||
class="absolute w-56 rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 dark:ring-gray-700 focus:outline-none z-10"
|
||||
>
|
||||
<div class="py-1" role="menu" aria-orientation="vertical" aria-labelledby="dropdown-menu-button">
|
||||
for _, item := range props.Items {
|
||||
if item.Href != "" {
|
||||
<a
|
||||
href={ templ.SafeURL(item.Href) }
|
||||
target={ item.Target }
|
||||
class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-white"
|
||||
role="menuitem"
|
||||
>{ item.Label }</a>
|
||||
} else {
|
||||
<button
|
||||
type="button"
|
||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-white"
|
||||
role="menuitem"
|
||||
@click={ fmt.Sprintf("$dispatch('dropdown-selected', { value: '%s' }); open = false", item.Value) }
|
||||
>{ item.Label }</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
214
pkg/components/dropdown_menu_templ.go
Normal file
214
pkg/components/dropdown_menu_templ.go
Normal file
@ -0,0 +1,214 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.778
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// DropdownMenuItem represents an item in the dropdown menu
|
||||
type DropdownMenuItem struct {
|
||||
Label string
|
||||
Value string
|
||||
Href string
|
||||
Target string
|
||||
}
|
||||
|
||||
// DropdownMenuProps defines the properties for the DropdownMenu component
|
||||
type DropdownMenuProps struct {
|
||||
Items []DropdownMenuItem
|
||||
Label string
|
||||
Class string
|
||||
Position string // "left" or "right", defaults to right if not specified
|
||||
}
|
||||
|
||||
// DropdownMenu renders a dropdown menu component.
|
||||
//
|
||||
// It provides a button that, when clicked, displays a list of options.
|
||||
// The menu can be positioned to the left or right of the button.
|
||||
// It supports both button and link items, with optional target attribute for links.
|
||||
//
|
||||
// Props:
|
||||
// - Items: Slice of DropdownMenuItem, defining the content of the dropdown
|
||||
// - Label: Text to display on the dropdown button
|
||||
// - Class: Additional CSS classes to apply to the root element
|
||||
// - Position: "left" or "right", determines the horizontal position of the dropdown
|
||||
//
|
||||
// DropdownMenuItem fields:
|
||||
// - Label: Text to display for the item
|
||||
// - Value: Value associated with the item (for button items)
|
||||
// - Href: URL for link items
|
||||
// - Target: Target attribute for link items (e.g., "_blank" for new tab)
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// @components.DropdownMenu(components.DropdownMenuProps{
|
||||
// Label: "Options",
|
||||
// Position: "right",
|
||||
// Items: []components.DropdownMenuItem{
|
||||
// {Label: "Option 1", Value: "opt1"},
|
||||
// {Label: "Option 2", Value: "opt2"},
|
||||
// {Label: "External Link", Href: "https://example.com", Target: "_blank"},
|
||||
// },
|
||||
// })
|
||||
//
|
||||
// The component uses Alpine.js for interactivity and Tailwind CSS for styling.
|
||||
// It includes dark mode support and responsive positioning.
|
||||
func DropdownMenu(props DropdownMenuProps) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var2 = []any{"relative inline-block text-left", props.Class}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/dropdown_menu.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" x-data=\"{ \n\t\t\topen: false,\n\t\t\tposition: $el.dataset.position,\n\t\t\tverticalPosition: 'bottom',\n\t\t\tupdatePosition() {\n\t\t\t\tconst menu = this.$refs.menu;\n\t\t\t\tconst rect = menu.getBoundingClientRect();\n\t\t\t\tconst viewportWidth = window.innerWidth || document.documentElement.clientWidth;\n\t\t\t\tconst viewportHeight = window.innerHeight || document.documentElement.clientHeight;\n\t\t\t\t\n\t\t\t\tif (this.position === 'left' && rect.left < 0) {\n\t\t\t\t\tthis.position = 'right';\n\t\t\t\t} else if (this.position !== 'left' && rect.right > viewportWidth) {\n\t\t\t\t\tthis.position = 'left';\n\t\t\t\t}\n\n\t\t\t\tif (this.verticalPosition === 'bottom' && rect.bottom > viewportHeight) {\n\t\t\t\t\tthis.verticalPosition = 'top';\n\t\t\t\t} else if (this.verticalPosition === 'top' && rect.top < 0) {\n\t\t\t\t\tthis.verticalPosition = 'bottom';\n\t\t\t\t}\n\t\t\t}\n\t\t}\" @resize.window=\"if (open) updatePosition()\" data-position=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(props.Position)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/dropdown_menu.templ`, Line: 82, Col: 32}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><button type=\"button\" class=\"inline-flex justify-center w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-800 text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-indigo-400\" id=\"dropdown-menu-button\" @click=\"open = !open; if (open) $nextTick(() => updatePosition())\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(props.Label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/dropdown_menu.templ`, Line: 90, Col: 16}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <svg class=\"-mr-1 ml-2 h-5 w-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\"><path fill-rule=\"evenodd\" d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\" clip-rule=\"evenodd\"></path></svg></button><div x-ref=\"menu\" x-show=\"open\" @click.away=\"open = false\" x-transition:enter=\"transition ease-out duration-100\" x-transition:enter-start=\"transform opacity-0 scale-95\" x-transition:enter-end=\"transform opacity-100 scale-100\" x-transition:leave=\"transition ease-in duration-75\" x-transition:leave-start=\"transform opacity-100 scale-100\" x-transition:leave-end=\"transform opacity-0 scale-95\" :class=\"{\n\t\t\t\t'right-0': position === 'left',\n\t\t\t\t'left-0': position !== 'left',\n\t\t\t\t'bottom-full mb-2': verticalPosition === 'top',\n\t\t\t\t'top-full mt-2': verticalPosition === 'bottom'\n\t\t\t}\" class=\"absolute w-56 rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 dark:ring-gray-700 focus:outline-none z-10\"><div class=\"py-1\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"dropdown-menu-button\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, item := range props.Items {
|
||||
if item.Href != "" {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(item.Href)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" target=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(item.Target)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/dropdown_menu.templ`, Line: 118, Col: 27}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-white\" role=\"menuitem\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(item.Label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/dropdown_menu.templ`, Line: 121, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button type=\"button\" class=\"block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-white\" role=\"menuitem\" @click=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("$dispatch('dropdown-selected', { value: '%s' }); open = false", item.Value))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/dropdown_menu.templ`, Line: 127, Col: 104}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(item.Label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/components/dropdown_menu.templ`, Line: 128, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
@ -658,6 +658,10 @@ body {
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.bottom-full {
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
.left-0 {
|
||||
left: 0px;
|
||||
}
|
||||
@ -670,6 +674,10 @@ body {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.top-full {
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
@ -687,6 +695,10 @@ body {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.-mr-1 {
|
||||
margin-right: -0.25rem;
|
||||
}
|
||||
|
||||
.mb-1 {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
@ -707,6 +719,10 @@ body {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.mr-2 {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
@ -827,6 +843,10 @@ body {
|
||||
width: 1.25rem;
|
||||
}
|
||||
|
||||
.w-56 {
|
||||
width: 14rem;
|
||||
}
|
||||
|
||||
.w-6 {
|
||||
width: 1.5rem;
|
||||
}
|
||||
@ -897,6 +917,18 @@ 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));
|
||||
}
|
||||
|
||||
.scale-100 {
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
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));
|
||||
}
|
||||
|
||||
.scale-95 {
|
||||
--tw-scale-x: .95;
|
||||
--tw-scale-y: .95;
|
||||
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));
|
||||
}
|
||||
@ -1065,6 +1097,11 @@ body {
|
||||
border-color: hsl(var(--foreground) / 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));
|
||||
@ -1126,6 +1163,11 @@ body {
|
||||
background-color: hsl(var(--secondary) / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-opacity-50 {
|
||||
--tw-bg-opacity: 0.5;
|
||||
}
|
||||
@ -1185,6 +1227,11 @@ body {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.py-1 {
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
@ -1404,6 +1451,21 @@ body {
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
.ring-1 {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.ring-black {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.ring-opacity-5 {
|
||||
--tw-ring-opacity: 0.05;
|
||||
}
|
||||
|
||||
.ring-offset-background {
|
||||
--tw-ring-offset-color: hsl(var(--background) / 1);
|
||||
}
|
||||
@ -1460,6 +1522,10 @@ body {
|
||||
transition-duration: 300ms;
|
||||
}
|
||||
|
||||
.duration-75 {
|
||||
transition-duration: 75ms;
|
||||
}
|
||||
|
||||
.ease-in {
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
|
||||
}
|
||||
@ -1518,6 +1584,11 @@ body {
|
||||
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-50:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-muted:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: hsl(var(--muted) / var(--tw-bg-opacity));
|
||||
@ -1546,6 +1617,11 @@ body {
|
||||
color: rgb(107 114 128 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:text-gray-900:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:text-primary\/80:hover {
|
||||
color: hsl(var(--primary) / 0.8);
|
||||
}
|
||||
@ -1578,6 +1654,10 @@ body {
|
||||
--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.focus\:ring-offset-2:focus {
|
||||
--tw-ring-offset-width: 2px;
|
||||
}
|
||||
|
||||
.focus-visible\:outline-none:focus-visible {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
@ -1624,11 +1704,26 @@ body {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.dark\:border-gray-600:is(.dark *) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(75 85 99 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-gray-800:is(.dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-gray-200:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(229 231 235 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:ring-gray-700:is(.dark *) {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(55 65 81 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.dark\:file\:text-foreground:is(.dark *)::file-selector-button {
|
||||
--tw-text-opacity: 1;
|
||||
color: hsl(var(--foreground) / var(--tw-text-opacity));
|
||||
@ -1639,6 +1734,16 @@ body {
|
||||
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:hover\:text-white:hover:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:focus\:ring-indigo-400:focus:is(.dark *) {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(129 140 248 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.sm\:my-8 {
|
||||
margin-top: 2rem;
|
||||
|
Loading…
x
Reference in New Issue
Block a user