Skip to main content

Study Settings Form and Study List

Two ready-made UI components let users edit the settings of the chart's studies and technical indicators:

ComponentPlain TypeScriptReact
Study settings form
One study's settings as a form, applied as they are edited
StudySettingsForm<StudySettingsForm>
Study list
The chart's studies as cards: each opens its settings form, and × removes the study
StudyList<StudyList>

Both edit the study's descriptor, the description of its settings that every study has. See Altering Study Settings to change settings from code instead. They work with every study, including your own.

Like the other UI components, each is plain DOM in scichart-scitrader, and scichart-scitrader-react wraps it for React.

StudySettingsForm: A Study's Settings Form​

StudySettingsForm draws a study's descriptor as a form, with the field each control type needs:

Control type (EDescriptorType)Field
NUMBERA number box
TEXTA text box
SELECTA dropdown of the control's options
COLORA Colour Picker, with opacity
STROKE_TYPEA solid, dashed or dotted line-style dropdown
GRADIENTA gradient editor: a colour ramp with a handle per stop
  • Edits apply as they are made, APPLY_DEBOUNCE_MS (150 ms) after the last change, through study.applyDescriptor. Pass onApply to do something else with them, such as logging or saving.
  • Reset to defaults applies the study's getDefaultDescriptor().
  • When settings change elsewhere, such as from code, the form shows the new values.
// Plain TypeScript
import { EDescriptorSectionName, StudySettingsForm } from "scichart-scitrader";

const form = StudySettingsForm.create(container, { study: rsi }); // the RSI's settings, in container
form.update({ sectionFilter: [EDescriptorSectionName.STYLES] }); // show only its styles
form.update({ study: macd }); // edit another study
form.destroy(); // remove it when done
// React: the props are the same options
import { StudySettingsForm } from "scichart-scitrader-react";

<StudySettingsForm study={rsi} sectionFilter={[EDescriptorSectionName.INPUTS]} hideSectionLabels />

To show part of a form, pass sectionFilter, e.g. [EDescriptorSectionName.INPUTS] for the inputs only. hideSectionLabels leaves out the "Inputs" and "Styles" headings, for a page with tabs of its own.

TypeScript Example: StudySettingsForm with Inputs and Styles Tabs​

A BTC-USD chart from Coinbase with SMA, Bollinger Bands, RSI and MACD. The panel on the right is a settings page built around one StudySettingsForm:

  • The dropdown picks the study to edit, with form.update({ study }).
  • The Inputs and Styles tabs show one section at a time, with sectionFilter and hideSectionLabels.
  • The status line comes from onApply, which applies the edit and reports it.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import {
BollingerBandsStudy,
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
EDescriptorSectionName,
idbPriceStore,
IStudy,
MACDStudy,
OHLCStudy,
RSIStudy,
SciFinanceChartPanel,
SMAStudy,
StudySettingsForm,
} from "scichart-scitrader";

// This example expects this HTML:
// <div style="display: flex; height: 100%">
// <div id="chart" style="flex: 1; min-width: 0"></div>
// <div id="settings" style="width: 320px; overflow-y: auto"></div>
// </div>

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

async function createChart() {
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById("chart"), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [new OHLCStudy(), new SMAStudy({ length: 50 }), new BollingerBandsStudy(), new RSIStudy(), new MACDStudy()],
});
const chart = financeChartPanel.financeApi;

const panel = document.getElementById("settings");
Object.assign(panel.style, panelStyle);

// A dropdown of the chart's studies: the form edits the one picked
const studySelect = document.createElement("select");
Object.assign(studySelect.style, controlStyle);
const fillStudies = () => studySelect.replaceChildren(...chart.studies.map((s) => new Option(s.type, s.id)));
fillStudies();
studySelect.value = chart.studies[3].id; // the RSI
chart.studiesChanged.subscribe(fillStudies); // keep the list in step with the chart

