# Field Label

## Usage

Standalone label component with optional/required indicators and tooltip support.

`FieldLabel` is the label half of `Field`. Use it directly when the control it names does not render a label of its own: a custom widget, a group of inputs, or a wrapper built outside this library. `label` and `input-id` are both required; the id is what makes the label point at the control.

```vue
<script setup lang="ts">
import { FieldLabel } from '@astryx-vue/core/Field'
import { ref } from 'vue'

const email = ref('')
</script>

<template>
  <div>
    <FieldLabel label="Email address" input-id="email-input" is-required />
    <input id="email-input" v-model="email" type="email">
  </div>
</template>
```

`isRequired` and `isOptional` print the "Required" or "Optional" marker next to the label. Inside a `FormLayout` with a `defaultOptionality`, only the exception gets marked, so a required-by-default form does not need the marker on every field. `description` adds a supporting line under the label that also focuses the control when it is clicked. `labelIcon` puts a small glyph before the label text, and `labelTooltip` adds an info button whose text a screen reader can reach.

Set `isGroupLabel` when the labelled thing is a group of controls rather than one input. The label then renders as a `span` instead of a `label`, so a click on it does not get handed to whichever control happens to sit first.

```ts
import { FieldLabel } from '@astryx-vue/core/Field'
```

## Examples

Common configurations, variations, and states.

### Basic

Standalone labels with required and optional indicators and a helper description. Use when labeling a custom control that does not render its own label.

```vue
<script setup lang="ts">
import { FieldLabel } from '@astryx-vue/core/Field'
import { VStack } from '@astryx-vue/core/Stack'
</script>

<template>
  <VStack :gap="4" style="width: min(100%, 20rem)">
    <FieldLabel label="Email address" input-id="email-input" is-required />
    <FieldLabel
      label="Phone number"
      input-id="phone-input"
      is-optional
      description="Include country code for international numbers"
    />
    <FieldLabel
      label="API key"
      input-id="api-input"
      label-tooltip="Your API key can be found in the developer settings"
    >
      <template #labelIcon>
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
          <rect x="3" y="11" width="18" height="11" rx="2" />
          <path d="M7 11V7a5 5 0 0 1 10 0v4" />
        </svg>
      </template>
    </FieldLabel>
    <FieldLabel label="Disabled field" input-id="disabled-input" is-disabled />
  </VStack>
</template>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | — | Label text. Required. |
| `inputId` | `string` | — | `id` of the control this label belongs to. Becomes the `for` attribute, and the base for the generated label and description ids. Required. |
| `labelId` | `string` | ``${inputId}-label`` | `id` put on the label element itself. Point the control's `aria-labelledby` at it when the label is not a real `label`. |
| `description` | `string` | — | Supporting line under the label. Clicking it focuses the control, unless the label is a group label or disabled. |
| `descriptionId` | `string` | ``${inputId}-description`` | `id` put on the description. Reference it from the control's `aria-describedby`. |
| `isGroupLabel` | `boolean` | `false` | Renders the label as a `span` with no `for`, for a group of controls instead of a single input. |
| `isLabelHidden` | `boolean` | `false` | Hides the label visually. It stays in the accessibility tree. |
| `isDisabled` | `boolean` | `false` | Dims the label and stops the description from focusing the control. |
| `isOptional` | `boolean` | `false` | Shows the optional marker. Wins over `isRequired` when both are set. |
| `isRequired` | `boolean` | `false` | Shows the required marker. Inside a `FormLayout` with `defaultOptionality="required"` the marker is suppressed, because being required is the default. |
| `labelIcon` | `IconName \| Component` | — | Icon rendered before the label text, inside a 16px box. The wrapper is `aria-hidden`, so the icon must not carry meaning on its own. |
| `labelTooltip` | `string` | — | Tooltip text for the info button at the end of the label row. |
| `optionalLabel` | `string` | `'Optional'` | Text of the optional marker. Override it to localize. |
| `requiredLabel` | `string` | `'Required'` | Text of the required marker. Override it to localize. |

## Slots

- `labelIcon`: icon before the label text. Same place as the `labelIcon` prop, and the slot wins when both are passed.

## Exposed

- `element`: the rendered label element.
