Gestalt Design System

repository·master·Indexed 11 days ago

https://github.com/pinterest/gestalt

Pinterest's open-source design system featuring a React component library, design tokens, and comprehensive guidelines. Includes specialized packages such as gestalt-charts, gestalt-datepicker, and eslint-plugin-gestalt, as well as a jscodeshift-based codemod toolkit for codebase migrations.

Tokens
28.4K
Snippets
44
Records
114
Agent score
88%

What's inside Gestalt

  1. Use Groups for non-reusable element collections

    master

    In Figma design files, use Groups to combine multiple elements into a single top-level layer when those elements are not intended to be reused across the file.

    Key Characteristics:

    • The group's bounds automatically adjust based on the size and position of its child elements.
    • Child elements inside a group do not require auto-layout or resizing properties.

    When NOT to use Groups:

    • Do not use groups if you need to implement auto-layout, constraints, or make elements dynamic.
  2. How to use the term 'inspiration' thoughtfully

    master

    On Pinterest, inspiration refers to anything that sparks a desire to try something new, from everyday recipes to life-changing ideas.

    Usage Strategy:

    • Use sparingly: Do not pepper the term across every experience. Use it thoughtfully, similar to how the brand limits the use of 'Pinterest red'.
    • High-level only: Use it for high-level company descriptions (e.g., "The inspiration company").
    • Prefer external validation: It is more effective to let Pinners describe the experience (e.g., "Inspired on Pinterest") than to claim it ourselves.
    • Advertiser context: Use it when discussing how businesses provide inspiration to users.
  3. The Gestalt RFC life-cycle

    master

    Understanding the stages of an RFC from proposal to implementation:

    1. Proposal & Discussion: The RFC is submitted and discussed via Pull Request.
    2. Acceptance: The RFC is merged into the repository.
    3. Implementation: Authors implement the feature and submit a separate Pull Request for the code. Note that code implementation requires its own review process.
    4. Maintenance:
      • If design changes occur during implementation, the RFC must be updated to reflect them.
      • Once the feature is shipped, the RFC should be updated with a link to the Pull Request that implemented it.
      • If authors decide not to proceed, the RFC is removed from the repository.
  4. Use Sections to organize the Figma canvas

    master

    Use Sections to organize information within pages and layouts by adding labels to guide collaborators through your design file.

    Key Characteristics:

    • Sections act as layer types that can contain other artboards.
    • Constraint: Sections cannot be contained within frames or groups.

    Best Practices:

    • Do: Use sections to label and organize specific parts of your design canvas.

    When NOT to use Sections:

    • Do not use sections as a replacement for groups or frames.
  5. How Masonry works

    master

    Masonry is a generic layout component that manages a grid of items by measuring their heights and calculating their positions.

    Key behaviors to note:

    • Measurement-driven: It renders items offscreen to measure their heights, uses those measurements to determine layout positions, and then renders them onscreen. This process repeats as users scroll and new items are fetched.
    • Generic & Decoupled: Masonry knows nothing about its items and does not communicate with them.
    • Constraint on Item Heights: Because Masonry does not communicate with items, item heights cannot change after their initial render. If an item's height changes, Masonry will not be aware of it, which will result in overlaps or gaps in the grid. This is intended behavior to maintain its generic nature.
  6. When to use the Gestalt RFC process

    master

    The Request for Comments (RFC) process is required for "substantial" changes to Gestalt packages or documentation. This process ensures design consensus and provides institutional knowledge for future engineers.

    Required for:

    • New building-block components that solve complex issues (e.g., ScrollBoundaryContainer, Z-Index classes) or introduce new patterns (e.g., Flex, TapArea).
    • New utility components (e.g., OnLinkNavigationProvider, useReducedMotion).
    • New features that create new API surface area (e.g., adding dangerouslyDisableOnNavigation to OnLinkNavigationProvider).
    • New idiomatic usage, conventions, or patterns (e.g., design tokens, boint units, or subcomponent modularity patterns like Table or Dropdown).
    • Technology migrations (e.g., migrating to Next.js).

    Not required for:

    • Rephrasing, reorganizing, or refactoring code.
    • Adding new general components.
    • Additions that strictly improve objective, numerical quality criteria (e.g., speedups or better browser support).

    Note: Pull requests implementing new features without a prior RFC will be archived.

  7. Use Frames to construct Gestalt components

    master

    In Figma design files, Frames are the primary tool for creating dynamic layouts and reusable assets. Gestalt components are always constructed using Frames.

    Key Characteristics:

    • Frame sizes are set independently of their child elements (unlike Groups).
    • Moving or scaling child elements does not automatically adjust the frame's bounds.

    Best Practices:

    • Do: Use frames to construct components or any reusable assets.
    • Do: Use frames to control padding, margins, and spacing.

    When NOT to use Frames:

    • Do not use frames if your elements are not reusable across the file and you do not require dynamic controls.
  8. Use GlobalEventsHandlerProvider to inject external logic into components

    master

    The GlobalEventsHandlerProvider is a utility used to share external logic (such as logging or analytics) with interactive Gestalt components. It works by passing handlers down unidirectionally from parent to child. You can define specific handlers for different component types (e.g., buttonHandlers, linkHandlers) to intercept events like onClick, onBlur, or onFocus.

    To avoid code duplication when using multiple providers in different parts of your application, it is recommended to encapsulate your handler logic within a custom React hook.

    // Example of providing button-specific logging logic
    <GlobalEventsHandlerProvider
      buttonHandlers={{ onClick: ({ name, surface }) => log("button", "campaign_form", name, surface)}}
    >
      {children}
    </GlobalEventsHandlerProvider>
  9. Available Masonry layout types

    master

    Masonry supports several layout modes which can be categorized into three functional buckets:

    1. Default Layouts ("basic", "basicCentered"):

      • Yields a grid with constant column widths.
      • If the grid width doesn't match the container, whitespace appears on the sides (depending on whether "basic" or "basicCentered" is used).
      • Column count is calculated by (width + gutter) / (columnWidth + gutter), which can be overridden by minCols.
    2. Uniform Row Layout ("uniformRow"):

      • Yields a grid where items are organized into rows of uniform height.
      • Rows always take the height of the tallest item in that row. Shorter items will have whitespace below them.
      • Column count is calculated by (width + gutter) / (columnWidth + gutter), which can be overridden by minCols.
    3. Full Width Layouts ("flexible", "serverRenderedFlexible"):

      • Yields a grid with flexible column widths.
      • The grid expands or shrinks to fill the container width by adjusting all column widths.
      • Column count is determined by an idealColumnWidth and the available width.
  10. How jscodeshift codemods work

    master

    Gestalt codemods are built using jscodeshift, which is a toolkit for running transformations over JavaScript files via Abstract Syntax Tree (AST) analysis.

    Core Concepts

    • Nodes (AST nodes): Plain JavaScript objects representing code structures (e.g., a function call or a variable declaration). They are identified by their type. Use AST Explorer to inspect them.
    • Node-paths (path objects): Wrappers around AST nodes provided by ast-types. They contain metadata about the node's scope and relationships, and provide methods to process the nodes.
    • Collections: Groups of zero or more node-paths returned by querying the AST. Collections have methods to process the nodes within them, often returning new collections.

    Hierarchy: Collections contain Node-paths $\rightarrow$ Node-paths contain Nodes $\rightarrow$ Nodes constitute the AST.

  11. How GlobalEventsHandlerProvider works with components

    master

    The GlobalEventsHandlerProvider works by exposing a context that components can consume via a hook (e.g., useGlobalEventsHandlerContext).

    When a Gestalt component (like SheetMobile) is rendered, it checks the context for its specific handler prop. If handlers are present, the component executes them during its lifecycle (for example, inside a useEffect for mounting/unmounting or during an onClick event).

    Mental Model:

    • Provider: Defines what should happen when an event occurs.
    • Component: Defines when that event occurs (e.g., onOpen, onClose, onClick).
    • Decoupling: This allows the core Gestalt component to remain agnostic of specific business logic (like Pinterest's impression tracking) while still allowing that logic to be executed seamlessly.
  12. Understand the Masonry component lifecycle

    master

    The Masonry component follows a specific lifecycle to manage measurements and rendering:

    1. Initialization: Sets up a measurement store to persist item heights and measures the container (provided via the scrollContainer prop).
    2. Width Detection:
      • If the container width is unknown and there are pending measurements (e.g., during SSR hydration), it renders a static grid of placeholder items.
      • If the width is unknown and no measurements are pending, it renders a 100% width div with a ref to measure the container width.
    3. Layout & Rendering: Once width is known, items are split into two buckets:
      • Unmeasured items: Positioned offscreen to allow height measurement. These measurements are saved to the measurement store.
      • Measured items: Positioned onscreen and painted to the DOM.
    4. Reflow: Masonry automatically reflows (recalculates the layout for all items) if the container size changes or the items array references change.