Add utility for using styles

This commit is contained in:
martinalong 2025-12-10 15:39:22 -08:00
commit aa8968808a
No known key found for this signature in database
4 changed files with 128 additions and 0 deletions

View file

@ -47,6 +47,7 @@ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
export { PostMessageTransport } from "./message-transport";
export * from "./types";
export { applyHostStyles } from "./styles";
/**
* Metadata key for associating a resource URI with a tool call.

View file

@ -9,6 +9,7 @@
* ## Main Exports
*
* - {@link useApp} - React hook to create and connect an MCP App
* - {@link useHostStyles} - React hook to apply host styles as CSS variables
* - {@link useAutoResize} - React hook for manual auto-resize control (rarely needed)
*
* @module @modelcontextprotocol/ext-apps/react
@ -32,3 +33,4 @@
*/
export * from "./useApp";
export * from "./useAutoResize";
export * from "./useHostStyles";

View file

@ -0,0 +1,84 @@
import { useEffect, useRef } from "react";
import { App } from "../app";
import { applyHostStyles } from "../styles";
import { McpUiHostContext } from "../types";
/**
* React hook that applies host styles as CSS custom properties.
*
* This hook listens to host context changes and automatically applies the
* `styles` CSS variables to `document.documentElement`. This allows your
* app to use the host's theming values via CSS variables like
* `var(--color-background-primary)`.
*
* The hook also applies styles from the initial host context when the app
* first connects.
*
* @param app - The connected App instance, or null during initialization
* @param initialContext - Initial host context from the connection (optional).
* If provided, styles will be applied immediately on mount.
*
* @example Basic usage with useApp
* ```tsx
* import { useApp } from '@modelcontextprotocol/ext-apps/react';
* import { useHostStyles } from '@modelcontextprotocol/ext-apps/react';
*
* function MyApp() {
* const { app, isConnected } = useApp({
* appInfo: { name: "MyApp", version: "1.0.0" },
* capabilities: {},
* });
*
* // Automatically apply host styles as CSS variables
* useHostStyles(app);
*
* return (
* <div style={{ background: 'var(--color-background-primary)' }}>
* Hello!
* </div>
* );
* }
* ```
*
* @example With initial context
* ```tsx
* const [hostContext, setHostContext] = useState<McpUiHostContext | null>(null);
*
* // ... get initial context from app.connect() result
*
* useHostStyles(app, hostContext);
* ```
*
* @see {@link applyHostStyles} for the underlying function
* @see {@link McpUiStyles} for available CSS variables
*/
export function useHostStyles(
app: App | null,
initialContext?: McpUiHostContext | null,
): void {
const initialStylesApplied = useRef(false);
// Apply initial styles once on mount
useEffect(() => {
if (initialStylesApplied.current) {
return;
}
if (initialContext?.styles) {
applyHostStyles(initialContext.styles);
initialStylesApplied.current = true;
}
}, [initialContext]);
// Listen for host context changes and apply updated styles
useEffect(() => {
if (!app) {
return;
}
app.onhostcontextchanged = (params) => {
if (params.styles) {
applyHostStyles(params.styles);
}
};
}, [app]);
}

41
src/styles.ts Normal file
View file

@ -0,0 +1,41 @@
import { McpUiStyles } from "./types";
/**
* Apply host styles as CSS custom properties on an element.
*
* This function takes the `styles` object from `McpUiHostContext` and sets
* each CSS variable on the specified root element (defaults to `document.documentElement`).
* This allows apps to use the host's theming values via CSS variables like
* `var(--color-background-primary)`.
*
* @param styles - The styles object from `McpUiHostContext.styles`
* @param root - The element to apply styles to (defaults to `document.documentElement`)
*
* @example Apply styles from host context
* ```typescript
* import { applyHostStyles } from '@modelcontextprotocol/ext-apps';
*
* app.onhostcontextchanged = (params) => {
* if (params.styles) {
* applyHostStyles(params.styles);
* }
* };
* ```
*
* @example Apply to a specific element
* ```typescript
* const container = document.getElementById('app-root');
* applyHostStyles(hostContext.styles, container);
* ```
*
* @see {@link McpUiStyles} for the available CSS variables
* @see {@link McpUiHostContext} for the full host context structure
*/
export function applyHostStyles(
styles: McpUiStyles,
root: HTMLElement = document.documentElement,
): void {
for (const [key, value] of Object.entries(styles)) {
root.style.setProperty(key, value);
}
}