// Inputs / Styles tabs: the form shows one section at a time
const tabs = document.createElement("div");
Object.assign(tabs.style, { display: "flex", gap: "4px" });
const tab = (label: string, section: EDescriptorSectionName) => {
const b = document.createElement("button");
b.textContent = label;
Object.assign(b.style, controlStyle);
b.onclick = () => {
// sectionFilter shows only that section. hideSectionLabels drops its heading: the tab says it
form.update({ sectionFilter: [section], hideSectionLabels: true });
Array.from(tabs.children as HTMLCollectionOf<HTMLElement>).forEach((t) => (t.style.fontWeight = t === b ? "700" : "400"));
};
return b;
};
tabs.append(tab("Inputs", EDescriptorSectionName.INPUTS), tab("Styles", EDescriptorSectionName.STYLES));

const status = document.createElement("div");
Object.assign(status.style, { color: "var(--st-ui-text-muted, #9da2bc)", fontSize: "12px" });

const formHost = document.createElement("div");
panel.append(studySelect, tabs, formHost, status);

// StudySettingsForm: a form generated from the study's descriptor. Edits apply 150 ms after the
// last change, through onApply. Without onApply it calls study.applyDescriptor(descriptor) itself
const byId = (id: string): IStudy => chart.studies.find((s) => s.id === id);
const form = StudySettingsForm.create(formHost, {
study: byId(studySelect.value),
sectionFilter: [EDescriptorSectionName.INPUTS],
hideSectionLabels: true,
onApply: (study, descriptor) => {
study.applyDescriptor(descriptor);
status.textContent = `Applied to ${study.type} at ${new Date().toLocaleTimeString()}`;
},
});
(tabs.firstElementChild as HTMLElement).style.fontWeight = "700";

// update({ study }) reloads the form for another study
studySelect.onchange = () => form.update({ study: byId(studySelect.value) });

// When the page goes away: form.destroy(); financeChartPanel.cleanup();
return { financeChartPanel, form };
}

// The panel uses SciTrader's UI colours: its --st-ui-* CSS variables, with the stylesheet's defaults
const panelStyle: Partial<CSSStyleDeclaration> = {
display: "flex",
flexDirection: "column",
gap: "8px",
padding: "12px",
boxSizing: "border-box",
background: "var(--st-ui-background, #2b2839)",
borderLeft: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
};
const controlStyle: Partial<CSSStyleDeclaration> = {
padding: "6px 10px",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
borderRadius: "6px",
background: "var(--st-ui-surface, #373447)",
color: "var(--st-ui-text, #ffffff)",
font: "inherit",
fontSize: "13px",
cursor: "pointer",
};

createChart();

React Example: StudySettingsForm with Inputs and Styles Tabs​

The same settings page in React. The study and the tab are React state, passed to the React StudySettingsForm as props.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import * as React from "react";
import {
BollingerBandsStudy,
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
EDescriptorSectionName,
idbPriceStore,
ISciFinanceChartPanelApi,
ISciFinanceChartPanelConfig,
IStudy,
MACDStudy,
OHLCStudy,
RSIStudy,
SMAStudy,
} from "scichart-scitrader";
import { SciFinanceChartView, StudySettingsForm } from "scichart-scitrader-react";

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

export function StudySettingsFormChart() {
// The chart's studies, kept in state so the dropdown follows the chart
const [studies, setStudies] = React.useState<readonly IStudy[]>([]);
const [studyId, setStudyId] = React.useState<string>();
const [section, setSection] = React.useState(EDescriptorSectionName.INPUTS);
const [status, setStatus] = React.useState("");

// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [new OHLCStudy(), new SMAStudy({ length: 50 }), new BollingerBandsStudy(), new RSIStudy(), new MACDStudy()],
}),
[]
);

// financeApi throws until the chart has initialised, so read it in onInit.
// The chart is deleted when this component unmounts, so there's no need to unsubscribe
const onInit = (api: ISciFinanceChartPanelApi) => {
const chart = api.financeApi;
setStudies(chart.studies);
setStudyId(chart.studies[3].id); // the RSI
chart.studiesChanged.subscribe(() => setStudies(chart.studies));
};

const study = studies.find((s) => s.id === studyId);

