{"id":20770554,"url":"https://github.com/ably/ably-ui","last_synced_at":"2026-02-06T13:22:16.500Z","repository":{"id":37413497,"uuid":"305371822","full_name":"ably/ably-ui","owner":"ably","description":"Home of the Ably design system library.","archived":false,"fork":false,"pushed_at":"2025-04-30T13:36:26.000Z","size":13455,"stargazers_count":2,"open_issues_count":1,"forks_count":4,"subscribers_count":20,"default_branch":"main","last_synced_at":"2025-04-30T13:44:57.532Z","etag":null,"topics":["components-library","design-system","rails","react","viewcomponents"],"latest_commit_sha":null,"homepage":"https://ably.github.io/ably-ui","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ably.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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,"zenodo":null}},"created_at":"2020-10-19T12:10:48.000Z","updated_at":"2025-04-30T13:36:29.000Z","dependencies_parsed_at":"2022-07-09T13:47:52.905Z","dependency_job_id":"13704141-f09f-4d64-91fc-7e5ae535d9a0","html_url":"https://github.com/ably/ably-ui","commit_stats":{"total_commits":1042,"total_committers":19,"mean_commits":54.8421052631579,"dds":"0.31573896353166986","last_synced_commit":"a4c833c9eb82f8816f20458a84c4ed8c89972520"},"previous_names":[],"tags_count":302,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ably%2Fably-ui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ably%2Fably-ui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ably%2Fably-ui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ably%2Fably-ui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ably","download_url":"https://codeload.github.com/ably/ably-ui/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251714021,"owners_count":21631635,"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":["components-library","design-system","rails","react","viewcomponents"],"created_at":"2024-11-17T12:10:20.359Z","updated_at":"2026-01-30T17:06:01.762Z","avatar_url":"https://github.com/ably.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ably-ui\n\n`ably-ui` is the of home of the Ably design system library ([https://ably-ui.herokuapp.com/](https://ably-ui.herokuapp.com/)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.\n\n### Library structure\n\nThe library is built out of modules, assets, and JavaScript components. A module is a container for all of those.\n\nFor example, the `core` module provides the most general elements one can build the “chrome” of a web-based interface — typography, colours, spacing (i.e., containers) etc. The components within the module support our most common needs to build that “chrome”, like navigation elements, footer, hero sections, code samples etc. Assets, and JavaScript are all shared between the components in the module.\n\nComponents do not require assets directly — instead, it's up to the consumer to load the assets and pass them to the components. This ensures flexibility in terms of URLs.\n\n### Installation\n\n### NPM\n\nThis type of installation gives you access to module/components assets as well as React components.\n\n```bash\npnpm add @ably/ui # Preferred\n```\n\nTo attach the imported JavaScript from the `Core` module to the `window` object:\n\n```js\nimport \"@ably/ui/core/scripts\";\n\n// AblyUi.Core is now available on window\n```\n\nTo import an es6 `core` module and expose nothing to window:\n\n```js\nimport ablyUiCore from \"@ably/ui/core/scripts\";\n```\n\nTo import the JavaScript for an `Accordion` component:\n\n```js\nimport Accordion from \"@ably/ui/core/accordion/component\";\n```\n\nIf your bundler supports CSS importing, you can import it as well:\n\n```js\nimport \"@ably/ui/core/styles.css\";\n```\n\n### Setting up TailwindCSS\n\nCurrently, AblyUI CSS is built to work with TailwindCSS. To integrate it into your app:\n\n1. Add AblyUI to your project\n2. Add TailwindCSS to your project\n   1. By project type:\n      1. In [HTML](https://tailwindcss.com/docs/installation#installing-tailwind-css-as-a-post-css-plugin)\n      2. In [Gatsby](https://tailwindcss.com/docs/guides/gatsby)\n         1. Add postCSS import with `npm install postcss-import`\n   1. Further to the instructions, if installation is hanging for over 5 minutes or otherwise problematic, try installing the libraries one at a time\n   1. Make sure you are installing v2 with `npm install -D tailwindcss@2.X`\n3. Make sure you are using the format `@import 'tailwindcss/base';...` in your `global.css` file rather than the `@tailwind/base` format from Tailwind v3\n4. Add the following to your `tailwind.config.js`. Note how different config properties are always extended by the `ablyUIConfig`:\n\n```js\nconst extendConfig = require(\"@ably/ui/tailwind.extend.js\");\n\nmodule.exports = extendConfig((ablyUIConfig) =\u003e ({\n  ...ablyUIConfig,\n  purge: {\n    content: [\n      ...(relative - globbed - paths - to - your - templates),\n      ...ablyUIConfig.purge.content,\n    ],\n    options: {\n      ...ablyUIConfig.purge.options,\n    },\n  },\n}));\n```\n\n1. In the CSS file you added your tailwind declarations to, import the CSS for the modules and components you need:\n\n```css\n@import \"tailwindcss/base\";\n@import \"tailwindcss/components\";\n@import \"tailwindcss/utilities\";\n\n@import \"@ably/ui/reset/styles.css\"; /* needed as we disable the default Tailwind reset */\n@import \"@ably/ui/core/styles.css\"; /* styles for core module components and more */\n@import \"@ably/ui/core/Flash/component.css\";\n```\n\n#### Importing React components\n\nNote that depending on the component, you might still need to include CSS \u0026 JS for it:\n\n```js\nimport Meganav from \"@ably/ui/core/Meganav\";\n```\n\n## Usage\n\n### Icons\n\nIcons are available in two formats to support different application types:\n\n1. **React Component Imports** (recommended for React apps)\n2. **SVG Spritesheets** (fallback for non-React apps)\n\nWe provide access to both custom local assets hosted in the repo and the third-party [Heroicons](https://heroicons.com/) library.\n\n#### For React Applications (Recommended)\n\n**Using the Icon React Component**\n\nThe `Icon` component is the preferred method for React applications, providing automatic fallback and consistent sizing:\n\n```tsx\n// Local custom icon\n\u003cIcon name=\"icon-display-live-chat\" size=\"3rem\" additionalCSS=\"block mb-16\" /\u003e\n\n// Heroicon with explicit variant\n\u003cIcon name=\"icon-gui-arrow-long-right-outline\" size=\"2rem\" /\u003e\n\n// Heroicon using variant prop (appends variant to name)\n\u003cIcon name=\"icon-gui-chevron-down\" variant=\"solid\" size=\"1.5rem\" /\u003e\n```\n\n**How the React Component Works**\n\n1. **First**: Attempts to load a local React component generated from your custom SVGs\n2. **Fallback**: If no local component exists, dynamically imports the corresponding heroicon\n3. **Graceful degradation**: If neither exists, returns null (no icon displayed)\n\n#### For Non-React Applications\n\n**Using SVG Spritesheets**\n\nFor applications that don't use React, icons are available as SVG sprites that can be referenced directly:\n\n```html\n\u003c!-- The width and height are required for correct sizing. The actual color class might depend on the svg and whether it uses strokes, fills etc. Note as well xlink:href, which is xlinkHref in react. --\u003e\n\u003csvg class=\"w-12 h-12 text-cool-black\"\u003e\n  \u003cuse xlink:href=\"#sprite-disclosure-arrow\" /\u003e\n\u003c/svg\u003e\n```\n\nEven in React applications, you can use the sprite method for advanced use cases like hover states with the [group](https://tailwindcss.com/docs/hover-focus-and-other-states#group-hover) class:\n\n```tsx\n\u003ca\n  href=\"{url}\"\n  className=\"text-gui-default hover:text-gui-hover focus:text-gui-focus group\"\n\u003e\n  {children}\n  \u003csvg className=\"w-12 h-12 transform -rotate-90 align-top ui-icon-dark-grey group-hover:icon-gui-hover group-focus:icon-gui-focus ml-4\"\u003e\n    \u003cuse xlinkHref=\"#sprite-disclosure-arrow\" /\u003e\n  \u003c/svg\u003e\n\u003c/a\u003e\n```\n\nThe sprites file can be loaded with the `loadSprites` helper available in the `core` module or included in the page directly.\n\n#### Icon Sources\n\n**Local Custom Icons**\n\nPutting SVG files inside a `src/core/icons` folder will:\n\n1. Generate React components that can be imported dynamically\n2. Add them to a per-group sprites file (e.g., `core/sprites-gui.svg`) for non-React usage\n\n**Heroicons Integration**\n\nThe system automatically falls back to [Heroicons](https://heroicons.com/) when a local icon isn't found, using this naming convention:\n\n- `icon-gui-{heroicon-name}-{variant}`\n\nWhere `variant` can be:\n\n- `outline` → 24px outline icons\n- `solid` → 24px solid icons\n- `mini` → 20px solid icons\n- `micro` → 16px solid icons\n\nThis hybrid approach allows you to use custom brand icons while having access to the entire heroicons library as a fallback.\n\nSee https://ably-ui.herokuapp.com/components/icon for more details.\n\n### Fonts\n\nFont assets are not included automagically but are part of the repo, together with an example of font-face file; see `src/core/fonts` for examples. Make sure to include the licence file declaration on usage.\n\n### Accessibility\n\nAn important part of ably-ui is ensuring the produced UI is accessible to as wide range of users as possible. All components should adhere to at least AA accessibility standards. In most cases, this can be accomplished by following a few simple rules:\n\n— use the correct [HTML elements](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML): anchors for navigation, buttons for interacting, lists for lists etc\n\n- test using a screen reader (for example [Voice Over on a Mac OSX with Web rotor](https://support.apple.com/en-gb/guide/voiceover/welcome/mac))\n  — confirm designs have appropriate tap targets, contrast\n  — use [aria attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) where you reach the limits of what you can do with HTML\n  — don't break the web platform (i.e., don't break the behaviour of a back button, scrolling, in-page links etc)\n\n## Development\n\nTo visualise the assets in `ably-ui`, there is a Storybook instance, which serves as both a showcase and a development environment.\n\n### Quick Start\n\nThe easiest way to get started is to use the development script:\n\n```bash\n./bin/dev\n```\n\nThis script will:\n\n- Check that all required tools (Node.js, pnpm) are installed at the correct versions via asdf\n- Install all project dependencies\n- Start Storybook automatically\n\n### Manual Setup\n\nIf you prefer to run commands manually:\n\nFirstly, ensure you have all of the required project dependencies by running `pnpm install` in the project root.\n\nThen, to run Storybook, run `pnpm storybook` in the project root - it should open automatically in your browser.\n\nTo build Storybook as if it was a statically built site (i.e. what it looks like when deployed), run `pnpm build-storybook` from the project root, go to the generated directory with `cd preview`, and then run `npx http-server` (accepting the prompt to install that package if you haven't done already). The built site will be available at the listed local URL.\n\n### SWC compile flags\n\nWe have a dynamic SWC configuration which allows us to support compile-time feature flags in the library. This allows us to change the behaviour of certain code paths during compilation time (not runtime), which is mostly useful in development mode.\n\nFor example, there could be a flag somewhere in our code that logs additional debug information in development that is useless in a released version. It could look like this:\n\n```ts\n// Example usage in api-client.ts\ndeclare const __DEBUG_MODE__: boolean;\n\nconst api = createApiClient();\nif (__DEBUG_MODE__) {\n  console.log(\"Debug mode enabled\");\n}\n```\n\nThe flag can be added to the list in `swc.config.ts`, and enabled with an environment variable:\n\n```\n$ DEBUG_MODE=true pnpm build\n```\n\n### Publishing pre-release packages for review apps\n\nMake sure you commit \u0026 push your work before doing this.\n\nYou will need to authenticate with [npmjs](https://docs.npmjs.com/creating-and-viewing-access-tokens) to publish.\n\nAfter the above, you should have:\n\n- NPM_TOKEN set in your environment\n- `.npmrc` file to read NPM_TOKEN from your environment like this:\n  ```\n  //registry.npmjs.org/:_authToken=${NPM_TOKEN}\n  ```\n\nTo deploy a review app with your in-progress code, you can use the `pre-release` script:\n\n```bash\n# in root\nscripts/pre-release.sh\n```\n\nThis script is a combination of two scripts:\n\n1. Pre-Release:\n\n- update your local dependencies for ably-ui and run a production build\n- release an NPM package with the version built from your current SemVer but adding a pre-release tag based on a short SHA of your HEAD commit\n\n2. Update Pre-Release Version:\n\n- commit all the above and push to origin\n\nThis will trigger a build of the review app.\n\n### Components\n\nComponents and modules contain JS and CSS files, but no templates. Instead, for each framework that a given component supports, a separate \"framework template\" is created. A component can still be used in any other framework by just using it's required assets.\n\nAll components live in `src` and follow a directory and filename convention:\n\n- module directory (TitleCase)\n  - module asset files: `scripts.js` for JavaScript and `styles.css` for CSS\n  - component directory (TitleCase)\n    - `component.js` - supporting JS script (legacy)\n    - `component.css` - additional CSS (legacy)\n    - `[ComponentName].stories.tsx` - if React, a Storybook presentation file\n  - if React, `[ComponentName].tsx` at a sibling level to the component directory\n\nFor example:\n\n```\n- Core\n  - script.js\n  - styles.css\n  - Accordion\n    - component.js\n    - component.css\n    - Accordion.stories.tsx\n  - Accordion.tsx\n```\n\n#### CSS\n\n##### z-index and positioning\n\nIf using positioning any other than static, be mindful of creating stacking contexts. In `properties.css` you'll find the `z-index` values for the HTML stacking context (used by components like the meganav). When creating a new one within your component, hoist the z-index values to the selector that creates the stacking context and define `z-index` values there for easy scanning (see https://www.oreilly.com/library/view/developing-web-components/9781491905685/ch04.html for a good write-up on stacking contexts and z-index.).\n\n### Formatting \u0026 linting files\n\nBy default, [Prettier](https://prettier.io/) \u0026 [ESLint](https://eslint.org/) will handle most of the frontend files. You can use them through your editor (which should pick up the relevant config files) or on the command line (see `scripts` in package.json).\n\n### Adding a new component\n\n#### To add a new component:\n\nAdd a `[ComponentName].tsx` file in `src`, in the module of your choice (most likely `core`). Any supporting files, i.e. stylesheets, should be placed in a directory with the same name of the component.\n\n#### To see this component in Storybook:\n\nCreate a `[ComponentName].stories.tsx` file alongside your `component` assets, following the examples of other Storybook stories, or their online documentation for guidance. When running Storybook, the story should be picked up and rendered in place automatically.\n\n### Publishing\n\nWe use [Semantic Versioning 2.0.0](https://semver.org/) to version different library versions.\n\nPackages are published to the [GitHub private registry](https://github.com/features/packages).\n\nPublishing is done by tagging a release in GitHub. This triggers a GitHub action that pushes to the private NPM registry as well as publishing new artefacts in the CDN, with the version taken from the tag of the GitHub release.\n\nThis will trigger GitHub actions in supported apps (currently [Voltaire](http://github.com/ably/voltaire) \u0026 [Website](http://github.com/ably/website)) to create a PR with an ably-ui version update.\n\n**To trigger a release:**\n\n- Make sure you have run pre-release script `./pre-release.sh` (This updates the npm package version for ably-ui in `package.json`).\n- Merge your PR into `main` after it has been approved.\n- On the Github [Ably-UI](http://github.com/ably/ably-ui) repo, [create a new release](https://github.com/ably/ably-ui/releases/new) tag.\n- Create a new tag with the new version number for the release.\n  - _Do not prefix the tag with a `v`_\n- Add a meaningful title for the Release.\n- Click on the Autogenerate release notes button.\n- Publish Release.\n- Check the Github `Actions` tab in the repo to make sure the release is green.\n- Upon successful release, a compiled version of the Storybook site will be deployed to Github Pages.\n\nThis will release the packages and update library and create \u0026 push the commit \u0026 tag, and also create corresponding PRs in Voltaire \u0026 Website. It will also deploy a new Storybook site to [https://ably.github.io/ably-ui/](https://ably.github.io/ably-ui/).\n\n### Review Apps\n\nReview apps allow you to create temporary deployments of Storybook for sharing UI changes with stakeholders without requiring local development setup.\n\nTo create a review app:\n\n1. Create a pull request with your changes\n2. Add the `review-app` label to your PR\n3. A Heroku review app will be automatically created and deployed\n4. The deployment will appear in the deployments section of your PR (basic auth is enabled - ask fellow contributors for credentials if needed)\n\nReview apps are automatically cleaned up when the PR is closed or the label is removed. Only repository contributors can create review apps.\n\n### Running tests\n\n`ably-ui` uses [vitest](https://vitest.dev/) with the [Storybook addon for vitest](https://storybook.js.org/docs/writing-tests/integrations/vitest-addon) to automatically turn all stories into executable tests. This means that we don't have to explicitly write tests for stories, though we have the ability to write [play functions](https://storybook.js.org/docs/writing-stories/play-function), which allow us to test more detailed interactions.\n\nThe tests run in a browser environment using Playwright, providing comprehensive visual regression testing and interaction testing capabilities.\n\nYou can run the tests locally using:\n\n```bash\npnpm test\n```\n\nThis will run all story tests using vitest in a headless browser environment.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fably%2Fably-ui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fably%2Fably-ui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fably%2Fably-ui/lists"}