or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

custom-icons.mdicon-components.mdindex.mdtheming.md
tile.json

custom-icons.mddocs/

Custom Icon Creation

Create custom icons using the Blank component while maintaining consistency with the grommet-icons theming system and styling.

Capabilities

Blank Component

Template component for creating custom icons that integrate seamlessly with the grommet-icons system.

/**
 * Blank icon component for creating custom icons
 * Provides the base StyledIcon wrapper with theming support
 */
declare const Blank: React.ComponentType<IconProps & JSX.IntrinsicElements['svg']>;

interface IconProps {
  /** Accessibility title for screen readers */
  a11yTitle?: string;
  /** Icon color - theme color name, CSS color value, or 'plain' for original colors */
  color?: string;
  /** Icon size - predefined size or custom CSS value */
  size?: 'small' | 'medium' | 'large' | 'xlarge' | string;
  /** Hide from screen readers (default: true for decorative icons) */
  'aria-hidden'?: boolean;
}

Basic Custom Icon Creation

Create simple custom icons using SVG content within the Blank component.

Usage Examples:

import React from 'react';
import { Blank } from 'grommet-icons';

// Decorative custom icon (default aria-hidden=true)
export const MyCustomIcon = (props) => (
  <Blank {...props}>
    <circle cx="12" cy="12" r="5" />
  </Blank>
);

// Semantic custom icon (accessible)
export const MyAccessibleIcon = (props) => (
  <Blank 
    a11yTitle="Custom action" 
    aria-hidden={undefined} 
    {...props}
  >
    <path d="M12 2L2 7V10C2 16 6 21.5 12 23C18 21.5 22 16 22 10V7L12 2Z" />
  </Blank>
);

// Usage
function MyComponent() {
  return (
    <div>
      <MyCustomIcon />
      <MyCustomIcon color="brand" size="large" />
      <MyAccessibleIcon color="accent" />
    </div>
  );
}

Advanced Custom Icon Patterns

Create more complex custom icons with multiple SVG elements and advanced styling.

Complex SVG Icons:

import React from 'react';
import { Blank } from 'grommet-icons';

export const ComplexCustomIcon = (props) => (
  <Blank {...props}>
    <g>
      <rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
      <line x1="8" y1="21" x2="16" y2="21" />
      <line x1="12" y1="17" x2="12" y2="21" />
    </g>
  </Blank>
);

export const MultiColorIcon = (props) => (
  <Blank {...props}>
    <svg viewBox="0 0 24 24">
      <circle cx="12" cy="12" r="10" fill="currentColor" />
      <path 
        d="M8 12l2 2 4-4" 
        stroke="white" 
        strokeWidth="2" 
        fill="none" 
      />
    </svg>
  </Blank>
);

Custom Icon with Theme Integration

Create custom icons that fully integrate with the grommet-icons theming system.

Theme-Aware Custom Icons:

import React from 'react';
import { Blank } from 'grommet-icons';

// Custom icon that responds to theme
export const ThemedCustomIcon = (props) => (
  <Blank {...props}>
    <g>
      {/* Main shape - inherits theme color */}
      <rect 
        x="3" 
        y="3" 
        width="18" 
        height="18" 
        rx="2" 
        fill="currentColor" 
      />
      {/* Inner detail - contrasting color */}
      <circle 
        cx="12" 
        cy="12" 
        r="6" 
        fill="none" 
        stroke="white" 
        strokeWidth="2" 
      />
    </g>
  </Blank>
);

// Usage with different theme colors
function ThemedExample() {
  return (
    <div>
      <ThemedCustomIcon color="brand" />
      <ThemedCustomIcon color="accent" />
      <ThemedCustomIcon color="#ff6600" />
    </div>
  );
}

Icon Libraries and Collections

Create collections of related custom icons for consistent usage.

Custom Icon Library:

import React from 'react';
import { Blank } from 'grommet-icons';

// Weather icon collection
export const WeatherSunny = (props) => (
  <Blank a11yTitle="Sunny weather" aria-hidden={undefined} {...props}>
    <circle cx="12" cy="12" r="5" />
    <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
  </Blank>
);