// Fills its parent, so give the parent a height
return (
<div style={{ display: "flex", height: "100%" }}>
<div style={{ flex: 1, minWidth: 0 }}>
<SciFinanceChartView config={config} onInit={onInit} />
</div>
<div style={panelStyle}>
{/* A dropdown of the chart's studies: the form edits the one picked */}
<select style={controlStyle} value={studyId ?? ""} onChange={(e) => setStudyId(e.target.value)}>
{studies.map((s) => (
<option key={s.id} value={s.id}>
{s.type}
</option>
))}
</select>
{/* Inputs / Styles tabs: the form shows one section at a time */}
<div style={{ display: "flex", gap: 4 }}>
{[
["Inputs", EDescriptorSectionName.INPUTS],
["Styles", EDescriptorSectionName.STYLES],
].map(([label, value]) => (
<button
key={value}
style={{ ...controlStyle, fontWeight: section === value ? 700 : 400 }}
onClick={() => setSection(value as EDescriptorSectionName)}
>
{label}
</button>
))}
</div>
{/* StudySettingsForm: a form generated from the study's descriptor. A new `study` reloads it.
sectionFilter shows one section, and hideSectionLabels drops its heading: the tab says it.
Edits apply 150 ms after the last change, through onApply. Without onApply the form
calls study.applyDescriptor(descriptor) itself */}
{study && (
<StudySettingsForm
study={study}
sectionFilter={[section]}
hideSectionLabels
onApply={(s, descriptor) => {
s.applyDescriptor(descriptor);
setStatus(`Applied to ${s.type} at ${new Date().toLocaleTimeString()}`);
}}
/>
)}
<div style={{ color: "var(--st-ui-text-muted, #9da2bc)", fontSize: 12 }}>{status}</div>
</div>
</div>
);
}

// The panel uses SciTrader's UI colours: its --st-ui-* CSS variables, with the stylesheet's defaults
const panelStyle: React.CSSProperties = {
display: "flex",
flexDirection: "column",
gap: 8,
width: 320,
padding: 12,
boxSizing: "border-box",
overflowY: "auto",
background: "var(--st-ui-background, #2b2839)",
borderLeft: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
};
const controlStyle: React.CSSProperties = {
padding: "6px 10px",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
borderRadius: 6,
background: "var(--st-ui-surface, #373447)",
color: "var(--st-ui-text, #ffffff)",
font: "inherit",
fontSize: 13,
cursor: "pointer",
};

StudySettingsForm API​

MemberWhat it does
StudySettingsForm.create(container, options)Creates a form in container
options.studyThe study whose settings it edits
options.onApplyCalled with edited settings. Default: study.applyDescriptor
options.sectionFilterOnly these sections. Default: all
options.hideSectionLabelsLeaves out the section headings
descriptorThe settings as edited, which may not be applied yet
update(options)Changes options; a different study reloads the form
destroy()Removes the form. A change still waiting to apply is dropped
The IStudySettingsFormOptions interface and StudySettingsForm class, with their TSDoc
/** Options for {@link StudySettingsForm}. */
interface IStudySettingsFormOptions {
/** The study whose settings the form edits. */
study: IStudy;
/**
* Called with the edited settings, {@link APPLY_DEBOUNCE_MS} after the user's last change.
* Default: `study.applyDescriptor(descriptor)`, which updates the study in place. Pass your own
* to do something else, e.g. rebuild a study that doesn't support in-place updates (see
* {@link StudyList}).
*/
onApply?: (study: IStudy, descriptor: TStudyDescriptor) => void;
/** Only these sections (e.g. just the inputs). Default: every section the study has. */
sectionFilter?: readonly EDescriptorSectionName[];
/** Leave out the section headings, e.g. when the page already shows "Inputs" / "Styles" tabs. */
hideSectionLabels?: boolean;
}

/** How long the form waits after the last change before applying it, in ms. */
const APPLY_DEBOUNCE_MS = 150;

/**
* A study's settings form, in plain DOM, generated from its descriptor (`study.getDescriptor()`).
* Each setting gets the field for its type: number and text boxes, dropdowns (including line
* style), a colour picker with opacity, a gradient editor. Unknown types are skipped.
*
* Changes apply as you make them: {@link APPLY_DEBOUNCE_MS} after the last one, the form calls
* `onApply` (by default `study.applyDescriptor`). "Reset to defaults" goes back to the study's
* `getDefaultDescriptor()`. When the study's settings change from elsewhere (its
* `descriptorApplied` event), the form shows them.
*
* Any study gets a form this way, including your own custom studies. The look is
* `.st-study-form` in `scitrader.css`.
*
* ```ts
* StudySettingsForm.create(panel, { study: chart.financeApi.studies[2] });
* ```
*
* React apps use the React `StudySettingsForm`.
*/
class StudySettingsForm {
/** The form, inside the container passed to {@link create}. */
readonly element: HTMLDivElement;
static create(container: HTMLElement, options: IStudySettingsFormOptions): StudySettingsForm;
/** The settings as edited, which may not be applied yet. */
get descriptor(): TStudyDescriptor;
/**
* Change any of the options; the ones not given stay as they are. A different `study` reloads
* the form from it.
*/
update(options: Partial<IStudySettingsFormOptions>): void;
/** Remove the form. A change still waiting to be applied is dropped. */
destroy(): void;
}

StudyList: The Chart's Studies with Their Settings​

StudyList lists a chart's studies as cards. Clicking a card opens that study's StudySettingsForm, one at a time, and × removes the study from the chart. The list follows the chart's studiesChanged, so studies added or removed elsewhere appear and disappear.

A study whose supportsLiveApply is false can't apply settings in place. For those, the list rebuilds the study with the new settings, through studyProvider, and swaps it in. Every built-in study applies settings in place.

// Plain TypeScript
import { StudyList } from "scichart-scitrader";

const studyList = StudyList.create(sidePanel, { chart: financeChartPanel.financeApi, title: "Indicators" });
studyList.expand(rsi.id); // open the RSI's settings from code
studyList.expand(null); // close them
studyList.destroy(); // remove it when done
// React. The chart is api.financeApi, from SciFinanceChartView's onInit
import { StudyList } from "scichart-scitrader-react";

<StudyList chart={chart} title="Indicators" emptyMessage="No indicators on the chart." />

TypeScript Example: StudyList Side Panel​

A BTC-USD chart from Coinbase with Volume, SMA and RSI, and a StudyList titled "Indicators" on the right. Click a card to edit that study's settings, or × to remove it. Add MACD and Add EMA 20 attach studies from code, and the list follows. Open RSI settings and Close settings use expand.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
EMAStudy,
idbPriceStore,
MACDStudy,
OHLCStudy,
RSIStudy,
SciFinanceChartPanel,
SMAStudy,
StudyList,
VolumeStudy,
} from "scichart-scitrader";

// This example expects this HTML:
// <div style="display: flex; flex-direction: column; height: 100%">
// <div id="toolbar"></div>
// <div style="display: flex; flex: 1; min-height: 0">
// <div id="chart" style="flex: 1; min-width: 0"></div>
// <div id="studies" style="width: 320px; overflow-y: auto"></div>
// </div>
// </div>

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

async function createChart() {
const toolbar = document.getElementById("toolbar");
Object.assign(toolbar.style, toolbarStyle);

const rsi = new RSIStudy();
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById("chart"), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [new OHLCStudy(), new VolumeStudy(), new SMAStudy({ length: 50 }), rsi],
});
const chart = financeChartPanel.financeApi;

// StudyList: a card per study on the chart. Click a card to open that study's settings form
// (one at a time); × removes the study. The list follows studiesChanged, so studies added
// or removed elsewhere, like by the buttons below, appear and disappear
const studyList = StudyList.create(document.getElementById("studies"), {
chart,
title: "Indicators",
emptyMessage: "No indicators on the chart.", // shown when the chart has no studies
});

toolbar.append(
button("Add MACD", () => chart.attachStudy(new MACDStudy())),
button("Add EMA 20", () => chart.attachStudy(new EMAStudy({ length: 20 }))),
// Open a study's card from code; expand(null) closes it
button("Open RSI settings", () => studyList.expand(rsi.id)),
button("Close settings", () => studyList.expand(null))
);

