mirror of
				https://github.com/vector-im/element-web.git
				synced 2025-10-31 16:21:46 +01:00 
			
		
		
		
	We're making an assumption here that the decorator is actually all over the app when it's not.
		
			
				
	
	
		
			72 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			72 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Skinning
 | |
| 
 | |
| The react-sdk can be skinned to replace presentation components, CSS, or
 | |
| other relevant parts of the SDK. Typically consumers will replace entire
 | |
| components and get the ability for custom CSS as a result.
 | |
| 
 | |
| This doc isn't exhaustive on how skinning works, though it should cover
 | |
| some of the more complicated parts such as component replacement.
 | |
| 
 | |
| ## Loading a skin
 | |
| 
 | |
| 1. Generate a `component-index.js` (preferably using the tools that the react-sdk
 | |
| exposes). This can typically be done with a npm script like `"reskindex -h src/header"`.
 | |
| 2. In your app's entry point, add something like this code:
 | |
|    ```javascript
 | |
|    import {loadSkin} from "matrix-react-sdk";
 | |
|    loadSkin(import("component-index").components);
 | |
|    // The rest of your imports go under this.
 | |
|    ```
 | |
| 3. Import the remainder of the SDK and bootstrap your app.
 | |
| 
 | |
| It is extremely important that you **do not** import anything else from the
 | |
| SDK prior to loading your skin as otherwise the skin might not work. Loading
 | |
| the skin should be one of the first things your app does, if not the very
 | |
| first thing.
 | |
| 
 | |
| Additionally, **do not** provide `loadSkin` with the react-sdk components
 | |
| themselves otherwise the app might explode. The SDK is already aware of its
 | |
| components and doesn't need to be told.
 | |
| 
 | |
| ## Replacing components
 | |
| 
 | |
| Components that replace the react-sdk ones MUST have a `replaces` static
 | |
| key on the component's class to describe which component it overrides. For
 | |
| example, if your `VectorAuthPage` component is meant to replace the react-sdk
 | |
| `AuthPage` component then you'd add `static replaces = 'views.auth.AuthPage';`
 | |
| to the `VectorAuthPage` class.
 | |
| 
 | |
| Other than that, the skin just needs to be loaded normally as mentioned above.
 | |
| Consumers of the SDK likely will not be interested in the rest of this section.
 | |
| 
 | |
| ### SDK developer notes
 | |
| 
 | |
| Components in the react-sdk MUST be decorated with the `@replaceableComponent`
 | |
| function. For components that can't use the decorator, they must use a
 | |
| variation that provides similar functionality. The decorator gives consumers
 | |
| an opportunity to load skinned components by abusing import ordering and 
 | |
| behaviour.
 | |
| 
 | |
| Decorators are executed at import time which is why we can abuse the import
 | |
| ordering behaviour: importing `loadSkin` doesn't trigger any components to
 | |
| be imported, allowing the consumer to specify a skin. When the consumer does
 | |
| import a component (for example, `MatrixChat`), it starts to pull in all the
 | |
| components via `import` statements. When the components get pulled in the
 | |
| decorator checks with the skinned components to see if it should be replacing
 | |
| the component being imported. The decorator then effectively replaces the
 | |
| components when needed by specifying the skinned component as an override for
 | |
| the SDK's component, which should in theory override critical functions like
 | |
| `render()` and lifecycle event handlers. 
 | |
| 
 | |
| The decorator also means that older usage of `getComponent()` is no longer
 | |
| required because components should be replaced by the decorator. Eventually
 | |
| the react-sdk should only have one usage of `getComponent()`: the decorator.
 | |
| 
 | |
| The decorator assumes that if `getComponent()` returns null that there is
 | |
| no skinned version of the component and continues on using the SDK's component.
 | |
| In previous versions of the SDK, the function would throw an error instead
 | |
| because it also expected the skin to list the SDK's components as well, however
 | |
| that is no longer possible due to the above.
 | |
| 
 | |
| In short, components should always be `import`ed.
 |