or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

block-kit.mdcalls.mddialog.mdevents.mdindex.mdinteractive-elements.mdmessage-attachments.mdmessage-metadata.mdviews.md

views.mddocs/

0

# Views and Modals

1

2

Views define the structure of Slack's interactive surfaces including modals, App Home tabs, and workflow step configurations. They provide the foundation for building rich user interfaces within Slack.

3

4

## Capabilities

5

6

### View Types

7

8

Union type covering all supported view types.

9

10

```typescript { .api }

11

type View = HomeView | ModalView | WorkflowStepView;

12

```

13

14

### Base View Interface

15

16

Common properties shared by all view types.

17

18

```typescript { .api }

19

interface BaseView {

20

blocks: AnyBlock[];

21

private_metadata?: string;

22

callback_id?: string;

23

external_id?: string;

24

}

25

```

26

27

### Modal View

28

29

Interactive modal dialogs with titles, submit/close buttons, and content blocks.

30

31

```typescript { .api }

32

interface ModalView extends BaseView {

33

type: 'modal';

34

title: PlainTextElement;

35

close?: PlainTextElement;

36

submit?: PlainTextElement;

37

clear_on_close?: boolean;

38

notify_on_close?: boolean;

39

}

40

```

41

42

**Usage Example:**

43

44

```typescript

45

import { ModalView, InputBlock, PlainTextInput } from "@slack/types";

46

47

const modal: ModalView = {

48

type: "modal",

49

title: {

50

type: "plain_text",

51

text: "User Registration"

52

},

53

submit: {

54

type: "plain_text",

55

text: "Submit"

56

},

57

close: {

58

type: "plain_text",

59

text: "Cancel"

60

},

61

blocks: [

62

{

63

type: "input",

64

block_id: "name_input",

65

label: {

66

type: "plain_text",

67

text: "Full Name"

68

},

69

element: {

70

type: "plain_text_input",

71

action_id: "name_value",

72

placeholder: {

73

type: "plain_text",

74

text: "Enter your full name"

75

}

76

}

77

},

78

{

79

type: "input",

80

block_id: "email_input",

81

label: {

82

type: "plain_text",

83

text: "Email Address"

84

},

85

element: {

86

type: "email_text_input",

87

action_id: "email_value",

88

placeholder: {

89

type: "plain_text",

90

text: "your.email@example.com"

91

}

92

}

93

}

94

],

95

callback_id: "user_registration_modal",

96

private_metadata: "registration_flow_v1"

97

};

98

```

99

100

### Home View

101

102

App Home tab interface for displaying custom content in the user's App Home.

103

104

```typescript { .api }

105

interface HomeView extends BaseView {

106

type: 'home';

107

}

108

```

109

110

**Usage Example:**

111

112

```typescript

113

import { HomeView, SectionBlock, HeaderBlock } from "@slack/types";

114

115

const homeView: HomeView = {

116

type: "home",

117

blocks: [

118

{

119

type: "header",

120

text: {

121

type: "plain_text",

122

text: "Welcome to Your Dashboard"

123

}

124

},

125

{

126

type: "section",

127

text: {

128

type: "mrkdwn",

129

text: "Here's a summary of your recent activity:"

130

}

131

},

132

{

133

type: "section",

134

fields: [

135

{

136

type: "mrkdwn",

137

text: "*Tasks Completed:*\n25"

138

},

139

{

140

type: "mrkdwn",

141

text: "*Messages Sent:*\n142"

142

}

143

]

144

},

145

{

146

type: "actions",

147

elements: [

148

{

149

type: "button",

150

text: {

151

type: "plain_text",

152

text: "View Reports"

153

},

154

action_id: "view_reports",

155

style: "primary"

156

},

157

{

158

type: "button",

159

text: {

160

type: "plain_text",

161

text: "Settings"

162

},

163

action_id: "open_settings"

164

}

165

]

166

}

167

]

168

};

169

```

170

171

### Workflow Step View (Deprecated)

172

173

Configuration modal for legacy Workflow Steps from Apps.

174

175

```typescript { .api }

176

interface WorkflowStepView extends BaseView {

177

type: 'workflow_step';

178

submit_disabled?: boolean;

179

}

180

```

181

182

**Note**: Workflow Steps from Apps are deprecated and will no longer be executed starting September 12, 2024.

183

184

## View Properties

185

186

### Blocks Array

187

188

All views contain an array of blocks that define their content structure.

189

190

```typescript { .api }

191

blocks: AnyBlock[];

192

```

193

194

The blocks array can contain any valid Block Kit blocks:

195

- `ActionsBlock` - Interactive elements

196

- `ContextBlock` - Contextual information

197

- `DividerBlock` - Visual separators

198

- `HeaderBlock` - Section headers

199

