mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-14 00:32:35 +10:00
perf: 🎨 remove fragment imports, optimize templates
This commit is contained in:
12
libs/hooks/src/hooks/use-template.ts
Normal file
12
libs/hooks/src/hooks/use-template.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { templatesList } from "@reactive-resume/templates";
|
||||
import { useMemo } from "react";
|
||||
|
||||
export const useTemplate = (templateId?: string) => {
|
||||
const template = useMemo(() => {
|
||||
return templatesList.find((template) => template.id === templateId);
|
||||
}, [templateId]);
|
||||
|
||||
if (!template || !template.Component) return null;
|
||||
|
||||
return template;
|
||||
};
|
||||
@ -1,4 +1,5 @@
|
||||
export * from "./hooks/use-breakpoint";
|
||||
export * from "./hooks/use-form-field";
|
||||
export * from "./hooks/use-password-toggle";
|
||||
export * from "./hooks/use-template";
|
||||
export * from "./hooks/use-theme";
|
||||
|
||||
@ -2,6 +2,7 @@ import { z } from "zod";
|
||||
|
||||
export const customFieldSchema = z.object({
|
||||
id: z.string().cuid2(),
|
||||
icon: z.string(),
|
||||
name: z.string(),
|
||||
value: z.string(),
|
||||
});
|
||||
|
||||
@ -7,7 +7,7 @@ export const customSectionSchema = itemSchema.extend({
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
date: z.string(),
|
||||
level: z.number().min(0).max(5).default(0),
|
||||
location: z.string(),
|
||||
summary: z.string(),
|
||||
keywords: z.array(z.string()).default([]),
|
||||
url: urlSchema,
|
||||
@ -22,7 +22,7 @@ export const defaultCustomSection: CustomSection = {
|
||||
name: "",
|
||||
description: "",
|
||||
date: "",
|
||||
level: 0,
|
||||
location: "",
|
||||
summary: "",
|
||||
keywords: [],
|
||||
url: defaultUrl,
|
||||
|
||||
@ -33,34 +33,48 @@ export const FrameWrapper = ({ children, style }: Props) => {
|
||||
setHeight(`${height}px`);
|
||||
}, []);
|
||||
|
||||
const loadFonts = useCallback(
|
||||
(frame: HTMLIFrameElement) => {
|
||||
if (font.family === "CMU Serif") {
|
||||
return webfontloader.load({
|
||||
classes: false,
|
||||
custom: {
|
||||
families: ["CMU Serif"],
|
||||
urls: ["https://cdn.jsdelivr.net/npm/computer-modern/cmu-serif.min.css"],
|
||||
},
|
||||
context: frame.contentWindow!,
|
||||
fontactive: () => handleResize(frame!),
|
||||
});
|
||||
}
|
||||
|
||||
webfontloader.load({
|
||||
classes: false,
|
||||
google: { families: [fontString] },
|
||||
context: frame.contentWindow!,
|
||||
fontactive: () => handleResize(frame!),
|
||||
});
|
||||
},
|
||||
[font, fontString, handleResize],
|
||||
);
|
||||
|
||||
const loadIconFonts = useCallback((frame: HTMLIFrameElement) => {
|
||||
const document = frame.contentDocument!;
|
||||
|
||||
const link = document.createElement("link");
|
||||
link.type = "text/css";
|
||||
link.rel = "stylesheet";
|
||||
link.href = "https://unpkg.com/@phosphor-icons/web@2.0.3/src/regular/style.css";
|
||||
|
||||
document.head.appendChild(link);
|
||||
}, []);
|
||||
|
||||
const onLoad = useCallback(() => {
|
||||
if (!frameRef.current) return;
|
||||
|
||||
handleResize(frameRef.current);
|
||||
|
||||
if (font.family === "CMU Serif") {
|
||||
return webfontloader.load({
|
||||
classes: false,
|
||||
custom: {
|
||||
families: ["CMU Serif"],
|
||||
urls: ["https://cdn.jsdelivr.net/npm/computer-modern/cmu-serif.min.css"],
|
||||
},
|
||||
context: frameRef.current.contentWindow!,
|
||||
fontactive: () => {
|
||||
handleResize(frameRef.current!);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
webfontloader.load({
|
||||
classes: false,
|
||||
google: { families: [fontString] },
|
||||
context: frameRef.current.contentWindow!,
|
||||
fontactive: () => {
|
||||
handleResize(frameRef.current!);
|
||||
},
|
||||
});
|
||||
}, [frameRef, font, fontString, handleResize]);
|
||||
loadFonts(frameRef.current);
|
||||
loadIconFonts(frameRef.current);
|
||||
}, [frameRef, handleResize, loadFonts, loadIconFonts]);
|
||||
|
||||
useEffect(() => {
|
||||
onLoad();
|
||||
|
||||
@ -41,17 +41,14 @@ export const Shared = css<GlobalStyleProps>`
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
line-height: calc(var(--line-height) + 1.5rem);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: calc(var(--line-height) + 1rem);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1rem;
|
||||
line-height: calc(var(--line-height) + 0rem);
|
||||
}
|
||||
|
||||
/* Paragraphs */
|
||||
@ -67,7 +64,7 @@ export const Shared = css<GlobalStyleProps>`
|
||||
|
||||
small {
|
||||
font-size: calc(var(--font-size) - 2px);
|
||||
line-height: calc(var(--line-height) - 0.5rem);
|
||||
line-height: calc(var(--line-height) - 2px);
|
||||
}
|
||||
|
||||
i,
|
||||
|
||||
@ -1 +1,16 @@
|
||||
export * from "./rhyhorn";
|
||||
import { TemplateProps } from "../shared";
|
||||
import { Rhyhorn } from "./rhyhorn";
|
||||
|
||||
type Template = {
|
||||
id: string;
|
||||
name: string;
|
||||
Component: (props: TemplateProps) => JSX.Element;
|
||||
};
|
||||
|
||||
export const templatesList: Template[] = [
|
||||
{
|
||||
id: "rhyhorn",
|
||||
name: "Rhyhorn",
|
||||
Component: Rhyhorn,
|
||||
},
|
||||
];
|
||||
|
||||
@ -16,7 +16,7 @@ import { References } from "./sections/references";
|
||||
import { Skills } from "./sections/skills";
|
||||
import { Summary } from "./sections/summary";
|
||||
import { Volunteer } from "./sections/volunteer";
|
||||
import { RhyhornStyles } from "./style";
|
||||
import { RhyhornWrapper } from "./style";
|
||||
|
||||
const sectionMap: Partial<Record<SectionKey, () => React.ReactNode>> = {
|
||||
summary: Summary,
|
||||
@ -44,7 +44,7 @@ const getSection = (id: SectionKey) => {
|
||||
};
|
||||
|
||||
export const Rhyhorn = ({ isFirstPage, columns }: TemplateProps) => (
|
||||
<RhyhornStyles>
|
||||
<RhyhornWrapper>
|
||||
{isFirstPage && <Header />}
|
||||
|
||||
{/* Main */}
|
||||
@ -52,5 +52,5 @@ export const Rhyhorn = ({ isFirstPage, columns }: TemplateProps) => (
|
||||
|
||||
{/* Sidebar */}
|
||||
{columns[1].map(getSection)}
|
||||
</RhyhornStyles>
|
||||
</RhyhornWrapper>
|
||||
);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Award as IAward } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,24 +11,27 @@ export const Awards = () => {
|
||||
<SectionBase<IAward>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.title}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.title}</h6>
|
||||
)}
|
||||
<h6>{item.title}</h6>
|
||||
<p>{item.awarder}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h6>{item.date}</h6>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item) => (
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Certification as ICertification } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,24 +11,27 @@ export const Certifications = () => {
|
||||
<SectionBase<ICertification>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.name}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.name}</h6>
|
||||
)}
|
||||
<h6>{item.name}</h6>
|
||||
<p>{item.issuer}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h6>{item.date}</h6>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item) => (
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -6,7 +6,6 @@ import {
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import get from "lodash.get";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -24,30 +23,32 @@ export const CustomSection = ({ id }: Props) => {
|
||||
<SectionBase<ICustomSection>
|
||||
section={section}
|
||||
header={(item: CustomSectionItem) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.name}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.name}</h6>
|
||||
)}
|
||||
<h6>{item.name}</h6>
|
||||
<p>{item.description}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h6>{item.date}</h6>
|
||||
<div className="rating">
|
||||
{Array.from({ length: item.level }).map((_, i) => (
|
||||
<span key={i} />
|
||||
))}
|
||||
</div>
|
||||
<p>{item.location}</p>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item: CustomSectionItem) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item: CustomSectionItem) => <small>{item.keywords.join(", ")}</small>}
|
||||
footer={(item: CustomSectionItem) => (
|
||||
<>
|
||||
<small>{item.keywords.join(", ")}</small>
|
||||
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Education as IEducation } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,15 +11,9 @@ export const Education = () => {
|
||||
<SectionBase<IEducation>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.institution}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.institution}</h6>
|
||||
)}
|
||||
<h6>{item.institution}</h6>
|
||||
<p>{item.area}</p>
|
||||
</div>
|
||||
|
||||
@ -31,9 +24,18 @@ export const Education = () => {
|
||||
{item.score ? ` | ${item.score}` : ""}
|
||||
</p>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item) => (
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Experience as IExperience } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,15 +11,9 @@ export const Experience = () => {
|
||||
<SectionBase<IExperience>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.company}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.company}</h6>
|
||||
)}
|
||||
<h6>{item.company}</h6>
|
||||
<p>{item.position}</p>
|
||||
</div>
|
||||
|
||||
@ -28,9 +21,18 @@ export const Experience = () => {
|
||||
<h6>{item.date}</h6>
|
||||
<p>{item.location}</p>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item) => (
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { Picture, useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
|
||||
export const Header = () => {
|
||||
const basics = useStore((state) => state.basics);
|
||||
|
||||
return (
|
||||
<div className="header">
|
||||
{basics.picture.url && !basics.picture.effects.hidden && (
|
||||
{isUrl(basics.picture.url) && !basics.picture.effects.hidden && (
|
||||
<Picture
|
||||
alt={basics.name}
|
||||
src={basics.picture.url}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Interest as IInterest } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -11,14 +10,14 @@ export const Interests = () => {
|
||||
<SectionBase<IInterest>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
<h6>{item.name}</h6>
|
||||
<p>{item.keywords.join(", ")}</p>
|
||||
</div>
|
||||
|
||||
<div />
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Language as ILanguage } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { getCEFRLevel } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,14 +11,14 @@ export const Languages = () => {
|
||||
<SectionBase<ILanguage>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
<h6>{item.name}</h6>
|
||||
<p>{item.fluency || getCEFRLevel(item.fluencyLevel)}</p>
|
||||
</div>
|
||||
|
||||
<div />
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Profile as IProfile } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
@ -18,7 +17,7 @@ export const Profiles = () => {
|
||||
<SectionBase<IProfile>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{item.icon && (
|
||||
<i>
|
||||
@ -42,7 +41,7 @@ export const Profiles = () => {
|
||||
</div>
|
||||
|
||||
<div />
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Project as IProject } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,25 +11,31 @@ export const Projects = () => {
|
||||
<SectionBase<IProject>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.name}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.name}</h6>
|
||||
)}
|
||||
<h6>{item.name}</h6>
|
||||
<p>{item.description}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h6>{item.date}</h6>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item) => <small>{item.keywords.join(", ")}</small>}
|
||||
footer={(item) => (
|
||||
<>
|
||||
<small>{item.keywords.join(", ")}</small>
|
||||
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Publication as IPublication } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,24 +11,27 @@ export const Publications = () => {
|
||||
<SectionBase<IPublication>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.name}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.name}</h6>
|
||||
)}
|
||||
<h6>{item.name}</h6>
|
||||
<p>{item.publisher}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h6>{item.date}</h6>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item) => (
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Reference as IReference } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,22 +11,25 @@ export const References = () => {
|
||||
<SectionBase<IReference>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.name}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.name}</h6>
|
||||
)}
|
||||
<h6>{item.name}</h6>
|
||||
<p>{item.description}</p>
|
||||
</div>
|
||||
|
||||
<div />
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item) => (
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Skill as ISkill } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -11,14 +10,14 @@ export const Skills = () => {
|
||||
<SectionBase<ISkill>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
<h6>{item.name}</h6>
|
||||
<p>{item.description}</p>
|
||||
</div>
|
||||
|
||||
<div />
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
footer={(item) => <small>{item.keywords.join(", ")}</small>}
|
||||
/>
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
|
||||
import { Heading } from "../shared/heading";
|
||||
|
||||
export const Summary = () => {
|
||||
const section = useStore((state) => state.sections.summary);
|
||||
|
||||
@ -9,7 +7,7 @@ export const Summary = () => {
|
||||
|
||||
return (
|
||||
<section id={section.id} className={`section section__${section.id}`}>
|
||||
<Heading>{section.name}</Heading>
|
||||
<h4 className="section__heading">{section.name}</h4>
|
||||
|
||||
<main className="section__item-content">
|
||||
<div
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Volunteer as IVolunteer } from "@reactive-resume/schema";
|
||||
import { useStore } from "@reactive-resume/templates";
|
||||
import { isUrl } from "@reactive-resume/utils";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { SectionBase } from "../shared/section-base";
|
||||
|
||||
@ -12,15 +11,9 @@ export const Volunteer = () => {
|
||||
<SectionBase<IVolunteer>
|
||||
section={section}
|
||||
header={(item) => (
|
||||
<Fragment>
|
||||
<>
|
||||
<div>
|
||||
{isUrl(item.url.href) ? (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.organization}</h6>
|
||||
</a>
|
||||
) : (
|
||||
<h6>{item.organization}</h6>
|
||||
)}
|
||||
<h6>{item.organization}</h6>
|
||||
<p>{item.position}</p>
|
||||
</div>
|
||||
|
||||
@ -28,9 +21,18 @@ export const Volunteer = () => {
|
||||
<h6>{item.date}</h6>
|
||||
<p>{item.location}</p>
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
)}
|
||||
main={(item) => <div dangerouslySetInnerHTML={{ __html: item.summary }} />}
|
||||
footer={(item) => (
|
||||
<div>
|
||||
{isUrl(item.url.href) && (
|
||||
<a href={item.url.href} target="_blank" rel="noopener noreferrer nofollow">
|
||||
<h6>{item.url.label || item.url.href}</h6>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
export const Heading = styled.h4`
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.2rem;
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 6px;
|
||||
text-transform: uppercase;
|
||||
border-bottom: 1px solid var(--color-text);
|
||||
`;
|
||||
@ -1,8 +1,6 @@
|
||||
import { Item, SectionItem, SectionWithItem } from "@reactive-resume/schema";
|
||||
import { ItemGrid } from "@reactive-resume/templates";
|
||||
|
||||
import { Heading } from "./heading";
|
||||
|
||||
type Props<T extends Item> = {
|
||||
section: SectionWithItem<T>;
|
||||
header?: (item: T) => React.ReactNode;
|
||||
@ -15,7 +13,7 @@ export const SectionBase = <T extends SectionItem>({ section, header, main, foot
|
||||
|
||||
return (
|
||||
<section id={section.id} className={`section section__${section.id}`}>
|
||||
<Heading>{section.name}</Heading>
|
||||
<h4 className="section__heading">{section.name}</h4>
|
||||
|
||||
<ItemGrid className="section__items" $columns={section.columns}>
|
||||
{section.items
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
export const RhyhornStyles = styled.div`
|
||||
export const RhyhornWrapper = styled.div`
|
||||
display: grid;
|
||||
row-gap: 16px;
|
||||
|
||||
@ -21,13 +21,17 @@ export const RhyhornStyles = styled.div`
|
||||
line-height: calc(var(--line-height) + 0.5rem);
|
||||
}
|
||||
|
||||
&__headline {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
&__meta {
|
||||
font-size: 0.875rem;
|
||||
line-height: var(--line-height);
|
||||
|
||||
span {
|
||||
padding: 0 6px;
|
||||
border-right: 1px solid var(--color-primary);
|
||||
border-right: 1px solid currentColor;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
@ -41,6 +45,16 @@ export const RhyhornStyles = styled.div`
|
||||
}
|
||||
|
||||
.section {
|
||||
&__heading {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.2rem;
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 6px;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-primary);
|
||||
border-bottom: 1px solid var(--color-text);
|
||||
}
|
||||
|
||||
&__item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@ -10,16 +10,18 @@ export const HoverCardContent = forwardRef<
|
||||
React.ElementRef<typeof HoverCardPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
|
||||
>(({ className, align = "center", sideOffset = 6, ...props }, ref) => (
|
||||
<HoverCardPrimitive.Content
|
||||
ref={ref}
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 rounded-md border bg-background p-4 text-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
<HoverCardPrimitive.Portal>
|
||||
<HoverCardPrimitive.Content
|
||||
ref={ref}
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 rounded-sm border bg-background p-4 text-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</HoverCardPrimitive.Portal>
|
||||
));
|
||||
|
||||
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
|
||||
|
||||
@ -312,16 +312,6 @@ export const fonts: Font[] = [
|
||||
"http://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZhrib2Bg-4.ttf",
|
||||
},
|
||||
},
|
||||
{
|
||||
family: "Material Icons",
|
||||
category: "monospace",
|
||||
subsets: ["latin"],
|
||||
variants: ["regular"],
|
||||
files: {
|
||||
regular:
|
||||
"http://fonts.gstatic.com/s/materialicons/v140/flUhRq6tzZclQEJ-Vdg-IuiaDsNZIhI8tIHh.ttf",
|
||||
},
|
||||
},
|
||||
{
|
||||
family: "Roboto Mono",
|
||||
category: "monospace",
|
||||
|
||||
Reference in New Issue
Block a user