Add visual polish and micro-interactions for editorial feel
Phase 1 - Critical Fixes: - EmptyState: warm palette, coral button, Playfair Display title - Pagination: design system colors, coral active state - LoadingSkeleton: warm shimmer with coral tint Phase 2 - Signature Patterns: - Navigation: sliding underline hover effect on links - globals.css: increased noise texture opacity for paper feel - RankingsView: alternating row backgrounds - HomeView: decorative coral bar under section headings Phase 3 - Polish: - SchoolCard: SVG trend icons replacing unicode arrows - RankingsView: styled metallic rank badges replacing emoji medals Phase 4 - Micro-interactions: - Navigation badge: pop animation when count changes - HomeView grid: staggered entry animation for cards Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -67,7 +67,7 @@ body {
|
|||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subtle noise texture overlay */
|
/* Subtle noise texture overlay - editorial paper feel */
|
||||||
.noise-overlay {
|
.noise-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -75,7 +75,7 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 0.03;
|
opacity: 0.06;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,43 +5,53 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 4rem 2rem;
|
padding: 4rem 2rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: white;
|
background: var(--bg-card, white);
|
||||||
border: 2px dashed #e5e7eb;
|
border: 2px solid var(--border-color, #e5dfd5);
|
||||||
border-radius: 12px;
|
border-radius: 16px;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
|
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
color: #d1d5db;
|
color: var(--text-muted, #8a847a);
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin: 0 0 0.5rem 0;
|
margin: 0 0 0.75rem 0;
|
||||||
font-size: 1.25rem;
|
font-size: 1.5rem;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
color: #1f2937;
|
color: var(--text-primary, #1a1612);
|
||||||
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
margin: 0 0 1.5rem 0;
|
margin: 0 0 2rem 0;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: #6b7280;
|
color: var(--text-secondary, #5c564d);
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
padding: 0.75rem 1.5rem;
|
padding: 0.875rem 2rem;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
background: #3b82f6;
|
background: var(--accent-coral, #e07256);
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 6px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:hover {
|
.button:hover {
|
||||||
background: #2563eb;
|
background: var(--accent-coral-dark, #c45a3f);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(224, 114, 86, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:active {
|
||||||
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.heroTitle {
|
.heroTitle {
|
||||||
font-size: 2.75rem;
|
font-size: 3rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--text-primary, #1a1612);
|
color: var(--text-primary, #1a1612);
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.2;
|
line-height: 1.1;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
font-family: var(--font-playfair), 'Playfair Display', serif;
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,11 +59,22 @@
|
|||||||
.sectionHeader h2 {
|
.sectionHeader h2 {
|
||||||
font-size: 1.875rem;
|
font-size: 1.875rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.75rem;
|
||||||
color: var(--text-primary, #1a1612);
|
color: var(--text-primary, #1a1612);
|
||||||
font-family: var(--font-playfair), 'Playfair Display', serif;
|
font-family: var(--font-playfair), 'Playfair Display', serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Decorative coral bar under section headings */
|
||||||
|
.sectionHeader h2::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 60px;
|
||||||
|
height: 3px;
|
||||||
|
background: var(--accent-coral, #e07256);
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.sectionDescription {
|
.sectionDescription {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: var(--text-secondary, #5c564d);
|
color: var(--text-secondary, #5c564d);
|
||||||
@@ -102,6 +114,33 @@
|
|||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Staggered grid entry animation */
|
||||||
|
.grid > * {
|
||||||
|
animation: gridItemFadeIn 0.4s ease-out both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid > *:nth-child(1) { animation-delay: 0ms; }
|
||||||
|
.grid > *:nth-child(2) { animation-delay: 50ms; }
|
||||||
|
.grid > *:nth-child(3) { animation-delay: 100ms; }
|
||||||
|
.grid > *:nth-child(4) { animation-delay: 150ms; }
|
||||||
|
.grid > *:nth-child(5) { animation-delay: 200ms; }
|
||||||
|
.grid > *:nth-child(6) { animation-delay: 250ms; }
|
||||||
|
.grid > *:nth-child(7) { animation-delay: 300ms; }
|
||||||
|
.grid > *:nth-child(8) { animation-delay: 350ms; }
|
||||||
|
.grid > *:nth-child(9) { animation-delay: 400ms; }
|
||||||
|
.grid > *:nth-child(n+10) { animation-delay: 450ms; }
|
||||||
|
|
||||||
|
@keyframes gridItemFadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(16px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.emptyState {
|
.emptyState {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 4rem 2rem;
|
padding: 4rem 2rem;
|
||||||
|
|||||||
@@ -5,17 +5,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.skeletonCard {
|
.skeletonCard {
|
||||||
background: white;
|
background: var(--bg-card, white);
|
||||||
border: 1px solid #e5e7eb;
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
border-radius: 8px;
|
border-radius: 12px;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
|
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
|
||||||
}
|
}
|
||||||
|
|
||||||
.skeleton {
|
.skeleton {
|
||||||
background: linear-gradient(90deg, #f3f4f6 25%, #e5e7eb 50%, #f3f4f6 75%);
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--bg-secondary, #f3ede4) 25%,
|
||||||
|
rgba(224, 114, 86, 0.08) 50%,
|
||||||
|
var(--bg-secondary, #f3ede4) 75%
|
||||||
|
);
|
||||||
background-size: 200% 100%;
|
background-size: 200% 100%;
|
||||||
animation: shimmer 1.5s infinite;
|
animation: shimmer 1.5s ease-in-out infinite;
|
||||||
border-radius: 4px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes shimmer {
|
@keyframes shimmer {
|
||||||
@@ -50,8 +56,8 @@
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background: #f9fafb;
|
background: var(--bg-secondary, #f3ede4);
|
||||||
border-radius: 6px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric {
|
.metric {
|
||||||
@@ -76,10 +82,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.skeletonListItem {
|
.skeletonListItem {
|
||||||
background: white;
|
background: var(--bg-card, white);
|
||||||
border: 1px solid #e5e7eb;
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
border-radius: 8px;
|
border-radius: 12px;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
|
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
|
||||||
}
|
}
|
||||||
|
|
||||||
.listTitle {
|
.listTitle {
|
||||||
|
|||||||
@@ -63,16 +63,39 @@
|
|||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sliding underline effect */
|
||||||
|
.navLink::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 4px;
|
||||||
|
left: 1rem;
|
||||||
|
right: 1rem;
|
||||||
|
height: 2px;
|
||||||
|
background: var(--accent-coral, #e07256);
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: left;
|
||||||
|
transition: transform 0.25s ease;
|
||||||
|
border-radius: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.navLink:hover {
|
.navLink:hover {
|
||||||
color: var(--text-primary, #1a1612);
|
color: var(--text-primary, #1a1612);
|
||||||
background: var(--bg-secondary, #f3ede4);
|
background: var(--bg-secondary, #f3ede4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navLink:hover::after {
|
||||||
|
transform: scaleX(1);
|
||||||
|
}
|
||||||
|
|
||||||
.navLink.active {
|
.navLink.active {
|
||||||
color: var(--accent-coral, #e07256);
|
color: var(--accent-coral, #e07256);
|
||||||
background: rgba(224, 114, 86, 0.1);
|
background: rgba(224, 114, 86, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navLink.active::after {
|
||||||
|
transform: scaleX(1);
|
||||||
|
}
|
||||||
|
|
||||||
.badge {
|
.badge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -85,6 +108,22 @@
|
|||||||
color: white;
|
color: white;
|
||||||
background: var(--accent-coral, #e07256);
|
background: var(--accent-coral, #e07256);
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
|
animation: badgePop 0.3s ease-out;
|
||||||
|
box-shadow: 0 2px 6px rgba(224, 114, 86, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes badgePop {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.6);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
.info {
|
.info {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
color: #6b7280;
|
color: var(--text-muted, #8a847a);
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
@@ -21,17 +21,18 @@
|
|||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
background: white;
|
background: var(--bg-card, white);
|
||||||
color: #374151;
|
color: var(--text-secondary, #5c564d);
|
||||||
border: 1px solid #d1d5db;
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
border-radius: 6px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navButton:hover:not(:disabled) {
|
.navButton:hover:not(:disabled) {
|
||||||
background: #f9fafb;
|
background: var(--bg-secondary, #f3ede4);
|
||||||
border-color: #9ca3af;
|
border-color: var(--accent-coral, #e07256);
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
}
|
}
|
||||||
|
|
||||||
.navButton:disabled {
|
.navButton:disabled {
|
||||||
@@ -50,26 +51,32 @@
|
|||||||
padding: 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
background: white;
|
background: var(--bg-card, white);
|
||||||
border: 1px solid #d1d5db;
|
border: 1px solid var(--border-color, #e5dfd5);
|
||||||
border-radius: 6px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageButton {
|
.pageButton {
|
||||||
color: #374151;
|
color: var(--text-secondary, #5c564d);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageButton:hover {
|
.pageButton:hover {
|
||||||
background: #f9fafb;
|
background: var(--bg-secondary, #f3ede4);
|
||||||
border-color: #9ca3af;
|
border-color: var(--accent-coral, #e07256);
|
||||||
|
color: var(--text-primary, #1a1612);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageButtonActive {
|
.pageButtonActive {
|
||||||
background: #3b82f6;
|
background: var(--accent-coral, #e07256);
|
||||||
color: white;
|
color: white;
|
||||||
border-color: #3b82f6;
|
border-color: var(--accent-coral, #e07256);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageButtonActive:hover {
|
||||||
|
background: var(--accent-coral-dark, #c45a3f);
|
||||||
|
border-color: var(--accent-coral-dark, #c45a3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ellipsis {
|
.ellipsis {
|
||||||
@@ -77,7 +84,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
color: #9ca3af;
|
color: var(--text-muted, #8a847a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
|
|||||||
@@ -143,6 +143,11 @@
|
|||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Alternating row backgrounds for visual rhythm */
|
||||||
|
.rankingsTable tbody tr:nth-child(even) {
|
||||||
|
background: rgba(243, 237, 228, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
.rankingsTable tbody tr:hover {
|
.rankingsTable tbody tr:hover {
|
||||||
background: var(--bg-secondary, #f3ede4);
|
background: var(--bg-secondary, #f3ede4);
|
||||||
}
|
}
|
||||||
@@ -168,14 +173,51 @@
|
|||||||
color: var(--text-primary, #1a1612);
|
color: var(--text-primary, #1a1612);
|
||||||
}
|
}
|
||||||
|
|
||||||
.medal {
|
/* Styled rank badges for top 3 */
|
||||||
font-size: 1.5rem;
|
.rankBadge {
|
||||||
line-height: 1;
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rankBadge::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: -2px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.4), transparent) border-box;
|
||||||
|
mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
|
||||||
|
mask-composite: exclude;
|
||||||
|
-webkit-mask-composite: xor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rankBadge1 {
|
||||||
|
background: linear-gradient(135deg, #c9a227 0%, #e8c547 50%, #c9a227 100%);
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rankBadge2 {
|
||||||
|
background: linear-gradient(135deg, #8c8c8c 0%, #c0c0c0 50%, #8c8c8c 100%);
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rankBadge3 {
|
||||||
|
background: linear-gradient(135deg, #a5673f 0%, #cd7f32 50%, #a5673f 100%);
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rankNumber {
|
.rankNumber {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: var(--accent-gold, #c9a227);
|
color: var(--text-secondary, #5c564d);
|
||||||
}
|
}
|
||||||
|
|
||||||
.schoolCell {
|
.schoolCell {
|
||||||
@@ -280,8 +322,10 @@
|
|||||||
padding: 0.75rem 0.5rem;
|
padding: 0.75rem 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.medal {
|
.rankBadge {
|
||||||
font-size: 1.25rem;
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.schoolHeader {
|
.schoolHeader {
|
||||||
|
|||||||
@@ -188,14 +188,13 @@ export function RankingsView({
|
|||||||
className={isTopThree ? styles[`rank${rank}`] : ''}
|
className={isTopThree ? styles[`rank${rank}`] : ''}
|
||||||
>
|
>
|
||||||
<td className={styles.rankCell}>
|
<td className={styles.rankCell}>
|
||||||
{isTopThree && (
|
{isTopThree ? (
|
||||||
<span className={styles.medal}>
|
<span className={`${styles.rankBadge} ${styles[`rankBadge${rank}`]}`}>
|
||||||
{rank === 1 && '🥇'}
|
{rank}
|
||||||
{rank === 2 && '🥈'}
|
|
||||||
{rank === 3 && '🥉'}
|
|
||||||
</span>
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className={styles.rankNumber}>{rank}</span>
|
||||||
)}
|
)}
|
||||||
<span className={styles.rankNumber}>{rank}</span>
|
|
||||||
</td>
|
</td>
|
||||||
<td className={styles.schoolCell}>
|
<td className={styles.schoolCell}>
|
||||||
<a href={`/school/${ranking.urn}`} className={styles.schoolLink}>
|
<a href={`/school/${ranking.urn}`} className={styles.schoolLink}>
|
||||||
|
|||||||
@@ -101,9 +101,38 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.trend {
|
.trend {
|
||||||
font-size: 1rem;
|
display: inline-flex;
|
||||||
font-weight: bold;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
cursor: help;
|
cursor: help;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trend:hover {
|
||||||
|
transform: scale(1.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trendIcon {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trendUp {
|
||||||
|
color: var(--accent-teal, #2d7d7d);
|
||||||
|
background: rgba(45, 125, 125, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trendDown {
|
||||||
|
color: var(--accent-coral, #e07256);
|
||||||
|
background: rgba(224, 114, 86, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trendStable {
|
||||||
|
color: var(--text-muted, #8a847a);
|
||||||
|
background: rgba(138, 132, 122, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
|
|||||||
@@ -55,11 +55,30 @@ export function SchoolCard({ school, onAddToCompare, showDistance, distance }: S
|
|||||||
<strong>{formatPercentage(school.rwm_expected_pct)}</strong>
|
<strong>{formatPercentage(school.rwm_expected_pct)}</strong>
|
||||||
{school.prev_rwm_expected_pct !== null && (
|
{school.prev_rwm_expected_pct !== null && (
|
||||||
<span
|
<span
|
||||||
className={styles.trend}
|
className={`${styles.trend} ${styles[`trend${trend.charAt(0).toUpperCase() + trend.slice(1)}`]}`}
|
||||||
style={{ color: trendColor }}
|
|
||||||
title={`Previous: ${formatPercentage(school.prev_rwm_expected_pct)}`}
|
title={`Previous: ${formatPercentage(school.prev_rwm_expected_pct)}`}
|
||||||
>
|
>
|
||||||
{trend === 'up' ? '↑' : trend === 'down' ? '↓' : '→'}
|
{trend === 'up' && (
|
||||||
|
<svg viewBox="0 0 16 16" fill="none" className={styles.trendIcon}>
|
||||||
|
<path
|
||||||
|
d="M8 3L14 10H2L8 3Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
{trend === 'down' && (
|
||||||
|
<svg viewBox="0 0 16 16" fill="none" className={styles.trendIcon}>
|
||||||
|
<path
|
||||||
|
d="M8 13L2 6H14L8 13Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
{trend === 'stable' && (
|
||||||
|
<svg viewBox="0 0 16 16" fill="none" className={styles.trendIcon}>
|
||||||
|
<rect x="2" y="7" width="12" height="2" rx="1" fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user