Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:TobikoData Sqlmesh SelectEnvironment

From Leeroopedia


Knowledge Sources
Domains Web_UI, Environment_Management
Last Updated 2026-02-07 20:00 GMT

Overview

A dropdown menu component for selecting and managing SQLMesh environments with create, delete, and switch functionality.

Description

SelectEnvironment is a sophisticated React component that provides a dropdown interface for managing SQLMesh environments. It displays all available environments (both local and remote) with visual indicators for environment type, status, and features (production, default, pinned). The component supports creating new environments, deleting remote environments, removing local environments, and switching between environments with appropriate callbacks and confirmations.

The dropdown uses HeadlessUI's Menu component for accessible menu interactions and displays rich information about each environment including its type (local/remote), whether it's a production environment, default environment, or pinned environment. The component implements smart button styling based on environment state, with different colors for local vs remote environments and disabled states. It also includes an AddEnvironment component at the bottom of the dropdown for creating new environments.

Usage

Use this component whenever users need to view, select, or manage SQLMesh environments. It's typically placed in the application header or toolbar for easy access across the application.

Code Reference

Source Location

  • Repository: TobikoData_Sqlmesh
  • File: web/client/src/library/components/environmentDetails/SelectEnvironment.tsx

Signature

export function SelectEnvironment({
  disabled = false,
  className,
  showAddEnvironment = true,
  size = EnumSize.sm,
  onSelect,
}: {
  className?: string
  size?: ButtonSize
  disabled?: boolean
  showAddEnvironment?: boolean
  onSelect?: () => void
}): JSX.Element

Import

import { SelectEnvironment } from '@components/environmentDetails/SelectEnvironment'

I/O Contract

Inputs

Name Type Required Description
disabled boolean No Whether the selector is disabled (default: false)
className string No Additional CSS classes for styling
showAddEnvironment boolean No Show the add environment form at bottom (default: true)
size ButtonSize No Size of the button (default: EnumSize.sm)
onSelect () => void No Callback when an environment is selected

Outputs

Name Type Description
JSX.Element JSX.Element The rendered dropdown menu component

Component Structure

Menu Button

The button displays the current environment with type indicator:

<ButtonMenu
  variant={EnumVariant.Info}
  size={size}
  disabled={disabled}
  className="flex justify-between w-full mx-0 pr-1"
>
  <span className={clsx(
    'block overflow-hidden truncate',
    (environment.isLocal || disabled) && 'text-neutral-500',
    environment.isRemote
      ? 'text-primary-600 dark:text-primary-300'
      : 'text-neutral-600 dark:text-neutral-200',
  )}>
    <span className="text-xs text-neutral-300 dark:text-neutral-500 mr-1">
      Environment:
    </span>
    <span>{environment.name}</span>
  </span>
  <ChevronDownIcon className="w-4" />
</ButtonMenu>

Environment Colors

State Color Description
Remote Primary (blue) Connected to backend
Local Neutral (gray) Local-only environment
Disabled Neutral (muted) Interaction disabled

Environment List Items

Each environment displays comprehensive information:

<Menu.Item
  key={env.name}
  disabled={env === environment}
>
  {({ active }) => (
    <div onClick={e => handleSelectEnvironment(e, env)}>
      <CheckCircleIcon />  {/* Active indicator */}

      <span>
        {env.name}
        <small>({env.type})</small>
      </span>

      {env.isProd && <small>Production Environment</small>}
      {env.isDefault && <small>Default Environment</small>}

      {env.isPinned && <StarIcon />}
      {/* Delete/Remove buttons for non-pinned environments */}
    </div>
  )}
</Menu.Item>

Environment Indicators

Indicator Icon Condition
Active CheckCircleIcon (primary) Current environment selected
Pinned StarIcon (primary) Environment is pinned
Production Text label Environment is production
Default Text label Environment is default target

Environment Actions

Selecting an Environment

function handleSelectEnvironment(e: MouseEvent, env: ModelEnvironment): void {
  e.stopPropagation()
  setEnvironment(env)
  onSelect?.()
}

Removing Local Environments

function handleRemoveLocalEnvironment(
  e: MouseEvent,
  env: ModelEnvironment,
): void {
  e.stopPropagation()
  removeLocalEnvironment(env)
}

Shows minus icon button for local, non-pinned environments.

Deleting Remote Environments

function handleDeleteEnvironment(e: MouseEvent, env: ModelEnvironment): void {
  e.stopPropagation()

  apiDeleteEnvironment(env.name)
    .then(() => {
      removeLocalEnvironment(env)
    })
    .catch(error => {
      addError(EnumErrorKey.Environments, error)
    })
}

Shows "Delete" button for remote, non-pinned environments.

Action Button Visibility Rules

Environment Type Pinned Is Current Action Button
Local No No Remove (minus icon)
Local Yes - None
Local - Yes None
Remote No No Delete (button)
Remote Yes - None
Remote - Yes None

Rule: Only non-pinned, non-current environments show action buttons.

Add Environment Section

At the bottom of the dropdown:

{showAddEnvironment && (
  <>
    <Divider />
    <AddEnvironment
      onAdd={close}
      className="p-2 pb-2"
    />
  </>
)}

The onAdd callback receives the close function from HeadlessUI, allowing the menu to automatically close after adding an environment.

Menu Styling

The dropdown menu uses absolute positioning:

<div className="!mx-0 absolute top-10 right-0 min-w-[16rem] max-w-[100%] overflow-hidden shadow-2xl bg-theme border-0 border-neutral-100 dark:border-neutral-800 rounded-md flex flex-col z-50">
  <Menu.Items className="mx-0 overflow-auto max-h-80 hover:scrollbar scrollbar--vertical">
    {/* Environment items */}
  </Menu.Items>
</div>

Menu Features

  • Position: Absolute, 10px below button, right-aligned
  • Size: Min 16rem width, max 100% width, max 80vh height
  • Scrolling: Vertical scroll for long environment lists
  • Styling: Themed background, shadow, rounded corners
  • Z-index: 50 (appears above most content)

Disabled State

When disabled:

disabled={
  isFetchingPlanRun ||
  planAction.isProcessing ||
  environment.isInitialProd
}
  • Button shows muted colors
  • Dropdown cannot be opened
  • Chevron icon is grayed out

Common reasons:

  • Plan is running
  • Fetching plan data
  • Initial production environment (cannot switch)

Menu Item States

HeadlessUI provides automatic state management:

<Menu.Item disabled={env === environment}>
  {({ active }) => (
    <div className={clsx(
      active
        ? 'text-neutral-600 bg-neutral-10'
        : 'text-neutral-400',
      env === environment
        ? 'cursor-default bg-neutral-5'
        : 'cursor-pointer',
    )}>
      {/* Content */}
    </div>
  )}
</Menu.Item>

States

State Background Cursor Condition
Active (hover) neutral-10 pointer Mouse over item
Selected neutral-5 default Current environment
Inactive transparent pointer Other environments

Transitions

The menu uses HeadlessUI's Transition:

<Transition
  as={Fragment}
  leave="transition ease-in duration-100"
  leaveFrom="opacity-100"
  leaveTo="opacity-0"
>
  {/* Menu.Items */}
</Transition>
  • Enter: Instant (no transition)
  • Leave: 100ms fade out

Usage Example

import { SelectEnvironment } from '@components/environmentDetails/SelectEnvironment'

// Basic usage
<SelectEnvironment />

// With custom configuration
<SelectEnvironment
  className="w-64"
  size={EnumSize.md}
  disabled={isProcessing}
  showAddEnvironment={false}
  onSelect={() => console.log('Environment changed')}
/>

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment