Fix split row right content promotion (#3039)

* Fix split row right content promotion

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>

* refactor: remove MetaLine component and update sections to use Text instead

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
Amruth Pillai
2026-05-11 15:59:26 +02:00
committed by GitHub
parent de7baa5faf
commit 0a8fe05653
4 changed files with 110 additions and 50 deletions
@@ -1,9 +0,0 @@
import { Small } from "./primitives";
export const MetaLine = ({ children }: { children: Array<string | undefined> }) => {
const content = children.filter(Boolean).join(" • ");
if (!content) return null;
return <Small>{content}</Small>;
};
+72 -41
View File
@@ -35,11 +35,11 @@ import {
} from "./context";
import { filterItems, hasVisibleItems, isSectionVisible, isVisibleSummary } from "./filtering";
import { LevelDisplay } from "./level-display";
import { MetaLine } from "./meta-line";
import { getTemplateMetrics } from "./metrics";
import { Bold, Div, Heading, Icon, Link, Small, Text } from "./primitives";
import { RichText } from "./rich-text";
import { getInlineItemWebsiteUrl, shouldRenderSeparateItemWebsite } from "./section-links";
import { hasSplitRowText, promoteSplitRowRight } from "./split-row";
import { composeStyles } from "./styles";
type SectionItemsContextValue = {
@@ -195,8 +195,8 @@ const awardTitleDateRowStyle = {
} satisfies Style;
const useSectionSplitRowStyle = () => {
const splitRowStyle = useTemplateStyle("splitRow");
const placement = useTemplatePlacement();
const splitRowStyle = useTemplateStyle("splitRow");
const stackSidebarItemHeader = useTemplateFeature("stackSidebarItemHeader");
return composeStyles(
@@ -331,6 +331,10 @@ const ExperienceSection = ({
{items.map((item) => {
const hasPosition = Boolean(item.position.trim());
const hasLocation = Boolean(item.location.trim());
const { top: headerLocation, bottom: headerPeriod } = promoteSplitRowRight({
top: item.location,
bottom: item.period,
});
const renderInlineHeader = () => (
<InlineItemHeader
@@ -352,13 +356,15 @@ const ExperienceSection = ({
<>
<View style={composeStyles(splitRowStyle)}>
<ItemTitle website={item.website}>{item.company}</ItemTitle>
<Text style={composeStyles(alignRightStyle)}>{item.location}</Text>
{hasSplitRowText(headerLocation) && (
<Text style={composeStyles(alignRightStyle)}>{headerLocation}</Text>
)}
</View>
{item.roles.length === 0 && (
{item.roles.length === 0 && (hasPosition || hasSplitRowText(headerPeriod)) && (
<View style={composeStyles(splitRowStyle)}>
<Text>{item.position}</Text>
<Text style={composeStyles(alignRightStyle)}>{item.period}</Text>
{hasPosition && <Text>{item.position}</Text>}
{hasSplitRowText(headerPeriod) && <Text style={composeStyles(alignRightStyle)}>{headerPeriod}</Text>}
</View>
)}
</>
@@ -368,7 +374,7 @@ const ExperienceSection = ({
<SectionItem key={item.id}>
<SectionItemHeader>{inlineItemHeader ? renderInlineHeader() : renderSplitHeader()}</SectionItemHeader>
{item.roles.length > 0 && <MetaLine>{[item.period]}</MetaLine>}
{item.roles.length > 0 && <Text>{item.period}</Text>}
{item.roles.map((role) => (
<View key={role.id}>
@@ -416,6 +422,10 @@ const EducationSection = ({
const gradeAndLocation = [item.grade, item.location].filter(Boolean).join(" • ");
const hasArea = Boolean(item.area.trim());
const hasDegree = Boolean(item.degree.trim());
const { top: headerDegreeAndGrade, bottom: headerLocationAndPeriod } = promoteSplitRowRight({
top: degreeAndGrade,
bottom: locationAndPeriod,
});
const renderInlineHeader = () => (
<>
@@ -440,13 +450,19 @@ const EducationSection = ({
<>
<View style={composeStyles(splitRowStyle)}>
<ItemTitle website={item.website}>{item.school}</ItemTitle>
<Text style={composeStyles(alignRightStyle)}>{degreeAndGrade}</Text>
{hasSplitRowText(headerDegreeAndGrade) && (
<Text style={composeStyles(alignRightStyle)}>{headerDegreeAndGrade}</Text>
)}
</View>
<View style={composeStyles(splitRowStyle)}>
<Text>{item.area}</Text>
<Text style={composeStyles(alignRightStyle)}>{locationAndPeriod}</Text>
</View>
{(hasArea || hasSplitRowText(headerLocationAndPeriod)) && (
<View style={composeStyles(splitRowStyle)}>
{hasArea && <Text>{item.area}</Text>}
{hasSplitRowText(headerLocationAndPeriod) && (
<Text style={composeStyles(alignRightStyle)}>{headerLocationAndPeriod}</Text>
)}
</View>
)}
</>
);
@@ -629,7 +645,7 @@ const AwardsSection = ({
<SectionItemHeader>
<View style={composeStyles(splitRowStyle, awardTitleDateRowStyle)}>
<ItemTitle website={item.website}>{item.title}</ItemTitle>
<Small style={composeStyles(alignRightStyle)}>{item.date}</Small>
<Text style={composeStyles(alignRightStyle)}>{item.date}</Text>
</View>
<Text>{item.awarder}</Text>
</SectionItemHeader>
@@ -653,6 +669,8 @@ const CertificationsSection = ({
const data = useRender();
const certifications = sectionData ?? data.sections.certifications;
const items = getVisibleItems(certifications, "certifications");
const splitRowStyle = useSectionSplitRowStyle();
const alignRightStyle = useTemplateStyle("alignRight");
if (items.length === 0) return null;
@@ -662,10 +680,13 @@ const CertificationsSection = ({
{items.map((item) => (
<SectionItem key={item.id}>
<SectionItemHeader>
<ItemTitle website={item.website}>{item.title}</ItemTitle>
<View style={composeStyles(splitRowStyle)}>
<ItemTitle website={item.website}>{item.title}</ItemTitle>
<Text style={composeStyles(alignRightStyle)}>{item.date}</Text>
</View>
<Text>{item.issuer}</Text>
<Small>{item.date}</Small>
</SectionItemHeader>
<RichText>{item.description}</RichText>
<ItemWebsiteLink website={item.website} />
@@ -686,6 +707,8 @@ const PublicationsSection = ({
const data = useRender();
const publications = sectionData ?? data.sections.publications;
const items = getVisibleItems(publications, "publications");
const splitRowStyle = useSectionSplitRowStyle();
const alignRightStyle = useTemplateStyle("alignRight");
if (items.length === 0) return null;
@@ -695,10 +718,14 @@ const PublicationsSection = ({
{items.map((item) => (
<SectionItem key={item.id}>
<SectionItemHeader>
<ItemTitle website={item.website}>{item.title}</ItemTitle>
<View style={composeStyles(splitRowStyle)}>
<ItemTitle website={item.website}>{item.title}</ItemTitle>
<Text style={composeStyles(alignRightStyle)}>{item.date}</Text>
</View>
<Text>{item.publisher}</Text>
<Small>{item.date}</Small>
</SectionItemHeader>
<RichText>{item.description}</RichText>
<ItemWebsiteLink website={item.website} />
@@ -728,31 +755,35 @@ const VolunteerSection = ({
return (
<SectionShell sectionId={sectionId} title={volunteer.title}>
<SectionItems columns={volunteer.columns}>
{items.map((item) => (
<SectionItem key={item.id}>
<SectionItemHeader>
{inlineItemHeader ? (
<InlineItemHeader
leading={<Text>{item.location}</Text>}
middle={<ItemTitle website={item.website}>{item.organization}</ItemTitle>}
trailing={<Text style={composeStyles(alignRightStyle)}>{item.period}</Text>}
/>
) : (
<>
<View style={composeStyles(splitRowStyle)}>
<ItemTitle website={item.website}>{item.organization}</ItemTitle>
<Text style={composeStyles(alignRightStyle)}>{item.location}</Text>
</View>
{items.map((item) => {
return (
<SectionItem key={item.id}>
<SectionItemHeader>
{inlineItemHeader ? (
<InlineItemHeader
leading={hasSplitRowText(item.location) ? <Text>{item.location}</Text> : null}
middle={<ItemTitle website={item.website}>{item.organization}</ItemTitle>}
trailing={<Text style={composeStyles(alignRightStyle)}>{item.period}</Text>}
/>
) : (
<>
<View style={composeStyles(splitRowStyle)}>
<ItemTitle website={item.website}>{item.organization}</ItemTitle>
{hasSplitRowText(item.period) && (
<Text style={composeStyles(alignRightStyle)}>{item.period}</Text>
)}
</View>
<MetaLine>{[item.period]}</MetaLine>
</>
)}
</SectionItemHeader>
<RichText>{item.description}</RichText>
<Text>{item.location}</Text>
</>
)}
</SectionItemHeader>
<RichText>{item.description}</RichText>
<ItemWebsiteLink website={item.website} />
</SectionItem>
))}
<ItemWebsiteLink website={item.website} />
</SectionItem>
);
})}
</SectionItems>
</SectionShell>
);
@@ -779,7 +810,7 @@ const ReferencesSection = ({
<SectionItemHeader>
<ItemTitle website={item.website}>{item.name}</ItemTitle>
<Text>{item.position}</Text>
<MetaLine>{[item.phone]}</MetaLine>
<Text>{item.phone}</Text>
</SectionItemHeader>
<RichText>{item.description}</RichText>
@@ -0,0 +1,27 @@
import { describe, expect, it } from "vitest";
import { hasSplitRowText, promoteSplitRowRight } from "./split-row";
describe("hasSplitRowText", () => {
it("returns true only for non-empty text", () => {
expect(hasSplitRowText("2019 - 2024")).toBe(true);
expect(hasSplitRowText(" ")).toBe(false);
expect(hasSplitRowText(undefined)).toBe(false);
});
});
describe("promoteSplitRowRight", () => {
it("keeps both right cells when the top-right cell has content", () => {
expect(promoteSplitRowRight({ top: "Remote", bottom: "2019 - 2024" })).toEqual({
top: "Remote",
bottom: "2019 - 2024",
});
});
it("moves bottom-right content to the top right when top-right content is missing", () => {
expect(promoteSplitRowRight({ top: "", bottom: "2019 - 2024" })).toEqual({ top: "2019 - 2024", bottom: "" });
});
it("treats whitespace-only cells as missing", () => {
expect(promoteSplitRowRight({ top: " ", bottom: "\t" })).toEqual({ top: "", bottom: "" });
});
});
@@ -0,0 +1,11 @@
export const hasSplitRowText = (value: string | undefined): value is string => {
return typeof value === "string" && value.trim().length > 0;
};
type SplitRowContent = { top: string; bottom: string };
export const promoteSplitRowRight = ({ top, bottom }: SplitRowContent): SplitRowContent => {
if (hasSplitRowText(top)) return { top, bottom: hasSplitRowText(bottom) ? bottom : "" };
return { top: hasSplitRowText(bottom) ? bottom : "", bottom: "" };
};