A fully-typed TypeScript wrapper for Zenity dialogs, providing an easy-to-use API for creating native desktop dialogs in your Bun applications.
Python Version: This is a TypeScript/Bun port of the original Python Zenity Wrapper. If you're working with Python, check out the original implementation!
Install Zenity on your system:
# macOS
brew install zenity
# Ubuntu/Debian
sudo apt-get install zenity
# Fedora
sudo dnf install zenitymacOS Note: This wrapper automatically configures Zenity to prevent GTK4-related crashes on macOS by setting the
GSETTINGS_BACKEND=memoryenvironment variable. No additional setup required!
Install from npm once published:
# With Bun
bun add zenity-wrapper
# With npm
npm install zenity-wrapper
# With pnpm
pnpm add zenity-wrapperimport Zenity from 'zenity-wrapper';
const zenity = new Zenity();
// Show an info dialog
await zenity.info("Hello, World!", { title: "Greeting" });
// Ask a question
const confirm = await zenity.question("Continue?");
if (confirm) {
console.log("User confirmed!");
}
// Get user input
const name = await zenity.entry("Enter your name:");
console.log(`Hello, ${name}!`);
// Forms with button differentiation (NEW!)
const result = await zenity.forms(
[
{ type: 'entry', label: 'Name' },
{ type: 'entry', label: 'Email' }
],
{
title: 'Contact Info',
extraButton: 'Skip' // Optional third button
}
);
// Now you can distinguish which button was clicked
if (result.button === 'ok') {
console.log('Submitted:', result.values);
} else if (result.button === 'extra') {
console.log('User clicked Skip button');
} else {
console.log('User cancelled');
}forms() method now returns a FormsResult object instead of string[] | null.
Before:
const values = await zenity.forms([...], options);
if (values) {
console.log(values);
}After:
const result = await zenity.forms([...], options);
if (result.button === 'ok' && result.values) {
console.log(result.values);
}This change allows you to distinguish between Cancel and Extra button clicks, which was previously impossible.
The demos directory contains TypeScript ports of the Python Zenity Wrapper demos. You can run any demo using bun:
bun demos/info_dialog.ts
bun demos/simple_form.tsinfo_dialog.ts- Information messagewarning_dialog.ts- Warning messageerror_dialog.ts- Error messagequestion_dialog.ts- Yes/No question
entry_dialog.ts- Text inputpassword_dialog.ts- Password inputscale_dialog.ts- Slider/Scalecalendar_dialog.ts- Date picker
list_dialog.ts- Simple list selectionchecklist_dialog.ts- Multiple selection checklistradiolist_dialog.ts- Single selection radio listfile_selection_dialog.ts- File/Directory picker
progress_dialog.ts- Progress bars
text_dialog.ts- Text viewer/editor
simple_form.ts- Basic form with entry fieldspassword_form.ts- Login/Registration formmultiline_form.ts- Form with multiline text areacalendar_form.ts- Form with date pickercombo_form.ts- Form with dropdownslist_form.ts- Form with list selectioncomprehensive_form.ts- Form showcasing all field types
![]() Info Dialog |
![]() Warning Dialog |
![]() Error Dialog |
![]() Question Dialog |
![]() Text Entry |
![]() Password Entry |
![]() Scale/Slider |
![]() Calendar |
![]() Single Selection List |
![]() Multiple Selection List |
![]() User Info Form |
![]() Registration Form |
![]() Login Form |
![]() Text Editor |
![]() Form with Multiline Entry |
When using forms with multiline text fields, you can control the height by setting the height option on the dialog. Zenity automatically distributes the available space among form fields, with multiline fields receiving proportionally more vertical space.
How it works:
- Single-line fields (entry, password, combo) have a fixed height
- Multiline fields expand to use the remaining available vertical space
- The
heightparameter controls the overall dialog height, not individual fields
Example:
const zenity = new Zenity();
// Small multiline area (default height)
const result1 = await zenity.forms(
[
{ type: 'entry', label: 'Title' },
{ type: 'multiline', label: 'Description' },
{ type: 'entry', label: 'Tags' }
],
{
text: "Create a Post",
separator: "||"
}
);
// Large multiline area (increased height)
const result2 = await zenity.forms(
[
{ type: 'entry', label: 'Title' },
{ type: 'multiline', label: 'Description' },
{ type: 'entry', label: 'Tags' }
],
{
text: "Create a Post",
separator: "||",
width: 600,
height: 800 // More dialog height = more space for multiline field
}
);Note: Zenity doesn't provide command-line options to control individual field heights. The layout is handled automatically based on the overall dialog dimensions.
See ZENITY_API.md for complete API documentation with examples for all dialog types.
The FormCollection class (demos/forms_collection.ts) provides pre-built, developer-focused forms for common workflows. These forms combine multiple input types to collect structured data for various tasks.
bun demos/forms_collection.tsThe collection includes 24+ ready-to-use forms organized by category:
- Package Initialization (npm/Bun packages)
- TypeScript Configuration
- Python Project Setup
- Web Project Setup (React, Vue, etc.)
- Conventional Git Commits
- Pull Requests
- Release Versioning
- .gitignore Generator
- Environment Variables
- ESLint/Prettier Config
- VS Code Workspace Settings
- Package.json Scripts
- Docker Container Config
- GitHub Actions Workflows
- SSH Configuration
- Database Connection Setup
- API Configuration
- README Generator
- Changelog Entries
- Blog Post Metadata
- Bug Reports
- Feature Requests
import { FormCollection } from './demos/forms_collection';
const forms = new FormCollection();
// Collect package initialization data
const pkgData = await forms.packageInit();
console.log(pkgData);
// {
// packageName: 'my-app',
// version: '0.1.0',
// description: 'My awesome app',
// author: 'Developer Name',
// license: 'MIT',
// runtime: 'Bun'
// }
// Collect git commit data
const commit = await forms.gitCommit();
console.log(commit);
// {
// type: 'feat',
// scope: 'api',
// summary: 'Add user authentication',
// description: 'Implemented JWT-based auth',
// breaking: 'No'
// }All forms return structured objects with named fields, making it easy to integrate into scripts and automation workflows.
bun run demo.tsThe demo showcases all available dialog types including:
- Message dialogs (info, warning, error, question)
- Input dialogs (entry, password, scale, calendar)
- Selection dialogs (list, color picker)
- File dialogs (open, save, directory)
- Progress dialogs
- Advanced dialogs (forms, text editor)
You can build your TypeScript files with Bun:
# Build a single file
bun build ./demo.ts --outdir ./dist
# Build with minification
bun build ./demo.ts --outdir ./dist --minify
# Build as a standalone executable
bun build ./demo.ts --compile --outfile zenity-demoFor more build options, see the Bun build documentation.
This library is written in TypeScript and includes full type definitions. All dialog options are properly typed for an excellent development experience.
import Zenity, { QuestionOptions, ListOptions } from './zenity-wrapper';
const options: QuestionOptions = {
title: "Confirm",
okLabel: "Yes",
cancelLabel: "No"
};This project was created using bun init in bun v1.3.2. Bun is a fast all-in-one JavaScript runtime.
To publish the package to npm:
# Build the package
bun run build
# Login to npm if needed
npm login
# Publish
npm publish --access public
# Alternatively, using Bun
bun publishIf the name zenity-wrapper is taken on npm, update the name field in package.json before publishing.














