npm package: @highlight-ui/visual-language-tools
Description: Welcome to Highlight UI's visual-language-tools library. This library provides a series of components and hooks to allow teams the flexibility to switch between desired visual languages at various stages throughout their application.
Author: Personio GmbH & Co. KG
Latest version: 2.1.0

# `@highlight-ui/visual-language-tools`

Welcome to Highlight UI's visual-language-tools library. This library provides a
series of components and hooks to allow teams the flexibility to switch between
desired visual languages at various stages throughout their application.

> Please note that these utilities are only designed to be used inside of the
> web monorepo.

## Installation

```
pnpm add @highlight-ui/visual-language-tools
```

## Utilities

- [`<VisualLanguageSwitch />`](#visuallanguageswitch-)
- [`useVisualLanguage`](#usevisuallanguage)

# `<VisualLanguageSwitch />`

`VisualLanguageSwitch` is a wrapper component to help teams abstract the logic
for switching between different components at any level in their application.
This can be used to load different UI modules in-place, or even entirely
different page layouts. The component supports both static and dynamically
imported components and makes use of `React.lazy` under the hood to enable
splitting bundles to keep the application size down.

## `props`

| Prop Name         | Description                                                                                                             |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `on`              | The static or dynamic component to render in the enabled state.                                                         |
| `off`             | The static or dynamic component to render in the disabled state.                                                        |
| `flag?`           | The name of a Split to determine if the visual language is turned on. Defaults to the global Flow visual language flag. |
| `visualLanguage?` | The name of a visual language to switch on. Accepts either `'Flow'` or `'Vintage'` and defaults to `'Flow'`.            |
| `force?`          | Explicitly set the use of the visual language (helpful for development).                                                |
| `fallback?`       | The "fallback" design to use while determining which state to display.                                                  |

## Basic Usage

This example shows a theoretical scenario in which the sidebar of an application
is being completely redesigned for the new Flow visual language. By default,
this will use the value of the global Split.

```tsx
import { VisualLanguageSwitch } from '@highlight-ui/visual-language-tools';
import { CharacterGrid } from './CharacterGrid';
import { CharacterList } from './CharacterList';

const MyApplication = () => (
  <article>
    <h1>The Silmarillion</h1>
    <p>...</p>
    <aside>
      <VisualLanguageSwitch
        on={() => <CharacterGrid />}
        off={() => <CharacterList />}
      />
    </aside>
  </article>
);
export default MyApplication;
```

## Advanced Usage

### Forcing a Visual Language

In development, it can be helpful to force on or off the use of a visual
language. This can be done by using the `force` prop.

```tsx
import { VisualLanguageSwitch } from '@highlight-ui/visual-language-tools';
import { CharacterGrid } from './CharacterGrid';
import { CharacterList } from './CharacterList';

const MyApplication = () => (
  <article>
    <h1>The Silmarillion</h1>
    <p>...</p>
    <aside>
      <VisualLanguageSwitch
        on={() => <CharacterGrid />}
        off={() => <CharacterList />}
        force
      />
    </aside>
  </article>
);
export default MyApplication;
```

### Using a Split

You can also provide your own Split to control the rendering of new layouts
separately from the global Flow visual language Split.

```tsx
import { VisualLanguageSwitch } from '@highlight-ui/visual-language-tools';
import { CharacterGrid } from './CharacterGrid';
import { CharacterList } from './CharacterList';

const MyApplication = () => (
  <article>
    <h1>The Silmarillion</h1>
    <p>...</p>
    <aside>
      <VisualLanguageSwitch
        on={() => <CharacterGrid />}
        off={() => <CharacterList />}
        flag="OMG-enable-grid-characters"
      />
    </aside>
  </article>
);
export default MyApplication;
```

### Using dynamic imports

The `on` and `off` props can also be used to dynamically import components. This
is useful for splitting bundle sizes and keeping the application size down. Note
that the `fallback` value will be used when waiting for the Split to load _and_
when waiting for a dynamic import to load.

```tsx
import { VisualLanguageSwitch } from '@highlight-ui/visual-language-tools';

const MyApplication = () => (
  <article>
    <h1>The Silmarillion</h1>
    <p>...</p>
    <aside>
      <VisualLanguageSwitch
        on={() => import('./CharacterGrid')}
        off={() => import('./CharacterList')}
        fallback="Loading Split and/or dynamic components..."
      />
    </aside>
  </article>
);
export default MyApplication;
```

### Using a fallback

A fallback can be used to provide a default design while the Split is being
loaded.

```tsx
import { VisualLanguageSwitch } from '@highlight-ui/visual-language-tools';
import { CharacterGrid } from './CharacterGrid';
import { CharacterList } from './CharacterList';

const MyApplication = () => (
  <article>
    <h1>The Silmarillion</h1>
    <p>...</p>
    <aside>
      <VisualLanguageSwitch
        on={() => <CharacterGrid />}
        off={() => <CharacterList />}
        fallback="Loading Split..."
      />
    </aside>
  </article>
);
export default MyApplication;
```

# `useVisualLanguage`

`useVisualLanguage` is a utility hook that allows teams to apply a specific
visual language at a given level and all children within the render tree will
use the design tokens and logic related to that visual language where necessary.

This can happen at _any level_ in the render tree: leaf, subtree, root. A child
can override a parent's visual language. The specific implementation detail is
left to the team to decide.

At the moment, only two visual languages are supported: Vintage and Flow.

## Prerequisites

- Your Frontend application _must_ be part of
  [Personio Web](https://gitlab.personio-internal.de/personio/frontend/personio-web)

## Options

| Prop Name         | Description                                                                                                             |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `visualLanguage?` | The name of a visual language to switch on. Accepts either `'Flow'` or `'Vintage'` and defaults to `'Flow'`.            |
| `flag?`           | The name of a Split to determine if the visual language is turned on. Defaults to the global Flow visual language flag. |
| `force?`          | Force-enable the specified visual language, regardless of the values of the other options or feature flag states.       |

## Returns

| Value               | Description                                                                                                                    |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `enabled: boolean`  | This indicates whether the specified visual language is enabled.                                                               |
| `className: string` | This is a CSS class name that you can attach to your DOM elements to apply the visual language at that level and its children. |

## Basic Usage

This example shows the common usage of scoping an entire module or page and
consuming the Vintage visual language controlled by the master feature flag.

```tsx
import { useVisualLanguage } from '@highlight-ui/visual-language-tools';

const MyPageModule = () => {
  const { className } = useVisualLanguage();

  return (
    <article className={className}>
      <h1>The Silmarillion</h1>
      <p>...</p>
      <nav>
        <Button onClick={handleBack}>Previous page</Button>
        <Button onClick={handleNext}>Next page</Button>
      </nav>
    </article>
  );
};
/*
<article class="hui-visual-language_vintage">
  <h1>The Silmarillion</h1>
  <p>...</p>
  <nav>
    <button>Previous page</button>
    <button>Next page</button>
  </nav>
</article>
*/
```

## Advanced Usage

This example makes use of `useVisualLanguage` to provide one treatment of the
Vintage visual language at the top level of the component, and then a different
visual language treatment at the `nav` level.

```tsx
import { useVisualLanguage } from '@highlight-ui/visual-language-tools';

const MyPageModule = () => {
  const { className: vintageClassName } = useVisualLanguage();
  const { className: flowClassName } = useVisualLanguage({
    flag: 'MPM-enable-flow-visual-language',
    visualLanguage: 'Flow',
  });

  return (
    <article className={vintageClassName}>
      <h1>The Silmarillion</h1>
      <p>...</p>
      <nav className={flowClassName}>
        <Button onClick={handleBack}>Previous page</Button>
        <Button onClick={handleNext}>Next page</Button>
      </nav>
    </article>
  );
};
/*
<article class="hui-visual-language_vintage">
  <h1>The Silmarillion</h1>
  <p>...</p>
  <nav class="hui-visual-language_flow">
    <button>Previous page</button>
    <button>Next page</button>
  </nav>
</article>
*/
```

## Forcing a Visual Language

A certain visual language can be forced on with the `force` option, regardless
of the value of the `visualLanguage` option or the status of the feature flag.
The value passed to this option will be used to inform the returned class name.

```tsx
import { useVisualLanguage } from '@highlight-ui/visual-language-tools';

const MyPageModule = () => {
  const { className: vintageClassName } = useVisualLanguage();
  const { className: flowClassName } = useVisualLanguage({
    visualLanguage: 'Flow'
    force: true
  });

  return (
    <article className={vintageClassName}>
      <h1>The Silmarillion</h1>
      <p>...</p>
      <nav className={flowClassName}>
        <Button onClick={handleBack}>Previous page</Button>
        <Button onClick={handleNext}>Next page</Button>
      </nav>
    </article>
  );
};
/*
<article class="hui-visual-language_vintage">
  <h1>The Silmarillion</h1>
  <p>...</p>
  <nav class="hui-visual-language_flow">
    <button>Previous page</button>
    <button>Next page</button>
  </nav>
</article>
*/
```