.page-header{margin-bottom:0}
.section-intro{font-size:14px;line-height:1.7;color:#374151;margin:0 0 16px}
.rule-tag{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:1px 6px;border-radius:3px;margin-right:4px;vertical-align:middle;white-space:nowrap}
.rule-must{background:#FDE7E9;color:#C50F1F}
.rule-should{background:#FFF4CE;color:#835C00}
.guideline-list{margin:0 0 24px;padding-left:20px;font-size:14px;line-height:1.75;color:#374151}
.guideline-list li{margin-bottom:6px}
.guideline-list li:last-child{margin-bottom:0}
.component-preview{border:1px solid #d0d7de;border-radius:8px;overflow:hidden;margin:16px 0 24px}
.component-preview-header{padding:8px 14px;background:#f6f8fa;border-bottom:1px solid #d0d7de;font-size:11px;font-weight:700;color:#6B7280;text-transform:uppercase;letter-spacing:.05em}
.component-preview-canvas{padding:32px;background:#f8f9fa;display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:center;gap:32px}
.preview-col{display:flex;flex-direction:column;gap:8px;align-items:center}
.preview-caption{font-size:11px;color:#666;font-weight:600;text-align:center;max-width:320px;line-height:1.45}
.dlg{background:#f0f0f0;border:1px solid #888;border-radius:3px;box-shadow:0 4px 18px rgba(0,0,0,.28);font-family:'Segoe UI',system-ui,sans-serif;font-size:12px;color:#1a1a1a;overflow:hidden}
.dlg--modal{width:300px}
.dlg--modeless,.dlg--anatomy{width:340px}
.dlg-title{background:linear-gradient(to bottom,#d6e8f8 0%,#c3ddef 100%);border-bottom:1px solid #8eb3d0;padding:5px 8px;display:flex;align-items:center;justify-content:space-between}
.dlg-title-left{display:flex;align-items:center;gap:5px;font-weight:600;font-size:11.5px;min-width:0}
.dlg-title-icon{width:14px;height:14px;background:#0078d4;border-radius:2px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.dlg-title-close{width:18px;height:18px;background:#e81123;border-radius:2px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff;font-size:12px;line-height:1}
.dlg-body{padding:12px 14px;background:#f0f0f0}
.dlg-msg-row{display:flex;gap:10px;align-items:flex-start}
.dlg-icon{width:28px;height:28px;flex-shrink:0;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700}
.dlg-icon-question{background:#ebf3fc;color:#0063b1}
.dlg-msg{font-size:12px;color:#1a1a1a;line-height:1.5}
.dlg-msg strong{font-weight:600;font-size:12.5px}
.dlg-tabs{display:flex;border-bottom:1px solid #c8c8c8;margin-bottom:8px}
.dlg-tab{padding:4px 12px;font-size:11.5px;border:1px solid transparent;margin-bottom:-1px;color:#444}
.dlg-tab.active{background:#f0f0f0;border-color:#c8c8c8 #c8c8c8 #f0f0f0 #c8c8c8;font-weight:600}
.dlg-sep-row{display:flex;align-items:center;gap:6px;margin:8px 0 5px}
.dlg-sep-label{font-size:11px;font-weight:600;color:#444;white-space:nowrap}
.dlg-sep-group{border:none;border-top:1px solid #aaa;flex:1;margin:0}
.dlg-field-row{display:flex;align-items:center;gap:6px;margin-bottom:7px}
.dlg-field-label{width:80px;font-size:11.5px;text-align:right;color:#444;flex-shrink:0}
.dlg-field-input{flex:1;height:20px;border:1px solid #8a8a8a;border-radius:2px;background:#fff;padding:0 4px;font-size:11px;font-family:'Segoe UI',system-ui,sans-serif;color:#1a1a1a;display:flex;align-items:center;box-sizing:border-box;min-width:0}
.dlg-bar{background:#f0f0f0;border-top:1px solid #c8c8c8;padding:8px 10px;display:flex;justify-content:flex-end;gap:6px;min-height:40px;box-sizing:border-box;align-items:center}
.dlg-bar-split{justify-content:space-between}
.dlg-bar-right{display:flex;gap:6px;align-items:center}
.dlg-btn{height:23px;min-width:75px;padding:0 10px;background:#e1e1e1;border:1px solid #8a8a8a;border-radius:2px;font-family:'Segoe UI',system-ui,sans-serif;font-size:11.5px;display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;color:#1a1a1a}
.dlg-btn-primary{background:#0078d4;border-color:#0067b8;color:#fff}
.dlg-btn-danger{background:#fde7e9;border-color:#c50f1f;color:#c50f1f}
.anatomy-layout{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:center;gap:40px;width:100%}
.anatomy-callouts{font-size:12px;color:#57606a;line-height:1.8;max-width:240px;display:flex;flex-direction:column;gap:10px}
.anatomy-callout{display:flex;gap:6px;align-items:flex-start}
.anatomy-callout__tag{background:#ebf3fc;color:#004e8c;font-size:10px;font-weight:700;padding:1px 7px;border-radius:3px;white-space:nowrap;flex-shrink:0;margin-top:2px}
.anatomy-callout__tag--title{background:#c3ddef}
.spec-table{width:100%;border-collapse:collapse;font-size:13px;margin:12px 0 24px}
.spec-table th{text-align:left;padding:8px 12px;background:#F3F4F6;font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:#6B7280;border-bottom:2px solid #E5E7EB}
.spec-table td{padding:8px 12px;border-bottom:1px solid #F3F4F6;vertical-align:top;line-height:1.5}
.spec-table code{background:#F3F4F6;padding:1px 5px;border-radius:3px;font-size:12px;font-family:Consolas,'Courier New',monospace;color:#9d174d;white-space:nowrap}
.when-use-copy{font-size:14px;line-height:1.7;color:#374151;margin:0 0 16px}
.when-use-copy:last-of-type{margin-bottom:24px}
.spec-table .rule-tag{margin-right:0}
.hint-callout{display:flex;align-items:flex-start;gap:16px;margin:16px 0 24px;padding:16px 20px 16px 16px;background:#eff6ff;border:1px solid #3b82f6;border-left:4px solid #3b82f6;border-radius:6px}
.hint-callout__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:32px;min-width:32px;height:32px;font-size:20px;line-height:1;margin:2px 0 0}
.hint-callout__content{flex:1;min-width:0}
.hint-callout__title{margin:0 0 6px;font-size:13px;font-weight:700;color:#0d1117}
.hint-callout__body{margin:0;font-size:13px;line-height:1.75;color:#57606a}
.hint-callout__body code{background:#F3F4F6;padding:1px 5px;border-radius:3px;font-size:12px;font-family:Consolas,'Courier New',monospace;color:#9d174d}
.format-row{background:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;padding:12px 16px;font-family:Consolas,'Courier New',monospace;font-size:13px;line-height:1.6;color:#374151;margin:12px 0}
.format-row-note{margin:0 0 16px;font-size:13px;line-height:1.6;color:#57606a}
.related-pages{margin-top:32px;padding-top:20px;border-top:1px solid #E5E7EB}

.warning-callout{display:flex;align-items:flex-start;gap:16px;margin:16px 0 24px;padding:16px 20px 16px 16px;background:#fff8f0;border:1px solid #f59e0b;border-left:4px solid #f59e0b;border-radius:6px}
.warning-callout__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:32px;min-width:32px;height:32px;font-size:20px;line-height:1;margin:2px 0 0}
.warning-callout__content{flex:1;min-width:0}
.warning-callout__title{margin:0 0 6px;font-size:13px;font-weight:700;color:#0d1117}
.warning-callout__body{margin:0;font-size:13px;line-height:1.75;color:#57606a}
.warning-callout__body code{background:#F3F4F6;padding:1px 5px;border-radius:3px;font-size:12px;font-family:Consolas,'Courier New',monospace;color:#9d174d}
.dlg-icon-error{background:#FDE7E9;color:#C50F1F}
.dlg-icon-warning{background:#FFF4CE;color:#835C00}
.dlg-icon-info{background:#EBF3FC;color:#0078D4}
.dlg-icon-progress{background:#EBF3FC;color:#0078D4}
.dlg-progress-bar{background:#DCDCDC;border:1px solid #B0B0B0;border-radius:2px;height:16px;overflow:hidden;margin:6px 0}
.dlg-progress-fill{height:100%;background:linear-gradient(to right,#0078D4,#47B37F);width:62%}
.dlg-label{font-size:11.5px;color:#444;margin-bottom:4px}
.dlg-note{font-size:11px;color:#666;font-style:italic;border-top:1px solid #D0D0D0;padding-top:6px;margin-top:6px}
.gap-callout{background:#F3EFFA;border:1px solid #C9B3E9;border-radius:8px;padding:14px 16px;margin:20px 0}
.gap-callout-header{display:flex;align-items:center;gap:7px;margin-bottom:7px}
.gap-callout-title{font-size:13px;font-weight:700;color:#5A3E9A}
.gap-callout-body{font-size:13px;line-height:1.6;color:#3D2870}
.gap-callout-body ul{list-style:disc;padding-left:18px;margin:0}
.gap-callout-body li{margin-bottom:5px}
.do-dont-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;margin:16px 0;align-items:stretch}
@media(max-width:900px){.do-dont-grid{grid-template-columns:1fr}}
.do-dont-card{border-radius:8px;overflow:hidden;border:1px solid;display:flex;flex-direction:column;min-width:0;background:#fff;height:100%}
.do-card{border-color:#90D4B3}
.dont-card{border-color:#F0A898}
.do-dont-label{display:flex;align-items:center;gap:6px;padding:8px 14px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em}
.do-card .do-dont-label{background:#F0FAF6;color:#1A7F5A}
.dont-card .do-dont-label{background:#FFF5F4;color:#B91C1C}
.do-dont-content{padding:14px;font-size:13px;color:#374151;line-height:1.6;border-top:1px solid;flex:1}
.do-card .do-dont-content{border-color:#90D4B3}
.dont-card .do-dont-content{border-color:#F0A898}
.dlg-bar-left{justify-content:flex-start}
kbd{display:inline-block;padding:1px 6px;font-size:11px;font-family:Consolas,'Courier New',monospace;background:#f6f8fa;border:1px solid #d0d7de;border-radius:4px;box-shadow:inset 0 -1px 0 #d0d7de}
.cmdbar-demo-label{font-size:11px;color:#666;font-weight:600;letter-spacing:.04em;text-transform:uppercase;margin-bottom:4px}
.cmdbar-demo{background:#F0F0F0;border:1px solid #C8C8C8;border-radius:3px;padding:8px 10px;display:flex;justify-content:space-between;align-items:center;height:40px;box-sizing:border-box}

.xaml-tabs{margin:20px 0;border:1px solid #d0d7de;border-radius:8px;background:#fff;max-width:100%;box-sizing:border-box;overflow:visible}
.xaml-tabs .tab-list{display:flex;flex-wrap:wrap;align-items:stretch;background:#f6f8fa;border-bottom:1px solid #d0d7de;border-radius:8px 8px 0 0;margin:0;padding:0;overflow:visible}
.xaml-tabs .tab-btn{font-family:'Segoe UI',system-ui,sans-serif;font-size:13px;font-weight:500;color:#6B7280;padding:10px 16px;border:none!important;border-bottom:2px solid transparent;background:transparent;transition:color .15s,border-color .15s,background .15s;white-space:nowrap;cursor:pointer;flex:0 0 auto;flex-shrink:0;width:auto!important;max-width:none!important;appearance:none;-webkit-appearance:none;box-sizing:border-box;line-height:1.4;margin:0;min-height:42px;box-shadow:none!important}
.xaml-tabs .tab-btn:hover{color:#0d1117;background:#eef2f6}
.xaml-tabs .tab-btn.active{color:#0078d4;border-bottom-color:#0078d4;background:#fff}
@media(min-width:960px){.xaml-tabs .tab-list{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:thin}.xaml-tabs .tab-list::-webkit-scrollbar{height:6px}.xaml-tabs .tab-list::-webkit-scrollbar-thumb{background:#d0d7de;border-radius:3px}}
.xaml-tabs .tab-panel{display:none;padding:20px;margin:0;min-height:520px;box-sizing:border-box;background:#fff}
.xaml-tabs .tab-panel.active{display:block}
.xaml-tabs .code-block{margin:0;border-radius:6px;overflow:hidden;border:none;background:#1A1A2E;min-height:480px;display:flex;flex-direction:column;height:100%}
.code-block-header{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:#13132A;border-bottom:1px solid rgba(255,255,255,.08);flex-shrink:0}
.code-lang{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:rgba(255,255,255,.45)}
.code-copy{font-family:'Segoe UI',system-ui,sans-serif;font-size:11px;color:rgba(255,255,255,.45);padding:2px 8px;border-radius:4px;cursor:pointer;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.12);width:auto!important;flex-shrink:0;box-shadow:none!important}
.code-copy:hover{background:rgba(255,255,255,.12);color:rgba(255,255,255,.75)}
.code-copy.copied{color:#47B37F;border-color:#47B37F}
.xaml-tabs .code-block pre{margin:0;padding:20px 18px;overflow:auto;scrollbar-width:thin;flex:1 1 auto;min-height:420px;box-sizing:border-box;white-space:normal!important}
.xaml-tabs .code-block code{font-family:Consolas,'Courier New',monospace;font-size:13px;line-height:1.65;color:#ABB2BF;background:none!important;border:none!important;padding:0!important;white-space:normal!important;display:block}
.xaml-tabs .code-line{display:block;white-space:pre;min-height:1.65em}
.tok-keyword{color:#C678DD}
.tok-string{color:#98C379}
.tok-comment{color:#5C6370;font-style:italic}
.tok-attr{color:#E06C75}
.tok-tag{color:#E06C75}
.tok-number{color:#D19A66}
.related-pages h3{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#6B7280;margin-bottom:10px}

# Dialogs

Dialogs interrupt the user's workflow to request confirmation, collect data, or display critical information. Use them deliberately — only when the task cannot be completed in the main window.
## When to use a dialog

Before introducing a new dialog, confirm that it is the right UI surface. Dialogs break the user's workflow — only use them when the interaction genuinely requires a separate window.
Situation
Use instead
Provide information the user did not request and can freely ignore
Notification / silent popup / message log pane
Display program status
Status bar
Show a non-critical input problem inline
Inline validation highlight or balloon tooltip
Present a collection of commands or tools
Toolbar or palette window
Open / save files, select font, choose color
Standard Windows common dialogs
Multi-step task requiring more than a single window
Wizard or multi-page task flow
Contextual settings that can be shown in-place
Inspector extension or task pane
Simple option variation of a toolbar command
Split button or submenu
A dialog is appropriate when: the purpose is to let users perform a command, answer a question, or select options; the task requires completion before or independently of the main workflow; or a contextual in-place alternative is not practical.
All dialogs in Petrel inherit from one of three base classes:
Base class
Purpose
Examples
UiSimpleDialog
Simple dialogs not owned by a project object. No tabs required.
Import/export dialogs, user input modals
UiSettingsDialog
Object settings dialogs. Always tab-based (minimum one tab).
Horizon settings, well settings, template editor
UiPage / UiPart
Custom dialogs for complex features.
Make Model dialog, Run Simulation dialog
## Dialog types

Choose the dialog type based on whether the task requires the user's full attention before they can continue, or whether they benefit from being able to switch between the dialog and other parts of Petrel.
Live preview — Modal vs. Modeless
Delete seismic cube
          
×
?
Delete 
"
North Sea 3D Stack
"
?
This action cannot be undone. All dependent objects will be unlinked.
Delete
Cancel
MODAL — blocks all input until dismissed
Make Horizon (Structural)
          
×
Make horizon
Settings
Hints
Output
Create new:
Horizon 1
Input
Seismic:
North Sea 3D Stack
Run
Apply
Close
MODELESS — user can switch to Petrel and back
Modal
Modeless
Blocks interaction
Yes — user cannot interact with any other part of Petrel until dismissed
No — user can freely switch between the dialog and the viewport
Commit model
Delayed — changes only take effect when OK is clicked
Immediate — changes take effect when Apply is clicked, without closing
Apply button
must
not have an Apply button
Typically has Apply (and optionally OK); Close replaces Cancel
Required for
File Import/Export, Error dialogs, destructive confirmation prompts
Feature configuration, ongoing analytical workflows (Make Horizon, Run Simulation)
Always on top
must
stay in front of all other Petrel windows
May be obscured by the owner window when user switches context
Dockable
No
May be dockable for flexible placement alongside the 3D/2D window
Use when
Critical, infrequent, one-off task that requires user attention before work continues
Frequent, repetitive, ongoing task — user benefits from toggling between dialog and viewport
### Modal dialogs

should
be avoided as much as possible — they take control away from the user and interrupt the analytical flow geoscientists rely on. When a modal dialog is unavoidable:
must
always be kept in front of any other application window or dialog.
must
not include an Apply button — Apply implies leaving the dialog open, which defeats the purpose of a modal.
must
be used for: File Import/Export, Warning, and Critical (Error) dialogs.
Use a delayed commit model — changes don't take effect until the user explicitly commits with OK.
### Modeless dialogs

Allow users to switch freely between the dialog and the rest of Petrel.
Use an immediate commit model — settings take effect when applied, without requiring the dialog to close.
Use an explicit 
Close
button (not Cancel) when there are no unsaved settings to discard.
Modeless dialogs may be dockable — allows users flexible placement alongside the 3D/2D window.
Best for frequent, repetitive, ongoing tasks (e.g., Run Simulation, Make Horizon).
## Custom dialog patterns

Custom dialogs in Petrel fall into three structural patterns depending on how users interact with the feature.
### Dialog-driven

All functionality is exposed within the dialog. Users enter parameters, invoke actions, and receive results — without interacting with the main Petrel viewport.
Rule
Detail
should
Layout order
Output → Input → Method → Settings (left-to-right tab order, or top-to-bottom within a single tab)
must
Single action
Dialogs with one significant action use 
Apply / OK
to invoke it
must
Multiple actions
Dialogs with multiple significant actions use individual named action buttons; use 
Close
rather than Apply / OK / Cancel on the command bar
Supporting actions
Minor actions (e.g., Reset, Preview) invoked with individual buttons alongside the main command bar
The 
Output section
uses the standard Create new / Edit existing pattern:
"
Create new
"
text field uses the output object type as the default name (e.g., 
"
Aquifer 1
"
) and appends an incrementing count to prevent duplicate names.
"
Edit existing
"
combo box must be inactive while empty. Selecting an object in it must update all dialog settings.
Selecting 
"
Create new
"
must 
not
reset dialog settings — this facilitates reuse of settings from existing objects.
A Reset button to restore to last-applied settings may be included where relevant.
### Graphical interactive

Functionality is exposed through tool palettes. Data is manipulated directly in the viewport (CRUD operations). The dialog holds settings that support the interactive work.
must
use Apply / OK to apply unsaved settings. Exception: dialogs without settings should use Close rather than Apply / OK / Cancel.
Minor supporting action buttons may be included (e.g., a button that opens a list of available formats).
### Mixed (dialog-driven + graphical interactive)

should
not be mixed in the same custom dialog. If mixing is unavoidable:
Apply / OK must exclusively apply unsaved settings. Actions must be invoked with individual named buttons — never with Apply / OK.
## Dialog anatomy

Every Petrel dialog consists of three zones: title bar, content area, and command bar.
Annotated dialog anatomy
Horizon tracking — Make horizon
          
×
Make horizon
Settings
Hints
Output
Create new:
Horizon 1
Input
Seismic cube:
North Sea 3D
Method:
Auto-picking
Run
Apply
OK
Close
Title bar
Feature icon + dialog title. Title must match the ribbon button label. Sentence case. No 
"
dialog
"
or 
"
window
"
suffix.
Tabs
Left-to-right logical order. Leftmost = default. Hints = rightmost. No icons on top-level tabs in custom dialogs.
Content
Controls left-aligned, grouped by titled separators. Output → Input → Method → Settings order.
Command bar
40 px height. Supporting actions left-aligned. Apply / OK / Cancel right-aligned. 8 px spacing.
### Title bar rules

must
reflect the operation or purpose of the dialog — typically matching the label and icon on the button that opens it.
must
use sentence-style capitalization (e.g., 
"
Make horizon
"
, not 
"
Make Horizon
"
).
must
include the feature icon in the title bar. Exception: object settings dialogs use the common Settings icon on the button but the actual object icon in the title bar.
should
not include generic suffixes like 
"
window
"
or 
"
dialog box
"
.
should
not use resize grips.
The title bar Close button (×) must always be present and must have the same effect as the Cancel or Close button in the command bar — never the same as OK.
## Tab design

Tab groups are used to pack more information into a dialog while keeping its physical size manageable.
Rule
Detail
should
Minimum one tab
Even simple dialogs should have at least one top-level tab for consistency
must
Left-to-right order
Tabs progress logically left to right. Leftmost tab is the default. Hints tab (if present) is rightmost.
must
No icons on top-level tabs
Custom dialogs — top-level tabs must not use icons. (Settings dialogs are the exception — they must use icons.)
must
Clear tab labels
Action tabs use action-object naming (e.g., 
"
Make model
"
, 
"
Manage completions
"
). Other tabs use common names (Settings, Style, Hints). Avoid meaningless names like 
"
More
"
.
must
Sentence case
All tab labels use sentence-style capitalization
must
Highlight invalid tabs
Replace the tab title icon with the standard Warning icon (Warning_16) when the tab contains invalid or incomplete settings. Provide a tooltip explaining the problem.
should
Fit without scrolling
All tabs should fit the dialog width without a horizontal scrollbar. Shorten labels if needed; consider a small width increase before enabling scroll or multi-line tabs.
should
No inter-dependencies
Tabs in a tab group should be independently usable — settings on one tab should not silently invalidate another.
## Layout & controls

### Control organization

must
be orderly and intuitively organized. Sub-tabbing is encouraged for complex dialogs.
must
use sentence-style capitalization for all dialog labels.
must
hide controls that are irrelevant to the active window or process context.
must
disable (not hide) controls that are valid in context but temporarily unavailable.
should
lay out controls in top-down / left-right reading order.
should
group similar functionality together.
should
favor combo boxes over radio buttons for mutually exclusive choices.
should
favor list boxes or drop sites over combo boxes when the combo requires frequent or large updates.
should
avoid non-standard toggle buttons unless screen real estate is genuinely limited.
must
precede optional text fields with a checkbox or radio button. The text field 
must
be disabled when the toggle is OFF — never leave an optional input active with no way to toggle it.
When a combo box selection controls which slave controls are shown, slave controls 
should
be stacked on top of each other and toggled visible/invisible based on the selection — not shifted around the layout dynamically.
### Grouping by titled separators

Titled separators are the 
preferred
grouping element in Petrel dialogs. Group boxes are discouraged — they create visual clutter and can result in non-standard blue-colored titles.
must
have left-aligned labels.
must
not touch the label or the window border.
must
not be used to group a single setting or control.
must
not be nested.
should
only be used when they serve a specific purpose — framing a logically related group of controls.
💡
WinForms coding hint — titled separator
WinForms has no built-in label-separator control. Workaround: to the right of the label, add a second label with 
Text=null
, 
AutoSize=false
, 
Size=100×1
, background color 
#777777
. Anchor the line to the label on the left and the dialog edge on the right. In WPF, use a 
Border
element with 
BorderThickness="0,1,0,0"
.
### Alignments

must
left-align controls (aligned on the controls themselves, not on their label text).
must
indent controls that follow a separator.
must
use additional indentation to show dependencies (subordination).
must
right-align extended tooltip help icons at the dialog edge — keeps the UI tidy and prevents tooltip overlapping the controls it describes.
Text fields and combo boxes should also be right-aligned within their column.
### Control row format

The standard sequence for a settings row is:
[Icon]  [Check/Radio]  Label  [:]  [Drop arrow]  
Control
[Units]  [Service button]  [Extended tooltip icon→]
Where 
Control
= text field / combo / spinner; 
Service button
= Default, Reset, New, etc.; 
Extended tooltip icon
is always right-aligned.
The standard sequence for a separator row is:
[Check/Radio]  Label  ─────────────────  [Extended tooltip icon→]
## Command Bar

The command bar is the horizontal button strip at the bottom of every dialog. It provides commit and cancel actions and optionally houses supporting action buttons.
Command Bar — Anatomy and Spacing
Standard — Apply · OK · Cancel
Run ▶
Apply
OK
Cancel
Multiple-action — Close only on right
Make property
Make optimized run
Close
### Button specifications

Spec
Value (100% DPI)
Button height
23 px
Minimum width (label)
75 px — with 5–15 px white space on each side of icon/label
Minimum width (icon only)
23 px
Label alignment within button
Centered
Spacing between buttons
8 px
Distance from rightmost button to dialog edge
8 px
Command bar background color
#F0F0F0
(WPF: 
#E1E1E1
default; WinForms: 
#DDDDDD
)
Command bar height
40 px
### Button order and behavior

should
include the following from left to right (optional in brackets):
Button
Position
Behavior
Apply
Right-aligned, leftmost of commit group
must
Apply settings to the project without closing the dialog. Must not affect project objects until clicked. Show a working dialog or busy cursor if the process may be time-consuming. If settings are insufficient, open a message dialog explaining what is missing.
OK
Right-aligned, after Apply
Same as Apply, and in addition 
must
close the dialog and any subordinate dialogs after successfully applying settings. If settings are insufficient, keep the dialog open.
[ OK for all ]
Optional, after OK
Same as OK but skips confirmation dialogs associated with the action.
[ Reset ]
Optional — do not combine with Default
must
Restore the dialog to the settings last applied. If nothing has been applied yet, restore to initial settings.
[ Default ]
Optional — do not combine with Reset
must
Restore the dialog to the application's factory-default settings.
Cancel
Rightmost
must
Close the dialog and all subordinate dialogs without applying anything. Use when the user can discard changes. Modal dialogs must have Cancel (or equivalent label).
Close
Rightmost (replaces Cancel)
Use instead of Cancel when there is nothing to cancel — either because settings are applied immediately, or the dialog has no editable state. Behavior is the same as Cancel.
[ Help ]
Leftmost of command bar, or after Cancel
Opens the relevant section of online documentation. Access with F1.
⚠
Standard Petrel button icons
Apply and OK must use the green checkmark pixmap (
IDB_BUTTON_OK
). Cancel and Close must use the red X pixmap (
IDB_BUTTON_CANCEL
). This is required for consistency and quick recognizability. Icon names in 
Slb.Ocean.Petrel.Resources.dll
.
💡
Disabling affirmative buttons
Apply and OK may be disabled when there is nothing to apply (e.g., no settings have changed since the last apply) or when there is a validation error. This gives users a clear signal that action is not yet possible, without requiring an error message popup. Re-enable the button as soon as the blocking condition is resolved — do not wait for the user to click Apply to surface the validation error.
### Default button

should
define a default button (shown with a surrounding frame) in simple, single-purpose dialogs with good defaults. Apply or OK is typically the default button. Pressing 
Enter
from anywhere in the dialog activates it.
should
not use a default button in complex or multi-purpose dialogs — the goal is to force conscious choices through explicit actions.
## Size & Placement

### Size

must
have a minimum size — it must not be possible to resize the dialog so small that controls are hidden.
must
default small enough to fit on a 1280×1024 screen at 125% DPI without overlapping a single-line task bar with large icons.
100% DPI
125% DPI
Max default width
1024 px
1280 px
Max default height
780 px
975 px
### Placement

should
open centered on top of the owner window the first time. On subsequent openings, consider restoring the last used position.
If the dialog is contextual (triggered by clicking a specific object), display it near that object — offset down and to the right so the object is not covered.
On re-display, restore the same position, size, and state (including which monitor) the user last left it on.
### Resizing behavior

must
be resizable when the dialog contains container controls (lists, text controls, graphical workspaces).
must
not resize simple controls (labels, buttons) when the dialog is resized.
should
resize container controls proportionally when the dialog is resized. When two container controls face each other, one may have a fixed size — this preserves relative emphasis between the two panels.
One-line text controls 
must
have a fixed height. They may have a fixed width if the layout requires it.
Separator lines and frames 
must
only resize if the controls inside them are resizing — do not stretch a separator independently.
must
not enable minimize / maximize. Exception: non-modal dialogs where a large table is the main content may include minimize / maximize — in this case, the dialog icon must appear in the Windows taskbar.
Command bars must not be resized — they remain at a fixed position next to the dialog border.
## Open / Re-open Behavior

must
bring the dialog to the front when the button that opened it is clicked, even if it is already open and partially hidden.
must
open with the settings last applied by this dialog (or by any other dialog that may update the same settings).
must
not change any dialog settings if re-opened from an already-open state — only a Reset or explicit navigation should change state.
## Keyboard Interaction

Key
Action
Enter
Activates the default button (if defined), or the button currently holding input focus
Esc
Closes the active dialog — always. Even if Cancel has been renamed Close. See exception for Question dialogs below.
Tab
Move focus to the next interactive control in tab order
Shift+Tab
Move focus to the previous interactive control
Arrow Left / Right
Shift focus between buttons in a question dialog
Ctrl+Tab
/ 
Ctrl+Shift+Tab
Cycle between tabs in a tab group
F1
Open the Help section for this dialog
Alt+letter
Access key — activates the labeled control or button. See Access Keys section below.
### Initial focus and tab order

Assign initial input focus to the control the user is most likely to interact with first — usually (but not always) the first interactive control.
Tab order must flow logically: generally left to right, top to bottom.
Put the most commonly used controls earlier in the tab order.
Put Help links at the bottom, after commit buttons, in tab order.
In WPF, set 
IsDefault="True"
on the primary button and 
IsCancel="True"
on the Cancel button.
### Access keys (mnemonics)

Assign unique access keys (
Alt+letter
) to all interactive controls or their labels whenever possible.
Do 
not
assign access keys to: OK, Cancel, or Close (use Enter/Esc instead); generic Help buttons (F1); tab names (Ctrl+Tab); browse buttons labeled "…".
Assign commit button access keys first — reserve standard assignments (Y for Yes, N for No).
Use early-appearing characters: prefer the first letter, or a wide, distinctive character (W, M, uppercase letters).
Avoid characters with descenders (g, j, p, q, y) or single-pixel width (i, l) as the underline is hard to see.
💡
WPF — IsDefault and IsCancel
Set 
IsDefault="True"
on the primary button so 
Enter
activates it from anywhere in the dialog. Set 
IsCancel="True"
on the Cancel button so 
Esc
activates it. Only one button of each type is allowed per window.
## Message Dialogs

Message dialogs present feedback, errors, warnings, or decision prompts. They 
must
be used sparingly — popup dialogs interrupt workflow. Before adding a message popup, work through this decision:
Situation
Preferred alternative to a popup
Task completed, result is visible in the viewport
No popup needed — the result speaks for itself
Non-critical status during a long process
Message log pane (
PetrelLogger.InfoOutputWindow()
)
Detailed error trace or call stack
Petrel log file (surfaced via a "Details…" button if needed)
Invalid input that can be caught early
Inline validation highlight + disabled Apply/OK button
Progress feedback for a task 
>
8 seconds
Petrel status bar progress bar or Task Manager
Attention-grabbing non-blocking notification
Silent (toast) popup — auto-dismisses, no user action required
A message popup is appropriate when: the situation is an error requiring correction before work can continue; a decision is needed that cannot be deferred; or the information is critical enough to interrupt workflow.
⚠
Use Ocean API whenever possible
Use 
Slb.Ocean.Petrel.PetrelLogger.ErrorBox()
, 
.WarnBox()
, and 
.InfoBox()
for all message popups. These ensure consistent Petrel styling and icon, auto-size to content, handle newlines, add scrollbars for long messages, allow the user to copy text, and provide standard keyboard shortcuts (Enter, Esc, Alt+O).
### How to write message text

must
be brief, concise, and free of technical jargon and system-oriented terms.
should
use complete sentences with ending punctuation.
should
avoid exclamation marks.
should
avoid contractions — write "do not" instead of "don't", "cannot" instead of "can't".
should
suggest a constructive solution when reporting an error or problem.
Terminology and icons must be consistent across all Petrel dialogs.
A "Details…" button may be included to expose additional information (call stack, error code) without cluttering the main message.
### Error popup

Use when a serious or critical problem has occurred. Intervention or correction is required before work can continue.
Error popup — 
PetrelLogger.ErrorBox()
Petrel

✕
Import failed.
The file "survey_2024.las" could not be parsed. Verify that the file format is LAS 2.0 and that all mandatory header fields are present.
OK
Details…
### Warning popup

Use for non-critical problems — something is not possible to do, or has not been carried out as expected.
Warning popup — 
PetrelLogger.WarnBox()
Petrel

⚠
No output name specified.
The "Create new" field is empty. Enter a name for the output horizon before running.
OK
### Info popup

Use when something has happened that the user should know about — for example, the results of an action that has been completed.
Info popup — 
PetrelLogger.InfoBox()
Petrel

i
Horizon created successfully.
"North_Cretaceous_Top" has been added to the project tree under Horizons.
OK
### Question popup

Use when user input is required before proceeding — for example, an action with potentially destructive or irreversible consequences. 
should
prefer custom question dialogs over standard Yes/No for a better user experience.
Question popup — Custom buttons, explicit labels
Petrel

?
Save changes to project?
You have unsaved changes. Do you want to save before closing?
Save
Don't save
Cancel
Petrel

?
Delete "North Sea 3D Stack"?
This will permanently delete the seismic cube and all dependent objects. This action cannot be undone.
Dependent objects: 3 horizons, 2 velocity models
Delete permanently
Cancel
#### Question popup rules

should
phrase the message as a question.
Button labels 
must
correspond to the choices available — never use bare "Yes" / "No" when specific labels are possible.
Button order: more positive / recommended actions first (leftmost); more negative / higher-risk actions last; Cancel always rightmost if present.
A default button may be defined (typically the leftmost / safest action).
If the dialog close (×) button is disabled — to force an explicit choice — 
must
also disable the Esc key shortcut for that dialog. Question popups with a disabled close button 
should
not have a default button (forces a conscious decision).
A note in italics below a separator may be added for additional context (e.g., listing dependent objects before a destructive action).
Access keys (
Alt+letter
) 
should
be defined for each button in custom question dialogs.
#### Question popup keyboard shortcuts

Key
Action
Enter
Invokes the default button (if defined), otherwise the button currently holding focus
Tab
/ 
Shift+Tab
or 
←
/ 
→
Shifts input focus to the next or previous button
Alt+letter
Invokes the button with that access key (if defined)
Esc
Closes the dialog — unless the close button (×) has been disabled
⚠
Always test the −1 return value
The close button (×) returns 
−1
from the question API. This case is easy to overlook. When a Cancel button is present, 
−1
must be treated as Cancel. Return values: 
0
= leftmost button, 
1
= second from left, 
2…n
= subsequent buttons, 
−1
= × button (if enabled).
### Silent (toast) popup

Use when the user needs to be informed in a non-disruptive but attention-grabbing way — for example, an ongoing background process or a completed task that doesn't require a decision.
Place in the outskirts of the work area (top or bottom, left or right).
An action button (e.g., "View details" or "Dismiss") may be included alongside the message.
Disappears automatically after a set duration (e.g., 5 seconds), when a monitored process finishes, or when the user explicitly closes it (×).
May fade away over 1–2 seconds rather than disappearing abruptly.
### Progress popup

Use for potentially time-consuming tasks where end-user attention to progress is particularly important.
Progress popup — Petrel DELFI branding style
Running horizon tracking…

↻
Tracking horizon: North_Cretaceous_Top
Processing inline 1250 of 2040…
62%
Time remaining: 1 min, 22 secs
Stop
#### Progress popup and progress bar rules

must
always have a label describing what the progress represents. Text must be displayed outside the progress bar itself. For very long-running tasks, also include a secondary line describing the current operation within the task (e.g., "Processing inline 1250 of 2040…").
must
never let the screen blank out — always show what the system is doing.
must
poll the Stop button regularly during time-consuming processes.
must
not be interactive — users cannot click on or interact with the bar itself.
Progress should scroll smoothly, not jump in large increments.
should
show a progress bar when processing may take longer than 8 seconds. Show a busy cursor for 5–8 second processes.
The dialog 
should
automatically disappear when the process completes (if results are clearly apparent to users).
Label the halt button 
Cancel
if canceling returns the environment to its previous state; label it 
Stop
if the partially completed operation remains intact.
For very long operations (over 30 seconds), use a modeless progress dialog with a Minimize button so the user can continue working.
should
not use a progress popup when the same feedback can be provided effectively via: busy cursor (synchronous, short), Petrel status bar progress bar (synchronous), Petrel Task Manager (asynchronous), or Message Log pane.
### Message log pane and Petrel log file

should
write run-time messages that do not need to interrupt workflow to the 
Message log pane
. Messages must be brief and well-structured.
should
write essential error details and support information (stack traces, database error codes) to the 
Petrel log file
at 
C:\Users\
<
user
>
\AppData\Local\Schlumberger\Petrel\
<
year
>
\OceanPetrel.log
.
Log file messages must be compact and well-structured for overview and readability.
## Settings Dialogs

Settings dialogs are the focal point for viewing and controlling attributes, operations, and features related to a specific project item (tree node, data object, or process object).
### Key rules

must
be possible to open a settings dialog on every project item.
must
not allow more than one settings dialog open per project item at a time. A second activation closes the current dialog for that item.
must
always be modeless. Any number of settings dialogs (for different project items) may be open simultaneously.
must
disable controls not relevant to the current window or process context (e.g., 2D style settings when a 3D window is active).
must
be tab-based (inherits from 
UiSettingsDialog
).
must
use icons next to tab labels (unlike custom dialogs which must not).
### Standard tab structure

Tabs appear left to right in this order (optional tabs in brackets):
Tab (in order)
Required?
Contents
[Style]
Optional (max 1)
Display style settings: line type/thickness/color, seismic wiggle style, volume walls, etc. Annotation settings must not be here — use a separate Annotation tab.
Info
Required
Name (editable), Color, Type + object icon, Domain (if applicable), Template (if applicable). A tabbed area at the bottom with at minimum a Comments tab. If the object can be modified, also a History tab (table of transactions).
[Primary action]
Optional
Settings for the object's primary action — e.g., Tracking for horizon objects, Cropping for seismic cubes.
[Statistics]
Optional
Statistical information: x/y/z min-max, attribute ranges, etc.
[Colors]
Optional
Editor for the object's color template.
[Other settings]
Optional
Additional attributes not covered by the above tabs. Give a specific name — not "Other settings".
[Operations]
Optional
Settings for object operations, plus one or more action buttons to execute operations.
[Other operations]
Optional
Additional operations and advanced features.
### System, Project, and Window settings

Dialog type
Contents
Persistence
System Settings
No project-dependent settings. Tabs: frequently used global tabs first, then module-dependent tabs, then secondary global tabs. Module-dependent tabs are always visible but disabled when the license is inactive.
User/system level (per user PC)
Project Settings
Only project-dependent settings.
Saved with the project file
Window Settings
One per window type; accessible from the Windows pane.
Saved with the project file
## Calculators

Calculator-type dialogs are a specialized sub-type of custom dialog used to compute or derive values for project objects (e.g., well trajectories, fluid contacts, attribute volumes). They have two additional rules on top of the standard Dialog Design guidelines.
Rule
Detail
must
Follow the standard Petrel calculator pattern
All calculator-type dialogs must be visually and behaviorally consistent with the established Petrel calculator pattern. This includes layout, output naming, and command bar conventions. Do not introduce a bespoke calculator UI.
must
Be accessible from the context menu
It must be possible to open a calculator for a project tree item via that item's right-click context menu. Additionally, a button to open the calculator may be placed on the object's Settings dialog 
>
Info tab (example: the well object).
## Inspector Extensions

An Inspector extension is a custom addition to the Petrel Inspector panel for a particular domain object. It is distinct from a standard dialog — its appearance is designed to complement highly visual, graphical workflows and provide an immersive in-window experience without interrupting the user's viewport focus.
💡
Inspector vs. Mini toolbar
Inspector
— a static panel containing object-specific property read-outs for informative purposes or quick setting adjustments. The Petrel framework provides a generic part; extensions add domain-object-specific controls.
Mini toolbar
— a floating transient toolbar that appears above the right-mouse-button (MB3) menu at the cursor location, providing object-specific tools. Both controls are "close to the action" of the user's viewpoint and intended to accelerate visual workflows. Refer to the Conceptual Model 
>
Tool Placement section to determine which tools belong in which control.
### The 5 Basic Criteria

An Inspector extension 
must
only be implemented when 
all five
of the following criteria are true:
The workflow has highly visual content and is highly graphical-interactive.
Users operate graphical windows in focused interactive sessions.
A standard dialog would distract users from the graphical view.
Users make only quick adjustments via the Inspector — no complex configuration.
Instant update/refresh can be supported (maximum 1–2 seconds per scene update).
If any criterion is false, use a standard custom dialog instead.
### Content rules

must
include only the minimal and essential set of controls needed for the highly visual workflow.
must
include only simple adjustment and tuning controls that do not require significant typing. Encouraged: sliders, spin boxes, toggle buttons, radio buttons. Discouraged: text fields, individual plus/minus buttons.
When new control types not previously documented in other Inspector extensions are introduced, they 
must
go through a usability review and 
should
be shared (as code) and documented in this guide.
Old settings that have been replaced by Inspector controls 
should
be removed from the original dialog — avoid duplicating the same control in two places.
Common controls (e.g., the color selector) 
should
be consistently implemented across all Inspector extensions.
Object players and manipulators may be included. If a player is included, it 
must
contain a slider and all the tools present in the original player.
### Behavior rules

must
honor auto-apply — all Inspector controls apply their changes immediately without requiring an explicit Apply or OK action.
must
update the display instantly (within a few seconds). If a control cannot update within this threshold, reconsider whether it belongs in the Inspector. If kept, a busy cursor 
must
be shown while the update is processing.
Inspector launch tools for specific domain objects may be included in the ribbon domain tab and the object context menu or mini toolbar. The corresponding Inspector icon 
must
be used.
### Appearance rules

must
be small and compact — Inspector extensions are panels, not full dialogs.
must
not override the default Petrel Inspector styling.
must
follow all Dialog Design layout rules wherever applicable: controls nicely laid out and aligned; controls indented to left-align with the tab label; height and width of controls are static unless specified in the Inspector settings; resize is properly supported (container controls resize, simple controls do not).
must
use standard Petrel tooltip and extended tooltip appearance — including background color. See Help Features for details.
### Standard layout order

Inspector extension controls 
must
follow this sequence (all sections are optional depending on the domain object):
Order
Section
Notes
1
Additional info and general
Note: the basic info section is provided by the Petrel framework at the top of the Inspector — extensions should consider integrating into this part rather than duplicating.
2
Style
Display style controls relevant to the object.
3
Primary actions
Controls for the primary interactive operation of the domain object.
## Gaps vs. Microsoft Win32 UX Guidelines

The Petrel Confluence wiki was cross-referenced against the official 
Microsoft Windows Win32 UX Guide — Dialog Boxes
. The following practices are in the Microsoft guide but absent from (or differ from) the Petrel wiki. Teams should apply these as supplementary best practices.
🔍
Supplementary guidance from Microsoft Win32 UX Guide
"Don't show this again" option.
When a dialog contains information the user is likely to find repetitive, provide a "Don't show this again" checkbox at the bottom of the dialog. This pattern is absent from the Petrel wiki but is a widely-adopted Windows standard. Recommended for low-stakes informational dialogs (not for destructive confirmation dialogs).
Never scroll a dialog.
If content requires scrolling to be fully visible during normal use, redesign the dialog — use progressive disclosure or tabs instead. The Petrel wiki does not explicitly state this.
No menu bar or status bar in dialogs.
Access to commands should be provided directly on the dialog itself or via context menus. Exceptions: dialogs used as primary windows (e.g., utilities).
Multiple dialog instances.
Do not display more than one owned choice dialog at a time from an owner choice dialog — the commit buttons become ambiguous. For a sequence of related dialogs, use a multi-page dialog instead of separate dialogs. Multi-page dialogs must not use Next/Back buttons and must not have more than three pages (they are not wizards).
Progress: 5-second threshold.
Microsoft recommends showing a progress dialog for operations taking longer than 5 seconds. The Petrel wiki recommends 8 seconds for a progress bar and 5–8 seconds for a busy cursor. Teams should align on a consistent threshold — consider using 5 seconds to match user expectations in modern Windows.
Always on top — avoid it.
Do not use the "Always on Top" window attribute except when a dialog implements an essentially modal operation that needs brief suspension (e.g., spell-check). Not mentioned in the Petrel wiki.
Taskbar flash for attention.
If a dialog requires immediate attention and the program is not active, flash the taskbar button exactly three times and leave it highlighted. Do not restore or activate the window programmatically, and do not play sound effects.
Body icons in message dialogs.
Use the warning icon only when there is potential loss of data or system access (not for informational questions). The Petrel wiki uses icon categories (Error, Warning, Info, Question) but does not specify when to suppress the icon or how to use it contextually within question dialogs.
## Do and Don't

Do
Match the dialog title to the ribbon button label exactly — use the same icon and the same words. "Make horizon" in the ribbon means "Make horizon" in the dialog title bar.
Don't
Don't add "dialog box", "window", or "tool" to dialog titles. "Make horizon dialog box" adds no information and breaks sentence case. Every participant in usability testing expects the title to match the button — this is a trust signal.
Do
Use explicit, action-specific labels on question dialog buttons: "Save", "Don't save", "Cancel" — not "Yes", "No", "Cancel". Screen readers announce button labels; "Yes" is meaningless without context.
Don't
Don't use bare "Yes" / "No" as the only differentiators in destructive confirmation dialogs. A user mid-flow who dismisses the popup without reading may click the wrong button. The cost of a wrong click on a destructive action is severe.
Do
Group controls with titled separators (horizontal line with label). Left-align the label, indent the controls beneath it, and never nest separators. This is the established Petrel grouping pattern.
Don't
Don't use group boxes (border frames with a title). They add extra horizontal and vertical lines that create visual clutter, and the title often renders in non-standard blue, making the UI look inconsistent across Petrel.
Do
Save and restore dialog geometry, state, and settings between sessions. Users invest time placing and sizing dialogs. Re-opening a dialog reset to defaults at position (0, 0) is a significant workflow interruption.
Don't
Don't reset dialog state on every open. The Petrel Serialization Policy requires geometry, state, and last-applied settings to persist. An un-persisted dialog is a regression against the policy.
Do
Use Ocean API message popups (
PetrelLogger.ErrorBox()
, 
.WarnBox()
, 
.InfoBox()
) for all message dialogs. They enforce consistent Petrel icon styling and keyboard shortcuts automatically.
Don't
Don't use raw Windows 
MessageBox()
or Infragistics dialogs when Ocean equivalents exist. They appear with the wrong title bar icon and bypass the consistent Petrel look and feel.
Do
Prefer modeless dialogs. Use them for all feature dialogs that don't require an exclusive decision. This keeps the user in control and matches how geoscientists actually work — iterating between the dialog and the 3D view.
Don't
Don't make feature dialogs modal unless they cover File Import/Export, or critical/destructive confirmation scenarios. Modal dialogs block the viewport, preventing users from checking reference data or adjusting their input in context.
Do
Use a combo box when users must choose one option from a list. A combo is compact, scannable, and keyboard-friendly. Reserve radio buttons for three options or fewer where all choices should be visible at once without clicking.
Don't
Don't use a column of radio buttons when a combo box would work. Five or more radio buttons consume significant vertical space, push other controls off-screen, and make the dialog feel physically larger than needed.
Do
Disable controls that are not applicable in the current context. A disabled control communicates "this exists but is not available right now" — the user understands why the option is greyed out and what they would need to change to enable it.
Don't
Don't hide controls that are temporarily unavailable. Hiding a control silently removes capability without explanation, leaving the user confused about whether the feature exists at all. Only hide controls that are irrelevant across all contexts.
Do
Disable Apply and OK when there is a validation error or nothing to apply. Show a tooltip on the disabled button explaining what is blocking — this prevents the user from having to click Apply to discover the problem.
Don't
Don't let Apply and OK remain enabled and then show a validation error message popup when clicked. This is a two-step interruption: the user tries to proceed, is blocked, reads an error, and has to fix the issue before trying again. Pre-emptive disabling with a tooltip is far less disruptive.
## Accessibility

Every interactive control must have a visible focus indicator. Do not suppress the WPF focus rectangle without providing a custom focus ring.
Assign 
AutomationProperties.Name
to all icon-only buttons and controls without a visible label.
Dialog title must be exposed via 
AutomationProperties.Name
on the window element for screen readers to announce on open.
Set 
WindowStartupLocation="CenterOwner"
in WPF to ensure the dialog appears near the owner window, not at an arbitrary screen position.
All error and validation messages must be programmatically associated with the control they describe (
AutomationProperties.HelpText
or 
LiveSetting
for dynamic updates).
Tab order in dialog controls must follow the logical reading order — WPF TabIndex should be explicitly set for complex layouts.
Do not rely on color alone to convey invalid state — pair it with an icon (e.g., the Warning_16 icon on the affected tab) and a descriptive tooltip.
High Contrast support: use system color brushes (
{DynamicResource SystemColors.*}
), not hardcoded hex values, for all dialog chrome, text, and borders.
Associate labels with their controls using 
AutomationProperties.LabeledBy
. When a 
TextBlock
acts as a visual label for a control, the screen reader will not connect them automatically — you must set this explicitly: 
AutomationProperties.LabeledBy="{Binding ElementName=myLabel}"
.
Use 
KeyboardNavigation.TabNavigation
to control tab behavior within composite controls (e.g., 
KeyboardNavigation.TabNavigation="Cycle"
within a radio group so Tab does not escape the group). Set 
TabIndex
explicitly on complex layouts — WPF's default visual-tree order may not match the intended logical order.
When a dialog has settings that can produce a validation error, use 
AutomationProperties.LiveSetting="Polite"
on the error text so screen readers announce it without stealing focus from the current control.
## XAML Implementation

Simple dialog (WPF)
Settings dialog
Message dialog (C#)
Question dialog (C#)
Remove min/max
XAML — UiSimpleDialog (WPF)
Copy
<
!-- Inherits UiSimpleDialog. Modeless with Apply/OK/Cancel. --
>
<
Window
x:Class
=
"MyPlugin.MakeHorizonDialog"
xmlns:petrel
=
"clr-namespace:Slb.Ocean.Petrel.UI;assembly=Slb.Ocean.Petrel"
Title
=
"Make horizon"
WindowStartupLocation
=
"CenterOwner"
ResizeMode
=
"CanResize"
MinWidth
=
"360"
MinHeight
=
"280"
AutomationProperties.Name
=
"Make horizon"
>
<
DockPanel
>
<
!-- Tab control — content area --
>
<
TabControl
DockPanel.Dock
=
"Top"
>
<
TabItem
Header
=
"Make horizon"
>
<
!-- Content --
>
<
/TabItem
>
<
TabItem
Header
=
"Settings"
>
<
/TabItem
>
<
TabItem
Header
=
"Hints"
>
<
/TabItem
>
<
/TabControl
>
<
!-- Command bar — 40px, light grey --
>
<
Grid
DockPanel.Dock
=
"Bottom"
Height
=
"40"
Background
=
"#F0F0F0"
>
<
Grid.ColumnDefinitions
>
<
ColumnDefinition
Width
=
"*"
/
>
<
ColumnDefinition
Width
=
"Auto"
/
>
<
/Grid.ColumnDefinitions
>
<
!-- Supporting actions (left) --
>
<
Button
Grid.Column
=
"0"
Content
=
"Run"
HorizontalAlignment
=
"Left"
Margin
=
"8,0,0,0"
Height
=
"23"
MinWidth
=
"75"
Command
=
"{Binding RunCommand}"
/
>
<
!-- Commit buttons (right) --
>
<
StackPanel
Grid.Column
=
"1"
Orientation
=
"Horizontal"
Margin
=
"0,0,8,0"
VerticalAlignment
=
"Center"
>
<
Button
Content
=
"Apply"
IsDefault
=
"True"
Height
=
"23"
MinWidth
=
"75"
Margin
=
"0,0,8,0"
Command
=
"{Binding ApplyCommand}"
/
>
<
Button
Content
=
"OK"
Height
=
"23"
MinWidth
=
"75"
Margin
=
"0,0,8,0"
Command
=
"{Binding OkCommand}"
/
>
<
Button
Content
=
"Cancel"
IsCancel
=
"True"
Height
=
"23"
MinWidth
=
"75"
Command
=
"{Binding CancelCommand}"
/
>
<
/StackPanel
>
<
/Grid
>
<
/DockPanel
>
<
/Window
>
XAML — UiSettingsDialog pattern (WPF)
Copy
<
!-- Settings dialogs inherit UiSettingsDialog.
Always modeless. Tabs must have icons.
Close (not Cancel) on command bar. --
>
<
petrel:UiSettingsDialog
x:Class
=
"MyPlugin.HorizonSettingsDialog"
Title
=
"Horizon settings"
WindowStartupLocation
=
"CenterOwner"
ResizeMode
=
"CanResize"
>
<
TabControl
>
<
!-- Info tab is always required --
>
<
TabItem
>
<
TabItem.Header
>
<
StackPanel
Orientation
=
"Horizontal"
Gap
=
"4"
>
<
Image
Source
=
"{StaticResource InfoIcon16}"
Width
=
"16"
Height
=
"16"
/
>
<
TextBlock
Text
=
"Info"
/
>
<
/StackPanel
>
<
/TabItem.Header
>
<
!-- Name, Color, Type, Domain, Template fields --
>
<
/TabItem
>
<
!-- Add Style, Statistics, Colors tabs as needed --
>
<
/TabControl
>
<
/petrel:UiSettingsDialog
>
C# — Ocean message dialogs
Copy
using
Slb.Ocean.Petrel;
// Error popup — serious/critical problem, intervention required
PetrelLogger.ErrorBox(
"Import failed. The file could not be parsed. "
+
"Verify that the format is LAS 2.0 and all "
+
"mandatory header fields are present."
);
// Warning popup — non-critical problem
PetrelLogger.WarnBox(
"No output name specified. "
+
"Enter a name for the output horizon before running."
);
// Info popup — information about a completed action
PetrelLogger.InfoBox(
"Horizon created successfully. "
+
"\"North_Cretaceous_Top\" has been added to the project tree."
);
// For non-interrupting messages — use message log pane
PetrelLogger.InfoOutputWindow(
"Tracking inline 1250 of 2040 — 62% complete."
);
C++ — Custom question dialog (Foundation.Primitives.Utility)
Copy
// Custom question dialog with 3 explicit-label buttons.
// Note: ms:: API is native C++/managed C++ only — not C#.
#include
"Petrel/src/Foundation/Primitives/Utility/Ms.h"
CString message(
"Delete \"North Sea 3D Stack\"?\n\n"
"This will permanently delete the seismic cube and all dependent "
"objects. This action cannot be undone."
);
StringVector buttonCaptions;
StringVector buttonBitmapIds;
buttonCaptions.push_back(
"
&
Delete permanently"
);
buttonBitmapIds.push_back(
"IDB_BUTTON_CANCEL"
);  
// red X = destructive
buttonCaptions.push_back(
"
&
Cancel"
);
buttonBitmapIds.push_back(
"IDB_BUTTON_CANCEL"
);
int
defaultButtonIndex = 
1
;  
// Cancel is safer default
bool
disableClose = 
false
;       
// allow Esc = Cancel
int
answer = ms::question(message, buttonCaptions,
buttonBitmapIds, defaultButtonIndex,
disableClose);
// 0 = Delete permanently, 1 = Cancel, -1 = X button
if
(answer == 
0
) {
performDeletion();
}
// Always test for -1 — easy to overlook, but required.
C# — Hide minimize/maximize buttons (WPF)
Copy
using
System.Runtime.InteropServices;
using
System.Windows.Interop;
public partial class
MyDialog : Window
{
private const int
GWL_STYLE       = -16;
private const int
WS_MAXIMIZEBOX  = 0x10000;
private const int
WS_MINIMIZEBOX  = 0x20000;
[DllImport(
"user32.dll"
)]
private static extern int
GetWindowLong(IntPtr hWnd, 
int
nIndex);
[DllImport(
"user32.dll"
)]
private static extern
IntPtr SetWindowLong(IntPtr hWnd, 
int
nIndex, 
int
dwNewLong);
// Call AFTER SourceInitialized — not in constructor
public static void
HideMinimizeMaximize(Window window)
{
var
hwnd = 
new
WindowInteropHelper(window).Handle;
int
style = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE,
(style 
&
~(WS_MAXIMIZEBOX | WS_MINIMIZEBOX)));
}
public
MyDialog()
{
InitializeComponent();
// Important: call after source initialized
this
.SourceInitialized += (s, e) =
>
HideMinimizeMaximize(
this
);
}
}
(function () {
  document.querySelectorAll('.xaml-tabs').forEach(function (tabs) {
    var btns = tabs.querySelectorAll('.tab-btn');
    var panels = tabs.querySelectorAll('.tab-panel');
    btns.forEach(function (btn, i) {
      btn.addEventListener('click', function () {
        btns.forEach(function (b) {
          b.classList.remove('active');
          b.setAttribute('aria-selected', 'false');
        });
        panels.forEach(function (p) { p.classList.remove('active'); });
        btn.classList.add('active');
        btn.setAttribute('aria-selected', 'true');
        if (panels[i]) panels[i].classList.add('active');
      });
    });
  });

  document.querySelectorAll('.xaml-tabs .code-copy').forEach(function (btn) {
    btn.addEventListener('click', function () {
      var pre = btn.closest('.code-block') && btn.closest('.code-block').querySelector('pre');
      if (!pre || !navigator.clipboard) return;
      var text = Array.from(pre.querySelectorAll('.code-line')).map(function (line) {
        return line.textContent.replace(/\u00a0/g, ' ').replace(/\s+$/,'');
      }).join('\n').trim();
      navigator.clipboard.writeText(text).then(function () {
        btn.textContent = 'Copied!';
        btn.classList.add('copied');
        window.setTimeout(function () {
          btn.textContent = 'Copy';
          btn.classList.remove('copied');
        }, 2000);
      });
    });
  });
})();

### Related pages

Buttons
— Dialog action button specifications
Form controls
— Inputs within dialogs
Keyboard and focus
— Focus management requirements
Responsive design
— Dialog sizing and resizing
Microsoft Win32 Dialog Guidelines