or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

communication.mderror-handling.mdindex.mdlayout-style.mdnativeview.mdregistry.mdutilities.mdwidget-classes.mdwidget-manager.md
tile.json

layout-style.mddocs/

0

# Layout & Style System

1

2

The layout and style system provides CSS-based positioning, sizing, and appearance management for Jupyter widgets through trait-based property handling.

3

4

## Capabilities

5

6

### Layout System

7

8

CSS-based layout management with support for flexbox, grid, positioning, and spacing properties.

9

10

```typescript { .api }

11

/**

12

* Model for widget layout properties, supports comprehensive CSS layout

13

*/

14

class LayoutModel extends WidgetModel {

15

/**

16

* Default attributes including all supported CSS properties

17

*/

18

defaults(): Backbone.ObjectHash;

19

}

20

```

21

22

**Supported Layout Properties:**

23

24

All layout properties default to `null` and map directly to CSS properties:

25

26

**Position & Size:**

27

- `top`, `right`, `bottom`, `left` - Positioning values

28

- `width`, `height` - Element dimensions

29

- `min_width`, `min_height`, `max_width`, `max_height` - Size constraints

30

31

**Flexbox Layout:**

32

- `flex` - Flex grow/shrink/basis shorthand

33

- `flex_flow` - Flex direction and wrap shorthand

34

- `align_content` - Align flex lines

35

- `align_items` - Align flex items

36

- `align_self` - Individual item alignment

37

- `justify_content` - Main axis alignment

38

- `justify_items` - Grid item justification

39

- `order` - Flex/grid item order

40

41

**Spacing:**

42

- `margin` - Outer spacing

43

- `padding` - Inner spacing

44

45

**Border:**

46

- `border_top`, `border_right`, `border_bottom`, `border_left` - Individual borders

47

48

**Display:**

49

- `display` - Display type (block, flex, grid, etc.)

50

- `visibility` - Element visibility

51

- `overflow` - Content overflow behavior

52

53

**Grid Layout:**

54

- `grid_auto_columns`, `grid_auto_rows` - Implicit grid sizing

55

- `grid_auto_flow` - Grid item placement algorithm

56

- `grid_gap` - Grid spacing

57

- `grid_template_rows`, `grid_template_columns` - Explicit grid tracks

58

- `grid_template_areas` - Named grid areas

59

- `grid_row`, `grid_column` - Item grid placement

60

- `grid_area` - Item grid area assignment

61

62

**Image-specific:**

63

- `object_fit` - Image scaling behavior

64

- `object_position` - Image positioning

65

66

### Layout View

67

68

View component that applies layout properties to the parent widget element.

69

70

```typescript { .api }

71

/**

72

* View for applying layout styles to the parent widget element

73

*/

74

class LayoutView extends WidgetView {

75

/**

76

* Initialize layout view and register all CSS traits

77

* @param parameters - View initialization parameters

78

*/

79

initialize(parameters: WidgetView.IInitializeParameters): void;

80

81

/**

82

* Register a CSS trait for monitoring and application

83

* @param trait - CSS property name to register

84

*/

85

registerTrait(trait: string): void;

86

87

/**

88

* Convert trait name to CSS property name

89

* @param trait - Model trait name (with underscores)

90

* @returns CSS property name (with hyphens)

91

*/

92

css_name(trait: string): string;

93

94

/**

95

* Handle changes to layout traits and apply to parent element

96

* @param trait - Name of the changed trait

97

* @param value - New value for the trait

98

*/

99

handleChange(trait: string, value: any): void;

100

101

/**

102

* Remove all layout styles from the parent element

103

*/

104

unlayout(): void;

105

}

106

```

107

108

**Usage Examples:**

109

110

```typescript

111

// Create layout model with flexbox properties

112

const layoutModel = new LayoutModel({

113

display: 'flex',

114

flex_direction: 'column',

115

align_items: 'center',

116

padding: '10px',

117

margin: '5px',

118

width: '300px',

119

height: '200px'

120

});

121

122

// Apply to widget

123

widget.set('layout', layoutModel);

124

125

// Dynamic layout updates

126

layoutModel.set({

127

width: '400px',

128

justify_content: 'space-between'

129

});

130

131

// Grid layout example

132

const gridLayout = new LayoutModel({

133

display: 'grid',

134

grid_template_columns: '1fr 2fr 1fr',

135

grid_template_rows: 'auto 1fr auto',

136

grid_gap: '10px',

137

grid_template_areas: `

