vscrui
v1.1.0
Published
A React components library for building webview-based extensions with React in Visual Studio Code.
Readme
Visual Studio Code - React UI Library (vscrui)
The vscrui is a React components library for building webview-based extensions with React in Visual Studio Code.
[!NOTE] The library is based on the VS Code Webview UI Toolkit, which was deprecated on January 6, 2025. See the deprecation announcement for more details. Instead of providing web components, this library provides React components.
Installation
To install the library, run the following command:
npm install vscrui[!IMPORTANT] When using the
Iconcomponent, make sure to import the Codicon CSS file in your project. You can use the following import statement:import 'vscrui/dist/codicon.css';.
Usage
To use the library, import the components you need and use them in your React components.
import { Badge, Button, Checkbox, Label, Tag } from "vscrui";
import "vscrui/dist/codicon.css"; // If using IconsComponents
import { Badge } from "vscrui";
<Badge>99</Badge>import { Button } from "vscrui";
<Button appearance="primary" onClick={() => console.log("Clicked")}>
Primary Button
</Button>
<Button appearance="secondary">
Secondary Button
</Button>
<Button appearance="icon" aria-label="Add">
<span className="codicon codicon-plus"></span>
</Button>import { Checkbox } from "vscrui";
<Checkbox
checked={true}
onChange={(checked) => console.log(checked)}
>
Checkbox Label
</Checkbox>import { Divider } from "vscrui";
<Divider />import { Dropdown } from "vscrui";
<Dropdown
options={["Option 1", "Option 2", "Option 3"]}
value="Option 1"
onChange={(value) => console.log(value)}
/>
// With object options
<Dropdown
options={[
{ label: "Option 1", value: "opt1" },
{ label: "Option 2", value: "opt2" }
]}
value="opt1"
onChange={(value) => console.log(value)}
/>import { Icon } from "vscrui";
<Icon name="add" />
<Icon name="refresh" spin />
// The size accepts a number (pixels) or any CSS length
<Icon name="add" size={24} />
<Icon name="add" size="1.5rem" />import { Label } from "vscrui";
<Label>Label Text</Label>import { Loader } from "vscrui";
// Full-page overlay with a progress bar on top (default)
<Loader />
// Progress bar only, without the overlay
<Loader overlay={false} />import { Pane } from "vscrui";
<Pane
title="Pane Title"
actions={[
{ iconName: "refresh", onClick: () => console.log("Refresh") }
]}
>
<p>Pane Content</p>
</Pane>
// The pane is collapsed by default. Use `open` to expand it and `onClick` to
// react to the user toggling it.
<Pane
title="Pane Title"
open={true}
onClick={(isOpen) => console.log(isOpen)}
>
<p>Pane Content</p>
</Pane>The icon button Pane renders for each of its actions. Use it directly when you compose your own header.
import { PaneActionButton } from "vscrui";
<PaneActionButton
iconName="refresh"
onClick={() => console.log("Refresh")}
/>The collapsible header used by Pane. Use it directly when you want to control the open state yourself.
import { PaneHeader } from "vscrui";
const [open, setOpen] = useState(false);
<PaneHeader
open={open}
triggerOpen={() => setOpen(!open)}
actions={[
{ iconName: "refresh", onClick: () => console.log("Refresh") }
]}
>
Pane Title
</PaneHeader>import { Panels } from "vscrui";
<Panels
tabs={[
{ id: "tab1", label: "Tab 1" },
{ id: "tab2", label: "Tab 2" }
]}
views={[
{ id: "tab1", content: <p>Tab 1 Content</p> },
{ id: "tab2", content: <p>Tab 2 Content</p> }
]}
/>
// Control which tab is selected and listen for changes
<Panels
tabs={tabs}
views={views}
activeTab="tab2"
onTabChange={(id) => console.log(id)}
/>[!NOTE] A tab is only rendered when its
idmatches theidof one of theviews.
The tab button used by Panels. Use it directly when you build your own tab list.
import { Tab } from "vscrui";
<Tab
isSelected={true}
onClick={() => console.log("Selected")}
>
Tab 1
</Tab>import { Table, TableRow, TableCell } from "vscrui";
<Table>
<TableRow isHeader>
<TableCell>Header 1</TableCell>
<TableCell>Header 2</TableCell>
</TableRow>
<TableRow>
<TableCell>Row 1 Col 1</TableCell>
<TableCell>Row 1 Col 2</TableCell>
</TableRow>
</Table>import { Tag } from "vscrui";
<Tag>Tag Text</Tag>import { TextArea } from "vscrui";
<TextArea
placeholder="Enter text..."
onChange={(value) => console.log(value)}
>
Label Text
</TextArea>import { TextField } from "vscrui";
<TextField
placeholder="Enter text..."
onChange={(value) => console.log(value)}
>
Label Text
</TextField>The panel container used by Panels and Pane. It stays mounted while hidden, so its content keeps its state.
import { View } from "vscrui";
<View isVisible={true}>
<p>View Content</p>
</View>Hooks
Returns the theme kind currently applied to the webview, and updates whenever the user switches themes in VS Code. It reads the data-vscode-theme-kind attribute VS Code sets on the body element.
import { useVscodeTheme } from "vscrui";
const MyComponent = () => {
const { theme } = useVscodeTheme();
// "vscode-light" | "vscode-dark" | "vscode-high-contrast" | "vscode-high-contrast-light"
return <div>The current theme is {theme}</div>;
};[!NOTE] The hook falls back to
vscode-lightwhen the attribute is not present, for instance when you render your webview outside of VS Code.
Future Components
- [ ] Tooltip
- [ ] Multi-select
Development
- Clone the repository
- Run
npm install - Run
npm run storybookto start the development server - Open the
http://localhost:6006in your browser - Test out the components or make changes to the library
Contributing
If you want to contribute, please find an open issue you would like to work on and leave us a comment. If you have any questions, feel free to ask in the issue or in the Discord server.
References
- https://github.com/facebook/sapling/tree/main/addons/components
- https://github.com/microsoft/vscode-webview-ui-toolkit
Sponsors
If you find this project useful, please consider becoming a sponsor to help Open Source sustainable. Thank you!
