# Chrome Configuration
*Configure the application chrome ([sidebar](../../02_Widgets/02_Layouts/06_SidebarLayout.md), header, footer) using ChromeSettings to customize [navigation](./09_Navigation.md), branding, and layout behavior.*
You can add custom elements to both the header and footer sections of the sidebar using `ChromeSettings`. The example uses [Layout](./04_Layout.md), [Button](../../02_Widgets/03_Common/01_Button.md), and [Text](../../02_Widgets/01_Primitives/01_TextBlock.md) widgets:
```csharp
var chromeSettings = new ChromeSettings()
.Header(
Layout.Vertical().Gap(2)
| new IvyLogo()
| Text.Lead("Enterprise Management System")
| Text.Muted("Comprehensive business application suite")
)
.Footer(
Layout.Vertical().Gap(2)
| new Button("Support")
.HandleClick(_ => { })
| Text.P("Enterprise Application Framework").Small()
)
.DefaultApp<MyApp>()
.UseTabs(preventDuplicates: true);
server.UseChrome(() => new DefaultSidebarChrome(chromeSettings));
```
## ChromeSettings Options
- **DefaultAppId(string? appId)** - Sets the default app to load by ID.
- **DefaultApp<T>()** - Sets the default app using a type (recommended for compile-time safety).
- **UseTabs(bool preventDuplicates)** - Enables tab navigation. When `preventDuplicates` is `true`, prevents duplicate tabs.
- **UsePages()** - Switches to page navigation (replaces content instead of opening tabs).
- **UseFooterMenuItemsTransformer(`Func<IEnumerable<MenuItem>, INavigator, IEnumerable<MenuItem>>` transformer)** - Provides a way to dynamically transform the footer menu items. Useful for adding, removing, or re-ordering links based on runtime context such as user roles or navigation state.
- **WallpaperAppId(string? appId)** / **WallpaperApp<T>()** - Sets a dedicated *wallpaper* app that is shown whenever the tab list is empty. Handy for welcome screens or branded backgrounds.
> **tip:** Use `server.UseDefaultApp(typeof(AppName))` instead of `UseChrome()` for single-purpose applications, embedded views, or minimal interfaces where sidebar navigation isn't needed.
## Wallpaper
Configure a dedicated background *app* that appears when no other tabs are open. Perfect for welcome screens, dashboards or branded imagery.
The **Wallpaper** is just another [app](./10_Apps.md) rendered full-screen by the Chrome host whenever the tab area is empty. This keeps your UI visually engaging instead of showing an empty canvas.
### Configuration
The wallpaper is selected through `ChromeSettings.WallpaperAppId`. Two helper extensions make this convenient:
```csharp
// Explicit id
var chromeSettings = ChromeSettings.Default()
.WallpaperAppId("welcome-screen");
// Or using a type – compile-time safety
chromeSettings = chromeSettings.WallpaperApp<WelcomeScreenApp>();
```
1. Implement a normal Ivy app (derive from [ViewBase](./02_Views.md)).
2. Register it like any other [app](./10_Apps.md) (`server.AddApp<WelcomeScreenApp>()`).
3. Reference it in `ChromeSettings` with one of the helpers above.
### Full Example
```csharp
public class WelcomeScreenApp : ViewBase
{
public override object? Build()
=> Layout.Center(
new Image("/ivy/img/brand-logo.svg").AltText("My Brand"),
Text.H1("Welcome to My System")
);
}
var server = new Server();
server.AddAppsFromAssembly();
var chromeSettings = ChromeSettings.Default()
.WallpaperApp<WelcomeScreenApp>()
.UseTabs();
server.UseChrome(() => new DefaultSidebarChrome(chromeSettings));
await server.RunAsync();
```
## Footer Transformer
Dynamically customize the list of links shown at the very bottom of the sidebar by providing a transformation function with `UseFooterMenuItemsTransformer`.
`ChromeSettings.UseFooterMenuItemsTransformer` accepts a delegate with the following signature:
```csharp
Func<IEnumerable<MenuItem>, INavigator, IEnumerable<MenuItem>>
```
- **items** – the menu items produced by Ivy (from discovered apps).
- **navigator** – helper you can use to build `MenuItem` actions that navigate to a URI or app.
- **return value** – the new collection that will be rendered. You can re-order, filter, or append items freely.
### Usage Example
```csharp
var chromeSettings = ChromeSettings.Default()
.UseFooterMenuItemsTransformer((items, navigator) =>
{
// Convert to list for easier manipulation
var list = items.ToList();
// Append a static link at the end
list.Add(new MenuItem("Logout", _ => navigator.Navigate("app://logout"), Icons.Logout));
// Move "Settings" to the top of the footer
var settings = list.FirstOrDefault(i => i.Id == "app://settings");
if (settings != null)
{
list.Remove(settings);
list.Insert(0, settings);
}
return list;
});
```
You can leverage a footer-menu items transformer to conditionally show or hide links, inject additional ones like "Docs", "Logout", or "Change theme", and rearrange or group items without having to update each individual app.
### Role-Based Filtering
```csharp
var chromeSettings = ChromeSettings.Default()
.UseFooterMenuItemsTransformer((items, navigator) =>
{
var user = AuthContext.CurrentUser;
// Hide admin-only links for non-admins
var filtered = items.Where(i =>
!i.Tags.Contains("admin") || user?.IsInRole("admin") == true);
return filtered;
});
```
In this example we tag certain `MenuItem`s with the custom tag `admin` when generating them elsewhere. The transformer then checks the current user's roles (via your auth system) and removes admin-only links for non-admins.
For more information about SideBar, check its [documentation](../../02_Widgets/02_Layouts/06_SidebarLayout.md)