or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-styling.mdcss-utilities.mdindex.mdreact-native.mdserver-side-rendering.mdtest-utilities.mdtheming.mdtypescript-integration.md
tile.json

core-styling.mddocs/

Core Styling

The core styling API is the foundation of styled-components, providing the primary styled function and HTML element shortcuts for creating styled React components using template literals.

Basic Styled Components

Main styled Function

Creates styled components from any valid React component or HTML element.

declare const styled: <Target extends WebTarget>(target: Target) => StyledInstance<'web', Target, ComponentProps<Target>>;

type WebTarget = string | React.ComponentType<any>;

Usage Examples:

// Style an HTML element
const StyledDiv = styled.div`
  background-color: blue;
  padding: 20px;
`;

// Style a custom component
const CustomButton = ({ children, ...props }) => <button {...props}>{children}</button>;
const StyledCustomButton = styled(CustomButton)`
  border-radius: 8px;
  font-weight: bold;
`;

// Style with TypeScript props
interface ButtonProps {
  primary?: boolean;
  size?: 'small' | 'medium' | 'large';
}

const Button = styled.button<ButtonProps>`
  background: ${props => props.primary ? '#007bff' : '#6c757d'};
  padding: ${props => {
    switch (props.size) {
      case 'small': return '4px 8px';
      case 'large': return '12px 24px';
      default: return '8px 16px';
    }
  }};
`;

HTML Element Shortcuts

Pre-configured styled functions for all standard HTML elements.

interface Styled {
  // Form elements
  button: StyledInstance<'web', 'button', React.ButtonHTMLAttributes<HTMLButtonElement>>;
  input: StyledInstance<'web', 'input', React.InputHTMLAttributes<HTMLInputElement>>;
  select: StyledInstance<'web', 'select', React.SelectHTMLAttributes<HTMLSelectElement>>;
  textarea: StyledInstance<'web', 'textarea', React.TextareaHTMLAttributes<HTMLTextAreaElement>>;
  
  // Layout elements
  div: StyledInstance<'web', 'div', React.HTMLAttributes<HTMLDivElement>>;
  section: StyledInstance<'web', 'section', React.HTMLAttributes<HTMLElement>>;
  article: StyledInstance<'web', 'article', React.HTMLAttributes<HTMLElement>>;
  header: StyledInstance<'web', 'header', React.HTMLAttributes<HTMLElement>>;
  footer: StyledInstance<'web', 'footer', React.HTMLAttributes<HTMLElement>>;
  nav: StyledInstance<'web', 'nav', React.HTMLAttributes<HTMLElement>>;
  main: StyledInstance<'web', 'main', React.HTMLAttributes<HTMLElement>>;
  aside: StyledInstance<'web', 'aside', React.HTMLAttributes<HTMLElement>>;
  
  // Text elements
  h1: StyledInstance<'web', 'h1', React.HTMLAttributes<HTMLHeadingElement>>;
  h2: StyledInstance<'web', 'h2', React.HTMLAttributes<HTMLHeadingElement>>;
  h3: StyledInstance<'web', 'h3', React.HTMLAttributes<HTMLHeadingElement>>;
  h4: StyledInstance<'web', 'h4', React.HTMLAttributes<HTMLHeadingElement>>;
  h5: StyledInstance<'web', 'h5', React.HTMLAttributes<HTMLHeadingElement>>;
  h6: StyledInstance<'web', 'h6', React.HTMLAttributes<HTMLHeadingElement>>;
  p: StyledInstance<'web', 'p', React.HTMLAttributes<HTMLParagraphElement>>;
  span: StyledInstance<'web', 'span', React.HTMLAttributes<HTMLSpanElement>>;
  strong: StyledInstance<'web', 'strong', React.HTMLAttributes<HTMLElement>>;
  em: StyledInstance<'web', 'em', React.HTMLAttributes<HTMLElement>>;
  
  // List elements
  ul: StyledInstance<'web', 'ul', React.HTMLAttributes<HTMLUListElement>>;
  ol: StyledInstance<'web', 'ol', React.OlHTMLAttributes<HTMLOListElement>>;
  li: StyledInstance<'web', 'li', React.LiHTMLAttributes<HTMLLIElement>>;
  
  // Media elements
  img: StyledInstance<'web', 'img', React.ImgHTMLAttributes<HTMLImageElement>>;
  video: StyledInstance<'web', 'video', React.VideoHTMLAttributes<HTMLVideoElement>>;
  audio: StyledInstance<'web', 'audio', React.AudioHTMLAttributes<HTMLAudioElement>>;
  
  // Table elements
  table: StyledInstance<'web', 'table', React.TableHTMLAttributes<HTMLTableElement>>;
  thead: StyledInstance<'web', 'thead', React.HTMLAttributes<HTMLTableSectionElement>>;
  tbody: StyledInstance<'web', 'tbody', React.HTMLAttributes<HTMLTableSectionElement>>;
  tfoot: StyledInstance<'web', 'tfoot', React.HTMLAttributes<HTMLTableSectionElement>>;
  tr: StyledInstance<'web', 'tr', React.HTMLAttributes<HTMLTableRowElement>>;
  th: StyledInstance<'web', 'th', React.ThHTMLAttributes<HTMLTableHeaderCellElement>>;
  td: StyledInstance<'web', 'td', React.TdHTMLAttributes<HTMLTableDataCellElement>>;
  