// When the page goes away: studyList.destroy(); financeChartPanel.cleanup();
return { financeChartPanel, studyList };
}

function button(text: string, onClick: () => void) {
const b = document.createElement("button");
b.textContent = text;
b.onclick = onClick;
Object.assign(b.style, buttonStyle);
return b;
}

// The toolbar uses SciTrader's UI colours: its --st-ui-* CSS variables, with the stylesheet's defaults
const toolbarStyle: Partial<CSSStyleDeclaration> = {
display: "flex",
flexWrap: "wrap",
alignItems: "center",
gap: "8px",
padding: "8px",
background: "var(--st-ui-background, #2b2839)",
borderBottom: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
};
const buttonStyle: Partial<CSSStyleDeclaration> = {
padding: "4px 10px",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
borderRadius: "6px",
background: "var(--st-ui-surface, #373447)",
color: "var(--st-ui-text, #ffffff)",
font: "inherit",
fontSize: "13px",
cursor: "pointer",
};

createChart();

React Example: StudyList Side Panel​

The same chart in React, with the React StudyList. It needs the chart's financeApi, so it renders once onInit has stored it. The React component has no expand: to open one study's settings in React, render its StudySettingsForm.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import * as React from "react";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
EMAStudy,
idbPriceStore,
ISciFinanceChartPanelApi,
ISciFinanceChartPanelConfig,
MACDStudy,
OHLCStudy,
RSIStudy,
SciFinanceChart,
SMAStudy,
VolumeStudy,
} from "scichart-scitrader";
import { SciFinanceChartView, StudyList } from "scichart-scitrader-react";

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

export function StudyListChart() {
// The chart's finance API, once it has initialised. StudyList needs it
const [chart, setChart] = React.useState<SciFinanceChart>(null);

// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [new OHLCStudy(), new VolumeStudy(), new SMAStudy({ length: 50 }), new RSIStudy()],
}),
[]
);

// Fills its parent, so give the parent a height
return (
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
<div style={toolbarStyle}>
<button style={buttonStyle} disabled={!chart} onClick={() => chart.attachStudy(new MACDStudy())}>
Add MACD
</button>
<button style={buttonStyle} disabled={!chart} onClick={() => chart.attachStudy(new EMAStudy({ length: 20 }))}>
Add EMA 20
</button>
</div>
<div style={{ display: "flex", flex: 1, minHeight: 0 }}>
<div style={{ flex: 1, minWidth: 0 }}>
{/* financeApi throws until the chart has initialised, so read it in onInit */}
<SciFinanceChartView config={config} onInit={(api: ISciFinanceChartPanelApi) => setChart(api.financeApi)} />
</div>
{/* StudyList: a card per study on the chart. Click a card to open that study's settings form
(one at a time); × removes the study. It follows studiesChanged, so studies added or
removed elsewhere, like by the buttons above, appear and disappear */}
{chart && (
<StudyList
chart={chart}
title="Indicators"
emptyMessage="No indicators on the chart." // shown when the chart has no studies
style={sidePanelStyle}
/>
)}
</div>
</div>
);
}

// The toolbar uses SciTrader's UI colours: its --st-ui-* CSS variables, with the stylesheet's defaults
const toolbarStyle: React.CSSProperties = {
display: "flex",
flexWrap: "wrap",
alignItems: "center",
gap: 8,
padding: 8,
background: "var(--st-ui-background, #2b2839)",
borderBottom: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
};
const buttonStyle: React.CSSProperties = {
padding: "4px 10px",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
borderRadius: 6,
background: "var(--st-ui-surface, #373447)",
color: "var(--st-ui-text, #ffffff)",
font: "inherit",
fontSize: 13,
cursor: "pointer",
};
const sidePanelStyle: React.CSSProperties = {
width: 320,
overflowY: "auto",
borderLeft: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
};

StudyList API​

