# Views & Modals

Open, update, and manage interactive modals and home tabs for rich user interfaces. The Views API allows you to create modal dialogs and App Home tabs that provide sophisticated user interactions within Slack.

## Capabilities

### Open View

Open a modal dialog or App Home tab.

```typescript { .api }
/**
 * Open a view for a user
 * @param options - View configuration with trigger or interactivity pointer
 * @returns Promise resolving to view details
 */
views.open(options: ViewsOpenArguments): Promise<ViewsOpenResponse>;

type ViewsOpenArguments = BaseViewsArguments & TokenOverridable & (ViewTriggerId | ViewInteractivityPointer);

interface BaseViewsArguments {
  /** A view payload defining the modal or home tab structure */
  view: View;
}

interface ViewTriggerId {
  /** Access token from a user interaction - required to open views */
  trigger_id: string;
}

interface ViewInteractivityPointer {
  /** Access token from a user interaction - alternative to trigger_id */
  interactivity_pointer: string;
}

interface ViewsOpenResponse extends WebAPICallResult {
  /** The opened view object */
  view?: View;
}
```

**Usage Examples:**

```typescript
import { WebClient } from "@slack/web-api";

const web = new WebClient(process.env.SLACK_BOT_TOKEN);

// Open a modal dialog
const result = await web.views.open({
  trigger_id: "123456.789.abc",
  view: {
    type: "modal",
    title: {
      type: "plain_text",
      text: "My Modal"
    },
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: "Hello from a modal!"
        }
      }
    ]
  }
});

// Open an App Home tab
await web.views.publish({
  user_id: "U1234567890",
  view: {
    type: "home",
    blocks: [
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: "Welcome to the App Home!"
        }
      }
    ]
  }
});
```

### Push View

Push a new view onto the modal stack.

```typescript { .api }
/**
 * Push a view onto the stack of a root view
 * @param options - View configuration with trigger or interactivity pointer
 * @returns Promise resolving to view details
 */
views.push(options: ViewsPushArguments): Promise<ViewsPushResponse>;

type ViewsPushArguments = BaseViewsArguments & TokenOverridable & (ViewTriggerId | ViewInteractivityPointer);

interface ViewsPushResponse extends WebAPICallResult {
  /** The pushed view object */
  view?: View;
}
```

### Update View

Update an existing view with new content.

```typescript { .api }
/**
 * Update an existing view
 * @param options - View configuration with view identifier
 * @returns Promise resolving to updated view details
 */
views.update(options: ViewsUpdateArguments): Promise<ViewsUpdateResponse>;

type ViewsUpdateArguments = BaseViewsArguments & TokenOverridable & (ViewExternalId | ViewViewId) & ViewHash;

interface ViewExternalId {
  /** Unique identifier set by developer - alternative to view_id */
  external_id: string;
}

interface ViewViewId {
  /** Unique identifier of the view to update */
  view_id: string;
}

interface ViewHash {
  /** String representing view state to prevent race conditions */
  hash?: string;
}

interface ViewsUpdateResponse extends WebAPICallResult {
  /** The updated view object */
  view?: View;
}
```

### Publish View

Publish a static view to a user's App Home tab.

```typescript { .api }
/**
 * Publish a static view for a user
 * @param options - View configuration with user ID
 * @returns Promise resolving to published view details
 */
views.publish(options: ViewsPublishArguments): Promise<ViewsPublishResponse>;

interface ViewsPublishArguments extends BaseViewsArguments, TokenOverridable, ViewHash {
  /** ID of the user to publish the view to */
  user_id: string;
}

interface ViewsPublishResponse extends WebAPICallResult {
  /** The published view object */
  view?: View;
}
```

## Core Types

```typescript { .api }
interface View {
  /** App ID that owns the view */
  app_id?: string;
  /** Team ID where app is installed */
  app_installed_team_id?: string;
  /** Array of blocks that define the view structure */
  blocks?: Block[];
  /** Bot ID associated with the view */
  bot_id?: string;
  /** Developer-defined callback identifier */
  callback_id?: string;
  /** Whether to clear view state when closed */
  clear_on_close?: boolean;
  /** Close button configuration */
  close?: TextObject;
  /** External ID set by developer */
  external_id?: string;
  /** Hash for preventing race conditions */
  hash?: string;
  /** Unique view identifier */
  id?: string;
  /** Whether to notify when view is closed */
  notify_on_close?: boolean;
  /** ID of the previous view in the stack */
  previous_view_id?: string;
  /** Private metadata string (up to 3000 characters) */
  private_metadata?: string;
  /** Root view ID in the stack */
  root_view_id?: string;
  /** Current state of input elements */
  state?: ViewState;
  /** Submit button configuration */
  submit?: TextObject;
  /** Whether submit button is disabled */
  submit_disabled?: boolean;
  /** Team ID associated with the view */
  team_id?: string;
  /** Title of the view */
  title?: TextObject;
  /** Type of view - 'modal' or 'home' */
  type?: string;
}

interface TextObject {
  /** Whether text contains emoji */
  emoji?: boolean;
  /** Text content */
  text?: string;
  /** Text type - 'plain_text' or 'mrkdwn' */
  type?: string;
  /** Whether to use verbatim text rendering */
  verbatim?: boolean;
}

interface ViewState {
  values?: Record<string, Record<string, any>>;
}

interface TokenOverridable {
  /** Override the default token for this request */
  token?: string;
}
```