Skip to content

Replace hand-scaled PDF widget sizes with one shared scale #12954

Description

@shervElmi

Feature Description

The PDF report follows a Figma design. The design is drawn on a 1180px-wide board, but the PDF page is only 612pt wide. So every size in the design has to be scaled down to fit the page.

Right now each widget scales its own sizes by hand, and they don't do it the same way. Some widgets use half the Figma size. The header, the footer, and the shared theme tokens use the full size. No single place sets the scale, so the report doesn't match the design, and every new widget guesses the sizes again.

Set the scale in one place, and apply it through one shared helper. A widget writes its styles with the real Figma sizes and passes them to the helper. The helper scales the sizes down and builds the final styles with StyleSheet.create. Every PDF widget uses the same helper, so the report matches the design and new widgets reuse the helper instead of guessing.


Do not alter or remove anything below. The following sections will be managed by moderators only.

Acceptance criteria

  • The Figma-to-point scale is defined in one place, as the page width divided by the Figma board width, 612 / 1180 (about 0.5186). Nothing else hardcodes the ratio.
  • Each PDF report widget writes its styles with raw Figma pixel sizes and passes them to the shared helper. The helper scales the sizes and builds the final styles, so no widget hardcodes a pre-scaled number.
  • The helper scales these length properties, and no others:
    • Text: fontSize, letterSpacing.
    • Margin: margin, marginHorizontal, marginVertical, marginTop, marginRight, marginBottom, marginLeft.
    • Padding: padding, paddingHorizontal, paddingVertical, paddingTop, paddingRight, paddingBottom, paddingLeft.
    • Size: width, height, minWidth, maxWidth, minHeight, maxHeight.
    • Position: top, right, bottom, left.
    • Gap: gap, rowGap, columnGap.
    • Border width: borderWidth, borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth.
    • Border radius: borderRadius, borderTopLeftRadius, borderTopRightRadius, borderBottomRightRadius, borderBottomLeftRadius.
    • Flex: flexBasis.
  • The helper leaves every other property unchanged. It never scales lineHeight, fontWeight, maxLines, flex, flexGrow, flexShrink, aspectRatio, opacity, or zIndex, and it never changes colors, font families, or any text value.
  • The helper scales a property only when its value is a number. A percent like 100% stays the same, and a negative number keeps its minus sign.
  • The width and height of an icon Svg are scaled by the same ratio. The shapes drawn inside the Svg and the page size stay the same.
  • Each PDF report widget matches the Figma design at the page width.
  • Every PDF report widget uses the shared helper.