MemberWhat it does
StudyList.create(container, options)Creates a list in container
options.chartThe chart whose studies it lists: financeChartPanel.financeApi
options.titleA heading above the list
options.emptyMessageShown when the chart has no studies. Default "No studies attached."
expand(studyId)Opens a study's settings; expand(null) closes them
expandedStudyIdThe id of the study whose settings are open, or null
update(options)Changes options
destroy()Removes the list
The IStudyListOptions interface and StudyList class, with their TSDoc
/** Options for {@link StudyList}. */
interface IStudyListOptions {
/** The chart whose studies to list: `panel.financeApi`. */
chart: SciFinanceChart;
/** A heading above the list. Default: none. */
title?: string;
/** Shown when the chart has no studies. Default `"No studies attached."`. */
emptyMessage?: string;
}

/**
* The chart's studies as a list, in plain DOM. Click a study to open its {@link StudySettingsForm}
* (one at a time); × removes it from the chart. The list follows the chart's `studiesChanged`, so
* studies added or removed elsewhere appear and disappear.
*
* Settings apply in place when the study supports it (`supportsLiveApply`). Otherwise the study is
* rebuilt with the new settings through `studyProvider` and swapped in. The look is
* `.st-study-list` in `scitrader.css`.
*
* ```ts
* StudyList.create(sidePanel, { chart: panel.financeApi, title: "Studies" });
* ```
*
* React apps use the React `StudyList`.
*/
class StudyList {
/** The list, inside the container passed to {@link create}. */
readonly element: HTMLDivElement;
static create(container: HTMLElement, options: IStudyListOptions): StudyList;
/** The id of the study whose settings are open, or `null`. */
get expandedStudyId(): string | null;
/** Change any of the options; the ones not given stay as they are. */
update(options: Partial<IStudyListOptions>): void;
destroy(): void;
/** Open one study's settings, or close them with `null`. */
expand(studyId: string | null): void;
}

StudySettingsForm and StudyList in React​

The React components take the same options as props, plus className and style for their <div>.

The React StudySettingsForm and StudyList components and their props, from scichart-scitrader-react, with their TSDoc
/** Props every React study-settings component takes besides its own. */
interface IHostProps {
className?: string;
style?: React.CSSProperties;
}

/** Props for {@link StudySettingsForm}. */
interface IStudySettingsFormProps extends IHostProps {
/** The study whose settings the form edits. */
study: IStudy;
/** Called with the edited settings after a short pause. Default: `study.applyDescriptor`. */
onApply?: (study: IStudy, descriptor: TStudyDescriptor) => void;
/** Only these sections. Default: all. */
sectionFilter?: readonly EDescriptorSectionName[];
/** Leave out the section headings. */
hideSectionLabels?: boolean;
}
/**
* The SDK's study settings form in React: the vanilla `StudySettingsForm`, generated from the
* study's descriptor, in a `<div>`. Edits apply to the chart as they are made.
*
* ```tsx
* <StudySettingsForm study={chart.financeApi.studies[2]} />
* ```
*/
function StudySettingsForm({ study, onApply, sectionFilter, hideSectionLabels, className, style, }: IStudySettingsFormProps): JSX.Element;

/** Props for {@link StudyList}. */
interface IStudyListProps extends IHostProps {
/** The chart whose studies to list: `api.financeApi`. */
chart: SciFinanceChart;
/** A heading above the list. */
title?: string;
/** Shown when the chart has no studies. */
emptyMessage?: string;
}
/**
* The SDK's study list in React: the chart's studies, each opening its settings form, with ×
* to remove. Follows studies added or removed elsewhere.
*
* ```tsx
* <StudyList chart={api.financeApi} title="Studies" />
* ```
*/
function StudyList({ chart, title, emptyMessage, className, style }: IStudyListProps): JSX.Element;

Styling the Study Settings Form and Study List​

The form and list are styled by scitrader.css, with these classes:

