---
title: "GroupBlock"
description: "A collapsible group that holds settings rows."
category: Layout
status: beta
since: 0.3.4
tags: [group, layout, settings]
syncStatus: reviewed
verified: true
---

## Usage

### Basic
`TxGroupBlock` holds a set of settings rows; clicking the header expands or collapses it.
:::TuffDemoWrapper{demo="GroupBlockGroupBlockDemo" code-lang="vue"}
---
code: |
  <template>
    <TxGroupBlock name="Preferences" description="Application options" default-icon="i-carbon-settings">
      <TxBlockSwitch
        v-model="notifications"
        title="Notifications"
        description="Enable desktop notifications"
        default-icon="i-carbon-notification"
        active-icon="i-carbon-notification-filled"
      />
      <TxBlockSlot title="Language" description="Display language" default-icon="i-carbon-translate">
        <TxSelect v-model="language" placeholder="Select language">
          <TuffSelectItem value="en" label="English" />
          <TuffSelectItem value="zh" label="Chinese" />
        </TxSelect>
      </TxBlockSlot>
      <TxBlockLine title="Version" description="2.4.13-beta.3" />
    </TxGroupBlock>
  </template>
---
:::

### Initially Collapsed
`:default-expand="false"` collapses the group on first render.
:::TuffDemoWrapper{demo="GroupBlockGroupBlockCollapsedDemo" code-lang="vue"}
---
code: |
  <template>
    <TxGroupBlock
      name="Project files"
      default-icon="i-carbon-folder"
      active-icon="i-carbon-folder-open"
      :default-expand="false"
    >
      <TxBlockLine title="Hidden content" description="The group body stays mounted" />
    </TxGroupBlock>
  </template>
---
:::

### Remembered State
With `memory-name` set, the expanded state survives a reload.
:::TuffDemoWrapper{demo="GroupBlockGroupBlockMemoryDemo" code-lang="vue"}
---
code: |
  <template>
    <TxGroupBlock name="Updates" description="Remember the expanded state" memory-name="tx-group-block-demo">
      <TxBlockSwitch v-model="autoUpdate" title="Auto update" description="Install updates when the app restarts" />
    </TxGroupBlock>
  </template>
---
:::

### Header Actions
The `header-extra` slot sits before the collapse chevron.
:::TuffDemoWrapper{demo="GroupBlockGroupBlockHeaderExtraDemo" code-lang="vue"}
---
code: |
  <template>
    <TxGroupBlock name="Sync" description="Header actions stay visible" :collapsible="false">
      <template #header-extra>
        <TxButton size="sm" variant="secondary">Run now</TxButton>
      </template>
      <TxBlockLine title="Last sync" description="Just now" />
    </TxGroupBlock>
  </template>
---
:::

