or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

dom-events.mddom-utilities.mdfocus-accessibility.mdfunction-utilities.mdindex.mdmath-utilities.mdobject-manipulation.mdreact-utilities.mdresponsive.mdtype-checking.md
tile.json

responsive.mddocs/

Responsive Design

Utilities for working with responsive breakpoints, media queries, and responsive prop values. These utilities support both object and array notation for responsive values and provide breakpoint analysis capabilities for building responsive UI systems.

Capabilities

Breakpoint Utilities

Core utilities for working with CSS units and media queries.

/**
 * Converts unitless values to px strings
 * @param value - Number, string, or null value to convert
 * @returns String with px unit or null
 */
function px(value: number | string | null): string | null;

/**
 * Creates CSS media query string from min and max values
 * @param min - Minimum breakpoint value
 * @param max - Maximum breakpoint value (optional)
 * @returns CSS media query string
 */
function toMediaQueryString(min: string | null, max?: string): string;

Usage Examples:

import { px, toMediaQueryString } from "@chakra-ui/utils";

// Unit conversion
const spacing = {
  sm: px(8),    // "8px"
  md: px(16),   // "16px"
  lg: px(24),   // "24px"
  xl: px("2rem") // "2rem"
};

// Media query generation
const breakpoints = {
  sm: "768px",
  md: "1024px",
  lg: "1200px"
};

const mediaQueries = {
  mobile: toMediaQueryString(null, breakpoints.sm),           // "@media (max-width: 768px)"
  tablet: toMediaQueryString(breakpoints.sm, breakpoints.md), // "@media (min-width: 768px) and (max-width: 1024px)"
  desktop: toMediaQueryString(breakpoints.md),                // "@media (min-width: 1024px)"
};

// CSS-in-JS usage
const styles = {
  container: {
    padding: px(16),
    [mediaQueries.mobile]: {
      padding: px(8)
    },
    [mediaQueries.desktop]: {
      padding: px(32)
    }
  }
};

Breakpoint Analysis

Advanced breakpoint system analysis and utility generation.

/**
 * Analyzes breakpoint configuration and provides utility functions
 * @param breakpoints - Object containing breakpoint definitions
 * @returns Object with breakpoint utilities or null if invalid
 */
function analyzeBreakpoints(breakpoints: Record<string, any>): AnalyzeBreakpointsReturn | null;

interface AnalyzeBreakpointsReturn {
  keys: string[];
  normalized: string[];
  asObject: Record<string, string>;
  asArray: string[];
  details: BreakpointDetail[];
  media: string[];
}

interface BreakpointDetail {
  breakpoint: string;
  maxWidth: string | undefined;
  minWidth: string;
  maxWidthValue: number | undefined;
  minWidthValue: number;
}

Usage Examples:

import { analyzeBreakpoints } from "@chakra-ui/utils";

// Analyze custom breakpoints
const customBreakpoints = {
  mobile: "320px",
  tablet: "768px", 
  desktop: "1024px",
  wide: "1440px"
};

const analysis = analyzeBreakpoints(customBreakpoints);

if (analysis) {
  console.log("Breakpoint keys:", analysis.keys);          // ["mobile", "tablet", "desktop", "wide"]
  console.log("Media queries:", analysis.media);           // ["@media (min-width: 320px)", ...]
  console.log("Breakpoint details:", analysis.details);   // Detailed breakpoint information
  
  // Use in styled components
  const StyledComponent = styled.div`
    ${analysis.media[0]} {
      font-size: 14px;
    }
    ${analysis.media[1]} {
      font-size: 16px;
    }
  `;
}

// Theme integration
function createTheme(breakpoints: Record<string, string>) {
  const analysis = analyzeBreakpoints(breakpoints);
  
  return {
    breakpoints: analysis?.asObject || {},
    mediaQueries: analysis?.media || [],
    space: analysis?.normalized.map(bp => px(parseInt(bp))) || []
  };
}

Responsive Value Processing

Default breakpoints and utilities for handling responsive prop values.

/**
 * Default breakpoint names used throughout Chakra UI
 */
const breakpoints: ["base", "sm", "md", "lg", "xl", "2xl"];

/**
 * Maps responsive prop values using a mapper function
 * @param prop - Responsive prop value (object, array, or single value)
 * @param mapper - Function to transform each value
 * @returns Transformed responsive value
 */
function mapResponsive(prop: any, mapper: (val: any) => any): any;

/**
 * Converts responsive object notation to array notation
 * @param obj - Responsive object with breakpoint keys
 * @param bps - Optional breakpoint names array
 * @returns Array of responsive values
 */
function objectToArrayNotation(obj: Record<string, any>, bps?: string[]): any[];

/**
 * Converts responsive array notation to object notation
 * @param values - Array of responsive values
 * @param bps - Optional breakpoint names array
 * @returns Object with breakpoint keys
 */
function arrayToObjectNotation(values: any[], bps?: string[]): Record<string, any>;

/**
 * Checks if an object looks like a responsive object
 * @param obj - Object to check
 * @param bps - Optional breakpoint names array
 * @returns true if object appears to be responsive
 */
function isResponsiveObjectLike(obj: Record<string, any>, bps?: string[]): boolean;

/**
 * Checks if a breakpoint key is custom (not in default set)
 * @param v - Breakpoint key to check
 * @returns true if breakpoint is custom
 */
function isCustomBreakpoint(v: string): boolean;

Usage Examples:

import { 
  breakpoints,
  mapResponsive, 
  objectToArrayNotation,
  arrayToObjectNotation,
  isResponsiveObjectLike 
} from "@chakra-ui/utils";

// Working with responsive props
interface BoxProps {
  padding?: ResponsiveValue<string | number>;
  margin?: ResponsiveValue<string | number>;
}

type ResponsiveValue<T> = T | T[] | Record<string, T>;

function Box({ padding, margin }: BoxProps) {
  // Transform responsive padding values
  const responsivePadding = mapResponsive(padding, (value) => {
    return typeof value === "number" ? `${value * 4}px` : value;
  });
  
  // Convert between notations
  const paddingArray = Array.isArray(padding) 
    ? padding 
    : isResponsiveObjectLike(padding) 
      ? objectToArrayNotation(padding, breakpoints)
      : [padding];
  
  const paddingObject = arrayToObjectNotation(paddingArray, breakpoints);
  
  return (
    <div 
      style={{
        padding: responsivePadding,
        margin: mapResponsive(margin, value => px(value))
      }}
    />
  );
}

// Usage examples
const responsiveProps = {
  // Object notation
  padding: { base: "4px", md: "8px", lg: "16px" },
  
  // Array notation  
  margin: ["2px", "4px", "8px", "16px"],
  
  // Single value
  border: "1px solid"
};

// Transform responsive spacing system
function createSpacingSystem(baseUnit: number) {
  const scale = [0, 1, 2, 4, 8, 16, 32, 64];
  
  return mapResponsive(scale, (value) => `${value * baseUnit}px`);
}

// Responsive typography
const responsiveText = {
  fontSize: { base: "14px", md: "16px", lg: "18px" },
  lineHeight: { base: 1.4, md: 1.5, lg: 1.6 }
};

const processedText = {
  fontSize: mapResponsive(responsiveText.fontSize, px),
  lineHeight: mapResponsive(responsiveText.lineHeight, (value) => value)
};

Responsive Component Patterns

Common patterns for building responsive components.

import { 
  mapResponsive, 
  analyzeBreakpoints,
  isResponsiveObjectLike 
} from "@chakra-ui/utils";

// Responsive Grid component
interface GridProps {
  columns?: ResponsiveValue<number>;
  gap?: ResponsiveValue<string | number>;
  children: React.ReactNode;
}

function ResponsiveGrid({ columns = 1, gap = "1rem", children }: GridProps) {
  const gridColumns = mapResponsive(columns, (cols) => `repeat(${cols}, 1fr)`);
  const gridGap = mapResponsive(gap, (g) => px(g));
  
  return (
    <div
      style={{
        display: "grid",
        gridTemplateColumns: gridColumns,
        gap: gridGap
      }}
    >
      {children}
    </div>
  );
}

// Usage
<ResponsiveGrid 
  columns={{ base: 1, md: 2, lg: 3 }}
  gap={["8px", "16px", "24px"]}
>
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
</ResponsiveGrid>

// Responsive Text component
interface TextProps {
  size?: ResponsiveValue<"sm" | "md" | "lg" | "xl">;
  children: React.ReactNode;
}

const textSizes = {
  sm: { fontSize: "14px", lineHeight: "1.4" },
  md: { fontSize: "16px", lineHeight: "1.5" },
  lg: { fontSize: "18px", lineHeight: "1.6" },
  xl: { fontSize: "24px", lineHeight: "1.4" }
};

function ResponsiveText({ size = "md", children }: TextProps) {
  const styles = mapResponsive(size, (s) => textSizes[s]);
  
  return <p style={styles}>{children}</p>;
}

// Usage
<ResponsiveText size={{ base: "sm", md: "md", lg: "lg" }}>
  This text scales with breakpoints
</ResponsiveText>

// Custom breakpoint system
const customBreakpoints = {
  xs: "320px",
  sm: "640px", 
  md: "768px",
  lg: "1024px",
  xl: "1280px"
};

const breakpointSystem = analyzeBreakpoints(customBreakpoints);

function useBreakpoints() {
  const [currentBreakpoint, setCurrentBreakpoint] = React.useState("xs");
  
  React.useEffect(() => {
    if (!breakpointSystem) return;
    
    const mediaQueries = breakpointSystem.details.map(detail => ({
      query: window.matchMedia(detail.minWidth ? `(min-width: ${detail.minWidth})` : "all"),
      breakpoint: detail.breakpoint
    }));
    
    const updateBreakpoint = () => {
      const matched = mediaQueries
        .reverse()
        .find(mq => mq.query.matches);
      
      if (matched) {
        setCurrentBreakpoint(matched.breakpoint);
      }
    };
    
    mediaQueries.forEach(mq => mq.query.addEventListener("change", updateBreakpoint));
    updateBreakpoint();
    
    return () => {
      mediaQueries.forEach(mq => mq.query.removeEventListener("change", updateBreakpoint));
    };
  }, []);
  
  return currentBreakpoint;
}