export const WeatherCloudy = (props) => (
  <Blank a11yTitle="Cloudy weather" aria-hidden={undefined} {...props}>
    <path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z" />
  </Blank>
);

export const WeatherRainy = (props) => (
  <Blank a11yTitle="Rainy weather" aria-hidden={undefined} {...props}>
    <path d="M16 13v8l-4-4-4 4v-8" />
    <path d="M18 7h-1.26A8 8 0 1 0 9 17h9a5 5 0 0 0 0-10z" />
  </Blank>
);

// Export as collection
export const WeatherIcons = {
  Sunny: WeatherSunny,
  Cloudy: WeatherCloudy,
  Rainy: WeatherRainy,
};

External SVG Integration

Integrate external SVG files or content into the Blank component system.

External SVG Usage:

import React from 'react';
import { Blank } from 'grommet-icons';

// From external SVG string
const externalSvgContent = `
  <path d="M12 2L2 7V10C2 16 6 21.5 12 23C18 21.5 22 16 22 10V7L12 2Z"/>
  <path d="M9 12L11 14L15 10"/>
`;

export const ExternalIcon = (props) => (
  <Blank {...props}>
    <g dangerouslySetInnerHTML={{ __html: externalSvgContent }} />
  </Blank>
);

// From imported SVG component
import CustomSvg from './custom-icon.svg';

export const ImportedIcon = (props) => (
  <Blank {...props}>
    <CustomSvg />
  </Blank>
);

Responsive Custom Icons

Create custom icons that adapt to different sizes and contexts.

Size-Responsive Icons:

import React from 'react';
import { Blank } from 'grommet-icons';

export const ResponsiveIcon = ({ size, ...props }) => {
  // Adjust detail based on size
  const isSmall = size === 'small' || (typeof size === 'string' && parseInt(size) < 16);
  
  return (
    <Blank size={size} {...props}>
      <rect x="2" y="2" width="20" height="20" rx="2" />
      {!isSmall && (
        <>
          {/* Additional detail for larger sizes */}
          <circle cx="8" cy="8" r="2" />
          <circle cx="16" cy="8" r="2" />
          <path d="M8 16s2-2 4-2 4 2 4 2" />
        </>
      )}
    </Blank>
  );
};

Best Practices for Custom Icons

Accessibility Guidelines:

import React from 'react';
import { Blank } from 'grommet-icons';

// Decorative icon - hidden from screen readers
export const DecorativeIcon = (props) => (
  <Blank {...props}>
    {/* Decorative SVG content */}
    <circle cx="12" cy="12" r="10" />
  </Blank>
);

// Semantic icon - accessible with title
export const SemanticIcon = (props) => (
  <Blank 
    a11yTitle="Semantic meaning" 
    aria-hidden={undefined} 
    {...props}
  >
    {/* Meaningful SVG content */}
    <path d="M12 2L2 7V10C2 16 6 21.5 12 23C18 21.5 22 16 22 10V7L12 2Z" />
  </Blank>
);

// Interactive icon - with proper ARIA labels
export const InteractiveIcon = ({ onClick, ...props }) => (
  <Blank 
    a11yTitle="Perform action"
    aria-hidden={undefined}
    role="button"
    tabIndex={0}
    onClick={onClick}
    onKeyDown={(e) => e.key === 'Enter' && onClick?.(e)}
    {...props}
  >
    <path d="M12 2L2 7V10C2 16 6 21.5 12 23C18 21.5 22 16 22 10V7L12 2Z" />
  </Blank>
);

Custom Icon Properties

Custom icons created with Blank inherit all standard icon properties and theming capabilities:

interface CustomIconProps extends IconProps {
  /** All standard SVG props are supported */
  className?: string;
  style?: React.CSSProperties;
  onClick?: (event: React.MouseEvent) => void;
  onKeyDown?: (event: React.KeyboardEvent) => void;
  role?: string;
  tabIndex?: number;
  
  /** Custom props for your specific icon */
  [customProp: string]: any;
}

Custom icons maintain full compatibility with the grommet-icons theming system, sizing options, and accessibility features while allowing complete creative control over the SVG content.