### Read-Only Rows
`TxBlockLine` shows a title and value side by side; when they don't fit, the value wraps below the title.
:::TuffDemoWrapper{demo="GroupBlockBlockLineBasicDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockLine title="Version" description="2.4.13-beta.3" />
    <TxBlockLine title="Build date" description="2026.07.06" />
    <TxBlockLine title="How to install?" description="pnpm add @talex-touch/tuffex" />
  </template>
---
:::

### Link Rows
`link` renders the row as a button that emits `click`; put its content in the `description` slot.
:::TuffDemoWrapper{demo="GroupBlockBlockLineLinkDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockLine title="Documentation" link @click="openDocs">
      <template #description>
        Open developer docs
        <span class="i-carbon-arrow-up-right" aria-hidden="true" />
      </template>
    </TxBlockLine>
  </template>
---
:::

### Custom Controls
The default slot of `TxBlockSlot` takes any control.
:::TuffDemoWrapper{demo="GroupBlockBlockSlotDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockSlot title="Theme" description="Choose the interface appearance" default-icon="i-carbon-color-palette">
      <TxSelect v-model="theme" placeholder="Select theme">
        <TuffSelectItem value="light" label="Light" />
        <TuffSelectItem value="dark" label="Dark" />
        <TuffSelectItem value="auto" label="System" />
      </TxSelect>
    </TxBlockSlot>
  </template>
---
:::

### Active State and Tags
`active` swaps in `activeIcon`; the `tags` slot sits beside the title.
:::TuffDemoWrapper{demo="GroupBlockBlockSlotActiveDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockSlot
      title="Pinned workspace"
      description="Show this workspace first"
      default-icon="i-carbon-star"
      active-icon="i-carbon-star-filled"
      active
    >
      <template #tags>
        <TxTag label="Active" icon="i-carbon-checkmark-filled" color="var(--tx-color-success)" />
      </template>
      <TxButton size="sm" variant="secondary">Manage</TxButton>
    </TxBlockSlot>
  </template>
---
:::

### Custom Labels
The `label` slot replaces the title and description.
:::TuffDemoWrapper{demo="GroupBlockBlockSlotCustomLabelDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockSlot default-icon="i-carbon-user-profile">
      <template #label>
        <strong>Profile name</strong>
        <p>Shown in shared workspaces.</p>
      </template>
      <TuffInput v-model="profileName" placeholder="Enter profile name" />
    </TxBlockSlot>
  </template>
---
:::

### Input Rows
`TxBlockInput` is a settings row with a built-in `TxInput`.
:::TuffDemoWrapper{demo="GroupBlockBlockInputDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockInput
      v-model="displayName"
      title="Display name"
      description="Shown in shared workspaces and notifications."
      placeholder="Enter display name"
      default-icon="i-carbon-user-profile"
      clearable
    />
  </template>
---
:::

### Select Rows
`TxBlockSelect` is a settings row with a built-in `TxSelect`; options go in the default slot.
:::TuffDemoWrapper{demo="GroupBlockBlockSelectDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockSelect
      v-model="timezone"
      title="Time display"
      description="Choose how activity timestamps are shown."
      placeholder="Select time display"
      default-icon="i-carbon-time"
    >
      <TuffSelectItem value="local" label="Local time" />
      <TuffSelectItem value="utc" label="UTC" />
      <TuffSelectItem value="relative" label="Relative time" />
    </TxBlockSelect>
  </template>
---
:::

### Switch Rows
:::TuffDemoWrapper{demo="GroupBlockBlockSwitchDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockSwitch
      v-model="autoUpdate"
      title="Auto update"
      description="Install updates when the app restarts"
      default-icon="i-carbon-renew"
    />
  </template>
---
:::

### Switch Loading
`loading` turns the inner switch's thumb into a spinning ring and freezes the row without dimming it.
:::TuffDemoWrapper{demo="GroupBlockBlockSwitchLoadingDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockSwitch
      v-model="syncEnabled"
      title="Sync status"
      description="Waiting for the latest state"
      default-icon="i-carbon-renew"
      loading
    />
  </template>
---
:::

### Switch Disabled
:::TuffDemoWrapper{demo="GroupBlockBlockSwitchDisabledDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockSwitch
      v-model="locked"
      title="Locked setting"
      description="Managed by your organization"
      default-icon="i-carbon-locked"
      disabled
    />
  </template>
---
:::

### Guidance Rows
`guidance` replaces the switch with a chevron and emits only `click`.
:::TuffDemoWrapper{demo="GroupBlockBlockSwitchGuidanceDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBlockSwitch
      v-model="dummy"
      title="Security settings"
      description="Open the security preferences page"
      default-icon="i-carbon-security"
      guidance
      @click="openSecurity"
    />
  </template>
---
:::

### Best Practices

- Keep each `memoryName` unique and stable; don't share a key between unrelated groups.
- Set `collapsible=false` on always-visible status or form sections so they don't imply hidden content.
- Use `TxBlockLine` for read-only values and light navigation, `TxBlockSlot` for custom controls, `TxBlockInput` / `TxBlockSelect` for standard form rows, and `TxBlockSwitch` for booleans and navigation.
- Keep row titles short and move long explanations into the description; don't nest complex layouts in a row.
- The group squares off its rows; don't hard-code `border-radius: 0` on a row to imitate that look.

## API Reference

### TxGroupBlock

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `name` | `string` | *required* | Group title. |
| `description` | `string` | `''` | Text below the title. |
| `defaultIcon` | `TxIconSource \| string` | - | Icon while collapsed; also the fallback for `activeIcon`. |
| `activeIcon` | `TxIconSource \| string` | - | Icon while expanded; falls back to `defaultIcon`. |
| `iconSize` | `number` | `22` | Header icon size in px. |
| `collapsible` | `boolean` | `true` | Lets the header expand and collapse the group. |
| `collapsed` | `boolean` | `false` | External collapsed state, re-applied on change until the user toggles or a stored state exists. |
| `defaultExpand` | `boolean` | - | Expanded state on first render; wins over `collapsed`, and defaults to `!collapsed`. |
| `memoryName` | `string` | `''` | Persists the expanded state in `localStorage` under the `tuff-block-storage-` prefix. |

#### Events

| Event | Params | Description |
|------|--------|-------------|
| `update:expanded` | `expanded: boolean` | Fires after the user toggles the group. |
| `toggle` | `expanded: boolean` | Fires together with `update:expanded`. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | - | Rows inside the group. |
| `icon` | `{ active: boolean }` | Custom header icon. |
| `header-extra` | `{ active: boolean }` | Header actions, before the collapse chevron. |

### TxBlockLine

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `title` | `string` | `''` | Row title. |
| `description` | `string` | `''` | Value of a non-link row; the `description` slot replaces it. |
| `link` | `boolean` | `false` | Renders a native button with link styling that emits `click`. |

#### Events

| Event | Params | Description |
|------|--------|-------------|
| `click` | `event: MouseEvent` | Fires only when `link` is set. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `description` | - | Custom value or link content. |

### TxBlockSlot

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `title` | `string` | `''` | Title; not rendered when the `label` slot is used. |
| `description` | `string` | `''` | Description; not rendered when the `label` slot is used. |
| `defaultIcon` | `TxIconSource \| string` | - | Icon while inactive; also the fallback for `activeIcon`. |
| `activeIcon` | `TxIconSource \| string` | - | Icon while active; falls back to `defaultIcon`. |
| `iconSize` | `number` | `20` | Icon size in px. |
| `active` | `boolean` | `false` | Swaps in `activeIcon` and passes `active` to slot scopes; doesn't restyle the row. |
| `disabled` | `boolean` | `false` | Disabled styling; blocks `click`. |

#### Events

| Event | Params | Description |
|------|--------|-------------|
| `click` | `event: MouseEvent` | Fires on row click; once bound, the row is focusable and also fires on Enter / Space. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | `{ active: boolean }` | Control area on the right. |
| `icon` | `{ active: boolean }` | Custom icon. |
| `label` | - | Replaces the title and description. |
| `tags` | - | Metadata beside the title, or below a custom label. |

### TxBlockInput

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `modelValue` | `string \| number` | `''` | Input value, bound with `v-model`. |
| `title` | `string` | `''` | Row title. |
| `description` | `string` | `''` | Row description. |
| `defaultIcon` | `TxIconSource \| string` | - | Icon while unfocused; also the fallback for `activeIcon`. |
| `activeIcon` | `TxIconSource \| string` | - | Icon while focused. |
| `disabled` | `boolean` | `false` | Disables the row and the input. |
| `placeholder` | `string` | `''` | Placeholder text. |
| `clearable` | `boolean` | `false` | Forwarded to `TxInput`. |
| `inputType` | `'text' \| 'password' \| 'number' \| 'email'` | `'text'` | Forwarded as the `TxInput` type. |

#### Events

| Event | Params | Description |
|------|--------|-------------|
| `update:modelValue` | `value: string \| number` | Fires when the input value changes. |
| `input` | `value: string \| number` | Mirrors the `TxInput` `input` event. |
| `focus` | `event: FocusEvent` | Fires when the input gains focus. |
| `blur` | `event: FocusEvent` | Fires when the input loses focus. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `control` | `{ value: string \| number, focused: boolean }` | Replaces the default `TxInput`. |
| `tags` | - | Metadata beside the title. |

### TxBlockSelect

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `modelValue` | `string \| number` | `''` | Selected value, bound with `v-model`. |
| `title` | `string` | `''` | Row title. |
| `description` | `string` | `''` | Row description. |
| `defaultIcon` | `TxIconSource \| string` | - | Icon with no value selected; also the fallback for `activeIcon`. |
| `activeIcon` | `TxIconSource \| string` | - | Icon with a value selected. |
| `disabled` | `boolean` | `false` | Disables the row and the select. |
| `placeholder` | `string` | `''` | Placeholder text. |

#### Events

| Event | Params | Description |
|------|--------|-------------|
| `update:modelValue` | `value: string \| number` | Fires when the selected value changes. |
| `change` | `value: string \| number` | Fires together with `update:modelValue`. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | - | `TxSelect` options such as `TuffSelectItem`. |
| `tags` | - | Metadata beside the title. |

### TxBlockSwitch

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `modelValue` | `boolean` | *required* | Switch value, bound with `v-model`. |
| `title` | `string` | *required* | Row title. |
| `description` | `string` | *required* | Row description. |
| `defaultIcon` | `TxIconSource \| string` | - | Icon while off; also the fallback for `activeIcon`. |
| `activeIcon` | `TxIconSource \| string` | - | Icon while on; falls back to `defaultIcon`. |
| `disabled` | `boolean` | `false` | Disables the row and the switch. |
| `guidance` | `boolean` | `false` | Shows a chevron instead of the switch, as a navigation row. |
| `loading` | `boolean` | `false` | Forwarded to the inner switch: the thumb spins, the row shimmers, and interaction pauses. |

#### Events

| Event | Params | Description |
|------|--------|-------------|
| `update:modelValue` | `value: boolean` | Fires when the switch value changes. |
| `change` | `value: boolean` | Mirrors the switch `change` after a user toggle. |
| `click` | `event: MouseEvent` | Fires only in `guidance` mode. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `tags` | - | Metadata beside the title. |

## Overview

- The first-render state comes from the stored state, then `defaultExpand`, then `!collapsed`; after the user toggles, prop changes no longer override it.
- The group body stays mounted; collapsing only changes height, opacity, and `display`.
- The group resets each row's `--fake-radius` and margin so only the group card is rounded; a standalone row keeps its 12px radius.
- `TxBlockLine` is a non-interactive `div` unless `link` is set, when it becomes a `<button type="button">`.
- `TxBlockSlot` never shrinks its control area; `TxBlockInput` is the exception, letting its field shrink to 120px to make room for the title.
- In `TxBlockSwitch`, the busy cue lives only on the inner switch (`is-loading` + `aria-busy`) and the row only shimmers; `guidance` mode never writes `modelValue`.

## Technologies

- GSAP animates height and opacity on expand and collapse, then releases to `auto` or `display: none`.
- Source: `packages/tuffex/packages/components/src/group-block/`.

<TuffDocSourceLink />

## Customization

| Theme token | Used for |
|-------------|----------|
| `--tx-border-color-lighter` | Group border and header divider. |
| `--tx-fill-color-dark` / `--tx-fill-color` / `--tx-fill-color-light` | Header, row, and hover surfaces. |
| `--tx-text-color-primary` / `--tx-text-color-secondary` | Titles, labels, descriptions, guidance arrows, and the loading ring. |
| `--tx-color-primary` / `--tx-color-primary-dark-2` | Link-row text and hover colors. |
| `--tx-color-white` | Loading shimmer highlight. |
