.ai/COMPONENTS.md
The component system bridges React components to Python with auto-generated wrappers.
React/TypeScript Source
↓
extract-meta.js (Node.js)
├── react-docgen (for .js/.jsx - parses PropTypes)
└── TypeScript Compiler API (for .tsx - parses type definitions)
↓
metadata.json
↓
dash-generate-components (Python CLI)
↓
Python component classes (+ R/Julia if requested)
dash/extract-meta.js - Node.js script that extracts component metadata. For JavaScript components, uses react-docgen to parse PropTypes. For TypeScript components, uses the TypeScript Compiler API to parse type definitions and convert them to metadata format.
dash/development/component_generator.py - CLI entry point (dash-generate-components). Orchestrates metadata extraction and code generation.
dash/development/_py_components_generation.py - Generates Python class files from metadata. Creates typed __init__ methods, docstrings, and prop validation.
dash/development/_py_prop_typing.py - Maps JavaScript/TypeScript types to Python types (e.g., arrayOf → typing.Sequence, shape → TypedDict).
dash/development/_generate_prop_types.py - For TypeScript components, generates a proptypes.js file since TSX doesn't have runtime PropTypes.
Components serialize to {type, namespace, props} via to_plotly_json() in base_component.py:
# Python component
html.Div(id='my-div', children='Hello')
# Serializes to JSON
{
"type": "Div",
"namespace": "dash_html_components",
"props": {
"id": "my-div",
"children": "Hello"
}
}
This JSON is sent to the frontend via /_dash-layout (initial load) and /_dash-update-component (callback responses).
Components must be available on the frontend at window[namespace][type]:
// Component packages register themselves
window.dash_html_components = {
Div: DivComponent,
Span: SpanComponent,
// ...
};
window.dash_core_components = {
Dropdown: DropdownComponent,
Graph: GraphComponent,
// ...
};
The renderer resolves components via registry.js:
resolve: (component) => {
const {type, namespace} = component;
return window[namespace][type]; // Returns React component class
}
_imports_.pyAuto-generated by generate_imports() in _py_components_generation.py:
from .Dropdown import Dropdown
from .Graph import Graph
from .Input import Input
# ... one import per component
__all__ = [
"Dropdown",
"Graph",
"Input",
# ...
]
__init__.pyManually maintained, imports from _imports_.py:
from ._imports_ import * # Re-exports all components
from ._imports_ import __all__ as _components
# Read version from package-info.json
with open(os.path.join(_basepath, "package-info.json")) as f:
package = json.load(f)
__version__ = package["version"]
# Define JavaScript assets to serve
_js_dist = [
{
"relative_package_path": "dash_core_components.js",
"namespace": "dash",
},
# async chunks, source maps, proptypes.js for dev, etc.
]
# Attach _js_dist to each component class
for _component in _components:
setattr(locals()[_component], "_js_dist", _js_dist)
_js_dist / _css_dist)dash/resources.py manages JavaScript and CSS asset loading for components.
{
"relative_package_path": "dcc/dash_core_components.js", # Path within package
"external_url": "https://unpkg.com/...", # CDN fallback
"namespace": "dash", # JS namespace
"async": True | "eager" | "lazy", # Async loading mode
"dynamic": True, # Loaded on demand (source maps)
"dev_package_path": "dcc/proptypes.js", # Dev-only path
"dev_only": True, # Only in dev mode
}
_js_dist (and optionally _css_dist) attribute set in __init__.pyComponentMeta registers module in ComponentRegistry.registryComponentRegistry.get_resources("_js_dist") iterates registered modules, collects all _js_dist listsScripts / Css classes in resources.py filter resources based on config:
serve_locally=True: Use relative_package_path, serve via /_dash-component-suites/serve_locally=False: Use external_url (CDN)eager_loading=True: Load async resources immediatelydev_bundles=True: Include dev_package_path resourcesasync: True - Dynamic unless eager_loading is enabledasync: "lazy" - Always loaded dynamically (on-demand)async: "eager" - Loaded dynamically only if server isn't in eager modedash-generate-components src/lib/components -p package_namepackage_name/ComponentName.py_imports_.py is auto-generated with imports for all componentsproptypes.js is also generated for runtime prop validationwindow[namespace]__init__.py to set _js_dist on componentsManaged as a Lerna monorepo in components/:
components/dash-core-components/ - Interactive components (Dropdown, Slider, Graph, Input, etc.)components/dash-html-components/ - HTML element wrappers (Div, Span, H1, etc.)components/dash-table/ - DataTable component (deprecated in favor of dash-ag-grid)Use dash-update-components "component-name" to rebuild after changes.