Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/css/support/blog.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
}

.recommendations-list {
@apply h-96 overflow-y-auto pr-2;
height: calc(var(--recommendations-section-min) * 0.8);
@apply overflow-y-auto pr-2;
@apply scroll-smooth;
}

Expand Down
11 changes: 9 additions & 2 deletions src/partials/RecommendationPartial.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<template>
<section class="space-y-8">
<section class="space-y-8" :style="recommendationsSectionStyle">
<div class="flex flex-wrap items-center justify-between gap-4">
<h2 class="h3 font-aspekta text-slate-800 dark:text-slate-100">Recommendations</h2>
<BackToTopLink :target="backToTopTarget" />
</div>
<ul class="recommendations-list space-y-8">
<ul class="recommendations-list custom-scrollbar space-y-8">
<!-- Item -->
<li v-for="item in paginatedRecommendations" :key="item.uuid" class="relative group">
<div class="flex items-start">
Expand Down Expand Up @@ -50,6 +50,7 @@ import { image, date } from '@/public.ts';
import type { RecommendationsResponse } from '@api/response/recommendations-response.ts';
import { renderMarkdown } from '@/support/markdown.ts';
import { usePagination } from '@/support/pagination.ts';
import { Heights } from '@/support/heights.ts';

const props = defineProps<{
recommendations: Array<RecommendationsResponse>;
Expand All @@ -60,6 +61,12 @@ const { recommendations, backToTopTarget } = toRefs(props);

const ITEMS_PER_PAGE = 3;

const RECOMMENDATIONS_SECTION_MIN_VARIABLE = '--recommendations-section-min';
const recommendationsSectionMinHeight = `${Heights.resumeSectionMinHeights().recommendations.base}rem`;
const recommendationsSectionStyle = computed(() => ({
[RECOMMENDATIONS_SECTION_MIN_VARIABLE]: recommendationsSectionMinHeight,
}));

const processedRecommendations = computed(() => {
return recommendations.value.map((item) => {
const sanitisedHtml = DOMPurify.sanitize(renderMarkdown(item.text));
Expand Down
34 changes: 17 additions & 17 deletions src/support/heights.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@ export class Heights {
private static readonly minInResume = Object.freeze({
education: Object.freeze({ base: 26, lg: 28 }),
experience: Object.freeze({ base: 34, lg: 36 }),
recommendations: Object.freeze({ base: 30, lg: 32 }),
recommendations: Object.freeze({ base: 42, lg: 44.8 }),
} satisfies SectionMinMap);

private static readonly classesInResume = Object.freeze({
education: 'min-h-[26rem] lg:min-h-[28rem]',
experience: 'min-h-[34rem] lg:min-h-[36rem]',
recommendations: 'min-h-[30rem] lg:min-h-[32rem]',
} satisfies SectionClassMap);

private static readonly safeInResume = Object.freeze([
'min-h-[26rem]',
'lg:min-h-[28rem]',
'min-h-[34rem]',
'lg:min-h-[36rem]',
'min-h-[30rem]',
'lg:min-h-[32rem]',
'min-h-[96rem]',
'lg:min-h-[102rem]',
] satisfies SectionSafe);
private static get classesInResume(): SectionClassMap {
const buildClasses = (section: SectionMin) => `min-h-[${section.base}rem] lg:min-h-[${section.lg}rem]`;

return Object.freeze({
education: buildClasses(this.minInResume.education),
experience: buildClasses(this.minInResume.experience),
recommendations: buildClasses(this.minInResume.recommendations),
} satisfies SectionClassMap);
}

private static get safeInResume(): SectionSafe {
const sectionClasses = Object.values(this.classesInResume).flatMap((c) => c.split(' '));
const totalClasses = this.resumeSectionsTotalHeight().split(' ');

return Object.freeze([...sectionClasses, ...totalClasses]);
}

static resumeSectionMinHeights(): SectionMinMap {
return this.minInResume;
Expand Down
14 changes: 7 additions & 7 deletions tests/support/heights.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Heights', () => {
expect(min).toEqual({
education: { base: 26, lg: 28 },
experience: { base: 34, lg: 36 },
recommendations: { base: 30, lg: 32 },
recommendations: { base: 42, lg: 44.8 },
});
expect(Object.isFrozen(min)).toBe(true);
expect(Object.isFrozen(min.education)).toBe(true);
Expand All @@ -21,12 +21,12 @@ describe('Heights', () => {
expect(Heights.resumeSectionHeights()).toEqual({
education: 'min-h-[26rem] lg:min-h-[28rem]',
experience: 'min-h-[34rem] lg:min-h-[36rem]',
recommendations: 'min-h-[30rem] lg:min-h-[32rem]',
recommendations: 'min-h-[42rem] lg:min-h-[44.8rem]',
});
});

it('calculates the total resume sections min-height', () => {
expect(Heights.resumeSectionsTotalHeight()).toBe('min-h-[96rem] lg:min-h-[102rem]');
expect(Heights.resumeSectionsTotalHeight()).toBe('min-h-[108rem] lg:min-h-[114.8rem]');
});

it('exposes safelisted resume section classes for tailwind', () => {
Expand All @@ -35,10 +35,10 @@ describe('Heights', () => {
'lg:min-h-[28rem]',
'min-h-[34rem]',
'lg:min-h-[36rem]',
'min-h-[30rem]',
'lg:min-h-[32rem]',
'min-h-[96rem]',
'lg:min-h-[102rem]',
'min-h-[42rem]',
'lg:min-h-[44.8rem]',
'min-h-[108rem]',
'lg:min-h-[114.8rem]',
]);
});
});
Loading