← Back to Policy Tracker guide

Toast Notifications, Replacing Notify()

Design decided from the mockups: option A (card with a coloured accent bar), sized up and moved to the top-left, overlapping the logo/title area on Main and the title on ViewItem — nothing clickable lives there, so covering it briefly when a toast fires doesn't block anything. Dismissible with an ×, auto-hides after ~3 seconds either way. Mockup for reference: toast style options (option A).

Scope of this guide: covers Main and ViewItem only — the two screens I have current, verified files for. Historic, Overview, and NewsletterPack also call Notify() and would need the exact same treatment, but I don't have fresh exports for those today and I'm not going to guess control names on them after today. Once you're happy with how this works on these two screens, post a fresh export of the other three and I'll do the same pass on them.

Jump to: 1. Why this works across screens (read this first) 2. Add the ShowToast() helper function 3. Build the toast on Main 4. Build the toast on ViewItem 5. Convert your first three Notify() calls 6. Converting the rest

1. Why this works across screens

The thing you were worried about — a "Saved" toast firing on Save & Close, then the screen changing to Main before anyone sees it — isn't actually a problem, and doesn't need any screen-aware logic. Two facts about how this app already behaves make it work automatically:

So the rule is the same everywhere, no special-casing "Save" vs. "Save & Close" vs. "Delete": call the toast before whatever happens next, whether that's staying put or navigating. Every button that saves or deletes already does exactly that in that order today — the data has to be handled before the screen can leave. The only real work is duplicating the toast's visuals and its Timer onto every screen that needs one, using the same variable names everywhere.

2. Add the ShowToast() helper function

One small user-defined function, same pattern as the existing BuildLinksForSource — add it to App's Formulas property (the same place BuildLinksForSource already lives), anywhere in that property, doesn't need to go in a specific spot:

ShowToast(Heading: Text, Message: Text, Type: Text): Boolean = {
    Set(varToastHeading, Heading);
    Set(varToastMessage, Message);
    Set(varToastType, Type);
    Set(varToastVisible, true);
    true
};

Every place that currently calls Notify(...) becomes a single call like ShowToast("Saved", "Your changes have been saved.", "success") instead — one line, same shape everywhere, easy to scan for later. Type is just "success" or "error" for now (matching the two colours in the mockup); add more later if you want a distinct warning colour.

3. Build the toast on Main

This is a new top-level child of the Main screen itself, not nested inside ScreenContainer1 — the same pattern Main already uses for MyItemsBG/MyItems/SearchOverlay/TypeFilterOverlay1, which are also floating overlays positioned on top of everything. If it were nested inside ScreenContainer1 (an AutoLayout container), it would get pushed into the flow after the header instead of floating over it.

Select the Main screen itself in Tree view (not a control inside it), then paste this in — Studio will add it as a new top-level child, sitting on top of everything since it's last in the list:

- ToastNotification:
    Control: GroupContainer@1.5.0
    Variant: ManualLayout
    Properties:
      DropShadow: =DropShadow.Regular
      Fill: =RGBA(255, 255, 255, 1)
      Height: =56
      RadiusBottomLeft: =10
      RadiusBottomRight: =10
      RadiusTopLeft: =10
      RadiusTopRight: =10
      Visible: =varToastVisible
      Width: =430
      X: =16
      Y: =16
    Children:
      - ToastAccentBar:
          Control: Rectangle@2.3.0
          Properties:
            Fill: =If(varToastType = "error", RGBA(194, 47, 47, 1), RGBA(11, 74, 54, 1))
            Height: =Parent.Height
            Width: =6
      - ToastHeading:
          Control: ModernText@1.0.0
          Properties:
            Color: =RGBA(22, 33, 28, 1)
            Font: =Font.'Lato Black'
            Height: =20
            Size: =13
            Text: =varToastHeading
            Width: =Parent.Width - 60
            X: =20
            Y: =7
      - ToastMessage:
          Control: ModernText@1.0.0
          Properties:
            Color: =RGBA(91, 105, 97, 1)
            Font: =Font.'Open Sans'
            Height: =20
            Size: =11
            Text: =varToastMessage
            Width: =Parent.Width - 60
            X: =20
            Y: =28
      - ToastClose:
          Control: Classic/Button@2.2.0
          Properties:
            BorderThickness: =0
            Color: =RGBA(91, 105, 97, 1)
            DisplayMode: =DisplayMode.Edit
            Fill: =RGBA(0, 0, 0, 0)
            Font: =Font.'Open Sans'
            Height: =28
            HoverFill: =RGBA(0, 0, 0, 0.05)
            OnSelect: =Set(varToastVisible, false)
            PressedFill: =RGBA(0, 0, 0, 0.08)
            Size: =16
            Text: ="×"
            Width: =28
            X: =Parent.Width - 34
            Y: =6
      - tmrToastHide:
          Control: Timer@2.1.0
          Properties:
            AutoStart: =varToastVisible
            Duration: =3000
            OnTimerEnd: =Set(varToastVisible, false)
            Repeat: =false
            Start: =varToastVisible
            Visible: =false

X=16, Y=16 matches ScreenContainer1's own padding, so the toast lines up flush with where the logo currently sits — it'll sit directly over the logo/"Policy Tracker"/V2 badge cluster when visible. Nudge Width/Height in the properties panel once you can see it live if it doesn't quite cover that whole cluster on your screen.

Test: temporarily change ToastNotification.Visible to =true in the formula bar, confirm it sits over the logo area and looks right, then change it back to =varToastVisible.

4. Build the toast on ViewItem

Same component, same idea — a new top-level child of the ViewItem screen, matching the existing pattern already used there for DeleteItemModal1/DeleteLinkModal1/UnsavedChangesModal/DuplicateModal1/ThursdayPickerModal1, all of which are also floating screen-level overlays.

Select the ViewItem screen itself in Tree view, paste this in:

- ToastNotification:
    Control: GroupContainer@1.5.0
    Variant: ManualLayout
    Properties:
      DropShadow: =DropShadow.Regular
      Fill: =RGBA(255, 255, 255, 1)
      Height: =56
      RadiusBottomLeft: =10
      RadiusBottomRight: =10
      RadiusTopLeft: =10
      RadiusTopRight: =10
      Visible: =varToastVisible
      Width: =420
      X: =16
      Y: =20
    Children:
      - ToastAccentBar:
          Control: Rectangle@2.3.0
          Properties:
            Fill: =If(varToastType = "error", RGBA(194, 47, 47, 1), RGBA(11, 74, 54, 1))
            Height: =Parent.Height
            Width: =6
      - ToastHeading:
          Control: ModernText@1.0.0
          Properties:
            Color: =RGBA(22, 33, 28, 1)
            Font: =Font.'Lato Black'
            Height: =20
            Size: =13
            Text: =varToastHeading
            Width: =Parent.Width - 60
            X: =20
            Y: =7
      - ToastMessage:
          Control: ModernText@1.0.0
          Properties:
            Color: =RGBA(91, 105, 97, 1)
            Font: =Font.'Open Sans'
            Height: =20
            Size: =11
            Text: =varToastMessage
            Width: =Parent.Width - 60
            X: =20
            Y: =28
      - ToastClose:
          Control: Classic/Button@2.2.0
          Properties:
            BorderThickness: =0
            Color: =RGBA(91, 105, 97, 1)
            DisplayMode: =DisplayMode.Edit
            Fill: =RGBA(0, 0, 0, 0)
            Font: =Font.'Open Sans'
            Height: =28
            HoverFill: =RGBA(0, 0, 0, 0.05)
            OnSelect: =Set(varToastVisible, false)
            PressedFill: =RGBA(0, 0, 0, 0.08)
            Size: =16
            Text: ="×"
            Width: =28
            X: =Parent.Width - 34
            Y: =6
      - tmrToastHide:
          Control: Timer@2.1.0
          Properties:
            AutoStart: =varToastVisible
            Duration: =3000
            OnTimerEnd: =Set(varToastVisible, false)
            Repeat: =false
            Start: =varToastVisible
            Visible: =false
