Skip to content
Docs

Developer guide

Building admin screens

The core provides all of the styling for admin screens. Module developers only need to write markup that follows the conventions to get the same look as the core admin, and when the core changes its design, module screens follow along.

Basic principles

  • Colors, spacing, and fonts on admin screens are set by the core's design tokens (--zm-* CSS variables). Don't hard-code color values in your module; reference the tokens.
  • Keep using the x_* classes inherited from the old XE days. The core kept the classes and only applied new styles to them, so existing modules get the new design without any changes.
  • If your module needs its own UI, create a prefix just for that module. Overriding core classes will break in the next core update.

Design tokens

These CSS variables are available across all admin screens. Both light and dark values are defined, so dark mode works automatically as long as you use the tokens.

TokenPurpose
--zm-brand --zm-brand-dark --zm-brand-softAccent color (default #2677e3), darker variant, light background
--zm-ink --zm-ink-soft --zm-ink-faintBody text, secondary text, faint text
--zm-bg --zm-card --zm-surface --zm-surface-2Page background, card, surface levels
--zm-line --zm-line-soft --zm-input-borderDivider, light divider, input border
--zm-ok --zm-warn --zm-errorStatus colors (success/warning/error)
--zm-radius --zm-radius-smCorner radius (12px / 8px)
--zm-hover --zm-solid --zm-solid-fgHover background, emphasized button fill and text
--zm-shadow --zm-fontCard shadow, font stack
/* 모듈 관리자 화면 예 */
.mymod-note {
	padding: 12px 16px;
	border: 1px solid var(--zm-line);
	border-radius: var(--zm-radius-sm);
	background: var(--zm-surface-2);
	color: var(--zm-ink-soft);
}

x_* components

These are the basic building blocks of admin markup. Combine the classes below to get the same screens as the core without any extra CSS.

  • Forms: .x_form-horizontal > .x_control-group > .x_control-label + .x_controls
  • Buttons: .x_btn, emphasized .x_btn.x_btn-primary, dangerous actions .x_btn-danger, sizes -large -small -mini
  • Tables: .x_table, .x_table-striped for row striping, .x_table-hover for hover
  • Alerts: .x_alert with -info -success -error variants
  • Badges: .x_badge with status variants; help text: .x_help-block .x_help-inline
  • Tabs: .x_nav.x_nav-tabs > li > a, with the active item as li.x_active
<form class="x_form-horizontal" method="post" action="./">
	<div class="x_control-group">
		<label class="x_control-label">{$lang->title}</label>
		<div class="x_controls">
			<input type="text" name="title" value="{$config->title}" />
			<p class="x_help-block">{$lang->about_title}</p>
		</div>
	</div>
	<div class="x_clearfix" style="text-align:right">
		<button type="submit" class="x_btn x_btn-primary">{$lang->cmd_save}</button>
	</div>
</form>

Legacy unprefixed Bootstrap classes such as .btn and .table are treated the same as x_* inside admin screens, but use x_* in new code.

Module-specific screens and prefixes

For screens that are hard to express with x_* components, such as list cards or dashboards, pick a module prefix and build them yourself. This is the same approach the core modules use.

  • Use a single prefix per module. For example, the store admin uses zmst- and the payment module uses zpay-
  • Even inside your prefix, reference --zm-* tokens for colors and spacing. That way you get dark mode and future redesigns for free.
  • Avoid overriding core rules with parent selectors (.x .something). They break when the priority of the core CSS changes.

Admin template location and registration

Modules with the modern structure keep admin templates in views/admin/*.blade.php (template v2).

modules/mymodule/
├── views/admin/
│   ├── _tabs.blade.php   ← 탭 공통 조각
│   ├── config.blade.php
│   └── list.blade.php
└── controllers/Admin.php
  • If there are several screens, create a tab partial (_tabs.blade.php) and @include it in each screen.
  • Register admin menus with the menu_name attribute on action declarations in module.xml. For details, see the Building modules document.
  • Admin screens have no mid, so build links to other screens as getUrl('', 'module', 'admin', 'act', ...). If you don't leave the first argument empty, all current request variables are carried along.

What not to do

  • Hard-coding colors. Using a white background (#fff) directly in particular breaks dark mode. Use tokens such as var(--zm-card).
  • Loading external CSS frameworks such as Bootstrap on admin screens. They conflict with the core styles.
  • Overriding other modules' admin screens with CSS. If an improvement is needed, propose it to the core.
  • Overusing inline scripts. The core is expanding CSP on admin screens, so it's safer to move scripts into separate js files.