I'm trying to replicate the Main Menu you implemented in your new TMS Subscription Dashboard as described in your blog post:
with WEB Core 1.3.6, but with no luck :-(

Ii is not clear to me if the 'side' menu of the TSD is a result of the TWebMainMenu or some sort of a 'hardcoded' html template written by hand, or maybe we just have to wait for 1.4 release to get this kind of menu?


The side menu is not a separate component, it's a combination of TWebResponsiveGridPanel + TWebPanel. On top of that we have a TWebMainMenu in a TWebPanel container that is not visible by default. When the layout changes the visibility of the container panel and the HeightStyle (ssAbsolute <-> ssPercent) of the side panel also changes. The buttons in the side panel and the menu items share the same events.

Hi, I also try to replicate that behavior and fail. Can you share more information how exactly the components are used? Can you share a screenshot of the structure view of the main form or the dfm file and the src of the OnLayoutChange handler method?


1. Add a TWebResponsiveGridPanel to the form, position it to 0,0 and set the HeightStyle and WidthStlye to ssPercent. 

2. Configure the TWebResponsiveGridPanel.Layout to contain only 2 elements (you can apply the settings at designtime too):
WebResponsiveGridPanel1.Layout.Items[0].Style := '1fr';
WebResponsiveGridPanel1.Layout.Items[1].Style := '300px 1fr'; //300px will be the width of the side menu
WebResponsiveGridPanel1.Layout.Items[0].Width:= 750; //when should the view change, make sure it's less than the width of the second element

3. Drop a TWebPanel onto your grid, this will be the side menu. Set the HeightStyle and WidthStyle to ssPercent. Add your buttons to it, you can also implement the OnClick events for the buttons.

4. Add another TWebPanel to the form (not to the TWebResponsiveGridPanel!),
WebPanel2.BorderStyle := bsNone;
WebPanel2.WidthStyle := ssPercent;
WebPanel2.Visible := False;

5. Add the TWebMainMenu, add the same menu items as the buttons, and assign the implemented OnClick evens to the corresponding menu items.
WebMainMenu1.Appearance.HamburgerMenu.Visible := hmAlways;
WebMainMenu1.Container := WebPanel2;
It should look like this:

6. Implement the TWebResponsiveGridPanel.OnLayoutChange event:
procedure TForm1.WebResponsiveGridPanel1LayoutChange(Sender: TObject;
  ALayout: TResponsiveLayoutItem);
  case ALayout.Index of
      WebButton1.Visible := False;
      WebButton2.Visible := False;
      WebButton3.Visible := False;
      WebPanel1.HeightStyle := ssAbsolute;
      WebPanel2.Visible := True;
      //Even though the panel was brought to front, the visibility setting interferes with the menu, so manual update trigger is needed
      WebButton1.Visible := True;
      WebButton2.Visible := True;
      WebButton3.Visible := True;
      WebPanel1.HeightStyle := ssPercent;
      WebPanel2.Visible := False;

And add TWebMainMenuProtected = class(TWebMainMenu); to the types.

7. Take WebPanel1 and make the height of it the same as WebPanel2:

You can adjust the font of WebPanel2 to make the TWebMainMenu bigger.

Thank you Tunde, 

this really helped. I have been nearly there but didn't figure to use the protected method TWebMainMenuProtected(WebMainMenu1).UpdateElement; Nice cheat to access those this way on the short route ...

I assume you place another TWebPanel in the ResponsiveGridPanel, make that alClient and then use that to host sub forms. Or is there a better way?

I also ran into a small layout oddity: If you remove / empty the caption of the side menu panel, then that panel is shown with a little gap at the top. Having a dummy caption and using ShowCaption := false doesn't lead to that glitch.

Anyway, it now works perfectly for me. Thank you very much!

That is correct, the sub forms are hosted in a client aligned TWebPanel in the ResponsiveGridPanel.