138

"header header header"

139

"sidebar main aside"

140

"footer footer footer"

141

`

142

});

143

```

144

145

### Style System

146

147

Flexible styling system with custom property definitions and selector-based application.

148

149

```typescript { .api }

150

/**

151

* Base model for widget styling with configurable style properties

152

*/

153

class StyleModel extends WidgetModel {

154

/**

155

* Default attributes based on defined style properties

156

*/

157

defaults(): Backbone.ObjectHash;

158

159

/**

160

* Static definition of available style properties

161

*/

162

static styleProperties: { [s: string]: IStyleProperty };

163

}

164

165

/**

166

* Configuration for individual style properties

167

*/

168

interface IStyleProperty {

169

/**

170

* CSS attribute name to apply

171

*/

172

attribute: string;

173

174

/**

175

* CSS selector for target elements (empty string for widget root)

176

*/

177

selector: string;

178

179

/**

180

* Default value for the property

181

*/

182

default: string;

183

}

184

```

185

186

### Style View

187

188

View component that applies custom styles to widget elements based on selectors.

189

190

```typescript { .api }

191

/**

192

* View for applying custom styles to widget elements

193

*/

194

class StyleView extends WidgetView {

195

/**

196

* Initialize style view and register all defined style traits

197

* @param parameters - View initialization parameters

198

*/

199

initialize(parameters: WidgetView.IInitializeParameters): void;

200

201

/**

202

* Register a style trait for monitoring

203

* @param trait - Style trait name to register

204

*/

205

registerTrait(trait: string): void;

206

207

/**

208

* Handle changes to style traits and apply to target elements

209

* @param trait - Name of the changed trait

210

* @param value - New value for the trait

211

*/

212

handleChange(trait: string, value: any): void;

213

214

/**

215

* Apply all registered styles to their target elements

216

*/

217

style(): void;

218

219

/**

220

* Remove all applied styles from target elements

221

*/

222

unstyle(): void;

223

}

224

```

225

226

**Usage Examples:**

227

228

```typescript

229

// Define custom style properties

230

class ButtonStyleModel extends StyleModel {

231

static styleProperties = {

232

button_color: {

233

attribute: 'background-color',

234

selector: 'button',

235

default: '#ffffff'

236

},

237

text_color: {

238

attribute: 'color',

239

selector: 'button',

240

default: '#000000'

241

},

242

border_radius: {

243

attribute: 'border-radius',

244

selector: 'button',

245

default: '4px'

246

},

247

font_weight: {

248

attribute: 'font-weight',

249

selector: '', // Apply to root element

250

default: 'normal'

251

}

252

};

253

}

254

255

// Create and apply styles

256

const buttonStyle = new ButtonStyleModel({

257

button_color: '#007bff',

258

text_color: '#ffffff',

259

border_radius: '8px',

260

font_weight: 'bold'

261

});

262

263

widget.set('style', buttonStyle);

264

265

// Dynamic style updates

266

buttonStyle.set('button_color', '#28a745'); // Changes button background

267

```

268

269

## Advanced Layout Patterns

270

271

### Responsive Layout

272

273

```typescript

274

// Create responsive layout that adapts to container size

275

const responsiveLayout = new LayoutModel({

276

display: 'grid',

277

grid_template_columns: 'repeat(auto-fit, minmax(250px, 1fr))',

278

grid_gap: '1rem',

279

padding: '1rem'

280

});

281

282

// Media query-like behavior through dynamic updates

283

const updateLayoutForSize = (containerWidth: number) => {

284

if (containerWidth < 600) {

285

responsiveLayout.set({

286

grid_template_columns: '1fr',

287

padding: '0.5rem'

288

});

289

} else if (containerWidth < 900) {

290

responsiveLayout.set({

291

grid_template_columns: 'repeat(2, 1fr)',

292

padding: '0.75rem'

293

});

294

} else {

295

responsiveLayout.set({

296

grid_template_columns: 'repeat(3, 1fr)',

297

padding: '1rem'

298

});

299

}

300

};

301

```

302

303

### Complex Grid Layouts

304

305

```typescript

306

// Dashboard-style grid layout

307

const dashboardLayout = new LayoutModel({

308

display: 'grid',

309

grid_template_columns: '200px 1fr 250px',

310

grid_template_rows: '60px 1fr 40px',

311

grid_template_areas: `

