{"id":16229859,"url":"https://github.com/indaco/tabber","last_synced_at":"2025-08-19T03:11:38.530Z","repository":{"id":239735323,"uuid":"792799818","full_name":"indaco/tabber","owner":"indaco","description":"Accessible, configurable and themeable server-rendered Tab component for Go web applications.","archived":false,"fork":false,"pushed_at":"2024-05-15T21:37:29.000Z","size":123990,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-28T19:06:13.555Z","etag":null,"topics":["component","go","golang","server-side","tabs","templ","ui-component"],"latest_commit_sha":null,"homepage":"","language":"Go","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-04-27T16:04:51.000Z","updated_at":"2025-02-14T13:09:04.000Z","dependencies_parsed_at":"2024-06-19T11:24:55.927Z","dependency_job_id":null,"html_url":"https://github.com/indaco/tabber","commit_stats":null,"previous_names":["indaco/tabber"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Ftabber","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Ftabber/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Ftabber/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indaco%2Ftabber/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/indaco","download_url":"https://codeload.github.com/indaco/tabber/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243996839,"owners_count":20380978,"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","go","golang","server-side","tabs","templ","ui-component"],"created_at":"2024-10-10T12:59:23.521Z","updated_at":"2025-08-19T03:11:38.515Z","avatar_url":"https://github.com/indaco.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\" style=\"font-size: 2.5rem;\"\u003e\n  tabber\n\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/indaco/tabber/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/tabber/\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://goreportcard.com/badge/github.com/indaco/tabber\" alt=\"go report card\" /\u003e\n    \u003c/a\u003e\n    \u0026nbsp;\n    \u003ca href=\"https://pkg.go.dev/github.com/indaco/tabber/\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://pkg.go.dev/badge/github.com/indaco/tabber/.svg\" alt=\"go reference\" /\u003e\n    \u003c/a\u003e\n    \u0026nbsp;\n    \u003ca href=\"https://www.jetify.com/devbox/docs/contributor-quickstart/\"\u003e\n      \u003cimg\n          src=\"https://www.jetify.com/img/devbox/shield_moon.svg\"\n          alt=\"Built with Devbox\"\n      /\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  \u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\n\u003c/p\u003e\n\nA fully accessible, themeable, and server-rendered Tab 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![tabber](https://raw.githubusercontent.com/indaco/gh-assets/main/tabber/demo.gif)\n\n\u003e **Disclaimer**: Please note that the demo video may not include the latest features and updates of the project. However, it still accurately represents the overall concepts and functionality.\n\n## Features\n\n- **Zero Dependencies**: No external CSS or JavaScript required — built entirely with Go and `templ`.\n- **Accessible by Design**: Fully compliant with the [WAI-ARIA Tabs Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/), including proper ARIA roles and keyboard navigation.\n- **Headless Component**: Offers full control over styling — bring your own design system or customize with CSS.\n- **Flexible Variants**: Use built-in variants or create your own reusable `tabber` styles as `templ` components.\n- **Responsive**: Adapts gracefully to different screen sizes and layouts.\n- **Multiple Instances**: Supports rendering multiple `tabber` components on the same page, each with distinct configuration and styling.\n- **Highly Configurable**: Customize alignment, positioning, and other behaviors to suit your app’s needs.\n- **Dark Mode Support**: Enable automatic dark mode based on the primary color or define a custom dark theme.\n- **CSS Variable Theming**: Easily theme components via CSS custom properties for consistent styling.\n\n## Installation\n\nTo install the `tabber` module, use the `go get` command:\n\n```sh\ngo get github.com/indaco/tabber@latest\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 `tabber` module into your project:\n\n```go\nimport \"github.com/indaco/tabber\"\n```\n\n### Configuration \u0026 Context\n\n```go\n// Default options\ntabberConfig := tabber.NewConfigBuilder().Build()\n```\n\n#### Available Options\n\nUsers can access each configuration option using the corresponding `With` method, such as `tabber.WithActiveTab(2)` or `tabber.WithPlacement(tabber.Left)`.\n\n| Option      | Type          | Description                                                                                                        |\n| :---------- | :------------ | :----------------------------------------------------------------------------------------------------------------- |\n| `ActiveTab` | _number_      | Specifies the index of the initially active tab. The indexing starts from 1 for the first tab.                     |\n| `Placement`  | [_Placement_]  | Determines the position of the tab list relative to the tab panels. Options: `Top`, `Bottom`, `Left`, and `Right`. |\n| `Variants`  | [][_Variant_] | Enables specific visual variants for the tab component.                                                            |\n| `Alignment` | [_Alignment_] | Defines the alignment of the tab items within the tab list. Options: `Start`, `Center`, and `End`.                 |\n\nTo allow configurations to be accessible at any level in the tabs hierarchy, `tabber` 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 `tabber` and attach it to the request context passed into the handler function.\n\n```go\nfunc HandleHome(w http.ResponseWriter, r *http.Request) {\n  tabberConfig := tabber.NewConfigBuilder().WithVariant(tabber.Underlined).Build()\n\n  configMap := tabber.NewConfigMap()\n  configMap.Add(\"my-tab\", tabberConfig)\n  ctx := context.WithValue(r.Context(), tabber.ConfigContextKey, configMap)\n  err := Page().Render(ctx, w)\n  if err != nil {\n    return\n  }\n}\n```\n\n#### Variants\n\nBy default `tabber` is headless, you have to enable single or multiple predefined variants.\n\n```go\n  tabberConfig := tabber.NewConfigBuilder().WithVariant(tabber.Underlined).Build()\n  // or enabling multiple variants. The first value is the default one.\n  tabberConfig := tabber.NewConfigBuilder().WithVariants(tabber.Underlined, tabber.Rounded).Build()\n```\n\nAvailable Predefined Variants:\n\n- `Accent`\n- `Bordered`\n- `Grouped`\n- `Rounded`\n- `Pills`\n- `Underlined`\n\nYou can also define and use your own variant. Please, refer to [Create Your Own Tabber Variant](#4-create-your-own-tabber-variant).\n\n### Tab Component Structure - Markup\n\nIn your `templ` file, defines the structure for the tab component.\n\n\u003e [!IMPORTANT]\n\u003e It is crucial to ensure that the value passed to `tabber.Root` **matches** the one used when adding the `tabberConfig` to the `configMap` as per step above. This ensures that multiple tabs on the same page function independently.\n\n```go\nconst (\n  profileIcon = `\u003csvg ...\u003e\u003c/svg\u003e`\n  settingsIcon = `\u003csvg ...\u003e\u003c/svg\u003e`\n)\n\ntempl Page() {\n  @tabber.Root(\"my-tab\") {\n    @tabber.TabList() {\n      @tabber.Tab(1, \"First\", tabber.Icon(profileIcon))\n      @tabber.Tab(2, \"Second\", tabber.Icon(settingsIcon))\n      @tabber.Tab(3, \"Third\")\n    }\n    @tabber.TabPanel(1) {\n      \u003ch3\u003e1 - Heading\u003c/h3\u003e\n      \u003cp\u003eLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n          incididunt ut labore et dolore magna aliqua.\u003c/p\u003e\n    }\n    @tabber.TabPanel(2) {\n      \u003ch3\u003e2 - Heading\u003c/h3\u003e\n      \u003cp\u003eLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n          incididunt ut labore et dolore magna aliqua.\u003c/p\u003e\n    }\n    @tabber.TabPanel(3) {\n      \u003ch3\u003e3 - Heading\u003c/h3\u003e\n      \u003cp\u003eLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor\n          incididunt ut labore et dolore magna aliqua.\u003c/p\u003e\n    }\n  }\n}\n```\n\n### CSS and Javascript\n\n`tabber` 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- `TabberCSS`: Supplies the required CSS, encapsulating the visual design and layout specifics of the component. Moreover, `TabberCSS` selectively includes styles specific to the enabled style variant, ensuring that only essential styles are loaded to optimize page performance and minimize unnecessary overhead.\n- `TabberJS`: 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, `tabber` 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- `TabberCSSToGoHTML`: Renders the `TabberCSS` component into a `template.HTML` value.\n- `TabberJSToGoHTML`: Renders the `TabberJS` 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;\"\u003etabber.\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 tab component. |\n\n\u003ch3 style=\"padding: 0.25rem; width: fit-content; color: #6b7280; background-color: #bef264;\"\u003etabber.\u003cspan style=\"font-weight: 600; color: #1f2937;\"\u003eTabList\u003c/span\u003e\u003c/h3\u003e\n\nNone\n\n\u003ch3 style=\"padding: 0.25rem; width: fit-content; color: #6b7280; background-color: #bef264;\"\u003etabber.\u003cspan style=\"font-weight: 600; color: #1f2937;\"\u003eTab\u003c/span\u003e\u003c/h3\u003e\n\n| Property | Type        | Description                                 |\n| :------- | :---------- | :------------------------------------------ |\n| `value`  | _int_       | The unique identifier for the tab.          |\n| `label`  | _string_    | The text displayed for the tab button.      |\n| `icon`   | [_TabIcon_] | The icon displayed close to the tab button. |\n\n\u003ch3 style=\"padding: 0.25rem; width: fit-content; color: #6b7280; background-color: #bef264;\"\u003etabber.\u003cspan style=\"font-weight: 600; color: #1f2937;\"\u003ePanel\u003c/span\u003e\u003c/h3\u003e\n\n| Property | Type  | Description                                                           |\n| :------- | :---- | :-------------------------------------------------------------------- |\n| `value`  | _int_ | The unique identifier for the tab panel referenced by the tab button. |\n\n## Accessibility (A11Y)\n\nThe tab component is designed to be accessible to screen readers and supports keyboard navigation according to the [WAI-ARIA Tabs Design Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).\n\n### Screen Reader Support\n\nEnsure that proper ARIA attributes are used to convey the state and role of the tab elements.\n\n### Keyboard Interaction\n\n- **Focusing the Tab Item**:\n  - Use the `Tab` key to navigate to the tab button. Pressing `Enter` or `Space` will switch the tab.\n- **Navigating within the Tab component**:\n  - Use the `Arrow` keys to move focus between items within the tabs list.\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 tab item with a label that starts with the typed character if such a tab item exists. Otherwise, focus does not move.\n- **Selecting an Item**:\n  - Press `Enter` to select the currently focused item in the tabs list.\n\n## Theming\n\nCustomizing the appearance of `tabber` to align with your design preferences is both straightforward and flexible, largely due to its extensive use of CSS custom properties (CSS variables) prefixed with `gtb`. For a comprehensive list of CSS custom properties, along with their default values and descriptions, please consult the tabber [CSS custom Props](./docs/css-props.md) document.\n\nThere are three primary methods you can employ to easily adjust `tabber` styles and variants. Depending on your specific requirements, choose the most suitable approach to achieve your desired styling.\n\nIn addition, you would create your own `tabber` variant as reusable `templ` component, register and use it. Refer to [Create your own tabber variant](#4-create-your-own-tabber-variant).\n\n### 1. Customise Color Palette\n\nBy default, `tabber` utilizes a single `hsl` color and dynamically generates shades of it using the `color-mix` function in the `oklab` color space. To change the primary color, simply override the `--gtb-base` property with your desired value. Refer to the [colors](./docs/css-props.md#colors) section in the CSS custom props documentation for more details.\n\n**[Example](_examples/theming/customise-color/)**\n\nIf you prefer a different color space other than `oklab`, you can customize it by overriding the `--gtb-color-space` property with your preferred value. For a comprehensive list of available color spaces, refer to the [documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix).\n\nTo view the default base color shades and their derivations, consult the _tabber-css.templ_ file [here](./tabber-css.templ#L16-L89).\n\n### 2. Customise Theme\n\nIf one of the predefined style variants suits your needs but you desire more flexibility in certain aspects, such as using different colors instead of shades of the base color, you can define values for the [Simplified set of css custom props](./docs/css-props.md#simplified-set-of-css-custom-props-to-make-themes).\n\n**[Example](_examples/theming/customise-theme/)**\n\n### 3. Customise CSS Variant\n\nThe majority of tabber components utilize CSS custom properties to facilitate the creation of style variants and enable extensive customization of styles.\n\n**[Example](_examples/theming/customise-variant/)**\n\n### 4. Create Your Own Tabber Variant\n\nHere, we are defining and creating a new variant called `sketched` in the `sketched-variant.templ` file:\n\n```go\n/*\n * sketched-variant.templ\n */\nimport \"github.com/indaco/tabber\"\n\nconst Sketched tabber.Variant = \"sketched\"\n\n// SketchedVariant is a new variant for tabber.\ntype SketchedVariant struct{}\n\n// Implement TabberVariant interface\nfunc (nv SketchedVariant) GetClassName() templ.Component {\n  return SketchedVariantCss()\n}\n\ntempl SketchedVariantCss() {\n  \u003cstyle\u003e\n    :root {\n      [data-variant=\"sketched\"] {\n        --gtb-root-py: 1.5em;\n        --gtb-root-px: 2em;\n        --gtb-root-border-width: 4px;\n        --gtb-root-border-style: solid;\n        /* refer to the source code... */\n      }\n    }\n  \u003c/style\u003e\n}\n```\n\nUse your newly create `sketched` variant:\n\n```go\n// register the Sketched variant and use it.\ntabber.RegisterVariant(Sketched, SketchedVariant{})\ntabberConfig := tabber.NewConfigBuilder().WithVariant(Sketched).Build()\n\nconfigMap := tabber.NewConfigMap()\nconfigMap.Add(\"sketched-tabber\", tabberConfig)\n```\n\n**[Example](_examples/theming/variant-creation/)**\n\n## Examples\n\nTo run the examples, make sure to compile them first by running `make examples`. Then, move to the example folder and run\n\n```bash\ncd _examples/demo/\ngo run .\n```\n\n- [demo](_examples/demo)\n- [use with `template/html`](_examples/go-html-template)\n- [multiple-tabs](_examples/multiple-tabs/)\n- [customise color](_examples/theming/customise-color/)\n- [customise theme](_examples/theming/customise-theme/)\n- [customise variant](_examples/theming/customise-variant/)\n- [variant creation](_examples/theming/variant-creation/)\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 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\n[_Placement_]: ./types.go#L11-L17\n[_Alignment_]: ./types.go#L19-L25\n[_Variant_]: ./types.go#L23-29\n[_TabIcon_]: ./types.go#L35-L38\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Findaco%2Ftabber","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Findaco%2Ftabber","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Findaco%2Ftabber/lists"}