# \<Slot>

Learn how to render the content of a slot using components.

This component fetches and renders the content of a [Slot](/explanation/slot), serving as the declarative equivalent of the [`useContent`](/reference/sdk/vue/api/composables/use-content) composable.

## Example

Here is a basic example of how to use this component:

**JavaScript**

```vue
<script setup>
import {Slot} from '@croct/plug-vue';
</script>

<template>
  <Slot id="home-hero" v-slot="{ content }">
    <div>
      <strong>{{ content.title }}</strong>
      <p>{{ content.subtitle }}</p>
      <a :href="content.button.link">{{ content.button.label }}</a>
    </div>
  </Slot>
</template>
```

**TypeScript**

```vue
<script setup lang="ts">
import {Slot} from '@croct/plug-vue';
</script>

<template>
  <Slot id="home-hero" v-slot="{ content }">
    <div>
      <strong>{{ content.title }}</strong>
      <p>{{ content.subtitle }}</p>
      <a :href="content.button.link">{{ content.button.label }}</a>
    </div>
  </Slot>
</template>
```

### Loading and error states

You can use named slots to handle loading and error states:

**JavaScript**

```vue
<script setup>
import {Slot} from '@croct/plug-vue';
</script>

<template>
  <Slot id="home-hero">
    <template #default="{ content }">
      <div>
        <strong>{{ content.title }}</strong>
        <p>{{ content.subtitle }}</p>
      </div>
    </template>

    <template #loading>
      <p>Loading...</p>
    </template>

    <template #error="{ error }">
      <p>Something went wrong: {{ error.message }}</p>
    </template>
  </Slot>
</template>
```

**TypeScript**

```vue
<script setup lang="ts">
import {Slot} from '@croct/plug-vue';
</script>

<template>
  <Slot id="home-hero">
    <template #default="{ content }">
      <div>
        <strong>{{ content.title }}</strong>
        <p>{{ content.subtitle }}</p>
      </div>
    </template>

    <template #loading>
      <p>Loading...</p>
    </template>

    <template #error="{ error }">
      <p>Something went wrong: {{ error.message }}</p>
    </template>
  </Slot>
</template>
```

### Initial content

When you provide the `initial` prop, the default slot renders immediately with the initial content while the actual content loads in the background:

**JavaScript**

```vue
<script setup>
import {Slot} from '@croct/plug-vue';
</script>

<template>
  <Slot id="home-hero" :initial="{ title: 'Welcome' }" v-slot="{ content }">
    <h1>{{ content.title }}</h1>
  </Slot>
</template>
```

**TypeScript**

```vue
<script setup lang="ts">
import {Slot} from '@croct/plug-vue';
</script>

<template>
  <Slot id="home-hero" :initial="{ title: 'Welcome' }" v-slot="{ content }">
    <h1>{{ content.title }}</h1>
  </Slot>
</template>
```

## Props

The following list describes the supported props:

- `id`: `string`

  The ID of the slot to fetch.

  You can specify the version of the slot by passing a versioned ID in the form `id@version`. For example, passing `home-hero@1` will fetch the content for the `home-hero` slot in version 1. Not specifying a version number is the same as passing `home-hero@latest`, which will load the content for the latest version.

  > **Best practice**
  >
  > Always specify a version to ensure the front end receives content with the expected structure despite future schema changes.
  >
  > For more information, see [Slot versioning](/explanation/slot#versioning).

- `initial`: `JSON` (optional)

  An initial value to render while loading the actual content.

  > **Auto-provided**
  >
  > If you are using the Croct CLI, you do not need to set an initial value unless you want to use a different one.

  This value is required for server-side rendering. For client-side rendering, when this prop is provided, the default slot renders immediately with the initial content. Without it, the `#loading` slot renders until the content is available.

- `fallback`: `JSON` (optional)

  A fallback value to render in case of an error.

  > **Auto-provided**
  >
  > If you are using the Croct CLI, you do not need to set a fallback unless you want to use a different one.

  If not specified, the `#error` slot renders on failure.

- `expiration`: `number` (optional) (default: 60000)

  The cache expiration time in milliseconds, extended on every render.

  If negative, the cache never expires. By default, the cache expires after 60 seconds.

  The SDK caches the result to prevent network requests on concurrent renders and re-renders.

- `cacheKey`: `string` (optional)

  A unique key to identify the cache entry.

  By default, the cache key is derived from the slot ID, locale, and attributes. You can specify a custom cache key to force re-fetching even if the other parameters are the same.

- `preferredLocale`: `string` (optional) (default: default locale)

  The locale code to fetch the content.

  The code consists of a two-part string that specifies the language and, optionally, the country. For example, `en` represents English, `en-us` stands for English (United States), and `pt-br` for Portuguese (Brazil). It is case-insensitive and supports both hyphens and underscores as separators to accommodate the different conventions used by browsers, libraries, and other systems.

  If no content is available in the preferred locale, the default locale content is returned instead.

- `timeout`: `number` (optional)

  The maximum fetch time in milliseconds.

  Once reached, the SDK will abort the request and reject the promise with a timeout error.

- `attributes`: `object` (optional)

  The map of attributes to inject in the evaluation context.

  The attributes can be referenced in audience conditions using the [`context`](/reference/cql/context#evaluation) variable. For example, suppose you pass the following attributes:

  ```json
  {cities: ["New York", "San Francisco"]}
  ```

  You can then reference them in queries like:

  ```cql
  context's cities include location's cityName
  ```

  For more information, see [Context variables](../../content-rendering#context-variables).

  The following restrictions apply to the attributes:

  - Up to 30 entries and 5 levels deep
  - Keys can be either numbers or non-empty strings with a maximum length of 50 characters
  - Values can be null, numbers, booleans, strings (up to 50 characters), or nested maps
  - Nested maps follow the same constraints for keys and values

## Slots

The following list describes the supported slots:

- `#default`: `object`

  Renders when content is available, either from the `initial` prop or after fetching.

  The scope exposes `content` with the slot content, and an optional `metadata` object.

- `#loading`: `object`

  Renders while the content is being fetched. Not used when the `initial` prop is provided, since the default slot renders immediately in that case.

- `#error`: `object`

  Renders when fetching fails. Not used when a `fallback` prop is provided.

  The scope exposes `error` with the error details.