312

"nav header tools"

313

"nav main sidebar"

314

"nav footer sidebar"

315

`,

316

height: '100vh',

317

grid_gap: '8px'

318

});

319

320

// Individual widget positioning

321

const headerWidget = new LayoutModel({

322

grid_area: 'header',

323

display: 'flex',

324

align_items: 'center',

325

padding: '0 20px'

326

});

327

328

const mainWidget = new LayoutModel({

329

grid_area: 'main',

330

overflow: 'auto',

331

padding: '20px'

332

});

333

```

334

335

### Flexbox Patterns

336

337

```typescript

338

// Centered content layout

339

const centeredLayout = new LayoutModel({

340

display: 'flex',

341

align_items: 'center',

342

justify_content: 'center',

343

min_height: '300px'

344

});

345

346

// Toolbar layout

347

const toolbarLayout = new LayoutModel({

348

display: 'flex',

349

align_items: 'center',

350

justify_content: 'space-between',

351

padding: '8px 16px',

352

border_bottom: '1px solid #ccc'

353

});

354

355

// Card layout with flex content

356

const cardLayout = new LayoutModel({

357

display: 'flex',

358

flex_direction: 'column',

359

border: '1px solid #ddd',

360

border_radius: '8px',

361

overflow: 'hidden',

362

max_width: '350px'

363

});

364

```

365

366

## Style Property Patterns

367

368

### Theme-based Styling

369

370

```typescript

371

// Define theme-aware style model

372

class ThemedStyleModel extends StyleModel {

373

static styleProperties = {

374

primary_color: {

375

attribute: '--primary-color',

376

selector: '',

377

default: '#007bff'

378

},

379

secondary_color: {

380

attribute: '--secondary-color',

381

selector: '',

382

default: '#6c757d'

383

},

384

background_color: {

385

attribute: 'background-color',

386

selector: '',

387

default: '#ffffff'

388

},

389

text_color: {

390

attribute: 'color',

391

selector: '',

392

default: '#333333'

393

}

394

};

395

}

396

397

// Apply theme

398

const lightTheme = new ThemedStyleModel({

399

primary_color: '#007bff',

400

background_color: '#ffffff',

401

text_color: '#333333'

402

});

403

404

const darkTheme = new ThemedStyleModel({

405

primary_color: '#0d6efd',

406

background_color: '#1a1a1a',

407

text_color: '#ffffff'

408

});

409

```

410

411

### Component-specific Styling

412

413

```typescript

414

// Multi-element styling

415

class FormStyleModel extends StyleModel {

416

static styleProperties = {

417

label_color: {

418

attribute: 'color',

419

selector: 'label',

420

default: '#495057'

421

},

422

input_border: {

423

attribute: 'border',

424

selector: 'input, select, textarea',

425

default: '1px solid #ced4da'

426

},

427

input_focus_color: {

428

attribute: 'border-color',

429

selector: 'input:focus, select:focus, textarea:focus',

430

default: '#007bff'

431

},

432

error_color: {

433

attribute: 'color',

434

selector: '.error-message',

435

default: '#dc3545'

436

}

437

};

438

}

439

```

440

441

## Layout and Style Integration

442

443

```typescript

444

// Combine layout and style for complete widget theming

445

class ThemedWidget extends DOMWidgetModel {

446

defaults() {

447

return {

448

...super.defaults(),

449

layout: new LayoutModel({

450

padding: '16px',

451

border_radius: '8px',

452

box_shadow: '0 2px 4px rgba(0,0,0,0.1)'

453

}),

454

style: new ThemedStyleModel({

455

background_color: '#f8f9fa',

456

text_color: '#495057'

457

})

458

};

459

}

460

}

461

462

// Apply coordinated layout and styling

463

const createStyledWidget = (theme: 'light' | 'dark') => {

464

const layout = new LayoutModel({

465

padding: '20px',

466

border_radius: '12px',

467

box_shadow: theme === 'light'

468

? '0 4px 6px rgba(0,0,0,0.1)'

469

: '0 4px 6px rgba(0,0,0,0.3)'

470

});

471

472

const style = new ThemedStyleModel(

473

theme === 'light'

474

? { background_color: '#ffffff', text_color: '#333333' }

475

: { background_color: '#2d3748', text_color: '#ffffff' }

476

);

477

478

return { layout, style };

479

};

480

```