@ansiversa/components 0.0.120 → 0.0.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/resume-templates/ResumeTemplateClassic.astro +17 -39
- package/src/resume-templates/ResumeTemplateExecutiveTimeline.astro +21 -26
- package/src/resume-templates/ResumeTemplateMinimal.astro +2 -15
- package/src/resume-templates/ResumeTemplateModernTwoTone.astro +38 -44
- package/src/styles/global.css +27 -0
package/package.json
CHANGED
|
@@ -47,32 +47,10 @@ const declaration = data.declaration ?? {};
|
|
|
47
47
|
const hasDeclaration = Boolean(declaration.text || declaration.place || declaration.name);
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
-
<
|
|
51
|
-
@media print {
|
|
52
|
-
.resume-template a {
|
|
53
|
-
text-decoration: none;
|
|
54
|
-
color: inherit;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.resume-template .classic-grid {
|
|
58
|
-
display: grid;
|
|
59
|
-
grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
|
|
60
|
-
gap: 2.5rem;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.resume-template .classic-divider {
|
|
64
|
-
background: none !important;
|
|
65
|
-
border-top: 1px solid #e2e8f0 !important;
|
|
66
|
-
-webkit-print-color-adjust: exact;
|
|
67
|
-
print-color-adjust: exact;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
</style>
|
|
71
|
-
|
|
72
|
-
<div class="resume-template bg-slate-100 text-slate-900 print:bg-white">
|
|
50
|
+
<div class="resume-template av-print-white bg-slate-100 text-slate-900 print:bg-white">
|
|
73
51
|
<main class="mx-auto max-w-4xl p-4 sm:p-6">
|
|
74
52
|
<section class="rounded-2xl bg-white p-6 shadow-sm ring-1 ring-slate-200 sm:p-10 print:shadow-none print:ring-0">
|
|
75
|
-
<header class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
53
|
+
<header class="av-print-avoid-break flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
76
54
|
<div>
|
|
77
55
|
<h1 class="text-3xl font-bold tracking-tight">{basics.fullName}</h1>
|
|
78
56
|
<p class="mt-1 text-base font-medium text-slate-700">{basics.headline}</p>
|
|
@@ -87,7 +65,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
87
65
|
{contactItems.map((item) =>
|
|
88
66
|
item.href ? (
|
|
89
67
|
<a
|
|
90
|
-
class="text-slate-900 underline underline-offset-2 hover:text-slate-700"
|
|
68
|
+
class="text-slate-900 underline underline-offset-2 hover:text-slate-700 print:no-underline"
|
|
91
69
|
href={item.href}
|
|
92
70
|
>
|
|
93
71
|
{item.label}
|
|
@@ -101,10 +79,10 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
101
79
|
)}
|
|
102
80
|
</header>
|
|
103
81
|
|
|
104
|
-
<div class="
|
|
82
|
+
<div class="my-8 h-0 border-t border-slate-200"></div>
|
|
105
83
|
|
|
106
|
-
<div class="
|
|
107
|
-
<div class="space-y-10 lg:col-span-2">
|
|
84
|
+
<div class="grid gap-10 lg:grid-cols-3 print:grid-cols-1">
|
|
85
|
+
<div class="space-y-10 lg:col-span-2 print:col-span-1">
|
|
108
86
|
{experienceItems.length > 0 && (
|
|
109
87
|
<section>
|
|
110
88
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">EXPERIENCE</h2>
|
|
@@ -113,7 +91,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
113
91
|
const range = formatDateRange(item);
|
|
114
92
|
const meta = item.location ? `${range} · ${item.location}` : range;
|
|
115
93
|
return (
|
|
116
|
-
<article>
|
|
94
|
+
<article class="av-print-avoid-break">
|
|
117
95
|
<div class="flex flex-col gap-1 sm:flex-row sm:items-baseline sm:justify-between">
|
|
118
96
|
<div>
|
|
119
97
|
<h3 class="text-base font-semibold">{item.role}</h3>
|
|
@@ -147,7 +125,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
147
125
|
? formatDateRange({ start: project.start, end: project.end, present: project.present })
|
|
148
126
|
: undefined;
|
|
149
127
|
return (
|
|
150
|
-
<article>
|
|
128
|
+
<article class="av-print-avoid-break">
|
|
151
129
|
<div class="flex items-baseline justify-between gap-3">
|
|
152
130
|
{project.link ? (
|
|
153
131
|
<a class="text-base font-semibold underline underline-offset-4" href={project.link}>
|
|
@@ -191,7 +169,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
191
169
|
{educationItems.map((edu) => {
|
|
192
170
|
const range = edu.start ? formatDateRange({ start: edu.start, end: edu.end }) : undefined;
|
|
193
171
|
return (
|
|
194
|
-
<div class="flex flex-col gap-1 sm:flex-row sm:items-baseline sm:justify-between">
|
|
172
|
+
<div class="av-print-avoid-break flex flex-col gap-1 sm:flex-row sm:items-baseline sm:justify-between">
|
|
195
173
|
<div>
|
|
196
174
|
<h3 class="text-base font-semibold">{edu.degree}</h3>
|
|
197
175
|
<p class="text-sm text-slate-700">{edu.school}</p>
|
|
@@ -211,7 +189,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
211
189
|
|
|
212
190
|
<aside class="space-y-10">
|
|
213
191
|
{skills.length > 0 && (
|
|
214
|
-
<section>
|
|
192
|
+
<section class="av-print-avoid-break">
|
|
215
193
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">SKILLS</h2>
|
|
216
194
|
<div class="mt-4 flex flex-wrap gap-2">
|
|
217
195
|
{skills.map((skill) => (
|
|
@@ -224,13 +202,13 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
224
202
|
)}
|
|
225
203
|
|
|
226
204
|
{certifications.length > 0 && (
|
|
227
|
-
<section>
|
|
205
|
+
<section class="av-print-avoid-break">
|
|
228
206
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">CERTIFICATIONS</h2>
|
|
229
207
|
<ul class="mt-4 space-y-3 text-sm text-slate-700">
|
|
230
208
|
{certifications.map((cert) => {
|
|
231
209
|
const meta = [cert.issuer, cert.year].filter(Boolean).join(" · ");
|
|
232
210
|
return (
|
|
233
|
-
<li class="space-y-1">
|
|
211
|
+
<li class="av-print-avoid-break space-y-1">
|
|
234
212
|
{cert.link ? (
|
|
235
213
|
<a class="font-semibold text-slate-900 underline underline-offset-2" href={cert.link}>
|
|
236
214
|
{cert.name}
|
|
@@ -247,7 +225,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
247
225
|
)}
|
|
248
226
|
|
|
249
227
|
{highlights.length > 0 && (
|
|
250
|
-
<section>
|
|
228
|
+
<section class="av-print-avoid-break">
|
|
251
229
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">HIGHLIGHTS</h2>
|
|
252
230
|
<ul class="mt-4 list-disc space-y-2 pl-5 text-sm leading-6 text-slate-700">
|
|
253
231
|
{highlights.map((item) => (
|
|
@@ -258,7 +236,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
258
236
|
)}
|
|
259
237
|
|
|
260
238
|
{languages.length > 0 && (
|
|
261
|
-
<section>
|
|
239
|
+
<section class="av-print-avoid-break">
|
|
262
240
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">LANGUAGES</h2>
|
|
263
241
|
<ul class="mt-4 space-y-2 text-sm text-slate-700">
|
|
264
242
|
{languages.map((language) => (
|
|
@@ -278,7 +256,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
278
256
|
{awards.map((award) => {
|
|
279
257
|
const meta = [award.by, award.year].filter(Boolean).join(" · ");
|
|
280
258
|
return (
|
|
281
|
-
<li class="space-y-1">
|
|
259
|
+
<li class="av-print-avoid-break space-y-1">
|
|
282
260
|
<div class="font-semibold text-slate-900">{award.title}</div>
|
|
283
261
|
{meta && <div class="text-xs text-slate-600">{meta}</div>}
|
|
284
262
|
{award.summary && <div class="text-sm text-slate-700">{award.summary}</div>}
|
|
@@ -293,8 +271,8 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
293
271
|
|
|
294
272
|
{hasDeclaration && (
|
|
295
273
|
<>
|
|
296
|
-
<div class="
|
|
297
|
-
<section class="space-y-4">
|
|
274
|
+
<div class="my-8 h-0 border-t border-slate-200"></div>
|
|
275
|
+
<section class="av-print-avoid-break space-y-4">
|
|
298
276
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">DECLARATION</h2>
|
|
299
277
|
{declaration.text && (
|
|
300
278
|
<p class="text-sm leading-6 text-slate-700">{declaration.text}</p>
|
|
@@ -25,6 +25,13 @@ for (const link of basics.links ?? []) {
|
|
|
25
25
|
contactChips.push(link.label ?? formatUrlLabel(link.url));
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
const normalizeSkillLabel = (value?: string) =>
|
|
29
|
+
(value ?? "")
|
|
30
|
+
.replace(/\s+/g, " ")
|
|
31
|
+
.replace(/[|•]+/g, " · ")
|
|
32
|
+
.replace(/(\d)([A-Za-z])/g, "$1 $2")
|
|
33
|
+
.trim();
|
|
34
|
+
|
|
28
35
|
const experienceItems = data.experience ?? [];
|
|
29
36
|
const projects = data.projects ?? [];
|
|
30
37
|
const skills = data.skills ?? [];
|
|
@@ -34,22 +41,10 @@ const declaration = data.declaration ?? {};
|
|
|
34
41
|
const hasDeclaration = Boolean(declaration.text || declaration.place || declaration.name);
|
|
35
42
|
---
|
|
36
43
|
|
|
37
|
-
<
|
|
38
|
-
@media print {
|
|
39
|
-
.resume-template a {
|
|
40
|
-
text-decoration: none;
|
|
41
|
-
color: inherit;
|
|
42
|
-
}
|
|
43
|
-
.resume-template {
|
|
44
|
-
background: white;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
</style>
|
|
48
|
-
|
|
49
|
-
<div class="resume-template bg-slate-100 text-slate-900 print:bg-white">
|
|
44
|
+
<div class="resume-template av-print-white bg-slate-100 text-slate-900 print:bg-white">
|
|
50
45
|
<main class="mx-auto max-w-4xl p-4 sm:p-6">
|
|
51
46
|
<section class="rounded-2xl bg-white p-7 shadow-sm ring-1 ring-slate-200 sm:p-10 print:shadow-none print:ring-0">
|
|
52
|
-
<header class="flex flex-col gap-5 sm:flex-row sm:items-end sm:justify-between">
|
|
47
|
+
<header class="av-print-avoid-break flex flex-col gap-5 sm:flex-row sm:items-end sm:justify-between">
|
|
53
48
|
<div>
|
|
54
49
|
<h1 class="text-3xl font-bold tracking-tight">{basics.fullName}</h1>
|
|
55
50
|
<p class="mt-1 text-sm font-medium text-slate-700">{basics.headline}</p>
|
|
@@ -63,7 +58,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
63
58
|
</div>
|
|
64
59
|
|
|
65
60
|
{basics.summary && (
|
|
66
|
-
<div class="rounded-xl border border-slate-200 bg-slate-50 p-4 text-sm text-slate-700 sm:max-w-sm">
|
|
61
|
+
<div class="av-print-avoid-break rounded-xl border border-slate-200 bg-slate-50 p-4 text-sm text-slate-700 sm:max-w-sm">
|
|
67
62
|
<div class="text-xs font-semibold tracking-widest text-slate-500">SUMMARY</div>
|
|
68
63
|
<p class="mt-2 leading-6">{basics.summary}</p>
|
|
69
64
|
</div>
|
|
@@ -72,14 +67,14 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
72
67
|
|
|
73
68
|
<div class="my-8 h-px bg-slate-200"></div>
|
|
74
69
|
|
|
75
|
-
<div class="grid gap-10 lg:grid-cols-3">
|
|
70
|
+
<div class="grid gap-10 lg:grid-cols-3 print:grid-cols-1">
|
|
76
71
|
<div class="lg:col-span-2">
|
|
77
72
|
{experienceItems.length > 0 && (
|
|
78
73
|
<>
|
|
79
74
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">EXPERIENCE</h2>
|
|
80
75
|
<div class="mt-6 space-y-8">
|
|
81
76
|
{experienceItems.map((item) => (
|
|
82
|
-
<div class="relative pl-6">
|
|
77
|
+
<div class="av-print-avoid-break relative pl-6">
|
|
83
78
|
<div class="absolute left-0 top-1.5 h-full w-px bg-slate-200"></div>
|
|
84
79
|
<div class="absolute left-[-5px] top-1.5 h-3 w-3 rounded-full bg-slate-900"></div>
|
|
85
80
|
|
|
@@ -112,7 +107,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
112
107
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">PROJECTS</h2>
|
|
113
108
|
<div class="mt-5 space-y-4">
|
|
114
109
|
{projects.map((project) => (
|
|
115
|
-
<div class="rounded-xl border border-slate-200 p-4">
|
|
110
|
+
<div class="av-print-avoid-break rounded-xl border border-slate-200 p-4">
|
|
116
111
|
<div class="flex items-baseline justify-between">
|
|
117
112
|
{project.link ? (
|
|
118
113
|
<a class="font-semibold underline underline-offset-4" href={project.link}>
|
|
@@ -143,22 +138,22 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
143
138
|
|
|
144
139
|
<aside class="space-y-8">
|
|
145
140
|
{skills.length > 0 && (
|
|
146
|
-
<section class="rounded-xl border border-slate-200 p-4">
|
|
141
|
+
<section class="av-print-avoid-break rounded-xl border border-slate-200 p-4">
|
|
147
142
|
<h2 class="text-xs font-bold tracking-widest text-slate-500">SKILLS</h2>
|
|
148
|
-
<
|
|
143
|
+
<ul class="mt-3 list-disc space-y-1 pl-5 text-sm text-slate-700">
|
|
149
144
|
{skills.map((skill) => (
|
|
150
|
-
<
|
|
145
|
+
<li>{normalizeSkillLabel(skill.name)}</li>
|
|
151
146
|
))}
|
|
152
|
-
</
|
|
147
|
+
</ul>
|
|
153
148
|
</section>
|
|
154
149
|
)}
|
|
155
150
|
|
|
156
151
|
{education.length > 0 && (
|
|
157
|
-
<section class="rounded-xl border border-slate-200 p-4">
|
|
152
|
+
<section class="av-print-avoid-break rounded-xl border border-slate-200 p-4">
|
|
158
153
|
<h2 class="text-xs font-bold tracking-widest text-slate-500">EDUCATION</h2>
|
|
159
154
|
<div class="mt-3 space-y-4 text-sm text-slate-700">
|
|
160
155
|
{education.map((edu) => (
|
|
161
|
-
<div>
|
|
156
|
+
<div class="av-print-avoid-break rounded-lg border border-slate-100 p-3">
|
|
162
157
|
<div class="font-semibold">{edu.degree}</div>
|
|
163
158
|
<div class="text-slate-600">{edu.school}</div>
|
|
164
159
|
{edu.location && <div class="text-slate-500">{edu.location}</div>}
|
|
@@ -174,7 +169,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
174
169
|
)}
|
|
175
170
|
|
|
176
171
|
{highlights.length > 0 && (
|
|
177
|
-
<section class="rounded-xl border border-slate-200 p-4">
|
|
172
|
+
<section class="av-print-avoid-break rounded-xl border border-slate-200 p-4">
|
|
178
173
|
<h2 class="text-xs font-bold tracking-widest text-slate-500">HIGHLIGHTS</h2>
|
|
179
174
|
<ul class="mt-3 space-y-2 text-sm leading-6 text-slate-700">
|
|
180
175
|
{highlights.map((highlight) => (
|
|
@@ -189,7 +184,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
189
184
|
{hasDeclaration && (
|
|
190
185
|
<>
|
|
191
186
|
<div class="my-8 h-px bg-slate-200"></div>
|
|
192
|
-
<section class="space-y-4">
|
|
187
|
+
<section class="av-print-avoid-break space-y-4">
|
|
193
188
|
<h2 class="text-sm font-bold tracking-widest text-slate-900">DECLARATION</h2>
|
|
194
189
|
{declaration.text && (
|
|
195
190
|
<p class="text-sm leading-6 text-slate-700">{declaration.text}</p>
|
|
@@ -41,20 +41,7 @@ const showSkillsAs = data.settings?.showSkillsAs ?? "levels";
|
|
|
41
41
|
const declaration = data.declaration ?? {};
|
|
42
42
|
const hasDeclaration = Boolean(declaration.text || declaration.place || declaration.name);
|
|
43
43
|
---
|
|
44
|
-
|
|
45
|
-
<style>
|
|
46
|
-
@media print {
|
|
47
|
-
.resume-template a {
|
|
48
|
-
text-decoration: none;
|
|
49
|
-
color: inherit;
|
|
50
|
-
}
|
|
51
|
-
.resume-template {
|
|
52
|
-
background: white;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
</style>
|
|
56
|
-
|
|
57
|
-
<div class="resume-template bg-slate-100 text-slate-900 print:bg-white">
|
|
44
|
+
<div class="resume-template av-print-white bg-slate-100 text-slate-900 print:bg-white">
|
|
58
45
|
<main class="mx-auto max-w-4xl p-4 sm:p-6">
|
|
59
46
|
<section class="rounded-2xl bg-white p-8 shadow-sm ring-1 ring-slate-200 sm:p-12 print:shadow-none print:ring-0">
|
|
60
47
|
<header class="space-y-4">
|
|
@@ -67,7 +54,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
67
54
|
<div class="text-sm text-slate-700 sm:text-right">
|
|
68
55
|
<div class="flex flex-col gap-1">
|
|
69
56
|
{contactLinks.map((item) => (
|
|
70
|
-
|
|
57
|
+
<a class="underline underline-offset-4 hover:text-slate-900 print:no-underline" href={item.href}>
|
|
71
58
|
{item.label}
|
|
72
59
|
</a>
|
|
73
60
|
))}
|
|
@@ -33,6 +33,8 @@ if (basics.contact.website) {
|
|
|
33
33
|
contactItems.push({ label: formatUrlLabel(basics.contact.website), href: basics.contact.website });
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
const directContactLine = [basics.contact.email, basics.contact.phone].filter(Boolean).join(" • ");
|
|
37
|
+
|
|
36
38
|
const skills = data.skills ?? [];
|
|
37
39
|
const links = basics.links ?? [];
|
|
38
40
|
const languages = data.languages ?? [];
|
|
@@ -44,39 +46,30 @@ const declaration = data.declaration ?? {};
|
|
|
44
46
|
const hasDeclaration = Boolean(declaration.text || declaration.place || declaration.name);
|
|
45
47
|
---
|
|
46
48
|
|
|
47
|
-
<
|
|
48
|
-
@media print {
|
|
49
|
-
.resume-template a {
|
|
50
|
-
text-decoration: none;
|
|
51
|
-
color: inherit;
|
|
52
|
-
}
|
|
53
|
-
.resume-template {
|
|
54
|
-
background: white;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
</style>
|
|
58
|
-
|
|
59
|
-
<div class="resume-template bg-slate-100 text-slate-900 print:bg-white">
|
|
49
|
+
<div class="resume-template av-print-white bg-slate-100 text-slate-900 print:bg-white">
|
|
60
50
|
<main class="mx-auto max-w-4xl p-4 sm:p-6">
|
|
61
51
|
<section class="overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-slate-200 print:shadow-none print:ring-0">
|
|
62
|
-
<div class="grid lg:grid-cols-12">
|
|
63
|
-
<aside class="bg-slate-900 p-7 text-
|
|
52
|
+
<div class="grid lg:grid-cols-12 print:grid-cols-1">
|
|
53
|
+
<aside class="bg-slate-900 p-7 text-slate-100 sm:p-10 lg:col-span-4 print:order-2 print:bg-white print:text-slate-900">
|
|
64
54
|
<div class="space-y-6">
|
|
65
55
|
<div>
|
|
66
56
|
<h1 class="text-3xl font-bold tracking-tight">{firstName}</h1>
|
|
67
57
|
{lastName && <h1 class="-mt-1 text-3xl font-bold tracking-tight">{lastName}</h1>}
|
|
68
|
-
<p class="mt-2 text-sm text-
|
|
58
|
+
<p class="mt-2 text-sm text-slate-200 print:text-slate-700">{basics.headline}</p>
|
|
69
59
|
</div>
|
|
70
60
|
|
|
71
|
-
<div class="h-px bg-
|
|
61
|
+
<div class="h-px bg-slate-700 print:bg-slate-200"></div>
|
|
72
62
|
|
|
73
63
|
{contactItems.length > 0 && (
|
|
74
|
-
<div class="space-y-2 text-sm">
|
|
75
|
-
<div class="text-
|
|
76
|
-
<div class="space-y-1 text-
|
|
77
|
-
{
|
|
64
|
+
<div class="av-print-avoid-break space-y-2 text-sm">
|
|
65
|
+
<div class="font-semibold text-slate-100 print:text-slate-900">CONTACT</div>
|
|
66
|
+
<div class="space-y-1 text-slate-200 print:text-slate-700">
|
|
67
|
+
{directContactLine && <div class="font-medium">{directContactLine}</div>}
|
|
68
|
+
{contactItems
|
|
69
|
+
.filter((item) => item.label !== basics.contact.email && item.label !== basics.contact.phone)
|
|
70
|
+
.map((item) =>
|
|
78
71
|
item.href ? (
|
|
79
|
-
<a class="underline underline-offset-2" href={item.href}>
|
|
72
|
+
<a class="underline underline-offset-2 print:no-underline" href={item.href}>
|
|
80
73
|
{item.label}
|
|
81
74
|
</a>
|
|
82
75
|
) : (
|
|
@@ -88,22 +81,22 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
88
81
|
)}
|
|
89
82
|
|
|
90
83
|
{skills.length > 0 && (
|
|
91
|
-
<div class="space-y-3">
|
|
92
|
-
<div class="text-sm text-
|
|
84
|
+
<div class="av-print-avoid-break space-y-3">
|
|
85
|
+
<div class="text-sm font-semibold text-slate-100 print:text-slate-900">SKILLS</div>
|
|
93
86
|
<div class="flex flex-wrap gap-2">
|
|
94
87
|
{skills.map((skill) => (
|
|
95
|
-
<span class="rounded-full bg-white/10 px-3 py-1 text-xs">{skill.name}</span>
|
|
88
|
+
<span class="rounded-full bg-white/10 px-3 py-1 text-xs text-slate-100 print:border print:border-slate-200 print:bg-slate-50 print:text-slate-800">{skill.name}</span>
|
|
96
89
|
))}
|
|
97
90
|
</div>
|
|
98
91
|
</div>
|
|
99
92
|
)}
|
|
100
93
|
|
|
101
94
|
{links.length > 0 && (
|
|
102
|
-
<div class="space-y-2">
|
|
103
|
-
<div class="text-sm text-
|
|
104
|
-
<div class="space-y-1 text-sm text-
|
|
95
|
+
<div class="av-print-avoid-break space-y-2">
|
|
96
|
+
<div class="text-sm font-semibold text-slate-100 print:text-slate-900">LINKS</div>
|
|
97
|
+
<div class="space-y-1 text-sm text-slate-200 print:text-slate-700">
|
|
105
98
|
{links.map((link) => (
|
|
106
|
-
<a class="underline underline-offset-2" href={link.url}>
|
|
99
|
+
<a class="underline underline-offset-2 print:no-underline" href={link.url}>
|
|
107
100
|
{link.label ?? formatUrlLabel(link.url)}
|
|
108
101
|
</a>
|
|
109
102
|
))}
|
|
@@ -112,23 +105,24 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
112
105
|
)}
|
|
113
106
|
|
|
114
107
|
{languages.length > 0 && (
|
|
115
|
-
<div class="space-y-2">
|
|
116
|
-
<div class="text-sm text-
|
|
117
|
-
<
|
|
118
|
-
{languages
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
108
|
+
<div class="av-print-avoid-break space-y-2">
|
|
109
|
+
<div class="text-sm font-semibold text-slate-100 print:text-slate-900">LANGUAGES</div>
|
|
110
|
+
<ul class="list-disc space-y-1 pl-5 text-sm text-slate-200 print:text-slate-700">
|
|
111
|
+
{languages.map((language) => (
|
|
112
|
+
<li>
|
|
113
|
+
{language.name}
|
|
114
|
+
{language.proficiency ? ` (${language.proficiency})` : ""}
|
|
115
|
+
</li>
|
|
116
|
+
))}
|
|
117
|
+
</ul>
|
|
124
118
|
</div>
|
|
125
119
|
)}
|
|
126
120
|
</div>
|
|
127
121
|
</aside>
|
|
128
122
|
|
|
129
|
-
<div class="p-7 sm:p-10 lg:col-span-8">
|
|
123
|
+
<div class="p-7 sm:p-10 lg:col-span-8 print:order-1">
|
|
130
124
|
{basics.summary && (
|
|
131
|
-
<section>
|
|
125
|
+
<section class="av-print-avoid-break">
|
|
132
126
|
<h2 class="text-xs font-bold tracking-widest text-slate-500">PROFILE</h2>
|
|
133
127
|
<p class="mt-3 text-sm leading-6 text-slate-700">{basics.summary}</p>
|
|
134
128
|
</section>
|
|
@@ -141,7 +135,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
141
135
|
<h2 class="text-xs font-bold tracking-widest text-slate-500">EXPERIENCE</h2>
|
|
142
136
|
<div class="mt-5 space-y-6">
|
|
143
137
|
{experienceItems.map((item) => (
|
|
144
|
-
<article>
|
|
138
|
+
<article class="av-print-avoid-break">
|
|
145
139
|
<div class="flex items-start justify-between gap-4">
|
|
146
140
|
<div>
|
|
147
141
|
<h3 class="text-base font-semibold">{item.role}</h3>
|
|
@@ -176,7 +170,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
176
170
|
<h2 class="text-xs font-bold tracking-widest text-slate-500">PROJECTS</h2>
|
|
177
171
|
<div class="mt-4 space-y-4">
|
|
178
172
|
{projects.map((project) => (
|
|
179
|
-
<div class="rounded-xl border border-slate-200 p-4">
|
|
173
|
+
<div class="av-print-avoid-break rounded-xl border border-slate-200 p-4">
|
|
180
174
|
<div class="flex items-baseline justify-between">
|
|
181
175
|
{project.link ? (
|
|
182
176
|
<a class="font-semibold underline underline-offset-4" href={project.link}>
|
|
@@ -211,7 +205,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
211
205
|
<h2 class="text-xs font-bold tracking-widest text-slate-500">EDUCATION</h2>
|
|
212
206
|
<div class="mt-4 space-y-4">
|
|
213
207
|
{education.map((edu) => (
|
|
214
|
-
<div class="rounded-xl border border-slate-200 p-4">
|
|
208
|
+
<div class="av-print-avoid-break rounded-xl border border-slate-200 p-4">
|
|
215
209
|
<h3 class="font-semibold">{edu.degree}</h3>
|
|
216
210
|
<p class="text-sm text-slate-600">{edu.school}</p>
|
|
217
211
|
{edu.location && (
|
|
@@ -242,7 +236,7 @@ const hasDeclaration = Boolean(declaration.text || declaration.place || declarat
|
|
|
242
236
|
</section>
|
|
243
237
|
|
|
244
238
|
{hasDeclaration && (
|
|
245
|
-
<section>
|
|
239
|
+
<section class="av-print-avoid-break">
|
|
246
240
|
<div class="my-8 h-px bg-slate-200"></div>
|
|
247
241
|
<h2 class="text-xs font-bold tracking-widest text-slate-500">DECLARATION</h2>
|
|
248
242
|
{declaration.text && (
|
package/src/styles/global.css
CHANGED
|
@@ -106,6 +106,15 @@
|
|
|
106
106
|
scrollbar-color: rgba(148, 163, 184, 0.6) transparent;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
@media print {
|
|
110
|
+
html,
|
|
111
|
+
body {
|
|
112
|
+
background: #fff !important;
|
|
113
|
+
background-image: none !important;
|
|
114
|
+
color: #000 !important;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
109
118
|
body::-webkit-scrollbar {
|
|
110
119
|
width: 8px;
|
|
111
120
|
}
|
|
@@ -1975,6 +1984,24 @@
|
|
|
1975
1984
|
color: var(--av-text);
|
|
1976
1985
|
}
|
|
1977
1986
|
|
|
1987
|
+
.av-print-avoid-break {
|
|
1988
|
+
break-inside: avoid;
|
|
1989
|
+
page-break-inside: avoid;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
@media print {
|
|
1993
|
+
.av-print-hide {
|
|
1994
|
+
display: none !important;
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
.av-print-white {
|
|
1998
|
+
background: #fff !important;
|
|
1999
|
+
color: #000 !important;
|
|
2000
|
+
box-shadow: none !important;
|
|
2001
|
+
background-image: none !important;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
|
|
1978
2005
|
/* Loading bar utility */
|
|
1979
2006
|
.av-loading-bar {
|
|
1980
2007
|
height: 4px;
|