Notebook Front End Overview

John Fultz, Wolfram Research

#WolframTechConf

ABSTRACT

2025 has been a big year for the Wolfram notebook front end.  Let's talk about it!

Version 14.3 is our current version, and I’ll discuss some things that are in it.

But we’re actively working on 15.0, and this presentation is running in a 15.0 FE.

Dark Mode

14.3 shipped dark mode; try it TODAY

We didn't just do dark mode migrations, we built a system for doing dark mode migrations

DarkModeTools is coming soon to the paclet repository

Noah Hardwicke is doing his deep dive presentation, “Dark Mode”, in the next 1/2 hour speaker block

Dark Mode — one of our largest projects

One local tracker I checked had over 80 separate development tasks, many nontrivial, for dark mode development, including:

Default notebook and package environment

Dialogs, toolbars, palettes, completions, hover effects, menus

Vis functions, Graph, Tree, Dataset, Tabular

Manipulate and many other programmatically generated interfaces

Typesetting of entities, quantities, progress meters, summary boxes

Documentation, particularly review of examples that used hard-coded colors that might work poorly in dark mode

Dark-mode aware color pickers

Dark Mode — technical underpinnings

Just five symbols in 14.3

Dark Mode

(RefLink[LightDark, paclet:ref/LightDark]) — display notebook contents in light or dark mode

(RefLink[LightDarkSwitched, paclet:ref/LightDarkSwitched]) — display colors differently in light and dark mode

(RefLink[LightDarkAutoColorRules, paclet:ref/LightDarkAutoColorRules]) — automatically map light mode colors to dark mode equivalents

And two more for 15.0

Dark Mode — LightDarkSwitched

Init

