Dividing "Cube transition" example into components for use in larger project

Hey!

Example: https://www.fusetools.com/examples/cube-transition

If I where to split this example and its side menu into a reusable component to use on a lagrer project, what would be the best way to go?

<DockPanel ux:Name="content">
	<Panel Dock="Top" Height="56">
		<Text Alignment="Center" FontSize="21" Color="ForegroundColor">boxify</Text>
	</Panel>
	<ScrollView Background="#f9f9f9">
		<Grid ColumnCount="4" DefaultColumn="1*" CellSpacing="10" Margin="10,10">
			<Each Count="23">
				<Rectangle BoxSizing="FillAspect" Aspect="1" Color="#eee" CornerRadius="2" />
			</Each>
		</Grid>
	</ScrollView>
</DockPanel>

To be more specific, in my current case the content area could be any of the pages that got top bar menu attached where you should be able to expand menu, and i was hoping to find a nice way to divide this into a reusable component for these pages. An example of best practice for this type of setup would be highly appreciated :slight_smile:

Hi! I’m having a little trouble understanding your navigation structure here. Have I understood correctly in that you want a Navigator where all the pages share the same top bar and menu?

Essentially what I’m asking is: is it enough to have a single instance of the outer structure (topbar+menu) while just replacing the content? Or do you have a more complex setup, where you for example need to change the content in the menu for different sections of your app?

Yes, i currently got this navigation structure: ( btw. class names are examples because project is commercial )

    <DockPanel>
        <Navigator DefaultPath="mytaskdetails">
        	<Project.Page ux:Template="main" router="router" iosStatusBar="iosStatusBar" />
            <Project.Page ux:Template="myTasks" router="router">
				<WhileActive>
					<Change iosStatusBar.Style="Dark"/>
				</WhileActive> 
            </Project.Page>
            <Project.Page ux:Template="mytaskdetails" />
            <Project.Page ux:Template="notifications" router="router">
            	<WhileActive>
					<Change iosStatusBar.Style="Dark"/>
				</WhileActive>
            </Project.Page>
        </Navigator>
   </DockPanel>

And this class for the top menu, that will contain hamburger button to expand menu:

     <DockPanel Alignment="Top" ux:Class="Project.TopMenu" >
		<Panel Height="65" >
			<float4 ux:Property="LogoColor"/>
			<float4 ux:Property="MenuIconColor"/>
			<float4 ux:Property="MenuBackground" />
            <float4 ux:Property="CenterTextColor" />
            <string ux:Property="CenterTextValue" />
			<Panel Height="65" Padding="10,20,10,0" Color="{Property MenuBackground}" >
				<Text Font="icon"  Value="&#xe908;" Alignment="CenterLeft" FontSize="27" TextColor="{Property MenuIconColor}" HitTestMode="LocalVisualAndChildren">
				</Text>
				<Text Font="icon" Value="&#xe907;"  TextColor="{Property LogoColor}" TextAlignment="Center" Alignment="VerticalCenter" FontSize="22" />
                <Text Font="Light" Value="{Property CenterTextValue}"  TextColor="{Property CenterTextColor}" TextAlignment="Center" Alignment="VerticalCenter" FontSize="22" />
			</Panel>
		</Panel>
	</DockPanel>

That still doesn’t answer my question unfortunately. Do you have a separate TopMenu inside each page, or is it a single TopMenu shared between all the pages in your navigator?

In general, this example is quite difficult to componentize, since it shares the same instance of HamburgerMenu between the content and the menu. If there’s only a single top menu (which means a single hamburger icon), this becomes a lot easier.

No, its the same TopMenu class i have implemented on each page like this, if i understood your question correctly:

Ex:

<Project.TopMenu ux:Name="topMenu" LogoColor="White" MenuIconColor="White"  />

I see. This example contains a lot of small moving parts that are pretty specific to this example, so I’ve extracted the essence into a component:

<Panel ux:Class="BoxNavigator">
	<bool ux:Property="MenuIsOpen" />

	<WhileTrue Value="{ReadProperty MenuIsOpen}">
		<Rotate Target="box" DegreesY="-90" Duration=".7" Delay="0" DelayBack="0" Easing="ExponentialOut" EasingBack="ExponentialIn" />
		<Change content.Opacity="0" Duration=".7" DelayBack="0" Easing="ExponentialOut" EasingBack="ExponentialIn" />
		<Change menu.Opacity="1" Duration=".3" DelayBack="0" Easing="QuarticIn" EasingBack="QuarticIn" />
	</WhileTrue>

	<Viewport Perspective="1.7" PerspectiveRelativeTo="Width" CullFace="Back">
		<Panel ux:Name="box" TransformOrigin="VerticalBoxCenter">
			<Panel ux:Name="sidePage" TransformOrigin="VerticalBoxCenter">
				<Rotation DegreesY="90" />
				
				<Panel ux:Name="menu" Opacity="0">
					<Instance TemplateSource="this" TemplateKey="Menu" />
				</Panel>
			</Panel>
			
			<Panel ux:Name="content" Color="#fff">
				<Instance TemplateSource="this" TemplateKey="Content" />
			</Panel>
		</Panel>
	</Viewport>
</Panel>

This BoxNavigator component takes two templates, Content and Menu, in addition to a boolean MenuIsOpen property. Here is a basic example:

<BoxNavigator ux:Name="box">
	<Panel ux:Template="Menu" Background="#212121">
		<Text Color="#fff" Alignment="Center">Menu goes here</Text>
		<Clicked>
			<Set box.MenuIsOpen="false" />
		</Clicked>
	</Panel>
	<Panel ux:Template="Content" Background="#303F9F">
		<Navigator>
			...
		</Navigator>
	</Panel>
</BoxNavigator>
```

Now, you want to use your `Navigator` as the `Content` template here.
To be able to open or close the menu from the `TopBar`, add a dependency from the `TopBar` to the `BoxNavigator`:

```
<DockPanel Alignment="Top" ux:Class="Project.TopMenu" >
    <BoxNavigator ux:Dependency="boxNavigator" />
...
            <Text Font="icon"  Value="&#xe908;" Alignment="CenterLeft" FontSize="27" TextColor="{Property MenuIconColor}" HitTestMode="LocalVisualAndChildren">
                <Clicked>
                    <Set boxNavigator.MenuIsOpen="false" />
                </Clicked>
            </Text>
...
</DockPanel>
```

I hope this made any kind of sense, let me know if you have any questions about any of this :)

Yes, thanks a lot! :smiley: I´ll give it a try and let you know how it goes

I think i am almost there now, only that when i specify the dependency inside the topmenu:

<Project.TopMenu ux:Name="topMenu" LogoColor="White" MenuIconColor="White" boxNavigator="boxNavigator" />

I get this error:
‘boxNavigator’ declared in Project.TopMenu.ux(2) is a member ‘Project.TopMenu’ and cannot be accessed from ‘Project.MainPage’. To make this work, consider making ‘Project.MainPage’ an ux:InnerClass of ‘Project.TopMenu’.

Could it be because the TopMenu is located inside another class already? here is an example of how its setup:

<Page ux:Class="Project.MainPage" ux:Name="mainPage" Transition="None" Color="White" >
	<JavaScript File="TopMenu.js"/>
	<Router ux:Dependency="router"/>
	<iOS.StatusBarConfig ux:Dependency="iosStatusBar" />
	<Project.TopMenu ux:Name="topMenu" LogoColor="White" MenuIconColor="White" boxNavigator="boxNavigator" />

Ah yes, unfortunately you’ll have to wire up the dependency on each of the pages as well.

yes, i did, or if you mean to specify it in each topmenu on each page, like in the first code example i added above? :slight_smile:

i could zip the project and post it in the slack support channel if you´d like to take a quick look, maybe thats easier :slight_smile:

Well, you don’t have access to it inside the page. You have to specify a ux:Dependency on the page class as well so that you can pass it down to the TopMenu, something like:

<Panel ux:Class="TopMenu">
    <BoxNavigator ux:Dependency="boxNavigator" />
    ...
</Panel>
<Page ux:Class="SomePage">
    <BoxNavigator ux:Dependency="boxNavigator" />
    <TopMenu boxNavigator="boxNavigator" />
    ...
</Page>
<BoxNavigator ux:Name="boxNavigator">
    <Navigator ux:Template="Content">
        <SomePage ux:Template="somePage" boxNavigator="boxNavigator" />
    </Navigator>
    ...
</BoxNavigator>