or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

children-utilities.mdcontext-api.mdcore-api.mdimmutability-helpers.mdindex.mdlegacy-apis.mdperformance-tools.mdrefs-system.mdserver-rendering.mdtransition-groups.md

transition-groups.mddocs/

0

# Transition Groups

1

2

Animation and transition components for managing component lifecycle animations and CSS transitions.

3

4

## Capabilities

5

6

### Transition Group

7

8

Container component that manages entering and leaving transitions for its children.

9

10

```javascript { .api }

11

/**

12

* Container for managing child component transitions

13

*/

14

class TransitionGroup extends Component {

15

/**

16

* TransitionGroup props

17

*/

18

props: {

19

/** Component type to render as (default: 'span') */

20

component?: string | ComponentType;

21

22

/** Additional props passed to component */

23

[key: string]: any;

24

};

25

}

26

27

/**

28

* CSS-based transition group with automatic class management

29

*/

30

class CSSTransitionGroup extends Component {

31

/**

32

* CSSTransitionGroup props

33

*/

34

props: {

35

/** Base name for CSS classes */

36

transitionName: string | TransitionClasses;

37

38

/** Enter transition duration in ms */

39

transitionEnterTimeout: number;

40

41

/** Leave transition duration in ms */

42

transitionLeaveTimeout: number;

43

44

/** Whether to apply transition on initial mount */

45

transitionAppear?: boolean;

46

47

/** Appear transition duration in ms */

48

transitionAppearTimeout?: number;

49

50

/** Component type to render as (default: 'span') */

51

component?: string | ComponentType;

52

53

/** Additional props passed to component */

54

[key: string]: any;

55

};

56

}

57

58

/**

59

* CSS class names for different transition states

60

*/

61

interface TransitionClasses {

62

enter: string;

63

enterActive: string;

64

leave: string;

65

leaveActive: string;

66

appear?: string;

67

appearActive?: string;

68

}

69

```

70

71

**Usage Examples:**

72

73

```javascript

74

import { CSSTransitionGroup } from 'preact-compat';

75

// or

76

import { CSSTransitionGroup } from 'preact-compat/lib/ReactTransitionGroup';

77

78

class TodoList extends Component {

79

state = {

80

todos: [

81

{ id: 1, text: 'Learn React' },

82

{ id: 2, text: 'Build an app' }

83

]

84

};

85

86

addTodo = () => {

87

const newTodo = {

88

id: Date.now(),

89

text: `Todo ${this.state.todos.length + 1}`

90

};

91

92

this.setState({

93

todos: [...this.state.todos, newTodo]

94

});

95

};

96

97

removeTodo = (id) => {

98

this.setState({

99

todos: this.state.todos.filter(todo => todo.id !== id)

100

});

101

};

102

103

render() {

104

return (

105

<div>

106

<button onClick={this.addTodo}>Add Todo</button>

107

108

<CSSTransitionGroup

109

transitionName="todo"

110

transitionEnterTimeout={300}

111

transitionLeaveTimeout={300}

112

component="ul"

113

>

114

{this.state.todos.map(todo => (

115

<li key={todo.id}>

116

{todo.text}

117

<button onClick={() => this.removeTodo(todo.id)}>

118

Remove

119

</button>

120

</li>

121

))}

122

</CSSTransitionGroup>

123

</div>

124

);

125

}

126

}

127

```

128

129

### CSS Classes and Animations

130

131

```css

132

/* CSS for the example above */

133

134

/* Enter transition */

135

.todo-enter {

136

opacity: 0;

137

transform: translateX(-100%);

138

}

139

140

.todo-enter-active {

141

opacity: 1;

142

transform: translateX(0);

143

transition: all 300ms ease-in;

144

}

145

146

/* Leave transition */

147

.todo-leave {

148

opacity: 1;

149

transform: translateX(0);

150

}

151

152

.todo-leave-active {

153

opacity: 0;

154

transform: translateX(100%);

155

transition: all 300ms ease-out;

156

}

157

158

/* Appear transition (optional) */

159

.todo-appear {

160

opacity: 0;

161

transform: scale(0.8);

162

}

163

164

.todo-appear-active {

165

opacity: 1;

166

transform: scale(1);

167

transition: all 300ms ease-in-out;

168

}

169

```

170

171

### Custom Transition Classes

172

173

```javascript

174

import { CSSTransitionGroup } from 'preact-compat';

175

176

const customTransitions = {

177

enter: 'slide-in',

178

enterActive: 'slide-in-active',

179

leave: 'slide-out',

180

leaveActive: 'slide-out-active',

181

appear: 'fade-in',

182

appearActive: 'fade-in-active'

183

};

184

185

function AnimatedList({ items }) {

186

return (

187

<CSSTransitionGroup

188

transitionName={customTransitions}

189

transitionEnterTimeout={500}

190

transitionLeaveTimeout={500}

191

transitionAppear={true}

192

transitionAppearTimeout={500}

193

component="div"

194

className="animated-container"

195

>

196

{items.map(item => (

197

<div key={item.id} className="animated-item">

198

{item.content}

199

</div>

200

))}

201

</CSSTransitionGroup>

202

);

203

}

204

```

205

206

### Modal with Transitions

207

208

