{"id":16229817,"url":"https://github.com/indaco/gropdown","last_synced_at":"2025-10-04T05:44:35.087Z","repository":{"id":227953371,"uuid":"765109232","full_name":"indaco/gropdown","owner":"indaco","description":"A fully accessible, configurable and themeable dropdown component for Go web applications. ","archived":false,"fork":false,"pushed_at":"2025-04-02T09:17:44.000Z","size":7186,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-02T10:25:42.689Z","etag":null,"topics":["component","dropdown","go","golang","server-side","templ","ui-component"],"latest_commit_sha":null,"homepage":"","language":"templ","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/indaco.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-29T09:52:06.000Z","updated_at":"2025-04-02T09:17:22.000Z","dependencies_parsed_at":"2024-06-21T12:57:04.100Z","dependency_job_id":"050fa615-d709-419e-aeb5-ca96efab1f5f","html_url":"https://github.com/indaco/gropdown","commit_stats":null,"previous_names":["indaco/gropdown"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/indaco/gropdown","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Fgropdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Fgropdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Fgropdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Fgropdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/indaco","download_url":"https://codeload.github.com/indaco/gropdown/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Fgropdown/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264614677,"owners_count":23637633,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component","dropdown","go","golang","server-side","templ","ui-component"],"created_at":"2024-10-10T12:59:18.364Z","updated_at":"2025-10-04T05:44:30.030Z","avatar_url":"https://github.com/indaco.png","language":"templ","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\" style=\"font-size: 2.5rem;\"\u003e\n  gropdown\n\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/indaco/gropdown/blob/main/LICENSE\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-mit-blue?style=flat-square\u0026logo=none\" alt=\"license\" /\u003e\n  \u003c/a\u003e\n  \u0026nbsp;\n  \u003ca href=\"https://goreportcard.com/report/github.com/indaco/gropdown/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://goreportcard.com/badge/github.com/indaco/gropdown\" alt=\"go report card\" /\u003e\n  \u003c/a\u003e\n  \u0026nbsp;\n  \u003ca href=\"https://pkg.go.dev/github.com/indaco/gropdown/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://pkg.go.dev/badge/github.com/indaco/gropdown/.svg\" alt=\"go reference\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.jetify.com/devbox/docs/contributor-quickstart/\"\u003e\n    \u003cimg  src=\"https://www.jetify.com/img/devbox/shield_moon.svg\" alt=\"Built with Devbox\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e •\n  \u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e •\n  \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e •\n  \u003ca href=\"#api-reference\"\u003eAPI Reference\u003c/a\u003e •\n  \u003ca href=\"#accessibility-a11y\"\u003eAccessibility (A11Y)\u003c/a\u003e •\n  \u003ca href=\"#theming\"\u003eTheming\u003c/a\u003e •\n  \u003ca href=\"#examples\"\u003eExamples\u003c/a\u003e\n\u003c/p\u003e\n\nA fully accessible, themeable, and server-rendered dropdown component for Go web applications. Built with the [templ](https://github.com/a-h/templ) library for seamless integration into Go-based frontends.\n\n![gropdown](https://raw.githubusercontent.com/indaco/gh-assets/main/gropdown/demo.gif)\n\n## Features\n\n- **Accessible by Design**: Fully compliant with the [WAI-ARIA Menu Button Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/), including proper roles, focus management, and keyboard interactions.\n- **Zero Dependencies**: Built with native Go and `templ` — no external JavaScript or CSS required.\n- **Highly Configurable**: Customize behavior such as positioning, default open state, and alignment to fit your needs.\n- **Multiple Instances**: Use several `gropdown` components on the same page, each with its own configuration and styling.\n- **Themeable via CSS Variables**: Easily style the component using CSS custom properties. Supports light and dark themes via the `data-theme` attribute and allows for custom themes.\n- **Versatile Items**: Dropdown items can be buttons or links (`\u003ca\u003e`). External links are automatically marked with an icon for better UX.\n\n## Installation\n\nTo install the Dropdown module, use the `go get` command:\n\n```sh\ngo get github.com/indaco/gropdown\n```\n\nEnsure your project is using Go Modules (it will have a `go.mod` file in its root if it already does).\n\n## Usage\n\n\u003e [!TIP]\n\u003e refer to the [Examples](#examples) section.\n\nImport the Dropdown module into your project:\n\n```go\nimport \"github.com/indaco/gropdown\"\n```\n\n### Configuration \u0026 Context\n\n```go\n// Default options\ndropdownConfig := gropdown.NewConfigBuilder().Build()\n```\n\n#### Available Options\n\nUsers can access each configuration option using the corresponding `With` method, such as `gropdown.WithOpen(true)` or `gropdown.WithPosition(gropdown.Left)`.\n\n| Option                | Type          | Default  | Description                                                                                                           |\n|:----------------------|:--------------|:---------|:----------------------------------------------------------------------------------------------------------------------|\n| `Open`                | _bool_        | `false`  | indicates whether the dropdown menu is currently open.                                                                |\n| `Placement`           | [_Placement_] | `Bottom` | indicates the position of the dropdown content relative to the button. Options: `Top`, `Bottom`, `Left`, and `Right`. |\n| `Animation`           | _bool_        | `true`   | indicates whether the dropdown button should use animations on open and close.                                        |\n| `CloseOnOutsideClick` | _bool_        | `true`   | indicates whether the dropdown should be closed when a click occurs outside of it.                                    |\n\nTo allow configurations to be accessible at any level in the dropdown hierarchy and make each component on the same page function independently, `gropdown` makes use of the templ component context and the implicit `ctx` variable. You can read more about templ component context [here](https://templ.guide/syntax-and-usage/context#using-context).\n\nIn your function handler, create a configuration for `gropdown` and attach it to the request context passed into the handler function.\n\n```go\nfunc HandleHome(w http.ResponseWriter, r *http.Request) {\n  dropdownConfig := gropdown.NewConfigBuilder().WithPlacement(gropdown.Top).Build()\n\n  configMap := gropdown.NewConfigMap()\n  configMap.Add(\"demo\", dropdownConfig)\n  ctx := context.WithValue(r.Context(), gropdown.ConfigContextKey, configMap)\n  err := Page().Render(ctx, w)\n  if err != nil {\n    return\n  }\n}\n```\n\n### Dropdown Component Structure - Markup\n\nIn your `templ` file, defines the structure for the dropdown component.\n\n\u003e [!IMPORTANT]\n\u003e It is crucial to ensure that the value passed to `gropdown.Root` **matches** the one used when adding the `gropdownConfig` to the `configMap` as per step above. This ensures that multiple dropdowns on the same page function independently.\n\n```go\n// Set the button label.\n@gropdown.Root(\"demo\") {\n  @gropdown.Button(\"Menu\")\n  @gropdown.Content() {\n    @gropdown.Item(\"Profile\",\n      gropdown.ItemOptions{\n        Href: \"/profile\",\n        Icon: profileIcon,\n      },\n    )\n    @gropdown.Item(\"Settings\",\n      gropdown.ItemOptions{\n        Href: \"/settings\",\n        Icon: settingsIcon,\n      },\n    )\n    @gropdown.Divider()\n    @gropdown.Item(\"GitHub\",\n      gropdown.ItemOptions{\n        Href:     \"https://github.com\",\n        External: true,\n        Icon:     globeIcon,\n      },\n    )\n    @gropdown.Divider()\n    @gropdown.Item(\"Button\",\n      gropdown.ItemOptions{\n        Icon:  clickIcon,\n        Attrs: templ.Attributes{\"onclick\": \"alert('Hello gropdown');\"},\n      },\n    )\n  }\n}\n```\n\n### CSS and Javascript\n\n`gropdown` leverages the `templ` library's features, including CSS Components and JavaScript Templates, to encapsulate all necessary styling and functionality without relying on external dependencies.\n\n- `GropdownCSS`: it supplies the required CSS, encapsulating the visual design and layout specifics of the component.\n- `GropdownJS`: it provides the JavaScript logic essential for dynamic behaviors such as displaying, keyboard navigation and interaction with the component.\n\nTo facilitate integration with Go's `template/html` standard library, `gropdown` includes a dedicated `HTMLGenerator` type to seamlessly integrate the component into web applications built with Go's `html/template standard` library.\n\nThere are methods acting as wrappers to the templ's `templ.ToGoHTML`, generate the necessary HTML to be embedded them into server-rendered pages:\n\n- `GropdownCSSToGoHTML`: render the `GropdownCSS` component into a `template.HTML` value.\n- `GropdownJSToGoHTML`: render the `GropdownJS` component into a `template.HTML` value.\n\n## API Reference\n\n\u003ch3 style=\"padding: 0.25rem; width: fit-content; color: #6b7280; background-color: #bef264;\"\u003egropdown.\u003cspan style=\"font-weight: 600; color: #1f2937;\"\u003eRoot\u003c/span\u003e\u003c/h3\u003e\n\n| Property | Type     | Description                                            |\n|:---------|:---------|:-------------------------------------------------------|\n| `id`     | _string_ | The unique identifier for the dropdown menu component. |\n\n\u003ch3 style=\"padding: 0.25rem; width: fit-content; color: #6b7280; background-color: #bef264;\"\u003egropdown.\u003cspan style=\"font-weight: 600; color: #1f2937;\"\u003eButton\u003c/span\u003e\u003c/h3\u003e\n\n| Property | Type           | Description                                          |\n|:---------|:---------------|:-----------------------------------------------------|\n| `label`  | _string_       | The text displayed for the dropdown menu button.     |\n| `icon`   | [_ButtonIcon_] | The icon displayed next to the dropdown menu button. |\n\n\u003ch3 style=\"padding: 0.25rem; width: fit-content; color: #6b7280; background-color: #bef264;\"\u003egropdown.\u003cspan style=\"font-weight: 600; color: #1f2937;\"\u003eContent\u003c/span\u003e\u003c/h3\u003e\n\nNone\n\n\u003ch3 style=\"padding: 0.25rem; width: fit-content; color: #6b7280; background-color: #bef264;\"\u003egropdown.\u003cspan style=\"font-weight: 600; color: #1f2937;\"\u003eItem\u003c/span\u003e\u003c/h3\u003e\n\n| Property | Type            | Description                                                          |\n|:---------|:----------------|:---------------------------------------------------------------------|\n| `label`  | _string_        | The text displayed for the dropdown menu item.                       |\n| `opts`   | [_ItemOptions_] | The options for configuring the behavior and appearance of the item. |\n\n\u003ch3 style=\"padding: 0.25rem; width: fit-content; color: #6b7280; background-color: #bef264;\"\u003egropdown.\u003cspan style=\"font-weight: 600; color: #1f2937;\"\u003eDivider\u003c/span\u003e\u003c/h3\u003e\n\nNone\n\n## Accessibility (A11Y)\n\nThe dropdown component is designed to be accessible to screen readers and supports keyboard navigation according to the [WAI-ARIA pattern for menu buttons](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-actions/#kbd_label).\n\n### Screen Reader Support\n\nEnsure that proper ARIA attributes are used to convey the state and role of the dropdown elements.\n\n### Keyboard Interaction\n\n- **Focusing the Dropdown**:\n  - Use the `Tab` key to navigate to the dropdown button. Pressing `Enter` or `Space` will open the dropdown menu.\n- **Navigating within the Dropdown Menu**:\n  - Use the `Arrow` keys to move focus between items within the dropdown menu.\n  - Pressing `Home` or `End` keys will move focus to the first or last item respectively.\n  - Use `A-Z` or `a-z` keys to move focus to the next menu item with a label that starts with the typed character if such a menu item exists. Otherwise, focus does not move.\n- **Selecting an Item**:\n  - Press `Enter` to select the currently focused item in the dropdown menu.\n- **Closing the Dropdown**:\n  - Press `Escape` to close the dropdown and sets focus to the menu button.\n\n## Theming\n\nDropdown is themeable using CSS variables (prefix `gdd`) to customize the appearance according to your design.\n\nBy default, it supports both light and dark modes. In addition to the built-in modes, you can define your\nown custom themes using the `data-theme` attribute. Simply add a `data-theme` attribute to the root element of your application\nand define the corresponding CSS variables for your custom theme.\n\nFor a comprehensive list of CSS custom properties, along with their default values and descriptions, please consult the `gropdown` [CSS custom Props](./docs/css-props.md) document.\n\n## Examples\n\n- [with `a-h/templ`](_examples/a-h-templ)\n- [custom animations](_examples/custom-animations)\n- [custom button icon](_examples/custom-button-icon)\n- [with `template/html`](_examples/go-html-template)\n- [icon only button](_examples/icon-only-button)\n- [multiple dropdowns](_examples/multiple-dropdowns/)\n- [positioning](_examples/positioning/)\n- [theming](_examples/theming)\n\n## Contributing\n\nContributions are welcome! Feel free to open an issue or submit a pull request.\n\n### Development Environment Setup\n\nTo set up a development environment for this repository, you can use [devbox](https://www.jetify.com/devbox) along with the provided `devbox.json` configuration file.\n\n1. Install devbox by following the instructions in the [devbox documentation](https://www.jetify.com/devbox/docs/installing_devbox/).\n2. Clone this repository to your local machine.\n3. Navigate to the root directory of the cloned repository.\n4. Run `devbox install` to install all packages mentioned in the `devbox.json` file.\n5. Run `devbox shell` to start a new shell with access to the environment.\n6. Once the devbox environment is set up, you can start developing, testing, and contributing to the repository.\n\n### Using the Makefile\n\nAdditionally, you can make use of the provided `Makefile` to run various tasks:\n\n```bash\nmake build       # The main build target\nmake examples    # Process templ files in the _examples folder\nmake templ       # Process TEMPL files\nmake test        # Run go tests\nmake help        # Print this help message\n```\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n\u003c!-- Resources --\u003e\n[_ItemOptions_]: ./types.go#L22-L27\n[_ButtonIcon_]: ./types.go#L30-L33\n[_Placement_]: ./constants.go#L8-L11\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Findaco%2Fgropdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Findaco%2Fgropdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Findaco%2Fgropdown/lists"}