forked from UKSOURCE/hailearning.edu.vn
feat: complete publications and research sections and resolve conflicts
This commit is contained in:
45
app/components/publications/PublicationHeader.tsx
Normal file
45
app/components/publications/PublicationHeader.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import React from 'react';
|
||||
|
||||
const PublicationHeader = () => {
|
||||
return (
|
||||
<section id="repo-header">
|
||||
<div className="max-w-[1440px] mx-auto px-6 lg:px-8">
|
||||
|
||||
{/* Title row + action buttons */}
|
||||
<div className="flex flex-col lg:flex-row justify-between items-start lg:items-end gap-6 mb-8 w-full">
|
||||
<div className="flex-1 max-w-3xl">
|
||||
<h1>Publication Repository</h1>
|
||||
<p>Search, filter, and access over 15,000 academic publications and research papers.</p>
|
||||
</div>
|
||||
<div className="flex gap-3 shrink-0">
|
||||
<button className="pub-btn-outline">
|
||||
<i className="fa-regular fa-bookmark"></i>
|
||||
Saved Searches
|
||||
</button>
|
||||
<button className="pub-btn-primary">
|
||||
<i className="fa-solid fa-download"></i>
|
||||
Export Results
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Search bar */}
|
||||
<div className="pub-search-bar">
|
||||
<span className="pub-search-icon">
|
||||
<i className="fa-solid fa-magnifying-glass"></i>
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search by title, author, keyword, or DOI..."
|
||||
/>
|
||||
<div className="pub-search-btn-wrap">
|
||||
<button className="pub-btn-primary">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicationHeader;
|
||||
169
app/components/publications/PublicationResults.tsx
Normal file
169
app/components/publications/PublicationResults.tsx
Normal file
@@ -0,0 +1,169 @@
|
||||
'use client';
|
||||
import React, { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
const SORT_OPTIONS = ['Relevance', 'Newest First', 'Oldest First', 'Most Cited'];
|
||||
|
||||
const PublicationResults = () => {
|
||||
const [isSortOpen, setIsSortOpen] = useState(false);
|
||||
const [selectedSort, setSelectedSort] = useState('Relevance');
|
||||
|
||||
return (
|
||||
<div className="pub-results">
|
||||
|
||||
{/* Toolbar */}
|
||||
<div className="pub-results-toolbar">
|
||||
<p className="pub-results-count">
|
||||
Showing <strong>1-10</strong> of <strong>12,450</strong> results
|
||||
</p>
|
||||
|
||||
<div className="pub-sort-wrap">
|
||||
<label>Sort by:</label>
|
||||
<div className="pub-sort-dropdown">
|
||||
<button
|
||||
className={`pub-sort-dropdown-btn ${isSortOpen ? 'open' : ''}`}
|
||||
onClick={() => setIsSortOpen(!isSortOpen)}
|
||||
>
|
||||
<span>{selectedSort}</span>
|
||||
<i className="fa-solid fa-chevron-down"></i>
|
||||
</button>
|
||||
{isSortOpen && (
|
||||
<div className="pub-sort-dropdown-menu">
|
||||
{SORT_OPTIONS.map((opt) => (
|
||||
<div
|
||||
key={opt}
|
||||
className={`pub-sort-dropdown-option ${selectedSort === opt ? 'selected' : ''}`}
|
||||
onClick={() => { setSelectedSort(opt); setIsSortOpen(false); }}
|
||||
>
|
||||
{opt}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Cards */}
|
||||
<div className="pub-card-list">
|
||||
|
||||
{/* Card 1 */}
|
||||
<div className="pub-card">
|
||||
<div className="pub-card-top">
|
||||
<h3 className="pub-card-title">
|
||||
<Link href="#">The Evolution of Democratic Institutions in Post-War Europe</Link>
|
||||
</h3>
|
||||
<div className="pub-badges">
|
||||
<span className="pub-badge pub-badge-open">
|
||||
<i className="fa-solid fa-lock-open"></i> Open Access
|
||||
</span>
|
||||
<span className="pub-badge pub-badge-peer">Peer Reviewed</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pub-card-meta">
|
||||
<div className="pub-meta-item">
|
||||
<i className="fa-solid fa-user"></i>
|
||||
<strong>Dr. Elena Rostova</strong>, Prof. Marcus Chen
|
||||
</div>
|
||||
<div className="pub-meta-item">
|
||||
<i className="fa-regular fa-calendar"></i> October 2024
|
||||
</div>
|
||||
<div className="pub-meta-item">
|
||||
<i className="fa-solid fa-link"></i> DOI: 10.1038/s41586-024
|
||||
</div>
|
||||
<div className="pub-meta-item">
|
||||
<i className="fa-solid fa-building-columns"></i> Center for Political Studies
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="pub-card-abstract">
|
||||
This paper examines the structural shifts in Western European democratic frameworks from 1945 to 1980. By analyzing institutional archives across France, Germany, and Italy, the research identifies a distinct divergence in how parliamentary powers were consolidated versus distributed. The findings challenge traditional narratives of a uniform democratic resurgence, suggesting instead that local historical contexts heavily dictated the adoption of specific liberal norms.
|
||||
</p>
|
||||
|
||||
<div className="pub-keywords">
|
||||
<span className="pub-keywords-label">Keywords:</span>
|
||||
<span className="pub-keyword-tag">Democracy</span>
|
||||
<span className="pub-keyword-tag">European History</span>
|
||||
<span className="pub-keyword-tag">Institutions</span>
|
||||
</div>
|
||||
|
||||
<div className="pub-card-actions">
|
||||
<button className="pub-action-btn pub-action-btn-primary">
|
||||
<i className="fa-solid fa-file-pdf"></i> View PDF
|
||||
</button>
|
||||
<button className="pub-action-btn pub-action-btn-secondary">
|
||||
<i className="fa-solid fa-quote-right"></i> Cite
|
||||
</button>
|
||||
<button className="pub-action-btn pub-action-btn-secondary">
|
||||
<i className="fa-regular fa-bookmark"></i> Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Card 2 */}
|
||||
<div className="pub-card">
|
||||
<div className="pub-card-top">
|
||||
<h3 className="pub-card-title">
|
||||
<Link href="#">Cognitive Linguistics and the Framing of Modern Ethics</Link>
|
||||
</h3>
|
||||
<div className="pub-badges">
|
||||
<span className="pub-badge pub-badge-institutional">
|
||||
<i className="fa-solid fa-building-user"></i> Institutional
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pub-card-meta">
|
||||
<div className="pub-meta-item">
|
||||
<i className="fa-solid fa-user"></i>
|
||||
<strong>Dr. Sarah Jenkins</strong>
|
||||
</div>
|
||||
<div className="pub-meta-item">
|
||||
<i className="fa-regular fa-calendar"></i> August 2024
|
||||
</div>
|
||||
<div className="pub-meta-item">
|
||||
<i className="fa-solid fa-link"></i> DOI: 10.1016/j.cogling.2024
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="pub-card-abstract">
|
||||
An exploration into how metaphor and cognitive framing shape contemporary ethical debates. The study utilizes computational linguistics to analyze over 10,000 policy documents and public speeches, demonstrating a significant correlation between specific metaphorical structures and the resulting ethical policy frameworks adopted by legislative bodies.
|
||||
</p>
|
||||
|
||||
<div className="pub-card-actions">
|
||||
<button className="pub-action-btn pub-action-btn-primary">
|
||||
<i className="fa-solid fa-arrow-right-to-bracket"></i> Login to Access
|
||||
</button>
|
||||
<button className="pub-action-btn pub-action-btn-secondary">
|
||||
<i className="fa-solid fa-quote-right"></i> Cite
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Pagination */}
|
||||
<div className="pub-pagination">
|
||||
<button className="pub-page-btn" disabled>
|
||||
<i className="fa-solid fa-arrow-left"></i> Previous
|
||||
</button>
|
||||
|
||||
<div className="pub-page-numbers">
|
||||
<button className="pub-page-num active">1</button>
|
||||
<button className="pub-page-num">2</button>
|
||||
<button className="pub-page-num">3</button>
|
||||
<span className="pub-page-ellipsis">...</span>
|
||||
<button className="pub-page-num">124</button>
|
||||
</div>
|
||||
|
||||
<button className="pub-page-btn">
|
||||
Next <i className="fa-solid fa-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicationResults;
|
||||
123
app/components/publications/PublicationSidebar.tsx
Normal file
123
app/components/publications/PublicationSidebar.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const YEARS = ['2024 (1,245)', '2023 (3,412)', '2022 (2,890)'];
|
||||
const DOMAINS = ['Liberal Arts (4,521)', 'Social Sciences (3,210)', 'Humanities (2,980)', 'Political Science (1,840)'];
|
||||
const ACCESS_TYPES = ['Open Access', 'Institutional Login', 'Request Access'];
|
||||
|
||||
const AccordionSection = ({
|
||||
title,
|
||||
open,
|
||||
onToggle,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
open: boolean;
|
||||
onToggle: () => void;
|
||||
children: React.ReactNode;
|
||||
}) => (
|
||||
<div className="pub-accordion-item">
|
||||
<button
|
||||
className={`pub-accordion-trigger ${open ? 'open' : ''}`}
|
||||
onClick={onToggle}
|
||||
>
|
||||
{title}
|
||||
<i className="fa-solid fa-chevron-down"></i>
|
||||
</button>
|
||||
<div className={`pub-accordion-body ${open ? 'open' : ''}`}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const PublicationSidebar = () => {
|
||||
const [isYearOpen, setIsYearOpen] = useState(true);
|
||||
const [isDomainOpen, setIsDomainOpen] = useState(true);
|
||||
const [isAccessOpen, setIsAccessOpen] = useState(true);
|
||||
const [minYear, setMinYear] = useState('');
|
||||
const [maxYear, setMaxYear] = useState('');
|
||||
|
||||
return (
|
||||
<aside className="pub-sidebar">
|
||||
<div className="pub-sidebar-inner">
|
||||
|
||||
<div className="pub-sidebar-header">
|
||||
<h2>
|
||||
<i className="fa-solid fa-filter"></i> Filters
|
||||
</h2>
|
||||
<button
|
||||
className="pub-clear-btn"
|
||||
onClick={() => { setMinYear(''); setMaxYear(''); }}
|
||||
>
|
||||
Clear All
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="pub-accordion">
|
||||
|
||||
{/* Publication Year */}
|
||||
<AccordionSection title="Publication Year" open={isYearOpen} onToggle={() => setIsYearOpen(!isYearOpen)}>
|
||||
<div className="pub-filter-list">
|
||||
{YEARS.map((year, idx) => (
|
||||
<label key={year} className="pub-filter-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="pub-checkbox"
|
||||
defaultChecked={idx === 0}
|
||||
/>
|
||||
<span>{year}</span>
|
||||
</label>
|
||||
))}
|
||||
<div className="pub-year-range">
|
||||
<input
|
||||
type="number"
|
||||
placeholder="Min"
|
||||
value={minYear}
|
||||
onChange={(e) => setMinYear(e.target.value)}
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="Max"
|
||||
value={maxYear}
|
||||
onChange={(e) => setMaxYear(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionSection>
|
||||
|
||||
{/* Research Domain */}
|
||||
<AccordionSection title="Research Domain" open={isDomainOpen} onToggle={() => setIsDomainOpen(!isDomainOpen)}>
|
||||
<div className="pub-filter-list">
|
||||
{DOMAINS.map((domain, idx) => (
|
||||
<label key={domain} className="pub-filter-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="pub-checkbox"
|
||||
defaultChecked={idx === 0}
|
||||
/>
|
||||
<span>{domain}</span>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</AccordionSection>
|
||||
|
||||
{/* Access Type */}
|
||||
<AccordionSection title="Access Type" open={isAccessOpen} onToggle={() => setIsAccessOpen(!isAccessOpen)}>
|
||||
<div className="pub-filter-list">
|
||||
{ACCESS_TYPES.map((type) => (
|
||||
<label key={type} className="pub-filter-label">
|
||||
<input type="checkbox" className="pub-checkbox" />
|
||||
<span>{type}</span>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</AccordionSection>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicationSidebar;
|
||||
787
app/components/publications/publications.css
Normal file
787
app/components/publications/publications.css
Normal file
@@ -0,0 +1,787 @@
|
||||
/* ============================================================
|
||||
publications.css — Scoped under .pub-wrapper
|
||||
Matches the HTML reference design exactly.
|
||||
All rules are scoped to avoid conflicts with Bootstrap/main.css
|
||||
============================================================ */
|
||||
|
||||
/* --- Local CSS Variables (override globals for this page) --- */
|
||||
.pub-wrapper {
|
||||
--pub-blue: #263c6f;
|
||||
--pub-blue-hover: #1d2e55;
|
||||
--pub-blue-light: #f0f4f8;
|
||||
--pub-border: #e5e7eb;
|
||||
--pub-text: #111827;
|
||||
--pub-muted: #6b7280;
|
||||
--pub-bg: #f9fafb;
|
||||
--pub-accent: #3b82f6;
|
||||
|
||||
background-color: var(--pub-bg);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
SEARCH HEADER SECTION
|
||||
============================================================ */
|
||||
.pub-wrapper #repo-header {
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
border-bottom: 1px solid var(--pub-border);
|
||||
padding-top: 3rem;
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
||||
.pub-wrapper #repo-header h1 {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 700;
|
||||
color: var(--pub-text);
|
||||
letter-spacing: -0.025em;
|
||||
margin-bottom: 0.5rem;
|
||||
line-height: 2.5rem;
|
||||
}
|
||||
|
||||
.pub-wrapper #repo-header p {
|
||||
color: var(--pub-muted);
|
||||
font-size: 1.125rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Search bar */
|
||||
.pub-wrapper .pub-search-bar {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border-radius: 0.75rem;
|
||||
box-shadow: 0 1px 2px 0 rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-search-bar input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 1rem 8rem 1rem 3rem;
|
||||
border: 1px solid var(--pub-border);
|
||||
border-radius: 0.75rem;
|
||||
font-size: 1.125rem;
|
||||
color: var(--pub-text);
|
||||
background-color: #ffffff;
|
||||
outline: none;
|
||||
transition: border-color 0.2s, box-shadow 0.2s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-search-bar input::placeholder {
|
||||
color: var(--pub-muted);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-search-bar input:focus {
|
||||
border-color: var(--pub-blue);
|
||||
box-shadow: 0 0 0 2px rgba(38, 60, 111, 0.15);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-search-bar .pub-search-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 1rem;
|
||||
transform: translateY(-50%);
|
||||
color: var(--pub-muted);
|
||||
font-size: 1.125rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-search-bar .pub-search-btn-wrap {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0.5rem;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
BUTTONS
|
||||
============================================================ */
|
||||
.pub-wrapper .pub-btn-primary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: var(--pub-blue);
|
||||
color: #ffffff;
|
||||
border: 1px solid var(--pub-blue);
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-btn-primary:hover {
|
||||
background-color: var(--pub-blue-hover);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-btn-outline {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: #ffffff;
|
||||
color: var(--pub-text);
|
||||
border: 1px solid var(--pub-border);
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s, color 0.2s;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 1px 2px 0 rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-btn-outline:hover {
|
||||
border-color: var(--pub-blue);
|
||||
color: var(--pub-blue);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
MAIN CONTENT LAYOUT
|
||||
============================================================ */
|
||||
.pub-wrapper #repo-content {
|
||||
padding-top: 2.5rem;
|
||||
padding-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.pub-wrapper .pub-layout {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
SIDEBAR
|
||||
============================================================ */
|
||||
.pub-wrapper .pub-sidebar {
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.pub-wrapper .pub-sidebar {
|
||||
width: 20rem; /* 320px */
|
||||
min-width: 20rem;
|
||||
max-width: 20rem;
|
||||
}
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sidebar-inner {
|
||||
background-color: #ffffff;
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid var(--pub-border);
|
||||
box-shadow: 0 1px 2px 0 rgba(0,0,0,0.05);
|
||||
padding: 1.25rem;
|
||||
position: sticky;
|
||||
top: 7rem; /* below fixed header */
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sidebar-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1.5rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--pub-border);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sidebar-header h2 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 700;
|
||||
color: var(--pub-text);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sidebar-header h2 i {
|
||||
color: var(--pub-blue);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sidebar-header .pub-clear-btn {
|
||||
font-size: 0.875rem;
|
||||
color: var(--pub-accent);
|
||||
font-weight: 500;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sidebar-header .pub-clear-btn:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Accordion */
|
||||
.pub-wrapper .pub-accordion {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-accordion-item {
|
||||
/* no extra styles needed */
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-accordion-trigger {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
text-align: left;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 600;
|
||||
color: var(--pub-text);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-accordion-trigger i {
|
||||
font-size: 0.75rem;
|
||||
color: var(--pub-muted);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-accordion-trigger.open i {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-accordion-body {
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease-out, opacity 0.3s ease-out;
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-accordion-body.open {
|
||||
max-height: 600px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-accordion-body .pub-filter-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Filter checkbox labels */
|
||||
.pub-wrapper .pub-filter-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-filter-label span {
|
||||
font-size: 0.875rem;
|
||||
color: var(--pub-text);
|
||||
transition: color 0.15s;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-filter-label:hover span {
|
||||
color: var(--pub-blue);
|
||||
}
|
||||
|
||||
/* Custom checkbox */
|
||||
.pub-wrapper .pub-checkbox {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
width: 1.15em;
|
||||
height: 1.15em;
|
||||
border: 1px solid var(--pub-border);
|
||||
border-radius: 0.25em;
|
||||
background-color: #ffffff;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
transition: background-color 0.15s, border-color 0.15s;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-checkbox::before {
|
||||
content: "";
|
||||
width: 0.65em;
|
||||
height: 0.65em;
|
||||
transform: scale(0);
|
||||
transition: transform 120ms ease-in-out;
|
||||
background-color: #ffffff;
|
||||
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-checkbox:checked {
|
||||
background-color: var(--pub-blue);
|
||||
border-color: var(--pub-blue);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-checkbox:checked::before {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
/* Year range inputs */
|
||||
.pub-wrapper .pub-year-range {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-year-range input {
|
||||
width: 50%;
|
||||
padding: 0.375rem 0.5rem;
|
||||
border: 1px solid var(--pub-border);
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--pub-text);
|
||||
background-color: #ffffff;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-year-range input:focus {
|
||||
border-color: var(--pub-blue);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
RESULTS AREA
|
||||
============================================================ */
|
||||
.pub-wrapper .pub-results {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Results toolbar */
|
||||
.pub-wrapper .pub-results-toolbar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
background-color: #ffffff;
|
||||
padding: 1rem;
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid var(--pub-border);
|
||||
box-shadow: 0 1px 2px 0 rgba(0,0,0,0.05);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.pub-wrapper .pub-results-toolbar {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-results-count {
|
||||
font-size: 0.875rem;
|
||||
color: var(--pub-text);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-results-count strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-wrap label {
|
||||
font-size: 0.875rem;
|
||||
color: var(--pub-muted);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-select {
|
||||
border: 1px solid var(--pub-border);
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--pub-text);
|
||||
background-color: #ffffff;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s;
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-select:focus,
|
||||
.pub-wrapper .pub-sort-select:hover {
|
||||
border-color: var(--pub-blue);
|
||||
}
|
||||
|
||||
/* Sort dropdown (custom React dropdown) */
|
||||
.pub-wrapper .pub-sort-dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-dropdown-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
border: 1px solid var(--pub-border);
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
background-color: #ffffff;
|
||||
color: var(--pub-text);
|
||||
cursor: pointer;
|
||||
min-width: 140px;
|
||||
transition: border-color 0.2s;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-dropdown-btn:hover,
|
||||
.pub-wrapper .pub-sort-dropdown-btn.open {
|
||||
border-color: var(--pub-blue);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-dropdown-btn i {
|
||||
font-size: 0.625rem;
|
||||
color: var(--pub-muted);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-dropdown-btn.open i {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-dropdown-menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
right: 0;
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid var(--pub-border);
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -2px rgba(0,0,0,0.04);
|
||||
z-index: 50;
|
||||
overflow: hidden;
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-dropdown-option {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 0.875rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.15s;
|
||||
color: var(--pub-text);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-dropdown-option:hover {
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-sort-dropdown-option.selected {
|
||||
background-color: var(--pub-blue-light);
|
||||
color: var(--pub-blue);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
PUBLICATION CARD
|
||||
============================================================ */
|
||||
.pub-wrapper .pub-card-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid var(--pub-border);
|
||||
padding: 1.5rem;
|
||||
transition: box-shadow 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-card:hover {
|
||||
border-color: var(--pub-blue);
|
||||
box-shadow: 0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -2px rgba(0,0,0,0.04);
|
||||
}
|
||||
|
||||
/* Card top row: title + badges */
|
||||
.pub-wrapper .pub-card-top {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.pub-wrapper .pub-card-top {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-card-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: var(--pub-text);
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-card:hover .pub-card-title {
|
||||
color: var(--pub-blue);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-card-title a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-card-title a:hover {
|
||||
color: var(--pub-blue);
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
.pub-wrapper .pub-badges {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-shrink: 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.25rem 0.625rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-badge-open {
|
||||
background-color: #f0fdf4;
|
||||
color: #15803d;
|
||||
border-color: #bbf7d0;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-badge-peer {
|
||||
background-color: var(--pub-blue-light);
|
||||
color: var(--pub-blue);
|
||||
border-color: rgba(38, 60, 111, 0.2);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-badge-institutional {
|
||||
background-color: #fefce8;
|
||||
color: #a16207;
|
||||
border-color: #fde68a;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-badge-request {
|
||||
background-color: #eff6ff;
|
||||
color: #1d4ed8;
|
||||
border-color: #bfdbfe;
|
||||
}
|
||||
|
||||
/* Card meta row */
|
||||
.pub-wrapper .pub-card-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.5rem 1.5rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--pub-muted);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-card-meta .pub-meta-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-card-meta .pub-meta-item strong {
|
||||
color: var(--pub-text);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Card abstract */
|
||||
.pub-wrapper .pub-card-abstract {
|
||||
font-size: 0.875rem;
|
||||
color: var(--pub-muted);
|
||||
line-height: 1.625;
|
||||
margin-bottom: 1rem;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Keywords */
|
||||
.pub-wrapper .pub-keywords {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-keywords-label {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
color: var(--pub-muted);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-keyword-tag {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.5rem;
|
||||
background-color: #f3f4f6;
|
||||
color: #4b5563;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
/* Card actions */
|
||||
.pub-wrapper .pub-card-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--pub-border);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-action-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
transition: color 0.2s;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-action-btn-primary {
|
||||
color: var(--pub-blue);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-action-btn-primary:hover {
|
||||
color: var(--pub-blue-hover);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-action-btn-secondary {
|
||||
color: var(--pub-muted);
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-action-btn-secondary:hover {
|
||||
color: var(--pub-text);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
PAGINATION
|
||||
============================================================ */
|
||||
.pub-wrapper .pub-pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-top: 1px solid var(--pub-border);
|
||||
padding-top: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-page-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
border: 1px solid var(--pub-border);
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
background-color: #ffffff;
|
||||
color: var(--pub-text);
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s, color 0.2s;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-page-btn:hover:not(:disabled) {
|
||||
border-color: var(--pub-blue);
|
||||
color: var(--pub-blue);
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-page-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-page-numbers {
|
||||
display: none;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.pub-wrapper .pub-page-numbers {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-page-num {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
background-color: #ffffff;
|
||||
color: var(--pub-text);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-page-num:hover {
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-page-num.active {
|
||||
background-color: var(--pub-blue);
|
||||
color: #ffffff;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pub-wrapper .pub-page-ellipsis {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--pub-muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
Reference in New Issue
Block a user