```javascript

209

import { CSSTransitionGroup } from 'preact-compat';

210

211

class Modal extends Component {

212

render() {

213

const { isOpen, onClose, children } = this.props;

214

215

return (

216

<CSSTransitionGroup

217

transitionName="modal"

218

transitionEnterTimeout={200}

219

transitionLeaveTimeout={200}

220

component="div"

221

>

222

{isOpen && (

223

<div key="modal" className="modal-backdrop" onClick={onClose}>

224

<div className="modal-content" onClick={e => e.stopPropagation()}>

225

<button className="modal-close" onClick={onClose}>×</button>

226

{children}

227

</div>

228

</div>

229

)}

230

</CSSTransitionGroup>

231

);

232

}

233

}

234

235

// CSS for modal transitions

236

/*

237

.modal-enter {

238

opacity: 0;

239

}

240

241

.modal-enter-active {

242

opacity: 1;

243

transition: opacity 200ms ease-in;

244

}

245

246

.modal-leave {

247

opacity: 1;

248

}

249

250

.modal-leave-active {

251

opacity: 0;

252

transition: opacity 200ms ease-out;

253

}

254

255

.modal-backdrop {

256

position: fixed;

257

top: 0;

258

left: 0;

259

right: 0;

260

bottom: 0;

261

background: rgba(0, 0, 0, 0.5);

262

display: flex;

263

align-items: center;

264

justify-content: center;

265

}

266

267

.modal-content {

268

background: white;

269

padding: 20px;

270

border-radius: 4px;

271

position: relative;

272

max-width: 500px;

273

width: 90%;

274

}

275

*/

276

```

277

278

### Route Transitions

279

280

```javascript

281

import { CSSTransitionGroup } from 'preact-compat';

282

283

class App extends Component {

284

state = { currentRoute: 'home' };

285

286

navigate = (route) => {

287

this.setState({ currentRoute: route });

288

};

289

290

renderRoute = () => {

291

const { currentRoute } = this.state;

292

293

switch (currentRoute) {

294

case 'home':

295

return <HomePage key="home" />;

296

case 'about':

297

return <AboutPage key="about" />;

298

case 'contact':

299

return <ContactPage key="contact" />;

300

default:

301

return <HomePage key="home" />;

302

}

303

};

304

305

render() {

306

return (

307

<div>

308

<nav>

309

<button onClick={() => this.navigate('home')}>Home</button>

310

<button onClick={() => this.navigate('about')}>About</button>

311

<button onClick={() => this.navigate('contact')}>Contact</button>

312

</nav>

313

314

<CSSTransitionGroup

315

transitionName="page"

316

transitionEnterTimeout={300}

317

transitionLeaveTimeout={300}

318

component="main"

319

className="page-container"

320

>

321

{this.renderRoute()}

322

</CSSTransitionGroup>

323

</div>

324

);

325

}

326

}

327

```

328

329

### Basic TransitionGroup

330

331

```javascript

332

import { TransitionGroup } from 'preact-compat';

333

334

class CustomTransitionGroup extends Component {

335

render() {

336

return (

337

<TransitionGroup component="div" className="transition-container">

338

{this.props.items.map(item => (

339

<CustomTransitionChild key={item.id} item={item} />

340

))}

341

</TransitionGroup>

342

);

343

}

344

}

345

346

// Custom child component that handles its own transitions

347

class CustomTransitionChild extends Component {

348

componentWillEnter(done) {

349

// Custom enter animation

350

const el = this.refs.element;

351

el.style.opacity = '0';

352

el.style.transform = 'translateY(-20px)';

353

354

requestAnimationFrame(() => {

355

el.style.transition = 'all 300ms ease';

356

el.style.opacity = '1';

357

el.style.transform = 'translateY(0)';

358

359

setTimeout(done, 300);

360

});

361

}

362

363

componentWillLeave(done) {

364

// Custom leave animation

365

const el = this.refs.element;

366

el.style.transition = 'all 300ms ease';

367

el.style.opacity = '0';

368

el.style.transform = 'translateY(20px)';

369

370

setTimeout(done, 300);

371

}

372

373

render() {

374

return (

375

<div ref="element">

376

{this.props.item.content}

377

</div>

378

);

379

}

380

}

381

```

382

383

## Import Patterns

384

385

```javascript

386

// Main imports

387

import { TransitionGroup, CSSTransitionGroup } from 'preact-compat';

388

389

// Library imports

390

import { TransitionGroup, CSSTransitionGroup } from 'preact-compat/lib/ReactTransitionGroup';

391

392

// CommonJS

393

const { TransitionGroup, CSSTransitionGroup } = require('preact-compat/lib/ReactTransitionGroup');

394

```

395

396

## Types

397

398

```javascript { .api }

399

interface TransitionGroupProps {

400

component?: string | ComponentType;

401

[key: string]: any;

402

}

403

404

interface CSSTransitionGroupProps {

405

transitionName: string | TransitionClasses;

406

transitionEnterTimeout: number;

407

transitionLeaveTimeout: number;

408

transitionAppear?: boolean;

409

transitionAppearTimeout?: number;

410

component?: string | ComponentType;

411

[key: string]: any;

412

}

413

414

interface TransitionClasses {

415

enter: string;

416

enterActive: string;

417

leave: string;

418

leaveActive: string;

419

appear?: string;

420

appearActive?: string;

421

}

422

423

interface TransitionChildComponent {

424

componentWillEnter?(done: () => void): void;

425

componentDidEnter?(): void;

426

componentWillLeave?(done: () => void): void;

427

componentDidLeave?(): void;

428

componentWillAppear?(done: () => void): void;

429

componentDidAppear?(): void;

430

}

431

```