Restyle individual page: FAB edit button, uncropped profile pics, silhouette placeholders, dark mode tabs
- Override individual-page-images template to request 400x400 contain (no server-side crop) - Move circle crop to CSS on a.gallery wrapper, fixing single-image profiles - Add gender-colored circular silhouette placeholders matching family navigator - Replace edit button with fixed FAB (bottom-right) using homepage pencil SVG - Add page cloak to prevent FOUC from JS DOM manipulations - Dark mode: white profile shadow, black active tab with light blue accent - Remove carousel arrows and "add media" link at template level
This commit is contained in:
+160
-38
@@ -10,23 +10,30 @@
|
||||
|
||||
/* ---------- Profile photo: large circle, no border ---------- */
|
||||
|
||||
.wt-route-IndividualPage .col-sm-3 .img-thumbnail {
|
||||
border-radius: 50%;
|
||||
aspect-ratio: 1 / 1;
|
||||
object-fit: cover;
|
||||
border: none;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
padding: 0;
|
||||
transition: box-shadow 0.3s ease, transform 0.3s ease;
|
||||
width: 100%;
|
||||
max-width: 260px;
|
||||
#individual-images .carousel-inner {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.wt-route-IndividualPage .col-sm-3 .img-thumbnail:hover {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
||||
transform: translateY(-2px);
|
||||
.wt-route-IndividualPage .col-sm-3 a.gallery {
|
||||
display: block;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.wt-route-IndividualPage .col-sm-3 a.gallery .img-thumbnail {
|
||||
border-radius: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* Center the photo column */
|
||||
.wt-route-IndividualPage .col-sm-3 {
|
||||
display: flex;
|
||||
@@ -34,26 +41,41 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Silhouette placeholder: constrain to match photo size, circular background */
|
||||
.wt-route-IndividualPage .col-sm-3 .wt-individual-silhouette {
|
||||
display: block;
|
||||
width: auto !important;
|
||||
max-height: 260px;
|
||||
aspect-ratio: 1 / 1;
|
||||
object-fit: contain;
|
||||
/* Silhouette placeholder: circular with gender-based background */
|
||||
.wt-route-IndividualPage .col-sm-3 > .img-thumbnail {
|
||||
border-radius: 50%;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
padding: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* "Add a media object" link — subtle */
|
||||
.wt-route-IndividualPage .col-sm-3 .text-center a {
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.45;
|
||||
transition: opacity 0.2s;
|
||||
.wt-route-IndividualPage .col-sm-3 .wt-individual-silhouette {
|
||||
display: block;
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
opacity: 0.15;
|
||||
filter: brightness(0);
|
||||
}
|
||||
.wt-route-IndividualPage .col-sm-3 .text-center a:hover {
|
||||
opacity: 1;
|
||||
|
||||
/* Gender-based silhouette container — light mode */
|
||||
.wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-m) {
|
||||
background-color: #d1dce7;
|
||||
}
|
||||
|
||||
.wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-f) {
|
||||
background-color: #ded7e2;
|
||||
}
|
||||
|
||||
.wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-u) {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- Individual header: photo + title + edit ---------- */
|
||||
|
||||
.wt-route-IndividualPage .bocken-individual-header {
|
||||
@@ -68,7 +90,7 @@
|
||||
width: auto;
|
||||
max-width: 260px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.wt-route-IndividualPage .wt-page-title {
|
||||
@@ -100,20 +122,56 @@
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
/* Edit button: icon-only pencil */
|
||||
.wt-route-IndividualPage .bocken-title-user a {
|
||||
color: #2E3440;
|
||||
}
|
||||
|
||||
/* Edit button: fixed FAB in bottom-right corner */
|
||||
.wt-route-IndividualPage .wt-page-menu-button {
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
padding: 2rem;
|
||||
margin: 2rem;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background-color: #BF616A;
|
||||
border: none;
|
||||
z-index: 100;
|
||||
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||
--shake-angle: 15deg;
|
||||
}
|
||||
|
||||
.wt-route-IndividualPage .wt-page-menu-button:hover,
|
||||
.wt-route-IndividualPage .wt-page-menu-button:focus {
|
||||
background-color: #2E3440;
|
||||
box-shadow: 0 0 0.4em 0.15em rgba(0, 0, 0, 0.15);
|
||||
animation: bocken-shake 0.5s forwards;
|
||||
}
|
||||
|
||||
.wt-route-IndividualPage .wt-page-menu-button .wt-icon-menu svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
fill: white;
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
@keyframes bocken-shake {
|
||||
0% { transform: rotate(0) scale(1); }
|
||||
25% { box-shadow: 0 0 0.5em 0.15em rgba(0, 0, 0, 0.25); transform: rotate(var(--shake-angle)) scale(1.2); }
|
||||
50% { box-shadow: 0 0 0.5em 0.15em rgba(0, 0, 0, 0.25); transform: rotate(calc(-1 * var(--shake-angle))) scale(1.2); }
|
||||
74% { box-shadow: 0 0 0.5em 0.15em rgba(0, 0, 0, 0.25); transform: rotate(var(--shake-angle)) scale(1.2); }
|
||||
100% { transform: rotate(0) scale(1.2); }
|
||||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
.wt-route-IndividualPage .wt-page-menu-button {
|
||||
margin: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide dropdown caret on the round button */
|
||||
@@ -516,9 +574,9 @@
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.wt-route-IndividualPage .col-sm-3 .img-thumbnail {
|
||||
max-width: 80px;
|
||||
.wt-route-IndividualPage .col-sm-3 a.gallery {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
/* Names accordion: full width */
|
||||
@@ -571,6 +629,38 @@
|
||||
background: var(--color-primary, #5E81AC);
|
||||
}
|
||||
|
||||
/* Active tab: black background, light blue accent */
|
||||
:root[data-theme=dark] .wt-tabs-individual .nav-tabs .nav-link.active {
|
||||
background: #000;
|
||||
border-bottom-color: #88C0D0;
|
||||
}
|
||||
|
||||
/* Silhouette icon tint */
|
||||
:root[data-theme=dark] .wt-route-IndividualPage .col-sm-3 .wt-individual-silhouette {
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
/* Silhouette gender colors */
|
||||
:root[data-theme=dark] .wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-m) {
|
||||
background-color: #505f73;
|
||||
}
|
||||
:root[data-theme=dark] .wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-f) {
|
||||
background-color: #5f596d;
|
||||
}
|
||||
:root[data-theme=dark] .wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-u) {
|
||||
background-color: #4C566A;
|
||||
}
|
||||
|
||||
/* Profile picture shadow */
|
||||
:root[data-theme=dark] .wt-route-IndividualPage .col-sm-3 a.gallery {
|
||||
box-shadow: 0 4px 8px rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
/* Username link */
|
||||
:root[data-theme=dark] .wt-route-IndividualPage .bocken-title-user a {
|
||||
color: #ECEFF4;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
:root[data-theme=dark] .wt-route-IndividualPage .wt-facts-table a,
|
||||
:root[data-theme=dark] .wt-route-IndividualPage .wt-family-navigator-family a,
|
||||
@@ -617,6 +707,38 @@
|
||||
background: var(--color-primary, #5E81AC);
|
||||
}
|
||||
|
||||
/* Active tab: black background, light blue accent */
|
||||
:root:not([data-theme=light]) .wt-tabs-individual .nav-tabs .nav-link.active {
|
||||
background: #000;
|
||||
border-bottom-color: #88C0D0;
|
||||
}
|
||||
|
||||
/* Silhouette icon tint */
|
||||
:root:not([data-theme=light]) .wt-route-IndividualPage .col-sm-3 .wt-individual-silhouette {
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
/* Silhouette gender colors */
|
||||
:root:not([data-theme=light]) .wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-m) {
|
||||
background-color: #505f73;
|
||||
}
|
||||
:root:not([data-theme=light]) .wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-f) {
|
||||
background-color: #5f596d;
|
||||
}
|
||||
:root:not([data-theme=light]) .wt-route-IndividualPage .col-sm-3 > .img-thumbnail:has(.wt-individual-silhouette-u) {
|
||||
background-color: #4C566A;
|
||||
}
|
||||
|
||||
/* Profile picture shadow */
|
||||
:root:not([data-theme=light]) .wt-route-IndividualPage .col-sm-3 a.gallery {
|
||||
box-shadow: 0 4px 8px rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
/* Username link */
|
||||
:root:not([data-theme=light]) .wt-route-IndividualPage .bocken-title-user a {
|
||||
color: #ECEFF4;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
:root:not([data-theme=light]) .wt-route-IndividualPage .wt-facts-table a,
|
||||
:root:not([data-theme=light]) .wt-route-IndividualPage .wt-family-navigator-family a,
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Fisharebest\Webtrees\Fact;
|
||||
use Fisharebest\Webtrees\Http\RequestHandlers\AddNewFact;
|
||||
use Fisharebest\Webtrees\I18N;
|
||||
use Fisharebest\Webtrees\Individual;
|
||||
use Fisharebest\Webtrees\Media;
|
||||
use Fisharebest\Webtrees\Module\ModuleSidebarInterface;
|
||||
use Fisharebest\Webtrees\Module\ModuleTabInterface;
|
||||
use Fisharebest\Webtrees\Tree;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* @var string $age
|
||||
* @var bool $can_upload_media
|
||||
* @var Collection<int,Media> $individual_media
|
||||
* @var Collection<int,Fact> $name_records
|
||||
* @var Individual $record
|
||||
* @var Collection<int,Fact> $sex_records
|
||||
* @var Collection<int,string> $shares
|
||||
* @var Collection<int,ModuleSidebarInterface> $sidebars
|
||||
* @var Collection<int,ModuleTabInterface> $tabs
|
||||
* @var Tree $tree
|
||||
* @var string $user_link
|
||||
*/
|
||||
?>
|
||||
|
||||
<?php if ($individual_media->isNotEmpty() || $tree->getPreference('USE_SILHOUETTE') === '1') : ?>
|
||||
<div class="col-sm-3">
|
||||
<?php if ($individual_media->isEmpty()) : ?>
|
||||
<div class="img-thumbnail">
|
||||
<i class="wt-individual-silhouette wt-individual-silhouette-<?= strtolower($record->sex()) ?> wt-icon-flip-rtl w-100"></i>
|
||||
</div>
|
||||
<?php elseif ($individual_media->count() === 1) : ?>
|
||||
<?= $individual_media->first()->displayImage(400, 400, 'contain', ['class' => 'img-thumbnail img-fluid w-100']) ?>
|
||||
<?php else : ?>
|
||||
<div id="individual-images" class="carousel slide" data-bs-interval="false">
|
||||
<div class="carousel-inner">
|
||||
<?php foreach ($individual_media as $n => $media_file) : ?>
|
||||
<div class="carousel-item <?= $n === 0 ? 'active' : '' ?>">
|
||||
<?= $media_file->displayImage(400, 400, 'contain', ['class' => 'img-thumbnail img-fluid w-100']) ?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
Reference in New Issue
Block a user