Skip to content

Major UI overhaul. Did several detailed changes to the look and feel.#106

Open
mimshwright wants to merge 27 commits into
ohmjs:mainfrom
mimshwright:ui
Open

Major UI overhaul. Did several detailed changes to the look and feel.#106
mimshwright wants to merge 27 commits into
ohmjs:mainfrom
mimshwright:ui

Conversation

@mimshwright

Copy link
Copy Markdown
Screenshot 2026-07-01 at 14 47 46

Biggest changes:

  • examples now have a dedicated editor panel

  • consistent styling of panels. Reconsidered placement of buttons and switches

  • some colors changed to brand colors

  • attempted to improve readability

  • collapsable built-in rules

  • replaced emojis with icons

  • added dark mode

  • Tried to avoid any functional changes

mimshwright and others added 27 commits June 30, 2026 15:18
Editor readability:
- Introduce semantic CSS variables and raise contrast of the light
  CodeMirror (Night Owl) token colors.
- Add a dark theme (theme-dark.css) covering the app chrome, both
  editors, dropdowns, dialogs and the parse-tree visualizer, plus an
  optional high-contrast mode. A small bootstrap in index.html applies
  the saved theme before first paint to avoid a flash.

Preferences in the three-dot menu:
- Extend ellipsis-dropdown to support toggle (checkbox) items that show
  a checkmark and keep the menu open.
- Add a preferences menu (src/preferences.js) in the grammar header with
  "Dark mode" and "High contrast" toggles. Dark mode follows the OS
  color scheme until the user makes an explicit choice, which is then
  remembered in localStorage.

Examples usability:
- Rework the main layout from a 2-column grid into a 2x2 grid: grammar
  editor and visualizer on top, examples list and example editor on the
  bottom. A single vertical splitter divides both columns and a single
  horizontal splitter divides both rows.
- The example editor is now a permanent inline pane instead of a
  pop-over overlay.
- Add a clear pass/fail switch at the top of the example editor
  indicating whether the example is expected to match (default) or not,
  and remove the per-row thumbs from the examples list (the list now
  only conveys pass/fail status via the colored row marker).

Tests:
- Update unit tests for the new pass/fail switch.
- Update e2e selectors for the inline editor and switch. NOTE: the e2e
  screenshot snapshots need regenerating (npm run update-snapshots)
  since the layout changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QC1xqnjMzbMz7F7yNFJYZn
In the new layout the example editor is a sibling pane in the bottom row,
so collapsing the examples list alone no longer shrinks the row. Drive a
`examples-collapsed` class on the grid (from both the chevron toggle and
the splitter-drag path) that hides the example editor, letting the bottom
row collapse down to just the examples header again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QC1xqnjMzbMz7F7yNFJYZn
- Combine the two ellipsis menus into one. The grammar "Save As..." item
  now registers into the preferences menu via ohmEditor.ui.addMenuItem().
