🚧 VeloxKit is pre-release software. APIs may change before v1.0. Get started →
Documentation
APIs & Bindings
dialog

dialog Stable WINMACLNX

Open native OS file dialogs — open, save, and folder picker. Dialogs are modal and block input to the app window while open.

Capability

veloxkit.config.json
{
  "capabilities": ["dialog"]
}

Import

import { dialog } from 'veloxkit'

API

dialog.openFile(opts?)

Show the native "Open File" dialog.

const paths = await dialog.openFile({
  multiple: false,   // true allows multi-select
  filters: [
    { name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'webp'] },
    { name: 'All Files', extensions: ['*'] },
  ],
})
 
if (paths === null) {
  // user cancelled
} else {
  const filePath = paths[0]  // always an array, even when multiple: false
}

Options

OptionTypeDefaultDescription
multiplebooleanfalseAllow selecting multiple files
filtersFilter[][]File type filters shown in the dialog

Filter shape

type Filter = {
  name: string          // display name, e.g. "Images"
  extensions: string[]  // without dots: ['png', 'jpg'] — or ['*'] for all
}

Returns Promise<string[] | null> — array of absolute paths, or null if cancelled.


dialog.saveFile(opts?)

Show the native "Save File" dialog.

const savePath = await dialog.saveFile({
  defaultName: 'export.csv',
  filters: [
    { name: 'CSV', extensions: ['csv'] },
    { name: 'JSON', extensions: ['json'] },
  ],
})
 
if (savePath !== null) {
  await fs.writeFile(savePath, csvContent)
}

Options

OptionTypeDefaultDescription
defaultNamestring''Pre-filled filename
filtersFilter[][]File type filters

Returns Promise<string | null> — absolute path chosen by the user, or null if cancelled.


dialog.openFolder()

Show the native "Select Folder" dialog.

const folderPath = await dialog.openFolder()
 
if (folderPath !== null) {
  const entries = await fs.listDir(folderPath)
  console.log(`${entries.length} items in folder`)
}

Returns Promise<string | null> — absolute folder path, or null if cancelled.


Examples

Image importer

import { dialog, fs } from 'veloxkit'
import { useState } from 'react'
 
const IMAGE_FILTERS = [
  { name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'webp', 'gif'] },
]
 
function ImageImporter() {
  const [imagePath, setImagePath] = useState<string | null>(null)
 
  const handlePick = async () => {
    const paths = await dialog.openFile({ filters: IMAGE_FILTERS })
    if (paths) setImagePath(paths[0])
  }
 
  return (
    <View style={{ gap: 12 }}>
      <Pressable onPress={handlePick}
                 style={{ padding: 12, backgroundColor: '#3a3a5e', borderRadius: 8 }}>
        <Text>Choose Image…</Text>
      </Pressable>
      {imagePath && (
        <Image src={imagePath} width={300} height={200} resizeMode="contain" />
      )}
    </View>
  )
}

Export with save dialog

import { dialog, fs } from 'veloxkit'
 
async function exportToCSV(rows: Record<string, unknown>[]) {
  const path = await dialog.saveFile({
    defaultName: `export-${Date.now()}.csv`,
    filters: [{ name: 'CSV', extensions: ['csv'] }],
  })
  if (!path) return
 
  const header = Object.keys(rows[0]).join(',')
  const body   = rows.map(r => Object.values(r).join(',')).join('\n')
  await fs.writeFile(path, `${header}\n${body}`)
}

Batch import (multiple files)

const paths = await dialog.openFile({
  multiple: true,
  filters: [{ name: 'Documents', extensions: ['pdf', 'txt', 'md'] }],
})
 
if (paths) {
  for (const p of paths) {
    const content = await fs.readFile(p)
    await db.run('INSERT INTO docs (path, content) VALUES (?, ?)', [p, content])
  }
}

FileInput component

For in-form file picking, use the built-in FileInput component instead of calling dialog.openFile() manually:

import { FileInput } from 'veloxkit'
 
<FileInput
  label="Attach file"
  onFilesSelected={(paths) => console.log(paths)}
  filters={[{ name: 'All Files', extensions: ['*'] }]}
/>

Dialogs are always attached to the main window and are fully modal. The Promise resolves only when the user confirms or cancels — there is no timeout.