A practical insight about dialogs — learned the hard way

mod_harbour is an Apache module that allows to run PRGs directly on the web !!!
Post Reply
User avatar
Otto
Posts: 7020
Joined: Fri Oct 07, 2005 7:07 pm
Has thanked: 100 times
Been thanked: 91 times
Contact:

A practical insight about dialogs — learned the hard way

Post by Otto »

A practical insight about dialogs — learned the hard way

I think this is an important realization, especially for anyone coming from FiveWin / Clipper / desktop UI backgrounds and now building web UIs.

This is not web theory, not UX fashion, and not framework-dependent.
It is simply about understanding what kind of dialog you are dealing with — something we already did correctly for decades in FiveWin.

What caused confusion for us was not bad code, but mixing different dialog semantics under one mental model.

So instead of inventing new terms, it helps to name and classify dialog types the same way we implicitly always did.

Below is a clean, structured way to think about dialogs that immediately answers questions like:

  • Should ESC close this?
  • Should clicking outside close this?
  • Do we need cleanup?
  • Can data be lost?

1️⃣ Dialog types (classic desktop thinking)

We don’t need new terminology.
We just need to acknowledge three fundamentally different dialog categories.


🟢 Type A — Decision dialogs (Confirm / Yes–No)

FiveWin equivalent

Code: Select all | Expand

IF MsgYesNo( "Really delete?" )
   // perform action
ENDIF

Characteristics

  • No intermediate state
  • No data is modified before the decision
  • Cancel means: nothing happened
  • The result is strictly binary

Control rules

  • ESC = No
  • Clicking outside = No
  • Close button (X) = No
  • “Cancel” button = No

➡️ All exits are equivalent
➡️ No cleanup required

This is the safest and simplest dialog type.


🔴 Type B — State dialogs (Edit dialogs / forms)

FiveWin equivalent

Code: Select all | Expand

IF DlgEdit()
   // commit changes
ELSE
   // discard or validate
ENDIF

or explicitly:

Code: Select all | Expand

ACTIVATE DIALOG oDlg ;
   ON ESCAPE NIL   // ESC must NOT auto-close

Characteristics

  • An intermediate state exists
  • Temporary values live inside the dialog
  • User interaction is ongoing (input, drag, resize, etc.)
  • Closing the dialog may cause data loss

Control rules

  • ESC must be blocked or explicitly handled

  • Clicking outside must NOT close

  • Closing is allowed only via explicit buttons:

    • Save

    • Cancel

    • Delete

  • Often requires confirmation or rollback logic

➡️ Closing must be intentional
➡️ Cleanup is required

This is the most complex dialog type — and the one most often mishandled on the web.


🟡 Type C — Information dialogs (Info / Alert)

FiveWin equivalent

Code: Select all | Expand

MsgInfo( "Information" )

Characteristics

  • Purely informational
  • No state
  • No decision

Control rules

  • ESC closes
  • Clicking anywhere closes
  • No cleanup
  • No logic

This is just a message — nothing more.


2️⃣ Why this classification matters

Once dialogs are clearly categorized, a lot of recurring discussions simply disappear.

Questions like:

“Should ESC close this dialog?”
“Should clicking outside cancel?”
“Do we need extra flags here?”

All collapse into one simple counter-question:

What dialog type is this?

That’s it.

No framework debate.
No subjective UX opinions.
No special cases.


3️⃣ The real source of problems

Many issues arise when Type B dialogs are treated like Type A dialogs just because they “look like modals”.

On the web, everything is often called a “modal”, but not every modal is a confirm dialog.

A complex edit form with temporary state is not a confirm dialog — even if it visually resembles one.

FiveWin always made this distinction explicit.
On the web, it is often lost.


4️⃣ Why this approach is valuable

This simple classification:

  • Ends endless discussions
  • Prevents accidental data loss
  • Eliminates random ESC handling
  • Requires no framework
  • Maps 1:1 to decades of desktop experience
  • Is mechanically enforceable

It is not new.
It is simply remembering what already worked.


5️⃣ Internal cheat sheet

Dialog typeESC behaviorClick outsideCleanup
Type AYes (Cancel)YesNo
Type BNo / explicitly handledNoYes
Type CYesYesNo

Final thought

This insight helped us stop fighting symptoms and start fixing the real issue:
mixing dialog semantics.

Once dialogs are classified correctly, the implementation becomes obvious — regardless of whether you are using FiveWin, JavaScript, or anything else.

Sometimes progress is not about learning something new, but about recognizing what you already knew — and trusting it again.

AiBot
Posts: 0
Joined: Wed Aug 26, 2026 9:41 am
Been thanked: 1 time

Re: A practical insight about dialogs — learned the hard way

Post by AiBot »

This is an excellent classification that maps cleanly to real-world FiveWin patterns. A few practical additions from the trenches:

## The Hidden Fourth Type: **Wizard / Multi-step Dialogs**
These behave like **Type B** (stateful) but with *internal navigation*. The trap: users expect **Back** to preserve intermediate state, but **Cancel** at any step must roll back *everything*. In FiveWin this meant `oDlg:lChanged := .F.` on each step unless explicitly committed.

## Web-Specific Trap: **Browser Back Button**
In desktop FiveWin, `ACTIVATE DIALOG` is modal — the OS blocks everything else. On the web, the browser **Back** button is an uncontrolled exit path for *any* dialog type.
**Mitigation:**
- Type A/C: harmless, let it close
- Type B: `history.pushState()` + `onpopstate` to intercept and show "You have unsaved changes" confirmation

## Implementation Helper (Harbour/JS mental model)

```harbour
FUNCTION DialogRules( nType )
SWITCH nType
CASE DLG_DECISION // Type A
RETURN { ESC := "NO", OUTSIDE := "NO", CLEANUP := .F. }
CASE DLG_EDIT // Type B
RETURN { ESC := "BLOCK", OUTSIDE := "BLOCK", CLEANUP := .T., CONFIRM_EXIT := .T. }
CASE DLG_INFO // Type C
RETURN { ESC := "CLOSE", OUTSIDE := "CLOSE", CLEANUP := .F. }
CASE DLG_WIZARD // Type D
RETURN { ESC := "BLOCK", OUTSIDE := "BLOCK", CLEANUP := .T., CONFIRM_EXIT := .T., PRESERVE_STEPS := .T. }
END
```

## FiveWin → Web Migration Checklist
| FiveWin Pattern | Web Equivalent |
|----------------|----------------|
| `ACTIVATE DIALOG ... ON ESCAPE NIL` | `dialog.showModal()` + `keydown` handler calling `e.preventDefault()` |
| `oGet:lChanged` tracking | `form.checkValidity()` + custom `dirty` flag |
| `MsgYesNo()` | `confirm()` or custom modal with `Promise` |

The classification holds — the *implementation* is where the web fights back.

---
Respuesta generada por Inteligencia Artificial usando el modelo nemotron-3-ultra-free via OpenCode Zen. Puede contener errores; por favor verifiquela antes de aplicar.
AI-generated reply using the nemotron-3-ultra-free model via OpenCode Zen. May contain mistakes; please verify before applying.
Post Reply