  // Link elements
  a: StyledInstance<'web', 'a', React.AnchorHTMLAttributes<HTMLAnchorElement>>;
}

StyledInstance Interface

The return type of styled functions, providing methods for configuration and composition.

interface StyledInstance<Runtime, Target, Props> {
  // Create styled component with template literal
  (strings: TemplateStringsArray, ...interpolations: Interpolation<Props>[]): StyledComponent<Target, Props>;
  
  // Add default props or computed attributes
  attrs<AttrsProps extends object>(
    attrs: Attrs<AttrsProps & Props>
  ): StyledInstance<Runtime, Target, Props & AttrsProps>;
  
  // Configure styled component options
  withConfig(config: StyledOptions<Runtime, Props>): StyledInstance<Runtime, Target, Props>;
}

.attrs() Method

Adds default props or computed attributes to styled components.

Usage Examples:

// Static attributes
const Input = styled.input.attrs({
  type: 'text',
  placeholder: 'Enter text...'
})`
  border: 1px solid #ccc;
  padding: 8px;
`;

// Dynamic attributes based on props
const Button = styled.button.attrs<{ variant?: string }>(props => ({
  type: 'button',
  'data-variant': props.variant || 'default'
}))`
  padding: 10px 20px;
  border: none;
  cursor: pointer;
`;

// TypeScript with specific attribute types
interface InputProps {
  hasError?: boolean;
}

const ValidatedInput = styled.input.attrs<InputProps>(props => ({
  'aria-invalid': props.hasError,
  className: props.hasError ? 'error' : ''
}))<InputProps>`
  border-color: ${props => props.hasError ? 'red' : '#ccc'};
`;

.withConfig() Method

Provides advanced configuration options for styled components.

interface StyledOptions<Runtime, Props> {
  // Custom component ID for consistent class names
  componentId?: string;
  
  // Display name for debugging
  displayName?: string;
  
  // Control which props are forwarded to DOM
  shouldForwardProp?: (prop: string, elementToBeCreated: any) => boolean;
}

Usage Examples:

// Custom component ID
const Button = styled.button.withConfig({
  componentId: 'my-button'
})`
  padding: 10px 20px;
`;

// Display name for debugging
const Card = styled.div.withConfig({
  displayName: 'Card'
})`
  border: 1px solid #ddd;
  border-radius: 4px;
`;

// Prop filtering
const Button = styled.button.withConfig({
  shouldForwardProp: (prop, defaultValidatorFn) => {
    return !['variant', 'size'].includes(prop) && defaultValidatorFn(prop);
  }
})<{ variant?: string; size?: string }>`
  padding: ${props => props.size === 'large' ? '12px 24px' : '8px 16px'};
`;

Dynamic Styling

Styled components support dynamic styling through prop interpolation and style functions.

Prop-based Styling

interface ThemeProps {
  theme: {
    colors: {
      primary: string;
      secondary: string;
    };
  };
}

interface ButtonProps extends ThemeProps {
  variant?: 'primary' | 'secondary';
  disabled?: boolean;
}

const Button = styled.button<ButtonProps>`
  background-color: ${props => {
    if (props.disabled) return '#ccc';
    return props.variant === 'primary' 
      ? props.theme.colors.primary 
      : props.theme.colors.secondary;
  }};
  
  opacity: ${props => props.disabled ? 0.6 : 1};
  cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
  
  &:hover {
    opacity: ${props => props.disabled ? 0.6 : 0.8};
  }
`;

Style Functions

type StyleFunction<Props> = (props: ExecutionContext & Props) => string | number | false | undefined | null;

const getButtonSize = (size?: 'small' | 'medium' | 'large') => {
  switch (size) {
    case 'small': return '24px';
    case 'large': return '48px';
    default: return '32px';
  }
};

const IconButton = styled.button<{ size?: 'small' | 'medium' | 'large' }>`
  width: ${props => getButtonSize(props.size)};
  height: ${props => getButtonSize(props.size)};
  border-radius: 50%;
`;

Component Composition

Extending Styled Components

const BaseButton = styled.button`
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
`;

const PrimaryButton = styled(BaseButton)`
  background-color: #007bff;
  color: white;
  
  &:hover {
    background-color: #0056b3;
  }
`;

const SecondaryButton = styled(BaseButton)`
  background-color: #6c757d;
  color: white;
  
  &:hover {
    background-color: #545b62;
  }
`;

Polymorphic Components with "as" prop

const Box = styled.div`
  padding: 20px;
  border: 1px solid #ddd;
`;

// Usage with different elements
<Box as="section">Section content</Box>
<Box as="article">Article content</Box>
<Box as={CustomComponent}>Custom component content</Box>

CSS Features

Styled components support all CSS features with template literal syntax:

Nested Selectors

const Card = styled.div`
  padding: 20px;
  border: 1px solid #ddd;
  
  h2 {
    margin-top: 0;
    color: #333;
  }
  
  p {
    line-height: 1.6;
    color: #666;
  }
  
  &:hover {
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  }
`;

Media Queries

const ResponsiveDiv = styled.div`
  padding: 10px;
  
  @media (min-width: 768px) {
    padding: 20px;
  }
  
  @media (min-width: 1024px) {
    padding: 40px;
  }
`;

CSS Variables

const ThemeableComponent = styled.div`
  --primary-color: #007bff;
  --secondary-color: #6c757d;
  
  background-color: var(--primary-color);
  border: 1px solid var(--secondary-color);
`;