One real edge case, not fully solved: ViewItem's top bar also has two conditional badges (High Priority / Top Newsletter Item) that appear around X=191 and X=435 when those flags are ticked. Most of the time neither is showing, so the toast at X=16436 has clear space. If a toast fires while both badges happen to be visible at once, it'll sit on top of the first one briefly. Rare enough not to be worth engineering around today — flagging it so it's not a surprise if you see it, not proposing a fix for it yet.
Test: same as Main — temporarily force Visible: =true, check it sits cleanly over the "Policy Tracker" title without covering the Save/Close buttons on the right, then revert to =varToastVisible.

5. Convert your first three Notify() calls REAL EXAMPLES FROM YOUR CURRENT FILE

These three cover exactly the cases you were asking about — a plain Save that stays on screen, a Save & Close that navigates away, and a Delete that also navigates away. Same swap pattern each time: replace the Notify(...) line(s) with one ShowToast(...) call, keep everything else in the formula untouched.

btnSave1 (plain Save, stays on ViewItem) — find these two lines:

Notify("Saved successfully!", NotificationType.Success),
Notify("Save failed. Please check your connection and try again.", NotificationType.Error)

Replace with:

ShowToast("Saved", "Your changes have been saved.", "success"),
ShowToast("Save failed", "Check your connection and try again.", "error")

btnSaveClose1 (Save & Close, navigates to Main or Historic) — find:

Notify("Saved successfully!", NotificationType.Success);
If(varSourceScreen = "Historic", Navigate(Historic, ScreenTransition.Fade), Navigate(Main, ScreenTransition.Fade)),
Set(varSaving, false);
Notify("Save failed. Please check your connection and try again.", NotificationType.Error)

Replace with:

ShowToast("Saved", "Your changes have been saved.", "success");
If(varSourceScreen = "Historic", Navigate(Historic, ScreenTransition.Fade), Navigate(Main, ScreenTransition.Fade)),
Set(varSaving, false);
ShowToast("Save failed", "Check your connection and try again.", "error")

The toast call stays before Navigate(...), same position as the old Notify() was — that ordering is exactly what makes it show up correctly on the destination screen, per item 1 above.

btnModalAction1 (Delete confirm, navigates to Main) — find:

Notify("Delete failed. The item may still exist. Please check and try again.", NotificationType.Error),
UpdateContext({locDisplayDeletePopUp1: false});
ClearCollect(colUnpublishedPolicies, Filter('Policy Proof Tracker', Published = false));
Notify("Item deleted successfully.", NotificationType.Success);

Replace with:

ShowToast("Delete failed", "The item may still exist, please check and try again.", "error"),
UpdateContext({locDisplayDeletePopUp1: false});
ClearCollect(colUnpublishedPolicies, Filter('Policy Proof Tracker', Published = false));
ShowToast("Item deleted", "The item was removed successfully.", "success");
Test all three: (1) edit a field, hit plain Save, confirm the toast appears over the title on ViewItem and you stay put. (2) Edit a field, hit Save & Close, confirm the toast appears over the logo on Main, not on ViewItem. (3) Delete a test item, confirm the toast appears on Main after the delete completes.

6. Converting the rest SAME PATTERN, YOUR OWN PACE

ViewItem has 20 Notify() calls total, Main has 4 — the three above are the highest-traffic ones. For every remaining one, same swap:

OldNew
Notify("some message", NotificationType.Success)ShowToast("Heading", "some message", "success")
Notify("some message", NotificationType.Error)ShowToast("Heading", "some message", "error")
Notify("some message", NotificationType.Warning)ShowToast("Heading", "some message", "error") — no separate warning colour yet, error accent reads close enough until you want a third colour

Pick a short 1-2 word Heading that matches what the message is about (skim the existing message text for the gist — "Link saved successfully!" becomes heading "Link saved", message "The document link was saved.", etc.). No need to do them all in one sitting — Notify() and ShowToast() can coexist in the app indefinitely while you convert call sites gradually, they don't interfere with each other.

Test: after converting a batch, grep your own exported YAML for Notify( to see what's left — or just ask me to check next time you post a fresh export, and I'll list exactly which ones remain.