Skip to content

Commit dff72f4

Browse files
committed
updated packages page design
Signed-off-by: bidi <bidi@apidemia.com>
1 parent b9db292 commit dff72f4

5 files changed

Lines changed: 181 additions & 14 deletions

File tree

public/css/app.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/js/app.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/App/assets/scss/components/_custom.scss

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
html[data-theme="light"] {
22
--bg: #FBF9F4;
33
--surface: #FFFFFF;
4-
--surface-2: #F3EFE6;
4+
--surface-2: #f8f6f2;
55
--border: #E3DDCF;
66
--border-soft: #EBE6DA;
77
--text: #0B0B0B;
@@ -17,6 +17,17 @@ html[data-theme="light"] {
1717
--teal-dim: rgba(163, 60, 75, .12);
1818
--nav-bg: rgba(251, 249, 244, .86);
1919
--on-accent: #FBF6F0;
20+
21+
/* OSS lifecycle states. The brand palette is deliberately one warm hue, so these are the
22+
only tokens that carry a second signal; they stay muted to sit beside the red. */
23+
--state-active: #2E7D64;
24+
--state-active-dim: rgba(46, 125, 100, .12);
25+
--state-maintenance: #96620A;
26+
--state-maintenance-dim: rgba(150, 98, 10, .12);
27+
--state-security: #C71F38;
28+
--state-security-dim: rgba(199, 31, 56, .12);
29+
--state-archived: #6B665C;
30+
--state-archived-dim: rgba(107, 102, 92, .1);
2031
}
2132

2233
html[data-theme="dark"] {
@@ -37,6 +48,16 @@ html[data-theme="dark"] {
3748
--amber-dim: rgba(218, 53, 80, .16);
3849
--teal-dim: rgba(232, 99, 122, .16);
3950
--nav-bg: rgba(11, 11, 11, .86);
51+
52+
/* Lifted for the dark surfaces; same four states as the light theme. */
53+
--state-active: #58B79A;
54+
--state-active-dim: rgba(88, 183, 154, .16);
55+
--state-maintenance: #DCA23C;
56+
--state-maintenance-dim: rgba(220, 162, 60, .16);
57+
--state-security: #E8637A;
58+
--state-security-dim: rgba(232, 99, 122, .16);
59+
--state-archived: #8A847C;
60+
--state-archived-dim: rgba(138, 132, 124, .14);
4061
}
4162

4263
html {
@@ -672,6 +693,136 @@ html[data-theme="light"] .theme-toggle {
672693
}
673694
}
674695

696+
/* ============================================================
697+
Package lifecycle cards
698+
============================================================ */
699+
700+
/* auto-fill keeps the packages grid responsive without breakpoints, since the
701+
number of packages changes with every cron run. */
702+
.packages-grid {
703+
display: grid;
704+
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
705+
gap: 18px;
706+
}
707+
708+
.package-card {
709+
border-top-width: 4px;
710+
transition: box-shadow .2s ease, transform .2s ease;
711+
712+
&:hover {
713+
box-shadow: 0 6px 20px var(--accent-dim);
714+
transform: translateY(-2px);
715+
}
716+
717+
.card-top {
718+
margin-bottom: 12px;
719+
}
720+
721+
h3 {
722+
margin: 0;
723+
}
724+
}
725+
726+
/* The pill carries the state, so it is the loudest thing on the card after the name. */
727+
.package-state {
728+
display: inline-flex;
729+
align-items: center;
730+
gap: 7px;
731+
margin-bottom: 8px;
732+
padding: 4px 10px;
733+
border: 1px solid var(--accent);
734+
border-radius: 999px;
735+
background: var(--accent-dim);
736+
color: var(--accent);
737+
font-family: var(--mono);
738+
font-size: 10.5px;
739+
font-weight: 600;
740+
letter-spacing: .1em;
741+
text-transform: uppercase;
742+
743+
/* Each state also changes the marker's shape, so the four are still telling apart
744+
when the hues are not (colour blindness, greyscale printing, forced-colours mode). */
745+
&::before {
746+
content: '';
747+
flex: none;
748+
width: 7px;
749+
height: 7px;
750+
border-radius: 50%;
751+
background: var(--accent);
752+
}
753+
}
754+
755+
.package-card--active {
756+
--accent: var(--state-active);
757+
--accent-dim: var(--state-active-dim);
758+
}
759+
760+
/* Hollow marker: still supported, no longer moving. */
761+
.package-card--maintenance {
762+
--accent: var(--state-maintenance);
763+
--accent-dim: var(--state-maintenance-dim);
764+
765+
.package-state::before {
766+
background: transparent;
767+
box-shadow: inset 0 0 0 2px var(--accent);
768+
}
769+
}
770+
771+
/* Haloed marker reads as a warning without leaning on hue alone. */
772+
.package-card--security-only {
773+
--accent: var(--state-security);
774+
--accent-dim: var(--state-security-dim);
775+
776+
.package-state::before {
777+
box-shadow: 0 0 0 3px var(--accent-dim);
778+
}
779+
}
780+
781+
/* Archived and unrecognised states recede: dashed edge, quieter surface, square marker. */
782+
.package-card--archived,
783+
.package-card--unknown {
784+
--accent: var(--state-archived);
785+
--accent-dim: var(--state-archived-dim);
786+
border-style: dashed;
787+
border-top-style: solid;
788+
789+
h3 {
790+
color: var(--text-muted);
791+
}
792+
793+
.package-state::before {
794+
border-radius: 2px;
795+
background: transparent;
796+
box-shadow: inset 0 0 0 2px var(--accent);
797+
}
798+
799+
.badges img {
800+
opacity: .65;
801+
}
802+
}
803+
804+
.package-archived {
805+
margin: 0;
806+
color: var(--text-dim);
807+
font-size: 12px;
808+
}
809+
810+
.packages-generated-at {
811+
margin-top: 22px;
812+
color: var(--text-dim);
813+
}
814+
815+
/* Respect a reduced-motion preference: the lift is decoration, the colour is the message. */
816+
@media (prefers-reduced-motion: reduce) {
817+
.package-card {
818+
transition: none;
819+
820+
&:hover {
821+
transform: none;
822+
}
823+
}
824+
}
825+
675826
.standards-grid {
676827
display: grid;
677828
grid-template-columns: repeat(3, 1fr);

src/App/templates/layout/default.html.twig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600" rel="stylesheet">
2020
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600" rel="stylesheet">
2121
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Barlow:wght@400;500;600;700&display=swap" rel="stylesheet"/>
22-
<link href="{{ asset('css/app.css') }}" rel="stylesheet" />
22+
<link href="{{ asset('css/app.css') }}?v=1" rel="stylesheet" />
2323
{% block json_ld %}{% endblock %}
2424
{% block stylesheets %}{% endblock %}
2525
</head>
@@ -103,7 +103,7 @@
103103
</div>
104104
</div>
105105
</footer>
106-
<script src="{{ asset('js/app.js') }}"></script>
106+
<script src="{{ asset('js/app.js') }}?v=1"></script>
107107
{% block javascript %}{% endblock %}
108108
</body>
109109
</html>

src/Blog/templates/page/dotkernel-packages-oss-lifecycle.html.twig

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@
1212

1313
{% block content %}
1414
{#
15-
Rendered from data/packages.json, rebuilt daily by bin/generate-packages.
15+
Rendered from public/packages.json, rebuilt daily by bin/generate-packages.
1616
The lifecycle value comes from each repository's OSSMETADATA file.
17+
18+
Every state gets its own colour, marker shape and card treatment, keyed off a
19+
`package-card--<state>` modifier. `title` spells out what the state means, since the
20+
label alone ("Security-only") does not say what a consumer should expect.
1721
#}
1822
{% set lifecycleMeta = {
19-
active: {label: 'Active', accent: 'var(--teal)'},
20-
maintenance: {label: 'Maintenance', accent: 'var(--brand-red)'},
21-
'security-only': {label: 'Security-only', accent: 'var(--amber)'},
22-
archived: {label: 'Archived', accent: 'var(--periwinkle)'},
23+
active: {label: 'Active', title: 'Actively developed, with new features and fixes.'},
24+
maintenance: {label: 'Maintenance', title: 'Still supported, receiving fixes but no new features.'},
25+
'security-only': {label: 'Security-only', title: 'Only security fixes are released. Plan an upgrade.'},
26+
archived: {label: 'Archived', title: 'No longer maintained. Do not use in new projects.'},
2327
} %}
2428

2529
<div class="wrap post-body-wrap">
@@ -28,13 +32,22 @@
2832
{{ include('@partial/left-menu.html.twig') }}
2933

3034
<main class="article">
31-
<div class="products-grid" style="grid-template-columns:repeat(auto-fill,minmax(240px,1fr));">
35+
<div class="packages-grid">
3236

3337
{% for package in packages %}
34-
{% set meta = lifecycleMeta[package.lifecycle] ?? {label: package.lifecycle|capitalize, accent: 'var(--periwinkle)'} %}
35-
<div class="card" style="--accent:{{ meta.accent }}">
38+
{# An unrecognised lifecycle falls back to the muted "unknown" treatment
39+
rather than emitting it into a class name. #}
40+
{% set state = lifecycleMeta[package.lifecycle] is defined ? package.lifecycle : 'unknown' %}
41+
{% set meta = lifecycleMeta[state]|default({
42+
label: package.lifecycle|capitalize,
43+
title: 'This package does not declare a recognised lifecycle.',
44+
}) %}
45+
<div class="card package-card package-card--{{ state }}">
3646
<div class="card-top">
37-
<div><span class="kicker">{{ meta.label }}</span><h3>{{ package.name }}</h3></div>
47+
<div>
48+
<span class="package-state" title="{{ meta.title }}">{{ meta.label }}</span>
49+
<h3>{{ package.name }}</h3>
50+
</div>
3851
</div>
3952
<div class="badges">
4053
<img alt="PHP version for dotkernel/{{ package.name }}" loading="lazy" src="https://img.shields.io/packagist/dependency-v/dotkernel/{{ package.name }}/php?style=social">
@@ -53,6 +66,9 @@
5366

5467
{% if generatedAt %}
5568
<p class="packages-generated-at"><small>Last updated {{ generatedAt|date('M d, Y H:i T') }}</small></p>
69+
<div class="card-btns">
70+
<a class="btn btn-ghost btn-sm" href="/packages.json">View as JSON</a>
71+
</div>
5672
{% endif %}
5773
</main>
5874
</div>

0 commit comments

Comments
 (0)