# WebUI

The `web-ui` repository contains the UI components for Luscii's frontend projects. It is published to NPM for usage into our projects. It uses Storybook and is published to Chromatic for easy review and tracking of visual changes.

## Table of contents

- 🚀 [Getting started](#getting-started)
  - 📖 [Fonts](#fonts)
- 📦 [How to use](#how-to-use)
- 🤝 [Contributing](#contributing)
  - 📐 [Coding standards & AI guidance](#coding-standards--ai-guidance)

## Getting started

To use WebUI, you need to add it as a dependency to your project:

```bash
yarn add @luscii-healthtech/web-ui
```

Then you can use components like this:

```tsx
import { Text } from "@luscii-healthtech/web-ui";

function MyComponent() {
  return <Text>Some beautiful text from WebUI!</Text>;
}
```

### Fonts

WebUI uses the Inter font family for most of its text. This font should be provided by your application if you're using WebUI. The weights needed to show the full gamut of weights in the design system are 300, 400, 500, 600 and 700. One way of doing this is using a Google Fonts link in your HTML file:

```html
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
  href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
  rel="stylesheet"
/>
```

For some headings WebUI uses the Avenir Next LT Pro font family. If you want to use these, you need to make them available in your project. You can do this by declaring the following `@font-face` rules in your CSS:

```css
@font-face {
  font-family: "AvenirNextLTPro-Regular";
  src:
    url("./<regular-font-file>.eot") format("embedded-opentype"),
    url("./<regular-font-file>.woff2") format("woff2"),
    url("./<regular-font-file>.woff") format("woff"),
    url("./<regular-font-file>.ttf") format("truetype");
}

@font-face {
  font-family: "AvenirNextLTPro-Bold";
  src:
    url("./<bold-font-file>.eot") format("embedded-opentype"),
    url("./<bold-font-file>.woff2") format("woff2"),
    url("./<bold-font-file>.woff") format("woff"),
    url("./<bold-font-file>.ttf") format("truetype");
}
```

The `font-family` property value is important, as this is what WebUI is referencing to use the font. The `src` property values should point to the font files you want to use.

If you don't declare these `@font-face` rules, the font will not be available and the headings will gracefully fall back to next available font in your application.

### LocaleProvider

WebUI exposes a `LocaleProvider`, which is used to make components adjust their data formats to the locale of the application.
You should wrap your app with the `LocaleProvider`.

```tsx
import { LocaleProvider } from "@luscii-healthtech/web-ui";
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

function start() {
  const root = createRoot(document.querySelector("#root"));
  root.render(
    <LocaleProvider value="nl-NL">
      <App />
    </LocaleProvider>
  );
}
```

The locale passed should adhere to the `{language}-{region}` format, for example:

- `nl-NL`
- `en-GB`
- `pt-PT`
- `de-DE`
- `fr-FR`

### Tooltip Provider

Install the `@radix-ui/react-tooltip` peer dependency into your project:

```bash
yarn add @radix-ui/react-tooltip
```

Wrap your app with the `Tooltip.Provider` component:

```tsx
import * as Tooltip from "@radix-ui/react-tooltip";
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

function start() {
  const root = createRoot(document.querySelector("#root"));
  root.render(
    <Tooltip.Provider delayDuration={800} skipDelayDuration={500}>
      <App />
    </Tooltip.Provider>
  );
}
```

More about this component can be found in its [documentation](https://www.radix-ui.com/primitives/docs/components/tooltip).

## How to use

The primary goal of WebUI is to make frontend development faster. It does this by providing a set of commonly used components that can be composed together to build user interfaces.  
WebUI aims to have every component well documented, both in the code and in Storybook. You can find all available components and documentation on how to
use them at [design.luscii.com](https://design.luscii.com/).

### Example scenario

Say you're tasked with building a UI that contains a card. This card has a title, a subtitle, some body text and a button. You could build this UI by writing the following code:

```tsx
import { Card, Text, Button } from "@luscii-healthtech/web-ui";

function MyComponent() {
  return (
    <div className="my-layout">
      <Card>
        <Card.Title>Heart program</Card.Title>
        <Card.Subtitle>79 participants</Card.Subtitle>
        <Card.Text>Some description of how great this program is.</Card.Text>
        <Card.Button>View program</Card.Button>
      </Card>
    </div>
  );
}
```

Often times WebUI will provide a component that is a composition of other components. In this case, the `Card` component is a composition of `Card.Title`, `Card.Subtitle`, `Card.Text` and `Card.Button`. This allows you to build UIs faster, as you don't have to think about where to get a certain component. You can just use `Card` and its subcomponents and everything will be styled correctly.

## Frequently asked questions

<details>
<summary>The feature I'm building needs a component from WebUI that doesn't exist.</summary>

Please get in touch with the design system circle by sending us a message in the [#design-system-circle channel](https://luscii.slack.com/archives/C03507ZKRCY). We'll discuss your needs and see what would be the best way to move forward.

</details>

<details>
<summary>The component I'm using doesn't have the props/subcomponents to build my feature.</summary>

In most cases you can build the UI you need by composing the components that are available. If for instance `Card.Text` doesn't exist, go "one level up" and find the component that is closest to what you need. In this case, you can use the `Text` component and configure it with the correct props to match the design.

In case the component is missing a prop that you need, please get in touch with the design system circle by sending us a message in the [#design-system-circle channel](https://luscii.slack.com/archives/C03507ZKRCY). We'll discuss your needs and see what would be the best way to move forward.

</details>

## Contributing

Great to have you help making WebUI better! We have a few guidelines and tips
to make sure we can keep the library consistent and easy to use. You can find
them in our [contributing guide](CONTRIBUTING.md).

### Coding standards & AI guidance

AI-agent guidance (including the Design System governance policy) lives in
[`CLAUDE.md`](CLAUDE.md).

Org-wide standards are kept in a separate repository and cloned into a local,
git-ignored `.coding-standards/` folder. Pull them in with:

```bash
yarn add-coding-standards   # first-time clone
yarn pull-coding-standards  # update to latest
```

### Reporting bugs

If you find a bug, please report it by sending us a message in the [#design-system-circle channel](https://luscii.slack.com/archives/C03507ZKRCY). It helps us a lot knowing of anything that is not working as expected.
