# `MishkaCmsCore.Layouts`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/layouts.ex#L5)

Layouts shared by extension LiveViews.

Mirrors the host app's `MishkaCmsWeb.Layouts` module: one module holds the
layout templates (auto-embedded from `layouts/*.html.heex`) and any helper
components that belong to the chrome.

## Wiring

Extension LiveViews opt in via `MishkaCmsCore.ExtensionLiveView`, which does
`use Phoenix.LiveView, layout: {MishkaCmsCore.Layouts, :app}`. The result:
every extension admin page is automatically wrapped by `app.html.heex` and
gets the flash group without each template repeating it.

## Why not reuse `MishkaCmsWeb.Layouts`?

Extensions compile before `MishkaCmsWeb`, so calling
`MishkaCmsWeb.Layouts.flash_group/1` from an extension template raises an
"undefined" warning at compile time. This module is the extension-side
counterpart and owns the flash chrome for everything under
`MishkaCmsCore.ExtensionLiveView`.

# `app`

# `copyright_years`

```elixir
@spec copyright_years(Date.t()) :: String.t()
```

The years the footer's copyright line covers, from 2026 up to `today`'s year: `"2026"` during
2026, `"2026-2027"` in 2027, and so on.

# `flash_group`

Renders both `:info` and `:error` flashes from the `@flash` map.

Styled with classes rather than `style` attributes. Every surface that renders this — the admin
chrome via `app.html.heex` and the page builder shell — sets `admin_css`, so the compiled admin
stylesheet is always there to carry them; the canvas iframe, the one admin surface without it,
mounts with `layout: false` and never draws a flash. Keeping the colours in classes is what lets
the policy in `MishkaCmsCore.Runtime.Plugs.SecurityHeaders` close `style-src-attr`, which no nonce
can ever reopen for an attribute.

    <.flash_group flash={@flash} />

Whatever the inner block holds is stacked under the notices — the admin chrome puts
`MishkaCmsCoreWeb.Live.Admin.Components.TranslationsRefusal` there.

## Attributes

* `flash` (`:map`) (required)
## Slots

* `inner_block`

# `footer_credit`

The line under every admin page: "© <years> · Powered by <name>", where the name links to the
product's own page.

`credit` is `%{name: name, url: url}` — what `MishkaCmsCore.Layouts.Nav` assigns as
`@footer_credit` from the extension that owns the page — or `nil` on the core's own pages, which
credit Mishka CMS. Only "Powered by" is translated; a product name is not.

## Attributes

* `credit` (`:map`) - Defaults to `nil`.

# `sidebar`

The admin sidebar — logo, collapsible nav groups, and the active item highlighted from
`@current_path` (set by `MishkaCmsCore.Layouts.Nav`). Groups collapse client-side via `JS.toggle`.

The nav itself is data, not markup: `MishkaCmsCore.Sidebar.menu/1` collects it from every
extension's `"sidebar:menus"` plugin, drops what `@current_user` may not see, and orders it from
Settings. This component only paints what it is handed, so an empty section is one that was
filtered away rather than one that has to be spelled out here. `version` is `@sidebar_version`: the
sidebar is drawn again each time it changes.

## Attributes

* `current_path` (`:string`) - Defaults to `nil`.
* `current_user` (`:any`) - Defaults to `nil`.
* `version` (`:integer`) - Defaults to `0`.

# `topbar`

The admin topbar — search, theme toggle, notifications, and the user's menu: Account settings, the
language the dashboard is read in, and Sign out.

`language` is the admin's language and `languages` the ones the menu offers
(`MishkaCmsCore.Layouts.Nav` assigns both); picking one sends `PUT /admin/language` with
`current_path` to come back to. Two are listed, the admin's own among them, and the rest behind
"Show more".

## Attributes

* `current_user` (`:any`) - Defaults to `nil`.
* `notification_count` (`:integer`) - Defaults to `0`.
* `notification_recent` (`:list`) - Defaults to `[]`.
* `current_path` (`:string`) - Defaults to `nil`.
* `language` (`:string`) - Defaults to `"en"`.
* `languages` (`:list`) - Defaults to `[]`.
* `sign_out` (`:string`) - Defaults to `"/auth/sign-out"`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
