0
# Provider System
1
2
The provider system is the core abstraction that allows consumers to customize and configure the Storybook UI. It consists of a base Provider class that must be extended, along with React components for custom implementations. The Provider class uses concrete methods that throw errors rather than abstract methods.
3
4
## Capabilities
5
6
### Provider Base Class
7
8
Base class that defines the interface for providing UI elements, handling API initialization, and supplying configuration. All methods throw errors by default and must be implemented by subclasses.
9
10
```typescript { .api }
11
/**
12
* Base class for Storybook UI providers
13
* All consumers must extend this class to use the Storybook UI
14
*/
15
class Provider {
16
/**
17
* Get UI elements by type - must be implemented by subclasses
18
* @param type - Type identifier for the UI elements to retrieve (from @storybook/addons Types enum)
19
* @returns Object containing UI elements for the specified type
20
* @throws Error with message "Provider.getElements() is not implemented!" if not overridden
21
*/
22
getElements(type: Types): any;
23
24
/**
25
* Handle API initialization - must be implemented by subclasses
26
* @param api - The Storybook API instance
27
* @throws Error with message "Provider.handleAPI() is not implemented!" if not overridden
28
*/
29
handleAPI(api: unknown): void;
30
31
/**
32
* Return configuration object - has default implementation that returns empty object
33
* @returns Configuration object for the Storybook UI
34
* @note Logs error "Provider.getConfig() is not implemented!" but doesn't throw, returns {}
35
*/
36
getConfig(): any;
37
}
38
```
39
40
**Usage Examples:**
41
42
```typescript
43
import { Provider } from "@storybook/ui";
44
45
class MyProvider extends Provider {
46
private stories = [];
47
private config = { theme: 'light' };
48
49
getElements(type) {
50
// Must implement - will throw error if not overridden
51
switch (type) {
52
case 'TAB':
53
return {
54
component: MyTabComponent,
55
props: { stories: this.stories }
56
};
57
case 'PANEL':
58
return {
59
component: MyPanelComponent,
60
props: { theme: this.config.theme }
61
};
62
case 'TOOL':
63
return {
64
component: MyToolComponent,
65
props: { addons: this.getAddons() }
66
};
67
default:
68
return {};
69
}
70
}
71
72
handleAPI(api) {
73
// Must implement - will throw error if not overridden
74
console.log('API initialized:', api);
75
76
// Initialize stories if available
77
if (this.stories.length > 0) {
78
api.setStories(this.stories);
79
}
80
}
81
82
getConfig() {
83
// Optional - has default implementation that returns {}
84
return {
85
theme: this.config.theme,
86
showNav: true,
87
showPanel: true
88
};
89
}
90
91
private getAddons() {
92
return [
93
{ name: 'controls', component: ControlsAddon },
94
{ name: 'actions', component: ActionsAddon }
95
];
96
}
97
}
98
99
// Example showing error behavior if methods not implemented
100
class IncompleteProvider extends Provider {
101
// Missing getElements and handleAPI implementations
102
}
103
104
const incomplete = new IncompleteProvider();
105
try {
106
incomplete.getElements('TAB'); // Throws: "Provider.getElements() is not implemented!"
107
} catch (error) {
108
console.error(error.message);
109
}
110
111
try {
112
incomplete.handleAPI({}); // Throws: "Provider.handleAPI() is not implemented!"
113
} catch (error) {
114
console.error(error.message);
115
}
116
117
// getConfig() doesn't throw, but logs error and returns {}
118
const config = incomplete.getConfig(); // Logs: "Provider.getConfig() is not implemented!"
119
console.log(config); // {}
120
```
121
122
### Root Component
123
124
React functional component that serves as the entry point for the Storybook UI application, wrapping the entire interface with necessary providers.
125
126
```typescript { .api }
127
/**
128
* Root component for the Storybook UI application
129
* @param props - RootProps containing provider and optional history
130
*/
131
const Root: FunctionComponent<RootProps>;
132
133
interface RootProps {
134
/** Provider instance that supplies UI elements and configuration */
135
provider: Provider;
136
/** Optional browser history instance for routing (currently unused in implementation) */
137
history?: History;
138
}
139
```
140
141
**Implementation Details:**
142
- Wraps the UI in HelmetProvider for document head management
143
- Uses LocationProvider for routing functionality
144
- Sets up emotion cache and theme providers
145
- Renders the main App component with provider integration
146
147
**Usage Examples:**
148
149
```typescript
150
import { Root, Provider } from "@storybook/ui";
151
152
class CustomProvider extends Provider {
153
getElements(type) {
154
// Must implement
155
return { component: MyComponent };
156
}
157
handleAPI(api) {
158
// Must implement
159
console.log('API ready');
160
}
161
}
162
163
// Basic usage (most common pattern)
164
function App() {
165
const provider = new CustomProvider();
166
return <Root provider={provider} />;
167
}
168
169
// With history parameter (currently unused by implementation)
170
function AppWithHistory() {
171
const provider = new CustomProvider();
172
const history = createBrowserHistory(); // Not currently used by Root component
173
174
return <Root provider={provider} history={history} />;
175
}
176
```
177
178
**Note**: The `history` prop is included in the interface but is not currently used by the Root component implementation. This may be for future compatibility or legacy reasons.
179
180
### Provider Implementation Requirements
181
182
All Provider subclasses must implement the following methods:
183
184
```typescript
185
class MyProvider extends Provider {
186
// REQUIRED: Must override, throws error otherwise
187
getElements(type: Types) {
188
// Return UI elements for the given type
189
// Types include: 'TAB', 'PANEL', 'TOOL', 'TOOLEXTRA', 'PREVIEW', 'NOTES_ELEMENT'
190
return {};
191
}
192
193
// REQUIRED: Must override, throws error otherwise
194
handleAPI(api: unknown) {
195
// Handle API initialization and setup
196
console.log('API initialized');
197
}
198
199
// OPTIONAL: Has default implementation that returns {}
200
getConfig() {
201
// Return configuration for the UI
202
return {};
203
}
204
}
205
```
206
207
## Types
208
209
```typescript { .api }
210
type Types = 'TAB' | 'PANEL' | 'TOOL' | 'TOOLEXTRA' | 'PREVIEW' | 'NOTES_ELEMENT';
211
212
interface History {
213
push(path: string): void;
214
replace(path: string): void;
215
go(delta: number): void;
216
back(): void;
217
forward(): void;
218
listen(listener: Function): Function;
219
}
220
```