55 title =" Monarch Publications"
66 class =" publications"
77 />
8- <AppSection >
8+
9+ <!-- Top metadata section: short description + key metrics -->
10+ <AppSection width =" big" >
911 <p class =" metadata" >
10- This list includes papers by the Monarch Team that were foundational to
11- the current Monarch work. The graph below shows the number of citations to
12- Monarch papers over time.
12+ The Monarch Initiative maintains a rich and foundational body of
13+ publications that trace back to its early days, underscoring how these
14+ works have been pivotal in shaping the fields of variant interpretation,
15+ knowledge graphs, and disease gene discovery. Committed to open science,
16+ Monarch shares much of this work as preprints or in open-access venues,
17+ ensuring broad, transparent, and lasting accessibility. Use this page to
18+ explore Monarch’s full body of publications.
1319 </p >
1420
15- <Apex
16- class =" chart"
17- type =" bar"
18- :options =" options"
19- :series =" [citesPerYear]"
20- height =" 300px"
21- />
22-
2321 <AppGallery >
2422 <p v-for =" (item, index) in metadata" :key =" index" class =" metadata" >
2523 <strong >{{ item.name }}</strong >
2927 </AppGallery >
3028 </AppSection >
3129
32- <AppSection >
33- <AppHeading >Years</AppHeading >
34- <!-- row of links to year sections -->
35- <p >
36- <template
37- v-for =" (group , index ) in publications .publications "
38- :key =" index "
39- >
40- <AppLink :to =" '#year-' + group.year" :replace =" true" >
41- {{ group.year }}</AppLink
30+ <!-- Publications grouped by year with a simple tab UI -->
31+ <AppSection width =" big" >
32+ <AppHeading >Publications by Year </AppHeading >
33+
34+ <div class =" tab-container" >
35+ <div class =" tabs" role =" tablist" aria-label =" Publication years" >
36+ <div
37+ v-for =" year in years"
38+ :key =" year"
39+ class =" tab-item"
40+ :class =" { active: activeYear === year }"
4241 >
43- <span v-if =" index !== publications.publications.length - 1" > · </span >
44- </template >
45- </p >
42+ <AppButton
43+ :text =" year"
44+ color =" none"
45+ :aria-selected =" activeYear === year"
46+ role =" tab"
47+ :class =" { active: activeYear === year }"
48+ @click =" setActiveYear(year)"
49+ />
50+ </div >
51+ </div >
52+
53+ <!-- Panel shows items for the currently active year -->
54+ <div
55+ class =" citations"
56+ role =" tabpanel"
57+ :aria-labelledby =" `tab-${activeYear}`"
58+ >
59+ <AppGallery >
60+ <AppCitation
61+ v-for =" (publication, idx) in currentGroup.items"
62+ :key =" idx"
63+ :link =" publication.link"
64+ :title =" publication.title"
65+ :authors =" publication.authors"
66+ :details =" [publication.journal, publication.issue]"
67+ />
68+ </AppGallery >
69+ </div >
70+ </div >
4671 </AppSection >
4772
48- <!-- by year -->
49- <AppSection
50- v-for =" (group, index) in publications.publications"
51- :key =" index"
52- width =" big"
53- >
54- <AppHeading :id =" 'year-' + group.year" >{{ group.year }}</AppHeading >
55- <AppGallery >
56- <AppCitation
57- v-for =" (publication, item) in group.items"
58- :key =" item"
59- :link =" publication.link"
60- :title =" publication.title"
61- :authors =" publication.authors"
62- :details =" [publication.journal, publication.issue]"
63- />
64- </AppGallery >
73+ <!-- Citations bar chart (ApexCharts) -->
74+ <AppSection >
75+ <AppHeading >Yearly Citation Trend </AppHeading >
76+ <Apex
77+ class =" chart"
78+ type =" bar"
79+ :options =" options"
80+ :series =" [citesPerYear]"
81+ height =" 300px"
82+ />
6583 </AppSection >
6684</template >
6785
6886<script setup lang="ts">
69- /** https://apexcharts.com/docs/vue-charts/ */
87+ import { computed , nextTick , onMounted , ref } from " vue " ;
7088import Apex from " vue3-apexcharts" ;
89+ import ApexCharts from " apexcharts" ;
7190import type { ApexOptions } from " apexcharts" ;
7291import AppBreadcrumb from " @/components/AppBreadcrumb.vue" ;
92+ import AppButton from " @/components/AppButton.vue" ;
7393import AppCitation from " @/components/AppCitation.vue" ;
94+ import AppSection from " @/components/AppSection.vue" ;
7495import PageTitle from " @/components/ThePageTitle.vue" ;
7596import publications from " @/data/publications.json" ;
7697
77- /** data for chart */
98+ // Types inferred directly from JSON for safety and IntelliSense
99+ type PublicationsData = typeof publications ;
100+ type PublicationGroup = PublicationsData [" publications" ][number ];
101+ const groups = publications .publications as PublicationGroup [];
102+ const years = computed (() => groups .map ((g ) => String (g .year )));
103+ const activeYear = ref <string >(years .value [0 ] ?? " " );
104+
105+ const currentGroup = computed <PublicationGroup >(() => {
106+ return groups .find ((g ) => String (g .year ) === activeYear .value ) || groups [0 ];
107+ });
108+
109+ // Convert the cites_per_year object into [{ x: year, y: count }, ...]
78110const citesPerYear = {
79111 name: " citations" ,
80112 data: Object .entries (publications .metadata .cites_per_year ).map (
81113 ([year , count ]) => ({ x: year , y: count }),
82114 ),
83115};
84116
85- /** extra metadata fields */
117+ // Cards shown above the tabs (keys reference publications. metadata fields)
86118const metadata: {
87119 name: string ;
88120 key: keyof (typeof publications )[" metadata" ];
@@ -92,17 +124,17 @@ const metadata: {
92124 { name: " Citations in last 5 years" , key: " last_5_yrs" },
93125];
94126
95- /** chart options */
127+ /** ----- Base chart options ----- */
96128const options: ApexOptions = {
97129 chart: {
98130 id: " citations" ,
99131 type: " bar" ,
100- redrawOnParentResize: true ,
132+ redrawOnParentResize: true , // keep chart responsive inside containers
101133 },
102134 title: {
103135 text: ` Monarch Citations ` ,
104136 },
105- colors: [" #00acc1" ],
137+ colors: [" #00acc1" ], // single series color
106138 plotOptions: {
107139 bar: {
108140 horizontal: false ,
@@ -111,53 +143,141 @@ const options: ApexOptions = {
111143 },
112144 },
113145 },
146+ states: {
147+ active: {
148+ allowMultipleDataPointsSelection: false ,
149+ filter: { type: " lighten" , value: 0.15 },
150+ },
151+ },
114152 tooltip: {
115- enabled: false ,
153+ enabled: false , // declutter; rely on selection highlight
116154 },
117155 xaxis: {
118- title: {
119- text: " Year" ,
120- },
121- axisBorder: {
122- color: " #000000" ,
123- },
124- axisTicks: {
125- show: true ,
126- color: " #000000" ,
127- },
156+ title: { text: " Year" },
157+ axisBorder: { color: " #000000" },
158+ axisTicks: { show: true , color: " #000000" },
128159 },
129160 yaxis: {
130- title: {
131- text: " # of Citations" ,
132- },
133- axisBorder: {
134- color: " #000000" ,
135- },
136- axisTicks: {
137- show: true ,
138- color: " #000000" ,
139- },
161+ title: { text: " # of Citations" },
162+ axisBorder: { color: " #000000" },
163+ axisTicks: { show: true , color: " #000000" },
140164 },
141165 grid: {
142- xaxis: {
143- lines: {
144- show: false ,
145- },
146- },
147- yaxis: {
148- lines: {
149- show: false ,
150- },
151- },
166+ xaxis: { lines: { show: false } },
167+ yaxis: { lines: { show: false } },
152168 },
153169};
170+
171+ /**
172+ * Update activeYear and mirror the selection on the bar chart for context. We
173+ * clear any previous selection and then select the data point at index
174+ * `dataPointIndex`.
175+ */
176+ function setActiveYear(year : string ) {
177+ activeYear .value = year ;
178+ nextTick (() => {
179+ const dataPointIndex = citesPerYear .data .findIndex (
180+ (item ) => String (item .x ) === year ,
181+ );
182+ if (dataPointIndex >= 0 ) {
183+ ApexCharts .exec (" citations" , " clearSelectedDataPoints" );
184+ ApexCharts .exec (
185+ " citations" ,
186+ " toggleDataPointSelection" ,
187+ 0 ,
188+ dataPointIndex ,
189+ );
190+ }
191+ });
192+ }
193+
194+ // Initialize selection on mount so the default tab and the chart match
195+ onMounted (() => setActiveYear (activeYear .value ));
154196 </script >
155197
156198<style scoped lang="scss">
199+ .section.center {
200+ padding-bottom : 10px ;
201+ }
202+
157203.metadata {
158- text-align : center ;
204+ text-align : left ;
159205}
160206.publications {
161207 background-color : #ffffff ;
162208}
209+
210+ .tab-container {
211+ display : flex ;
212+ flex-direction : column ;
213+ align-items : center ;
214+ width : 100% ;
215+ margin : 0 auto ;
216+ padding : 1rem ;
217+ gap : 1.5em ;
218+ }
219+
220+ .tabs {
221+ display : flex ;
222+ width : 100% ;
223+ margin-bottom : 1rem ;
224+ overflow-x : auto ;
225+ gap : 0.3rem ;
226+ border-bottom : 3px solid $theme ;
227+ background-color : #fff ;
228+ }
229+
230+ .tab-item {
231+ display : flex ;
232+ flex-direction : column ;
233+ align-items : center ;
234+ text-align : center ;
235+ }
236+
237+ .tab-item.active {
238+ border : 1px solid #ccc ;
239+ border-bottom : 0 ;
240+ background-color : #008080 ;
241+ color : #fff ;
242+ }
243+
244+ /* Ensure AppButton text remains readable in active tab */
245+ .tab-item.active :deep(.button ) {
246+ color : #fff !important ;
247+ }
248+
249+ .tab-item :not (.active ) {
250+ border : 1px solid transparent ;
251+ border-bottom : 0 ;
252+ background-color : #f5f5f5 ;
253+ }
254+
255+ :deep(.button ) {
256+ width : 100% ;
257+ border : none ;
258+ background-color : transparent ;
259+ font-weight : bold ;
260+ cursor : pointer ;
261+ & :hover ,
262+ & :focus {
263+ outline : none !important ;
264+ box-shadow : none !important ;
265+ }
266+ }
267+
268+ .citations {
269+ max-height : 32rem ;
270+ overflow-x : hidden ;
271+ overflow-y : auto ;
272+ scrollbar-color : $theme ;
273+ scrollbar-gutter : stable both- edges;
274+ scrollbar-width : thin ;
275+ }
276+
277+ /* Subtle dark-mode contrast for the custom scrollbar colors */
278+ @media (prefers-color-scheme : dark ) {
279+ .citations {
280+ scrollbar-color : rgba (0 , 200 , 200 , 0.7 ) rgba (255 , 255 , 255 , 0.08 );
281+ }
282+ }
163283 </style >
0 commit comments