- `ImageBlock` - Image displays

200

- `InputBlock` - Form inputs (modals only)

201

- `SectionBlock` - Text content with optional accessories

202

- `RichTextBlock` - Formatted rich text

203

- `VideoBlock` - Embedded videos

204

205

### Private Metadata

206

207

String data passed to interaction payloads for maintaining state.

208

209

```typescript { .api }

210

private_metadata?: string;

211

```

212

213

**Usage Example:**

214

215

```typescript

216

const modal: ModalView = {

217

// ... other properties

218

private_metadata: JSON.stringify({

219

user_id: "U123456",

220

flow_step: "confirmation",

221

original_message_ts: "1609459200.000300"

222

})

223

};

224

```

225

226

### Callback ID

227

228

Identifier for recognizing view interactions and submissions.

229

230

```typescript { .api }

231

callback_id?: string;

232

```

233

234

### External ID

235

236

Custom identifier unique per team for external reference.

237

238

```typescript { .api }

239

external_id?: string;

240

```

241

242

## Modal-Specific Properties

243

244

### Title

245

246

Required title displayed in modal header.

247

248

```typescript { .api }

249

title: PlainTextElement;

250

```

251

252

### Submit Button

253

254

Optional submit button text (required when input blocks are present).

255

256

```typescript { .api }

257

submit?: PlainTextElement;

258

```

259

260

### Close Button

261

262

Optional close button text.

263

264

```typescript { .api }

265

close?: PlainTextElement;

266

```

267

268

### Clear on Close

269

270

When true, clicking close clears all modal views and closes the modal.

271

272

```typescript { .api }

273

clear_on_close?: boolean;

274

```

275

276

### Notify on Close

277

278

When true, sends `view_closed` event when user clicks close button.

279

280

```typescript { .api }

281

notify_on_close?: boolean;

282

```

283

284

## Modal Interaction Patterns

285

286

Modals support several interaction patterns:

287

288

### Form Collection

289

290

Use input blocks to collect structured data from users:

291

292

```typescript

293

const formModal: ModalView = {

294

type: "modal",

295

title: { type: "plain_text", text: "Project Details" },

296

submit: { type: "plain_text", text: "Create Project" },

297

blocks: [

298

{

299

type: "input",

300

label: { type: "plain_text", text: "Project Name" },

301

element: {

302

type: "plain_text_input",

303

action_id: "project_name"

304

}

305

},

306

{

307

type: "input",

308

label: { type: "plain_text", text: "Team Members" },

309

element: {

310

type: "multi_users_select",

311

action_id: "team_members",

312

placeholder: { type: "plain_text", text: "Select team members" }

313

}

314

},

315

{

316

type: "input",

317

label: { type: "plain_text", text: "Due Date" },

318

element: {

319

type: "datepicker",

320

action_id: "due_date"

321

}

322

}

323

]

324

};

325

```

326

327

### Multi-Step Workflows

328

329

Use `private_metadata` to track workflow state across multiple modal views:

330

331

```typescript

332

const step1Modal: ModalView = {

333

type: "modal",

334

title: { type: "plain_text", text: "Setup - Step 1 of 3" },

335

submit: { type: "plain_text", text: "Next" },

336

blocks: [/* step 1 content */],

337

private_metadata: JSON.stringify({ step: 1, data: {} }),

338

callback_id: "setup_workflow"

339

};

340

```

341

342

### Dynamic Content

343

344

Modal content can be updated using the `views.update` API method with the same view structure.

345

346

## App Home Patterns

347

348

App Home views provide a persistent interface for users:

349

350

### Dashboard Layout

351

352

```typescript

353

const dashboardHome: HomeView = {

354

type: "home",

355

blocks: [

356

{ type: "header", text: { type: "plain_text", text: "Dashboard" } },

357

{ type: "divider" },

358

{

359

type: "section",

360

text: { type: "mrkdwn", text: "*Recent Activity*" },

361

accessory: {

362

type: "button",

363

text: { type: "plain_text", text: "Refresh" },

364

action_id: "refresh_dashboard"

365

}

366

}

367

]

368

};

369

```

370

371

### Navigation Menu

372

373

```typescript

374

const navigationHome: HomeView = {

375

type: "home",

376

blocks: [

377

{

378

type: "actions",

379

elements: [

380

{

381

type: "button",

382

text: { type: "plain_text", text: "πŸ“Š Reports" },

383

action_id: "show_reports"

384

},

385

{

386

type: "button",

387

text: { type: "plain_text", text: "βš™οΈ Settings" },

388

action_id: "show_settings"

389

},

390

{

391

type: "button",

392

text: { type: "plain_text", text: "❓ Help" },

393

action_id: "show_help"

394

}

395

]

396

}

397

]

398

};

399

```