Implementation Brief

  • Create assets/js/components/pdf-export/pdf-scale.ts

    • Add the page width, the Figma board width, the scale built from them, and the page padding:

      export const PDF_PAGE_WIDTH = 612;
      export const PDF_FIGMA_BOARD_WIDTH = 1180;
      export const PDF_SCALE = PDF_PAGE_WIDTH / PDF_FIGMA_BOARD_WIDTH;
      export const PDF_PAGE_PADDING = 24;
    • Add a Set such as PDF_SCALED_PROPERTIES holding the length property names the acceptance criteria lists.

    • Add a helper such as scalePDFValue( value: number ) that returns value * PDF_SCALE.

    • Add a wrapper such as createPDFStyles around StyleSheet.create that takes a styles object and returns the same shape. For each named style, build a new style object from its entries:

      • the property is in PDF_SCALED_PROPERTIES and its value is a number: multiply the value by PDF_SCALE.
      • any other property, or a value that is not a number such as '100%': keep the value.
      • Pass the rebuilt styles to StyleSheet.create and return the result.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/DashboardReport.tsx

    • Build styles with createPDFStyles in place of StyleSheet.create, and set each numeric length to its Figma design value.

    • In the <Page> size, use PDF_PAGE_WIDTH in place of 612.

    • Keep the page padding unscaled: remove paddingTop, paddingBottom, and paddingHorizontal from the page style, and set padding to PDF_PAGE_PADDING on the <Page> instead:

      <Page
          size={ [ PDF_PAGE_WIDTH, pageHeight ] }
          style={ [ styles.page, { padding: PDF_PAGE_PADDING } ] }
          wrap={ false }
      >
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFHeader.tsx

    • The same createPDFStyles change for styles.

    • Keep the header's marginTop, marginHorizontal, and paddingHorizontal unscaled: remove them from the header style, and apply them on the header <View> through a constant such as headerPageBleed:

      const headerPageBleed = {
          marginTop: -PDF_PAGE_PADDING,
          marginHorizontal: -PDF_PAGE_PADDING,
          paddingHorizontal: PDF_PAGE_PADDING,
      };
      <View style={ [ styles.header, headerPageBleed ] }>
    • Set the chevron Svg width and height to their raw Figma value wrapped in scalePDFValue, keeping the viewBox.

  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFSiteKitLogo.tsx

    • The same createPDFStyles change for styles.
    • Set the logo Svg width and height to their raw Figma value wrapped in scalePDFValue, keeping the viewBox and inner paths.
  • Update assets/js/components/pdf-export/section-icons.ts

    • In makeIcon, wrap the Svg width and height (size) with scalePDFValue, keeping the viewBox and the inner Rect and Path shapes.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFHeaderSectionChip.tsx

    • The same createPDFStyles change for styles.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFEmailReportingNotice.tsx

    • The same createPDFStyles change for styles.
    • Set the star Svg width and height to their raw Figma value wrapped in scalePDFValue, keeping the viewBox.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFMetricTile.tsx

    • The same createPDFStyles change for tileStyles.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFMetricChartTile.tsx

    • The same createPDFStyles change for styles.
    • Set the ChangeArrow Svg and the LegendSwatch Svg width and height to their raw Figma value wrapped in scalePDFValue, keeping each viewBox and the inner Path and Line.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFFooter.tsx

    • The same createPDFStyles change for styles.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFTable.tsx

    • The same createPDFStyles change for styles.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFWidgetSection.tsx

    • The same createPDFStyles change for styles.
  • Update assets/js/modules/analytics-4/components/dashboard/DashboardAllTrafficWidgetGA4/indexPDF.tsx

    • The same createPDFStyles change for styles.
  • Update assets/js/modules/analytics-4/components/module/ModulePopularPagesWidgetGA4/ModulePopularPagesWidgetGA4PDF.tsx

    • The same createPDFStyles change for styles.
    • Wrap each inline cardStyle length (borderRadius, paddingVertical, paddingHorizontal) with scalePDFValue at its Figma value.
  • Update assets/js/modules/search-console/components/dashboard/SearchFunnelWidgetGA4/indexPDF.tsx

    • The same createPDFStyles change for styles.
  • Update any later PDF report widget the same way

    • If an in-flight PDF ticket adds another report widget, build its styles with createPDFStyles and wrap any Svg size or inline length with scalePDFValue.

Test Coverage

  • Create assets/js/components/pdf-export/pdf-scale.test.ts
    • createPDFStyles multiplies a length by PDF_SCALE for one property from each scaled group the acceptance criteria lists: fontSize, letterSpacing, a margin, a padding, width, height, top, a gap, a border width, borderRadius, and flexBasis.
    • createPDFStyles leaves each never-scaled property unchanged: lineHeight, fontWeight, maxLines, flex, flexGrow, flexShrink, aspectRatio, opacity, zIndex, a color, and a font family.
    • createPDFStyles leaves a percent like '100%' unchanged, and keeps the minus sign on a negative length.
    • scalePDFValue multiplies a number by PDF_SCALE.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFWidgetSection.test.tsx
    • Update the default card "padding" and "borderRadius" assertions to the values createPDFStyles now produces. Set each expected value to the raw Figma value multiplied by PDF_SCALE, not a fixed decimal.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFTable.test.tsx
    • Update the "columnGap" and "paddingHorizontal" assertions to the values createPDFStyles now produces. Set each expected value to the raw Figma value multiplied by PDF_SCALE, not a fixed decimal.
  • Update assets/js/components/pdf-export/shared-react-pdf-components/PDFHeader.test.tsx
    • The rendered header keeps "marginTop":-24, "marginHorizontal":-24, and "paddingHorizontal":24.
    • The header's marginBottom, paddingTop, and paddingBottom equal their Figma value multiplied by PDF_SCALE.
    • The chevron Svg width is scalePDFValue( 10 ).
  • Update assets/js/components/pdf-export/shared-react-pdf-components/DashboardReport.test.tsx
    • The page keeps "padding":24, and the <Page> size width is PDF_PAGE_WIDTH.

QA Brief

Changelog entry

Metadata

Metadata

Assignees

Labels

P1Medium priorityTeam SIssues for Squad 1Type: EnhancementImprovement of an existing featureType: InfrastructureEngineering infrastructure & tooling

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions