Use new lte skin preview class for themes instead of colored circles

This commit is contained in:
johnnyq
2026-08-25 18:31:33 -04:00
parent d20e3f78d1
commit c6d642fbe7
4 changed files with 142 additions and 39 deletions

View File

@@ -49,11 +49,29 @@ $theme_colors_array = array(
value="<?= $theme_color ?>" value="<?= $theme_color ?>"
<?php if ($config_theme == $theme_color) { echo "checked"; } ?>> <?php if ($config_theme == $theme_color) { echo "checked"; } ?>>
<label class="itflow-theme-swatch" for="theme-<?= $theme_color ?>"> <label class="itflow-theme-swatch" for="theme-<?= $theme_color ?>">
<?php /* the circle paints itself from --itflow-accent, so it can <?php /* A miniature of the app, after AdminLTE 4's theme generator.
never drift out of step with the stylesheet */ ?> The wrapper carries .theme-<name>, so everything inside
<span class="itflow-theme-circle theme-<?= $theme_color ?>"> paints from that theme's --itflow-accent and the preview can
<i class="fas fa-circle"></i> never drift out of step with the stylesheet. Decorative -
<i class="fas fa-check itflow-theme-tick"></i> the name below is what the label actually announces. */ ?>
<span class="itflow-theme-preview theme-<?= $theme_color ?>" aria-hidden="true">
<span class="itflow-theme-preview-sidebar">
<span class="itflow-theme-preview-brand"></span>
<span class="itflow-theme-preview-item itflow-theme-preview-active"></span>
<span class="itflow-theme-preview-item"></span>
<span class="itflow-theme-preview-item"></span>
</span>
<span class="itflow-theme-preview-main">
<span class="itflow-theme-preview-header">
<span class="itflow-theme-preview-item"></span>
<span class="itflow-theme-preview-avatar"></span>
</span>
<span class="itflow-theme-preview-body">
<span class="itflow-theme-preview-box"></span>
<span class="itflow-theme-preview-box itflow-theme-preview-box-muted"></span>
<span class="itflow-theme-preview-card"></span>
</span>
</span>
</span> </span>
<span class="itflow-theme-name"><?= escapeHtml($theme_color) ?></span> <span class="itflow-theme-name"><?= escapeHtml($theme_color) ?></span>
</label> </label>

View File

@@ -29,8 +29,8 @@ if (isset($_GET['calendar_id'])) {
<div class="row"> <div class="row">
<div class="col-md-3 d-print-none"> <div class="col-md-3 d-print-none">
<div class="card"> <div class="card card-dark mb-3">
<div class="card-header bg-dark"> <div class="card-header">
<h3 class="card-title">Calendars</h3> <h3 class="card-title">Calendars</h3>
<div class="card-tools"> <div class="card-tools">
<button type="button" class="btn btn-tool ajax-modal" data-modal-url="modals/calendar/calendar_add.php"><i class="fas fa-plus" title="New Calendar"></i></button> <button type="button" class="btn btn-tool ajax-modal" data-modal-url="modals/calendar/calendar_add.php"><i class="fas fa-plus" title="New Calendar"></i></button>
@@ -81,8 +81,8 @@ if (isset($_GET['calendar_id'])) {
</div> </div>
</div> </div>
<div class="card"> <div class="card card-dark">
<div class="card-header bg-dark"> <div class="card-header">
<h3 class="card-title">Built-in</h3> <h3 class="card-title">Built-in</h3>
</div> </div>
<div class="card-body"> <div class="card-body">

View File

@@ -325,7 +325,7 @@ $summary_total_income = floatval($row['total_income']);
</form> </form>
</div> </div>
<div class="row"> <div class="row px-3 pt-3">
<div class="col-lg-4 col-md-6 col-sm-12"> <div class="col-lg-4 col-md-6 col-sm-12">
<!-- small box --> <!-- small box -->
<div class="small-box bg-blue text-white"> <div class="small-box bg-blue text-white">
@@ -370,8 +370,8 @@ $summary_total_income = floatval($row['total_income']);
</div> </div>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped table-borderless table-hover mb-0"> <table class="table table-hover mb-0">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap"> <thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap table-light border-top">
<tr> <tr>
<?php if (lookupUserPermission("module_sales") >= 3 && lookupUserPermission("module_financial") >= 3) { ?> <?php if (lookupUserPermission("module_sales") >= 3 && lookupUserPermission("module_financial") >= 3) { ?>
<td class="bg-light checkbox-column"> <td class="bg-light checkbox-column">

View File

@@ -486,13 +486,26 @@ a:focus {
/* --- Theme picker (admin/settings_theme.php) ----------------------------- /* --- Theme picker (admin/settings_theme.php) -----------------------------
Keeps the coloured circles - the radio button beside each one is what was Each choice is a miniature of the app rather than a colour circle, so you
in the way, so the input is now a visually hidden .btn-check and the label can see where the colour actually lands before committing to it. Structure
is the control. Selection reads as a tick in the circle plus a bolder name. and proportions are lifted from AdminLTE 4's own theme generator
(dist/generate/theme.html) - note those .lte-skin-preview-* rules live in
that page's inline <style> and are NOT in adminlte.min.css, so they are
reproduced here under ITFlow-owned names to avoid colliding with anything
upstream may ship later.
The circle carries .theme-<name> and paints itself from --itflow-accent, so The mini-app reflects how ITFlow actually applies a theme, not AdminLTE's
it always shows the colour that theme will actually apply - add a theme to presets: the sidebar is always dark with the accent on its active item, the
the stylesheet and its swatch is correct with no extra rule. */ top bar takes the accent, and the content area shows an accent widget
beside a neutral one.
The preview carries .theme-<name>, so --itflow-accent is re-scoped for that
subtree and every swatch paints itself from the same variable the theme
will apply - add a theme to the stylesheet and its preview is correct with
no extra rule.
The radio is a visually hidden .btn-check and the label is the control.
Selection reads as a ring around the preview plus a bolder name. */
.itflow-theme-swatch { .itflow-theme-swatch {
display: block; display: block;
padding: .5rem .25rem; padding: .5rem .25rem;
@@ -504,29 +517,100 @@ a:focus {
.itflow-theme-swatch:hover { .itflow-theme-swatch:hover {
background-color: var(--bs-secondary-bg); background-color: var(--bs-secondary-bg);
} }
.itflow-theme-circle { .itflow-theme-preview {
position: relative;
display: inline-flex; display: inline-flex;
align-items: center; width: 6rem;
justify-content: center; height: 3.75rem;
line-height: 1; overflow: hidden;
vertical-align: middle;
background-color: var(--bs-tertiary-bg);
border: 1px solid var(--bs-border-color);
border-radius: var(--bs-border-radius);
transition: border-color .15s ease, box-shadow .15s ease;
} }
.itflow-theme-circle .fa-circle { /* the sidebar is always dark in ITFlow, whatever the theme */
font-size: 3.5rem; .itflow-theme-preview-sidebar {
color: var(--itflow-accent, #007bff); display: flex;
} flex: 0 0 30%;
.itflow-theme-tick { flex-direction: column;
position: absolute; gap: 9%;
font-size: 1.35rem; padding: 10% 12%;
color: #fff; color: #fff;
opacity: 0; background-color: #343a40;
transition: opacity .15s ease;
} }
/* light circles need a dark tick - same L>0.335 cut as the buttons */ .itflow-theme-preview-brand,
.itflow-theme-circle.theme-yellow .itflow-theme-tick, .itflow-theme-preview-item {
.itflow-theme-circle.theme-orange .itflow-theme-tick, display: block;
.itflow-theme-circle.theme-teal .itflow-theme-tick { flex: none;
color: #000; height: 7%;
min-height: 2px;
background: currentColor;
border-radius: 99px;
opacity: .45;
}
.itflow-theme-preview-brand {
width: 70%;
height: 11%;
min-height: 3px;
margin-bottom: 6%;
opacity: .9;
}
/* only the active sidebar item takes the accent - same as the real sidebar */
.itflow-theme-preview-active {
background: var(--itflow-accent, #007bff);
opacity: 1;
}
.itflow-theme-preview-main {
display: flex;
flex: auto;
flex-direction: column;
min-width: 0;
}
.itflow-theme-preview-header {
display: flex;
flex: 0 0 24%;
gap: 6%;
align-items: center;
padding: 0 8%;
color: #fff;
background-color: var(--itflow-accent, #007bff);
}
.itflow-theme-preview-header .itflow-theme-preview-item {
width: 24%;
height: 22%;
opacity: .55;
}
.itflow-theme-preview-avatar {
display: block;
width: 14%;
margin-left: auto;
aspect-ratio: 1;
background: currentColor;
border-radius: 50%;
opacity: .55;
}
.itflow-theme-preview-body {
display: grid;
flex: auto;
grid-template-rows: 1fr 1fr;
grid-template-columns: 1fr 1fr;
gap: 8%;
padding: 10%;
}
.itflow-theme-preview-box {
display: block;
background-color: var(--itflow-accent, #007bff);
border-radius: 2px;
}
.itflow-theme-preview-box-muted {
background-color: var(--bs-secondary-bg);
}
.itflow-theme-preview-card {
display: block;
grid-column: 1 / -1;
background-color: var(--bs-body-bg);
border: 1px solid var(--bs-border-color);
border-radius: 2px;
} }
.itflow-theme-name { .itflow-theme-name {
display: block; display: block;
@@ -534,8 +618,9 @@ a:focus {
font-size: .8125rem; font-size: .8125rem;
text-transform: capitalize; text-transform: capitalize;
} }
.btn-check:checked + .itflow-theme-swatch .itflow-theme-tick { .btn-check:checked + .itflow-theme-swatch .itflow-theme-preview {
opacity: 1; border-color: var(--bs-body-color);
box-shadow: 0 0 0 1px var(--bs-body-color);
} }
.btn-check:checked + .itflow-theme-swatch .itflow-theme-name { .btn-check:checked + .itflow-theme-swatch .itflow-theme-name {
font-weight: 600; font-weight: 600;