React component library for building TetraScience applications.
📖 Storybook – Live Component Demos | 🛠️ Contributing Guide
This library provides:
- UI Components: Reusable React components following atomic design principles
- Data Visualisation: Interactive charts powered by Plotly.js
- Theming: Customisable design system with ThemeProvider
- TypeScript: Full type support with exported prop types
- React 19+
- Node.js 18+
- TypeScript 5.5+ (optional, but recommended)
yarn add @tetrascience-npm/tetrascience-react-ui// 1. Import the CSS (required)
import '@tetrascience-npm/tetrascience-react-ui/index.css';
// 2. Import components
import { Button, Card, BarGraph } from '@tetrascience-npm/tetrascience-react-ui';
function App() {
return (
<Card title="Welcome">
<p>My first TetraScience app!</p>
<Button variant="primary">Get Started</Button>
</Card>
);
}Badge, Button, ButtonControl, Card, Checkbox, CodeEditor, Dropdown, ErrorAlert, Icon, Input, Label, MarkdownDisplay, MenuItem, Modal, PopConfirm, SupportiveText, Tab, TableCell, TableHeaderCell, Textarea, Toast, Toggle, Tooltip
AppHeader, AssistantModal, ButtonControlGroup, CardSidebar, CodeScriptEditorButton, FormField, LaunchContent, Menu, Navbar, ProtocolConfiguration, ProtocolYamlCard, PythonEditorModal, SelectField, Sidebar, TabGroup, Table, ToastManager
AppLayout, AreaGraph, BarGraph, Boxplot, Chromatogram, DotPlot, Heatmap, Histogram, LineGraph, Main, PieChart, ScatterGraph, TaskScripts
Customise colours, border radius, and spacing:
import { ThemeProvider } from '@tetrascience-npm/tetrascience-react-ui';
const customTheme = {
colors: {
primary: '#DC2626',
primaryHover: '#B91C1C',
},
radius: {
medium: '12px',
},
};
<ThemeProvider theme={customTheme}>
<App />
</ThemeProvider>See THEMING.md for the complete theming guide.
Beyond UI components, this library includes server-side helper functions for building TetraScience applications. These are available via the /server subpath to avoid pulling Node.js dependencies into browser bundles.
JWT Token Manager - Manages JWT token retrieval for data apps:
import { jwtManager } from '@tetrascience-npm/tetrascience-react-ui/server';
// In Express middleware
app.use(async (req, res, next) => {
const token = await jwtManager.getTokenFromExpressRequest(req);
req.tdpAuth = { token, orgSlug: process.env.ORG_SLUG };
next();
});
// Or with raw cookies
const token = await jwtManager.getUserToken(req.cookies);Environment Variables:
ORG_SLUG- Organization slug (required)CONNECTOR_ID- Connector ID for ts-token-ref flowTDP_ENDPOINT- API base URLTS_AUTH_TOKEN- Service account token (fallback for local dev)
Note: The singleton
jwtManagerreads environment variables when the module is imported. Ensure these are set before importing the module.
TypeScript equivalents of the Python helpers from ts-lib-ui-kit-streamlit for connecting to database providers (Snowflake, Databricks, Athena).
Getting Provider Configurations:
import { TDPClient } from '@tetrascience-npm/ts-connectors-sdk';
import {
getProviderConfigurations,
buildProvider,
jwtManager,
} from '@tetrascience-npm/tetrascience-react-ui/server';
// Get user's auth token from request (e.g., in Express middleware)
const userToken = await jwtManager.getTokenFromExpressRequest(req);
// Create TDPClient with the user's auth token
// Other fields (tdpEndpoint, connectorId, orgSlug) are read from environment variables
const client = new TDPClient({
authToken: userToken,
artifactType: 'data-app',
});
await client.init();
// Get all configured providers for this data app
const providers = await getProviderConfigurations(client);
for (const config of providers) {
console.log(`Provider: ${config.name} (${config.type})`);
// Build a database connection from the config
const provider = await buildProvider(config);
const results = await provider.query('SELECT * FROM my_table LIMIT 10');
await provider.close();
}Using Specific Providers:
import {
buildSnowflakeProvider,
buildDatabricksProvider,
getTdpAthenaProvider,
type ProviderConfiguration,
} from '@tetrascience-npm/tetrascience-react-ui/server';
// Snowflake
const snowflakeProvider = await buildSnowflakeProvider(config);
const data = await snowflakeProvider.query('SELECT * FROM users');
await snowflakeProvider.close();
// Databricks
const databricksProvider = await buildDatabricksProvider(config);
const data = await databricksProvider.query('SELECT * FROM events');
await databricksProvider.close();
// TDP Athena (uses environment configuration)
const athenaProvider = await getTdpAthenaProvider();
const data = await athenaProvider.query('SELECT * FROM files');
await athenaProvider.close();Exception Handling:
import {
QueryError,
MissingTableError,
ProviderConnectionError,
InvalidProviderConfigurationError,
} from '@tetrascience-npm/tetrascience-react-ui/server';
try {
const results = await provider.query('SELECT * FROM missing_table');
} catch (error) {
if (error instanceof MissingTableError) {
console.error('Table not found:', error.message);
} else if (error instanceof QueryError) {
console.error('Query failed:', error.message);
}
}Environment Variables:
DATA_APP_PROVIDER_CONFIG- JSON override for local development onlyCONNECTOR_ID- Connector ID for fetching providers from TDPTDP_ENDPOINT- TDP API base URLORG_SLUG- Organization slugATHENA_S3_OUTPUT_LOCATION- S3 bucket for Athena query resultsAWS_REGION- AWS region for Athena
Note: Authentication tokens are obtained from the user's JWT via
jwtManager. TheTS_AUTH_TOKENenvironment variable is only for local development fallback.
The TDP connector key/value store lets data apps persist small pieces of state (user preferences, cached results, last-run timestamps, etc.) without an external database. The TDPClient from @tetrascience-npm/ts-connectors-sdk provides getValue, getValues, saveValue, and saveValues methods.
Reading and writing values with the user's JWT token:
import { TDPClient } from '@tetrascience-npm/ts-connectors-sdk';
import { jwtManager } from '@tetrascience-npm/tetrascience-react-ui/server';
// In an Express route handler:
app.get('/api/kv/:key', async (req, res) => {
// 1. Get the user's JWT from request cookies
const userToken = await jwtManager.getTokenFromExpressRequest(req);
if (!userToken) return res.status(401).json({ error: 'Not authenticated' });
// 2. Create a TDPClient authenticated as the user
// (CONNECTOR_ID, TDP_ENDPOINT, ORG_SLUG are read from env vars)
const client = new TDPClient({
authToken: userToken,
artifactType: 'data-app',
});
await client.init();
// 3. Read a value
const value = await client.getValue(req.params.key);
res.json({ key: req.params.key, value });
});
app.put('/api/kv/:key', async (req, res) => {
const userToken = await jwtManager.getTokenFromExpressRequest(req);
if (!userToken) return res.status(401).json({ error: 'Not authenticated' });
const client = new TDPClient({
authToken: userToken,
artifactType: 'data-app',
});
await client.init();
// Write a value (any JSON-serialisable type)
await client.saveValue(req.params.key, req.body.value, { secure: false });
res.json({ key: req.params.key, saved: true });
});Reading multiple values at once:
const values = await client.getValues(['theme', 'locale', 'last-run']);
// values[0] → theme, values[1] → locale, values[2] → last-runSee the example app for a complete working server with KV store endpoints.
TdpSearchManager - Server-side handler for the TdpSearch component. Resolves auth from request cookies (via jwtManager), calls TDP searchEql, and returns the response so the frontend hook works with minimal wiring.
import { tdpSearchManager } from "@tetrascience-npm/tetrascience-react-ui/server";
// Express: mount a POST route (e.g. /api/search)
app.post("/api/search", express.json(), async (req, res) => {
try {
const body = req.body; // SearchEqlRequest (searchTerm, from, size, sort, order, ...)
const response = await tdpSearchManager.handleSearchRequest(req, body);
res.json(response);
} catch (err) {
res.status(401).json({ error: err instanceof Error ? err.message : "Search failed" });
}
});Frontend: use <TdpSearch columns={...} /> with default apiEndpoint="/api/search", or pass apiEndpoint if you use a different path. Auth is taken from cookies (ts-auth-token or ts-token-ref via jwtManager).
Full TypeScript support with exported types:
import { Button } from '@tetrascience-npm/tetrascience-react-ui';
import type { ButtonProps, BarGraphProps, BarDataSeries } from '@tetrascience-npm/tetrascience-react-ui';This repository uses component driven development with storybook.js. To see the examples run the following.
# Clone the repository
git clone https://github.com/tetrascience/ts-lib-ui-kit.git
cd ts-lib-ui-kit
# Install dependencies
yarn
# Run the storybook
yarn devVisit http://localhost:6006.
- Storybook – Live Component Demos - Browse all components with interactive examples
- NPM Package - Installation and version info
- Getting Started Guide - Step-by-step tutorial
- Theming Guide - Customise the design system
- Contributing - Clone the repo and run
yarn storybook
- React 18
- TypeScript
- styled-components
- Plotly.js (charts)
- Monaco Editor (code editing)
- React Flow (workflow diagrams)
Licensed under the Apache License, Version 2.0 – see LICENSE for details.