- Move the examples collapse chevron next to the section title.
- Animate the examples panel collapse/expand (transition pixel row heights,
  since grid fr<->px tracks don't interpolate).
- Move the parse options into the Parse section header and relabel
  "Explain parse" to "Show unmatched rules" (it reveals failed/unmatched
  rule applications). Move the step controls into the same header; remove
  the floating option panel.
- Fix low-contrast read-only text in dark mode: --grey-text-color resolved
  on :root to the light value and never updated, so use --muted-text.
- Remove the doubled border below the example editor's start-rule toolbar.
- Draw a faint rounded outline around each character in the parse tool.
- Fix parse-results onWheel writing to the component instead of the scroll
  element, so horizontal panning works.
- Fix a pre-existing eslint quotes error in preferences.js.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…trast

- Unify all four panel headers (Grammar, Parse, Examples, Example) into one
  style: pink title, fixed 38px height, room for tools on the right. Drop the
  grey/uppercase Examples title override.
- Convert the example editor's header to the shared section-head and move the
  start-rule selector up into it.
- Add a Remove button to the example editor header.
- Confirm before deleting an example (from the list ✕ or the editor's Remove).
- Make high contrast always on: add the class to <body> and remove the toggle
  (and its storage) from the preferences menu.
- Update test selector for the relocated start-rule error icon.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Parse panel now shows "Select or add an example to see how it's parsed."
  whenever the input is empty (no example selected, selected example is empty,
  or there are no examples), instead of a stale/empty tree.
- Clear the selection (and input) when the last example is deleted, instead of
  keeping the last example. Rewrote deleteExample to pick a neighbor from the
  remaining ids and fall back to null.
- Give each panel header a subtle background (--surface-bg): slightly darker
  than the body in light mode, slightly lighter in dark mode.
- Remove the doubled rule above the first example (the list no longer draws a
  border-top now that the header has a bottom border).
- Style the read-only built-in rules panel under the grammar editor: grey
  background, a "Built-in rules" header, and hide it when there are none.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…fresh

- Light theme: editable areas (grammar + example editors) stay pure white;
  non-interactive surfaces use a light grey, getting slightly darker for the
  header bars and read-only panels. Editors get an explicit white background so
  the grey panel can't show through.
- Add a gap above the built-in rules panel and make its grey background win
  over the generic `.CodeMirror div` rule (it's a line widget).
- Example editor header: order is now Start rule then Should match, both
  right-anchored like the other panels; the Remove button is a close (×) icon.
- Fix the blank space on the right of the grammar editor after resizing:
  CodeMirror caches its width, so refresh the editors (coalesced per frame)
  whenever the splitter changes the grid tracks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Convert the panel to a native <details>/<summary> accordion with a rotating
  disclosure triangle; CodeMirror remeasures the line widget on toggle.
- Remove the grammar editor's bottom line padding so the panel sits flush and
  the 8px white strip beneath it is gone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Move the panel out of the CodeMirror line widget and make it a flex child at
  the bottom of #grammarContainer, so it's pinned to the bottom with the editor
  scrolling above it. Cap it at half the pane height; its content scrolls.
- Rewrite externalRules.js to update the static panel instead of cloning and
  placing a line widget; refresh the grammar editor on content/accordion change.
- Drop the now-unused #protos template and the line-widget padding workaround.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- "Should (NOT) match" -> "Should (NOT) parse" on the example toggle.
- "Show unmatched rules" -> "Show all steps" for the parse option.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- New top app bar with title and a light/dark theme toggle; remove the
  now-empty ellipsis/preferences menu (deleted preferences.js).
- Move "Save As" out of the ellipsis menu into a grammar-header button.
- Default layout: ~1/4-3/4 columns, ~3/4-1/4 rows, built-in rules collapsed,
  light mode. Fix runaway column resize via minmax(0, fr) tracks.
- Rename "Examples"/"Example" to "Tests"/"Edit Test" throughout the UI strings.
- Test list: white row strips, red/green status dots, blue hover/selection,
  count badge (green all-pass / red any-fail) next to the title, "+ Add"
  button, and a "No tests yet" empty state.
- Edit Test header: reorder to switch -> starting rule -> remove, add a status
  dot, and replace the warning emoji with a bold "Invalid Grammar" label.
- Panel headings are now uppercase and slightly larger; built-in rules content
  gets a lighter background for legibility.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Parse tree rule labels are now dark boxes with white text for much stronger
  contrast against the light panel (dark mode unchanged).
- Expanded-input strip: theme-aware background/ink (no more hardcoded white),
  extra vertical padding, and a single subtle divider instead of the grey box.
- Remove the per-character outline on the expanded input; it was framing the
  overlapping "remaining input" characters in the failed-parse view and making
  them look scrambled.
- Replace the PNG play/step buttons with clean inline-SVG icon buttons that use
  currentColor (theme-aware).
- Replace the "Show all steps" / "Show spaces" checkboxes with neutral toggle
  switches (the native inputs are kept, visually hidden, so the logic that
  reads .checked is untouched).
- Add an error label beside the "Parse" heading: "Invalid Grammar" when the
  grammar won't parse, otherwise "Error at char N" for input failures. Reuse
  the same .grammar-error styling in the Edit Test header.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the CSS disclosure triangle with the same circular chevron button used
by the Tests panel, and slide/fade the rules in when the panel opens.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vue runs the selectedId watcher (which copies the example text into the input
editor) asynchronously, but index.js runs an initial refresh() synchronously in
the same tick. That refresh emitted change:input with the still-empty editor,
and the change:input listener wrote the empty string back over the freshly
selected first example -- leaving it blank. Populate the input editor
synchronously right after selecting so the initial refresh sees the real text.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The expanded-input strip is canvas-drawn and doesn't repaint on its own, so
toggling dark/light left it showing the previous theme's colours until the next
parse. Dispatch a resize event (which it already listens to) on theme change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Move the built-in rules accordion chevron to the right of its label (matching
  the Tests panel).
- Headers use normal case again (drop the uppercase/letter-spacing on panel
  headings and the app title); still pink.
- Replace the theme toggle's text label with a monochrome sun/moon icon button.
- Add a "Documentation" link (https://ohmjs.org/) to the top bar, left of the
  theme toggle.
- Remove #grammarContainer's min-width so a very narrow left column clips its
  content at the splitter instead of overflowing into the Parse panel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Collapsed parse-tree nodes now use a bold, bright dashed underline that reads
  on the dark label box (the old thin grey dash was invisible after the
  dark-box restyle). Underline keeps the box height/text length unchanged.
- Point the Documentation link at https://ohmjs.org/docs/intro.
- Split the sun icon's path so the line stays under the max-len lint limit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Set --heading-color (panel headings + app title) to the new purple in both
themes; other accent uses (focus rings, syntax highlighting) are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Point .app-title back at --accent (pink) while panel headings stay purple.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Set --accent to #FE3093 in both themes (drives the app title and other pink
accents).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the dashed underline on collapsed nodes with a thick double border
(8px double #f3f3f6) so they read as a stack of hidden children.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Clamp column and row drags so no panel goes below 50px (collapsed panels are
  the exception; dragging the examples row below 50px collapses it).
- Rename the top-bar "Documentation" link to "Ohm Docs" and always underline it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Relocate #grammarList (grammar selector) into the top app bar, right of the
title. persistence.js still finds/populates it by id, so selection and saving
are unchanged; Save / Save As stay in the Grammar header.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mimshwright

Copy link
Copy Markdown
Author
Screenshot 2026-07-01 at 14 51 43 for comparison, here is the before picture

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants