diff --git a/config/assets.php b/config/assets.php index 8711955..b5269d5 100644 --- a/config/assets.php +++ b/config/assets.php @@ -28,6 +28,7 @@ return [ 'css/components/app-details-titlebar.css', 'css/components/app-details-validation-summary.css', 'css/components/app-dashboard-titlebar.css', + 'css/components/app-empty-state.css', 'css/components/app-details.css', 'css/components/app-details-card.css', 'css/components/app-list-table.css', diff --git a/pages/admin/stats/index(default).phtml b/pages/admin/stats/index(default).phtml index 6e489cc..9471a6f 100644 --- a/pages/admin/stats/index(default).phtml +++ b/pages/admin/stats/index(default).phtml @@ -257,7 +257,7 @@ require templatePath('partials/app-breadcrumb.phtml'); - + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -291,7 +291,7 @@ require templatePath('partials/app-breadcrumb.phtml'); - + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -546,7 +546,7 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -569,12 +569,12 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -625,7 +625,7 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -650,12 +650,12 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -806,7 +806,7 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -916,7 +916,7 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -948,7 +948,7 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -1068,7 +1068,7 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -1109,7 +1109,7 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
@@ -1137,7 +1137,7 @@ require templatePath('partials/app-breadcrumb.phtml');
- + t('No entries found'), 'size' => 'compact']; require templatePath('partials/app-empty-state.phtml'); ?>
diff --git a/pages/admin/tenants/_form.phtml b/pages/admin/tenants/_form.phtml index 3cb9f33..aa77a8d 100644 --- a/pages/admin/tenants/_form.phtml +++ b/pages/admin/tenants/_form.phtml @@ -282,7 +282,13 @@ $ssoSyncNeedsGraph = !empty($ssoUiState['sync_needs_graph']);
-

+ t('No custom fields configured yet'), + 'size' => 'compact', + ]; + require templatePath('partials/app-empty-state.phtml'); + ?>

+ $tenant): ?> + + +

-

+ t('No custom fields configured for this tenant'), + 'size' => 'compact', + ]; + require templatePath('partials/app-empty-state.phtml'); + ?>
@@ -829,8 +839,14 @@ foreach ($tenants as $tenant) {

- -

+ + t('No custom fields configured for selected tenants'), + 'size' => 'compact', + ]; + require templatePath('partials/app-empty-state.phtml'); + ?> diff --git a/templates/partials/app-empty-state.phtml b/templates/partials/app-empty-state.phtml new file mode 100644 index 0000000..dc32266 --- /dev/null +++ b/templates/partials/app-empty-state.phtml @@ -0,0 +1,58 @@ + $emptyState + */ + +$emptyState = is_array($emptyState ?? null) ? $emptyState : []; +$emptyMessage = trim((string) ($emptyState['message'] ?? '')); +if ($emptyMessage === '') { + return; +} + +$emptyHint = trim((string) ($emptyState['hint'] ?? '')); +$emptySize = strtolower(trim((string) ($emptyState['size'] ?? 'default'))); +if (!in_array($emptySize, ['default', 'compact'], true)) { + $emptySize = 'default'; +} + +$emptyAlign = strtolower(trim((string) ($emptyState['align'] ?? 'center'))); +if (!in_array($emptyAlign, ['center', 'left'], true)) { + $emptyAlign = 'center'; +} + +$emptyAction = is_array($emptyState['action'] ?? null) ? $emptyState['action'] : []; +$emptyActionLabel = trim((string) ($emptyAction['label'] ?? '')); +$emptyActionHref = trim((string) ($emptyAction['href'] ?? '')); +$emptyActionForm = trim((string) ($emptyAction['form'] ?? '')); +$emptyActionClass = trim((string) ($emptyAction['class'] ?? 'secondary outline small')); +$emptyActionTarget = trim((string) ($emptyAction['target'] ?? '')); +$emptyActionRel = trim((string) ($emptyAction['rel'] ?? '')); +$showAction = $emptyActionLabel !== '' && ($emptyActionHref !== '' || $emptyActionForm !== ''); + +?> +
+

+ + + + + + target="" + rel="" + > + + + + + + +
diff --git a/web/css/base/variables.base.css b/web/css/base/variables.base.css index d95132e..8d10d5b 100644 --- a/web/css/base/variables.base.css +++ b/web/css/base/variables.base.css @@ -311,6 +311,10 @@ --app-card-box-shadow: var(--app-box-shadow); --app-card-sectioning-background-color: rgb(251, 251.5, 252.25); --app-details-card-open-summary-bg: var(--app-card-sectioning-background-color); + --app-empty-border-color: var(--app-muted-border-color); + --app-empty-bg: var(--app-card-background-color); + --app-empty-text: var(--app-color); + --app-empty-hint: var(--app-muted-color); --app-dropdown-background-color: #fff; --app-dropdown-border-color: #eff1f4; --app-dropdown-box-shadow: var(--app-box-shadow); diff --git a/web/css/components/app-empty-state.css b/web/css/components/app-empty-state.css new file mode 100644 index 0000000..ee2b5f4 --- /dev/null +++ b/web/css/components/app-empty-state.css @@ -0,0 +1,44 @@ +@layer components { + .app-empty-state { + border: 1px dashed var(--app-empty-border-color); + border-radius: var(--app-border-radius); + background: var(--app-empty-bg); + color: var(--app-empty-text); + padding: calc(var(--app-spacing) * 0.875) var(--app-spacing); + display: grid; + gap: calc(var(--app-spacing) * 0.35); + text-align: center; + } + + .app-empty-state[data-size="compact"] { + padding: calc(var(--app-spacing) * 0.625) calc(var(--app-spacing) * 0.75); + gap: calc(var(--app-spacing) * 0.25); + } + + .app-empty-state[data-align="left"] { + text-align: left; + } + + .app-empty-state-message { + margin: 0; + color: var(--app-empty-text); + font-size: 0.95rem; + line-height: 1.4; + } + + .app-empty-state-hint { + margin: 0; + color: var(--app-empty-hint); + font-size: 0.85rem; + line-height: 1.3; + } + + .app-empty-state-action { + justify-self: center; + margin-top: calc(var(--app-spacing) * 0.15); + } + + .app-empty-state[data-align="left"] .app-empty-state-action { + justify-self: start; + } +}