# Text

Text is used to add an additional visual meaning on your content

## Design & usage guidelines

The default styling of a text is used as the body text for almost everything.

```tsx
import React from "react";
import { Text } from "@jobber/components/Text";

export function TextDefaultExample() {
  return (
    <Text>Ask the information you need upfront from clients and new leads</Text>
  );
}
```

### Subdued

De-emphasize a piece of text that is less important to the user.

```tsx
import React from "react";
import { Text } from "@jobber/components/Text";

export function TextSubduedExample() {
  return <Text variation="subdued">Job note linked to related invoice</Text>;
}
```

### Feedback message

The variation also includes text that conveys feedback messages.

```tsx
import React from "react";
import { Content } from "@jobber/components/Content";
import { Text } from "@jobber/components/Text";

export function TextFeedbackExample() {
  return (
    <Content>
      <Text variation="success">Invoice sent</Text>
      <Text variation="error">Name is required</Text>
      <Text variation="warn">Your message is over 160 characters</Text>
      <Text variation="info">
        Drag to rearrange the order that the fields show up in Jobber
      </Text>
    </Content>
  );
}
```

### Disabled

Use when the text is part of a disabled section of the interface.

Do not use `disabled` text to explain why an element is disabled. That text
should be default text with full intended contrast so that the user can clearly
identify why an element is disabled.

```tsx
import React from "react";
import { Checkbox } from "@jobber/components/Checkbox";
import { Content } from "@jobber/components/Content";
import { Text } from "@jobber/components/Text";

export function TextDisabledExample() {
  return (
    <Content>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: "var(--space-small)",
          marginBottom: "var(--space-small)",
        }}
      >
        <Checkbox disabled checked={false} />
        <Text variation="disabled">A checkbox option</Text>
      </div>
      <Text>
        You must enable your other settings before you can select this option.
      </Text>
    </Content>
  );
}
```

## Alignment

Use left-aligned text for the the vast majority of use cases, particularly when
setting paragraphs. You may need to right-align text in cases where a label or
other small typographic element helps maintain vertical alignment on the right
side of a layout.

Centered text should be used sparingly, and largely in standalone cases like
empty states where the content is vertically and horizontally centered.

For text alignment, we use `start` and `end` instead of `left` and `right`. This
allows us to support
[bi-directionality](https://material.io/design/usability/bidirectionality.html#mirroring-layout)
when needed.

```tsx
import React from "react";
import { Text } from "@jobber/components/Text";
import { ContentBlock } from "@jobber/components/ContentBlock";

export function TextAlignmentExample() {
  return (
    <ContentBlock maxWidth="100%">
      <Text align="start">
        Start aligns text to the left in Latin and other LTR scripts
      </Text>
      <Text align="center">Center is always in... the center</Text>
      <Text align="end">
        End aligns text to the right in Latin and other LTR scripts
      </Text>
    </ContentBlock>
  );
}
```

## maxLines

Used to truncate large text with `...` based on line wrapping, such that the
total number of lines does not exceed the preset. This is an optional prop. If
left undefined all the contents are shown.

```tsx
import React from "react";
import { Content } from "@jobber/components/Content";
import { Text } from "@jobber/components/Text";

export function TextMaxLinesExample() {
  return (
    <Content>
      <Text maxLines="single">
        This will show 1 line. Lorem ipsum dolor sit amet, consectetur
        adipiscing elit. Vestibulum nec pulvinar nunc. Suspendisse nec eros
        pretium, rutrum purus sit amet, finibus ante. Donec pretium condimentum
        scelerisque.
      </Text>
      <Text maxLines="small">
        This will show 2 lines. Lorem ipsum dolor sit amet, consectetur
        adipiscing elit. Vestibulum nec pulvinar nunc. Suspendisse nec eros
        pretium, rutrum purus sit amet, finibus ante. Donec pretium condimentum
        scelerisque. Duis eu ligula nec metus suscipit feugiat.Etiam sapien
        sapien, mattis eu tincidunt quis, pretium sed metus. Maecenas quis dolor
        lacinia libero rhoncus fringilla. Cras mi ante, euismod nec tortor in,
        tempus mollis nulla.
      </Text>
      <Text maxLines="base">
        This will show 4 lines. Lorem ipsum dolor sit amet, consectetur
        adipiscing elit. Vestibulum nec pulvinar nunc. Suspendisse nec eros
        pretium, rutrum purus sit amet, finibus ante. Donec pretium condimentum
        scelerisque. Duis eu ligula nec metus suscipit feugiat.Etiam sapien
        sapien, mattis eu tincidunt quis, pretium sed metus. Maecenas quis dolor
        lacinia libero rhoncus fringilla. Cras mi ante, euismod nec tortor in,
        tempus mollis nulla.
      </Text>
      <Text maxLines="large">
        This will show 8 lines. Lorem ipsum dolor sit amet, consectetur
        adipiscing elit. Vestibulum nec pulvinar nunc. Suspendisse nec eros
        pretium, rutrum purus sit amet, finibus ante. Donec pretium condimentum
        scelerisque. Duis eu ligula nec metus suscipit feugiat.Etiam sapien
        sapien, mattis eu tincidunt quis, pretium sed metus. Maecenas quis dolor
        lacinia libero rhoncus fringilla. Cras mi ante, euismod nec tortor in,
        tempus mollis nulla. Etiam eu lacus nibh. Donec tristique lacus magna,
        vulputate tristique lacus blandit vitae. Aenean vitae commodo metus.
        Fusce eu risus quis orci pharetra consequat nec nec libero.
      </Text>
      <Text maxLines="larger">
        This will show 16 lines. Lorem ipsum dolor sit amet, consectetur
        adipiscing elit. Vestibulum nec pulvinar nunc. Suspendisse nec eros
        pretium, rutrum purus sit amet, finibus ante. Donec pretium condimentum
        scelerisque. Duis eu ligula nec metus suscipit feugiat.Etiam sapien
        sapien, mattis eu tincidunt quis, pretium sed metus. Maecenas quis dolor
        lacinia libero rhoncus fringilla. Cras mi ante, euismod nec tortor in,
        tempus mollis nulla. Etiam eu lacus nibh. Donec tristique lacus magna,
        vulputate tristique lacus blandit vitae. Aenean vitae commodo metus.
        Fusce eu risus quis orci pharetra consequat nec nec libero. Lorem ipsum
        dolor sit amet, consectetur adipiscing elit. Vestibulum nec pulvinar
        nunc. Suspendisse nec eros pretium, rutrum purus sit amet, finibus ante.
        Donec pretium condimentum scelerisque. Duis eu ligula nec metus suscipit
        feugiat.Etiam sapien sapien, mattis eu tincidunt quis, pretium sed
        metus. Maecenas quis dolor lacinia libero rhoncus fringilla. Cras mi
        ante, euismod nec tortor in, tempus mollis nulla. Etiam eu lacus nibh.
        Donec tristique lacus magna, vulputate tristique lacus blandit vitae.
        Aenean vitae commodo metus. Fusce eu risus quis orci pharetra consequat
        nec nec libero.
      </Text>
    </Content>
  );
}
```

## Platform Considerations (Web)

### Sizes

Text can be used with different sizes.

```tsx
import React from "react";
import { Content } from "@jobber/components/Content";
import { Text } from "@jobber/components/Text";

export function TextSizesExample() {
  return (
    <Content>
      <Text size="base">
        Both Trains and Text come in all different kinds of sizes
      </Text>
      <Text size="small">Sometimes they are small</Text>
      <Text size="large">Other times they are large</Text>
    </Content>
  );
}
```

#### Base

Base is the default size and is optimized for the widest range of uses,
including:

* Long paragraphs of text content
* Descriptions of subsequent UI elements
* Labels on UI elements such as checkboxes and radio buttons
* Freeform user-generated content

#### Large

Typically large is to be used as an introductory paragraph that gives important
information about a page, and requires greater prominence.

#### Small

The small size is intended to be used as helper content on things like
checkboxes, radio buttons, inputs or any other UI elements that need help
provided.


## Component customization

### UNSAFE\_ props (advanced usage)

General information for using `UNSAFE_` props can be found
[here](../customizing-components/customizing-components.md).

**Note**: Use of `UNSAFE_` props is **at your own risk** and should be
considered a **last resort**. Future Text updates may lead to unintended
breakages.

#### UNSAFE\_ props (web)

### UNSAFE\_className

Use `UNSAFE_className` to apply custom classes to the Text component. This
can be useful for applying styles via CSS Modules.

```tsx
// YourComponent.tsx
<Text UNSAFE_className={{ textStyle: styles.customText }}>
  Custom text style
</Text>

// YourComponent.module.css
.customText {
  color: var(--color-purple);
}
```

### UNSAFE\_style

Use `UNSAFE_style` to apply inline custom styles to the Text component.

```tsx
<Text UNSAFE_style={{ textStyle: { color: "var(--color-purple)" } }}>
  Custom text style
</Text>
```

#### UNSAFE\_style (mobile)

The mobile Text component can be custom styled using the `textStyle` type via
the `UNSAFE_style` prop.

React Native does not support className. Instead, you can use `UNSAFE_style` to
apply styles either inline or through a StyleSheet.

##### Inline styles

```tsx
UNSAFE_style={{ textStyle: { color: tokens["color-purple--light"] } }}
```

##### StyleSheet

```tsx
// Text.tsx
  UNSAFE_style={{
    textStyle: styles.customTextStyle,
  }}

// Text.style.ts
export const styles = StyleSheet.create({
  customTextStyle: {
    color: tokens["color-purple--light"],
  },
});
```

## Platform Considerations (Mobile)

### Notes

Text uses the core component [Text](https://reactnative.dev/docs/text) from
`react-native`.

#### Nested text (mobile)

The mobile `Text` component now supports nested children like React Native’s
`Text`. You can compose inline layouts and mixed formatting:

```tsx
<Text>
  Normal <Text emphasis="strong">Bold</Text> and
  <Text italic> italic</Text> text
</Text>
```

Transforms (e.g., `transform="uppercase"`) apply only to string children of the
component they are set on. Nested `Text`/`Typography` elements can set their own
`transform` independently.

### Copying text

There are a few caveats around copying text on Android and iOS that you can read
under the [Typography](../Typography/Typography.md) documentation.


## Props

### Web

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `align` | `"center" | "end" | "start"` | No | `start` |  |
| `element` | `TextElement` | No | `p` | The HTML element to render the text as. |
| `maxLines` | `"base" | "large" | "larger" | "single" | "small" | "unlimited"` | No | `unlimited` |  |
| `size` | `"base" | "large" | "small"` | No | `base` |  |
| `UNSAFE_className` | `{ textStyle?: string; }` | No | — | **Use at your own risk:** Custom classNames for specific elements. This should only be used as a **last resort**. Usi... |
| `UNSAFE_style` | `{ textStyle?: CSSProperties; }` | No | — | **Use at your own risk:** Custom style for specific elements. This should only be used as a **last resort**. Using th... |
| `variation` | `"default" | "disabled" | "error" | "info" | "subdued" | "success" | "warn"` | No | `default` |  |