ClassElement
.st-study-formThe form
.st-study-form__section, .st-study-form__section-labelAn "Inputs" or "Styles" section, and its heading
.st-study-form__footer, .st-study-form__resetThe footer, and its Reset to defaults button
.st-study-form__emptyShown for a study with no settings
.st-study-listThe list
.st-study-list__title, .st-study-list__emptyIts heading, and the message when the chart has no studies
.st-study-list__items, .st-study-list__cardThe cards, and one card
.st-study-list__header, .st-study-list__name, .st-study-list__chevron, .st-study-list__removeA card's header row: the study name, the open/close chevron and the × button
.st-study-list__bodyAn open card's settings form

The fields inside a form are the SDK's shared fields: .st-text-field (number and text boxes), .st-select-field (dropdowns) and the Colour Picker's .st-color-field. Colours come from the --st-ui-* CSS variables, so a theme restyles them all. To change one thing, override its rule after importing scitrader.css:

/* Tighter cards in the study list */
.st-study-list__items { padding: 0 8px 8px; } /* less space around the cards */
.st-study-list__card { border-radius: 0; } /* square corners */

/* Accent-coloured section headings in the settings form */
.st-study-form__section-label { color: #ff9f1c; }
The default settings form CSS (.st-study-form), from scitrader.css
.st-study-form {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px;
font-family: var(--st-font-family, "DM Sans", sans-serif);
}

.st-study-form__section {
display: flex;
flex-direction: column;
gap: 8px;
}

.st-study-form__section-label {
color: var(--st-ui-text-muted, #9da2bc);
font-size: 12px;
line-height: 1.66;
letter-spacing: 0.04em;
text-transform: uppercase;
}

.st-study-form__empty {
margin: 0;
padding: 8px;
color: var(--st-ui-text-muted, #9da2bc);
font-size: 14px;
}

.st-study-form__footer {
display: flex;
justify-content: flex-end;
padding-top: 4px;
}

.st-study-form__reset {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 4px 5px;
border: 0;
border-radius: 6px;
background: none;
color: var(--st-ui-text-muted, #9da2bc);
font-family: inherit;
font-size: 12px;
font-weight: 500;
line-height: 1.75;
cursor: pointer;
}

.st-study-form__reset:hover {
color: var(--st-ui-text, #ffffff);
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.04);
}
The default study list CSS (.st-study-list), from scitrader.css
.st-study-list {
height: 100%;
background: var(--st-ui-background, #2b2839);
font-family: var(--st-font-family, "DM Sans", sans-serif);
}

.st-study-list__title {
flex-shrink: 0;
padding: 20px 24px 16px;
color: var(--st-ui-text, #ffffff);
font-size: 22px;
font-weight: 700;
letter-spacing: -0.01em;
}

.st-study-list__empty {
margin: 0;
padding: 0 24px;
color: var(--st-ui-text-muted, #9da2bc);
font-size: 14px;
line-height: 1.43;
}

.st-study-list__items {
display: flex;
flex-direction: column;
gap: 8px;
padding: 0 16px 16px;
scrollbar-width: thin;
scrollbar-color: var(--st-ui-scrollbar-thumb, #4a4560) var(--st-ui-scrollbar-track, #1e1b2e);
}

.st-study-list__card {
flex-shrink: 0;
overflow: hidden;
border-radius: 6px;
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.03);
}

.st-study-list__header {
display: flex;
align-items: center;
padding: 8px 12px;
cursor: pointer;
outline: none;
}

.st-study-list__header:hover,
.st-study-list__header:focus-visible {
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.04);
}

.st-study-list__chevron {
display: inline-flex;
color: var(--st-ui-text-muted, #9da2bc);
transition: transform 160ms ease;
}

.st-study-list__header[aria-expanded="true"] .st-study-list__chevron {
transform: rotate(180deg);
}

.st-study-list__name {
flex: 1;
margin-left: 8px;
color: var(--st-ui-text, #ffffff);
font-size: 14px;
}

.st-study-list__remove {
display: inline-flex;
padding: 5px;
border: 0;
border-radius: 50%;
background: none;
color: var(--st-ui-text-muted, #9da2bc);
cursor: pointer;
}

.st-study-list__remove:hover {
color: var(--st-ui-text, #ffffff);
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.08);
}

.st-study-list__body {
padding: 8px 12px 12px;
}