Clear[System`LightModePane];
System`LightModePane[expr_,args___]:=
Module[{background},
background=Background /. Select[{args},OptionQ] /. {Background->Automatic};
If[background === Automatic,background = ThemeColor["Background"]];
ExpressionCell[Pane[expr,args],LightDark->"Light",Background->background]
]

Clear[System`DarkModePane];
System`DarkModePane[expr_,args___]:=
Module[{background},
background=Background /. Select[{args},OptionQ] /. {Background->Automatic};
If[background === Automatic,background = ThemeColor["Background"]];
ExpressionCell[Pane[expr,args],LightDark->"Dark",Background->background]
]

LightDarkSwitched[Red,Blue]

#[Graphics[{LightDarkSwitched[Red,Blue],Disk[]}]]&/@{LightModePane,DarkModePane}

Dark Mode — LightDarkAutoColorRules

#[Graphics[{Red,Disk[{0,0}],Green,Disk[{2,0}],Blue,Disk[{1,2}]},BaseStyle->{LightDarkAutoColorRules->All}]]&/@{LightModePane,DarkModePane}

Dark Mode — more colors

We had the regular and Light variant named colors before...now we've expanded to Dark variants.

Named Colors

Light Named Color Variants

Dark Named Color Variants

Dark Mode — and some  “standard” colors

Standard Named Color Variants

These are colors which tend to “pop” in both light and dark mode

Chosen for their aesthetic appeal

For instance, many documentation examples have been rewritten to use these colors so they work well in both modes

Theme colors

Infrastructure was developed as part of dark mode

Consists of a “vector” of theme colors respected by our stylesheets

Choosers not yet in 15.0 builds, but coming soon

Init

str="$base03:#002b36;
$base02:#073642;
$base01:#586e75;
$base00:#657b83;
$base0:#839496;
$base1:#93a1a1;
$base2:#eee8d5;
$base3:#fdf6e3;
$yellow:#b58900;
$orange:#cb4b16;
$red:#dc322f;
$magenta:#d33682;
$violet:#6c71c4;
$blue:#268bd2;
$cyan:#2aa198;
$green:#859900;";

cols["Solarized"]=Association[Rule@@@MapAt[RGBColor,StringSplit[StringSplit[StringDelete[str,"\n"|"$"],";"],":"],{All,2}]]

light["Solarized"]=Quiet@<|"Background"->"base3","Foreground"->"base01","Accent1"->"red","Accent2"->"yellow","Accent3"->Lighter["yellow",.2],"Accent4"->Lighter["yellow",.1],"Accent5"->"violet","Accent6"->"yellow","Accent7"->Darker["base2",.1],"Accent8"->"red","Accent9"->"blue"|>;

dark["Solarized"]=ReplaceAll[{Lighter->Darker,Darker->Lighter,s_String:>StringReplace[s,{"base0"~~d:DigitCharacter:>"base"<>d,"base"~~d:DigitCharacter:>"base0"<>d}]}]/@light["Solarized"]//Quiet

theme["Solarized"]=Map[
ReplaceAll[s_String:>cols["Solarized"][s]],
<|"LightModeColors"->light["Solarized"],"DarkModeColors"->dark["Solarized"]|>,
{-1}]

Map[Hue,#->CurrentValue[EvaluationNotebook[],{StyleHints,#}]&/@<|"LightModeColors","DarkModeColors"|>,{-2}]

theme["BlueHues"]=\[LeftAssociation]"LightModeColors"->\[LeftAssociation]"Foreground"->,"Background"->,"Accent1"->,"Accent2"->,"Accent3"->,"Accent4"->,"Accent5"->,"Accent6"->,"Accent7"->,"Accent8"->,"Accent9"->\[RightAssociation],"DarkModeColors"->\[LeftAssociation]"Foreground"->,"Background"->,"Accent1"->,"Accent2"->,"Accent3"->,"Accent4"->,"Accent5"->,"Accent6"->,"Accent7"->,"Accent8"->,"Accent9"->\[RightAssociation]\[RightAssociation]

Color vector

theme["Solarized"]

Row[{Button["Sample \"Solarized\"",NotebookPut@],Button["Sample \"BlueHues\"",NotebookPut@]}," "]

Side notebook

Like a docked cell, but on the left instead of the top

In 15.0, home for a properties interface and the Chat Notebook LLM interface

Not in 15.0 builds yet, but coming very soon!

Button["Sidebar notebook",NotebookOpen[FileNameJoin[{NotebookDirectory[],"FrontEnd - Sidebar.nb"}]]]

In-window multi-find interface

FE`FindReplaceUI[False]

Some code from GitLink to show Find working

(* create tmpBranch at result, check it out, move dest, set HEAD to dest, and clean up *)
relocateHeadBranchIfItExists[repo_GitRepo, result_GitObject, throwTag_] :=
	Module[{headBranch = GitProperties[repo, "HeadBranch"]},
		If[GitBranchQ[repo, headBranch] ,
			If[Quiet@GitCheckoutReference[repo, result] === $Failed,
				Message[throwTag::checkoutconflict]; Throw[$Failed, throwTag]];
			GitMoveBranch[headBranch, result];
			GL`GitSetHead[repo["GitDirectory"], headBranch];
		]
	];

Fast-find

Multi-find won’t work unless find in notebooks gets a lot faster

And not just find, but other deeper parts of the system

Panel[Row[{Checkbox[Dynamic[CurrentValue[$FrontEnd,{PrivateFrontEndOptions,"ExperimentalNotebookParser"}]]]," New parser"}]]

Init

OpenRefPage[name_String]:=NotebookOpen[FileNameJoin[{SystemInformation["FrontEnd","DocumentationInformation"]["Directory"],"English","System","ReferencePages","Symbols",name<>".nb"}]];
OpenRefPage[name_]:=OpenRefPage[ToString[name]]

CurrentValue[$FrontEnd,{PrivateFrontEndOptions,"ExperimentalNotebookParser"}]=True;

Find timings

EchoTiming[
NotebookFind[OpenRefPage[StreamDensityPlot],"vorticity"]];

Fast-find — timings on the individual steps

Opening the notebook:

EchoTiming[nb=OpenRefPage[StreamDensityPlot]];

Doing the first find:

EchoTiming[NotebookFind[nb,"vorticity"]];

Fast-find — what’s going on?

Notebooks are brought entirely into memory when opened

A new notebook parser makes parsing much faster

The new parser supports multi-threaded parsing, so we can use your idle processor cores to help

Find no longer requires fully constructing internal data structures; only using the notebook parser results

Rapid find data structures are built and maintained for the life of the notebook

Smart labels in Labeled

Old style Labeled constructs awkwardly attached labels to graphics

(* 14.2 *)
Labeled[Graphics[],StringRiffle[RandomWord[10]," "]]

New-style Labeled integrates the label fully into the graphic, while still allowing it to flowingly line-wrap

Evaluated in 14.3 or 15.0, but improved resizing behavior in 15.0:

(* 15.0 *)
Labeled[Graphics[],StringRiffle[RandomWord[10]," "]]

Some other miscellanea...

CoreExtensions

A new mechanism for paclet extensions to Core.nb

Many paclet examples in the layout

Drag and drop out of the product

Any 2D graphic...click on it and drag out of the window

Drops to the file system as a .png file, or drops as a bitmap to other applications

Symmetric delimiter insertion

Select input, and type a [, (, {, or "; the selected input will be wrapped with the matching operators

Coding ligatures improvements

14.2 and earlier had coding ligatures, e.g. typing -> collapses visually into -> while still being stored as ->

Backspacing will still split the characters apart

But using arrow keys to cursor through the characters also split them apart, which we realized was confusing...now fixed!

Some other related talks to check out

James Lane — Improvements in Labeling and Graphics (this talk already happened...go check the recording!)

Noah Hardwick — Dark Mode (happening next!)

Lou D’Andria — User Interface Patterns in Wolfram Language, 3:30pm CST today

Yuzhu Lu — Customized Rendering with GLSL, 4:00pm CST today

Jason Harris — From Text to Boxes: How the Front End Parses and Typesets Math, 4:30pm CST today

Front End Meetup — 10:30am tomorrow

Itai Seggev — Hands-on Introduction to Formula Typesetting, 3:30pm Friday