Foundational classes and utilities for building interactive widgets in Jupyter environments
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The layout and style system provides CSS-based positioning, sizing, and appearance management for Jupyter widgets through trait-based property handling.
CSS-based layout management with support for flexbox, grid, positioning, and spacing properties.
/**
* Model for widget layout properties, supports comprehensive CSS layout
*/
class LayoutModel extends WidgetModel {
/**
* Default attributes including all supported CSS properties
*/
defaults(): Backbone.ObjectHash;
}Supported Layout Properties:
All layout properties default to null and map directly to CSS properties:
Position & Size:
top, right, bottom, left - Positioning valueswidth, height - Element dimensionsmin_width, min_height, max_width, max_height - Size constraintsFlexbox Layout:
flex - Flex grow/shrink/basis shorthandflex_flow - Flex direction and wrap shorthandalign_content - Align flex linesalign_items - Align flex itemsalign_self - Individual item alignmentjustify_content - Main axis alignmentjustify_items - Grid item justificationorder - Flex/grid item orderSpacing:
margin - Outer spacingpadding - Inner spacingBorder:
border_top, border_right, border_bottom, border_left - Individual bordersDisplay:
display - Display type (block, flex, grid, etc.)visibility - Element visibilityoverflow - Content overflow behaviorGrid Layout:
grid_auto_columns, grid_auto_rows - Implicit grid sizinggrid_auto_flow - Grid item placement algorithmgrid_gap - Grid spacinggrid_template_rows, grid_template_columns - Explicit grid tracksgrid_template_areas - Named grid areasgrid_row, grid_column - Item grid placementgrid_area - Item grid area assignmentImage-specific:
object_fit - Image scaling behaviorobject_position - Image positioningView component that applies layout properties to the parent widget element.
/**
* View for applying layout styles to the parent widget element
*/
class LayoutView extends WidgetView {
/**
* Initialize layout view and register all CSS traits
* @param parameters - View initialization parameters
*/
initialize(parameters: WidgetView.IInitializeParameters): void;
/**
* Register a CSS trait for monitoring and application
* @param trait - CSS property name to register
*/
registerTrait(trait: string): void;
/**
* Convert trait name to CSS property name
* @param trait - Model trait name (with underscores)
* @returns CSS property name (with hyphens)
*/
css_name(trait: string): string;
/**
* Handle changes to layout traits and apply to parent element
* @param trait - Name of the changed trait
* @param value - New value for the trait
*/
handleChange(trait: string, value: any): void;
/**
* Remove all layout styles from the parent element
*/
unlayout(): void;
}Usage Examples:
// Create layout model with flexbox properties
const layoutModel = new LayoutModel({
display: 'flex',
flex_direction: 'column',
align_items: 'center',
padding: '10px',
margin: '5px',
width: '300px',
height: '200px'
});
// Apply to widget
widget.set('layout', layoutModel);
// Dynamic layout updates
layoutModel.set({
width: '400px',
justify_content: 'space-between'
});
// Grid layout example
const gridLayout = new LayoutModel({
display: 'grid',
grid_template_columns: '1fr 2fr 1fr',
grid_template_rows: 'auto 1fr auto',
grid_gap: '10px',
grid_template_areas: `
"header header header"
"sidebar main aside"
"footer footer footer"
`
});Flexible styling system with custom property definitions and selector-based application.
/**
* Base model for widget styling with configurable style properties
*/
class StyleModel extends WidgetModel {
/**
* Default attributes based on defined style properties
*/
defaults(): Backbone.ObjectHash;
/**
* Static definition of available style properties
*/
static styleProperties: { [s: string]: IStyleProperty };
}
/**
* Configuration for individual style properties
*/
interface IStyleProperty {
/**
* CSS attribute name to apply
*/
attribute: string;
/**
* CSS selector for target elements (empty string for widget root)
*/
selector: string;
/**
* Default value for the property
*/
default: string;
}View component that applies custom styles to widget elements based on selectors.
/**
* View for applying custom styles to widget elements
*/
class StyleView extends WidgetView {
/**
* Initialize style view and register all defined style traits
* @param parameters - View initialization parameters
*/
initialize(parameters: WidgetView.IInitializeParameters): void;
/**
* Register a style trait for monitoring
* @param trait - Style trait name to register
*/
registerTrait(trait: string): void;
/**
* Handle changes to style traits and apply to target elements
* @param trait - Name of the changed trait
* @param value - New value for the trait
*/
handleChange(trait: string, value: any): void;
/**
* Apply all registered styles to their target elements
*/
style(): void;
/**
* Remove all applied styles from target elements
*/
unstyle(): void;
}Usage Examples:
// Define custom style properties
class ButtonStyleModel extends StyleModel {
static styleProperties = {
button_color: {
attribute: 'background-color',
selector: 'button',
default: '#ffffff'
},
text_color: {
attribute: 'color',
selector: 'button',
default: '#000000'
},
border_radius: {
attribute: 'border-radius',
selector: 'button',
default: '4px'
},
font_weight: {
attribute: 'font-weight',
selector: '', // Apply to root element
default: 'normal'
}
};
}
// Create and apply styles
const buttonStyle = new ButtonStyleModel({
button_color: '#007bff',
text_color: '#ffffff',
border_radius: '8px',
font_weight: 'bold'
});
widget.set('style', buttonStyle);
// Dynamic style updates
buttonStyle.set('button_color', '#28a745'); // Changes button background// Create responsive layout that adapts to container size
const responsiveLayout = new LayoutModel({
display: 'grid',
grid_template_columns: 'repeat(auto-fit, minmax(250px, 1fr))',
grid_gap: '1rem',
padding: '1rem'
});
// Media query-like behavior through dynamic updates
const updateLayoutForSize = (containerWidth: number) => {
if (containerWidth < 600) {
responsiveLayout.set({
grid_template_columns: '1fr',
padding: '0.5rem'
});
} else if (containerWidth < 900) {
responsiveLayout.set({
grid_template_columns: 'repeat(2, 1fr)',
padding: '0.75rem'
});
} else {
responsiveLayout.set({
grid_template_columns: 'repeat(3, 1fr)',
padding: '1rem'
});
}
};// Dashboard-style grid layout
const dashboardLayout = new LayoutModel({
display: 'grid',
grid_template_columns: '200px 1fr 250px',
grid_template_rows: '60px 1fr 40px',
grid_template_areas: `
"nav header tools"
"nav main sidebar"
"nav footer sidebar"
`,
height: '100vh',
grid_gap: '8px'
});
// Individual widget positioning
const headerWidget = new LayoutModel({
grid_area: 'header',
display: 'flex',
align_items: 'center',
padding: '0 20px'
});
const mainWidget = new LayoutModel({
grid_area: 'main',
overflow: 'auto',
padding: '20px'
});// Centered content layout
const centeredLayout = new LayoutModel({
display: 'flex',
align_items: 'center',
justify_content: 'center',
min_height: '300px'
});
// Toolbar layout
const toolbarLayout = new LayoutModel({
display: 'flex',
align_items: 'center',
justify_content: 'space-between',
padding: '8px 16px',
border_bottom: '1px solid #ccc'
});
// Card layout with flex content
const cardLayout = new LayoutModel({
display: 'flex',
flex_direction: 'column',
border: '1px solid #ddd',
border_radius: '8px',
overflow: 'hidden',
max_width: '350px'
});// Define theme-aware style model
class ThemedStyleModel extends StyleModel {
static styleProperties = {
primary_color: {
attribute: '--primary-color',
selector: '',
default: '#007bff'
},
secondary_color: {
attribute: '--secondary-color',
selector: '',
default: '#6c757d'
},
background_color: {
attribute: 'background-color',
selector: '',
default: '#ffffff'
},
text_color: {
attribute: 'color',
selector: '',
default: '#333333'
}
};
}
// Apply theme
const lightTheme = new ThemedStyleModel({
primary_color: '#007bff',
background_color: '#ffffff',
text_color: '#333333'
});
const darkTheme = new ThemedStyleModel({
primary_color: '#0d6efd',
background_color: '#1a1a1a',
text_color: '#ffffff'
});// Multi-element styling
class FormStyleModel extends StyleModel {
static styleProperties = {
label_color: {
attribute: 'color',
selector: 'label',
default: '#495057'
},
input_border: {
attribute: 'border',
selector: 'input, select, textarea',
default: '1px solid #ced4da'
},
input_focus_color: {
attribute: 'border-color',
selector: 'input:focus, select:focus, textarea:focus',
default: '#007bff'
},
error_color: {
attribute: 'color',
selector: '.error-message',
default: '#dc3545'
}
};
}// Combine layout and style for complete widget theming
class ThemedWidget extends DOMWidgetModel {
defaults() {
return {
...super.defaults(),
layout: new LayoutModel({
padding: '16px',
border_radius: '8px',
box_shadow: '0 2px 4px rgba(0,0,0,0.1)'
}),
style: new ThemedStyleModel({
background_color: '#f8f9fa',
text_color: '#495057'
})
};
}
}
// Apply coordinated layout and styling
const createStyledWidget = (theme: 'light' | 'dark') => {
const layout = new LayoutModel({
padding: '20px',
border_radius: '12px',
box_shadow: theme === 'light'
? '0 4px 6px rgba(0,0,0,0.1)'
: '0 4px 6px rgba(0,0,0,0.3)'
});
const style = new ThemedStyleModel(
theme === 'light'
? { background_color: '#ffffff', text_color: '#333333' }
: { background_color: '#2d3748', text_color: '#ffffff' }
);
return { layout, style };
};