Lists

All lists components

Basic usage

Installation

You can reuse components from this library by copying them to your project. It's recommended to copy source code into folder aliased with '@mailingui/components' For BulletList support you have to copy that one too.

"use client";

import React, {
  FC,
  CSSProperties,
  ReactNode,
  createContext,
  useContext,
} from "react";
import { theme } from "@mailingui/themes";

const {
  color: { foreground, brand },
} = theme;

const variants = {
  default: {
    color: foreground["100"],
  },
  subtle: {
    color: foreground["200"],
  },
  brand: {
    color: brand,
  },
};

const sizes: Record<"xs" | "sm" | "md" | "lg", CSSProperties> = {
  xs: {
    fontSize: 12,
    lineHeight: "16px",
  },
  sm: {
    fontSize: 14,
    lineHeight: "20px",
  },
  md: {
    fontSize: 16,
    lineHeight: "24px",
  },
  lg: {
    fontSize: 18,
    lineHeight: "28px",
  },
};

type BulletListContextType = {
  size: keyof typeof sizes;
};

const BulletListContext = createContext<BulletListContextType>({
  size: "md",
});

type BulletListProps = {
  type: "unordered" | "ordered";
  style?: CSSProperties;
  children?: ReactNode;
  size?: keyof typeof sizes;
};

const BulletList: FC<BulletListProps> = ({ type, size, style, children }) => {
  const ListRoot = type === "unordered" ? "ul" : "ol";
  const contextValue: BulletListContextType = {
    size: size ?? "md",
  };

  return (
    <BulletListContext.Provider value={contextValue}>
      <ListRoot
        style={{
          paddingLeft: 20,
          ...style,
        }}
      >
        {children}
      </ListRoot>
    </BulletListContext.Provider>
  );
};

type BulletListItemProps = {
  variant?: keyof typeof variants;
  children?: ReactNode;
  style?: CSSProperties;
  size?: keyof typeof sizes;
};

const BulletListItem: FC<BulletListItemProps> = ({
  variant = "default",
  style: styleProp,
  size = "md",
  children,
}) => {
  const { size: sizeContext } = useContext(BulletListContext);

  const style: CSSProperties = {
    padding: "2px 0",
    ...variants[variant],
    ...sizes[size ?? sizeContext],
    ...styleProp,
  };

  return <li style={style}>{children}</li>;
};

export { BulletList, type BulletListProps, BulletListItem };

Common BulletList depends on a Paragraph component, so you have to copy that one too.

"use client";

import * as React from "react";
import { Text as ReactEmailText } from "@react-email/components";
import { theme } from "@mailingui/themes";

const {
  color: { foreground, brand },
} = theme;

const variants = {
  default: {
    color: foreground["100"],
  },
  subtle: {
    color: foreground["200"],
  },
  brand: {
    color: brand,
  },
} as const;

type TextVariant = keyof typeof variants;

const sizes = {
  xs: {
    fontSize: 12,
    lineHeight: "16px",
  },
  sm: {
    fontSize: 14,
    lineHeight: "20px",
  },
  md: {
    fontSize: 16,
    lineHeight: "24px",
  },
  lg: {
    fontSize: 18,
    lineHeight: "28px",
  },
} as const;

type RootProps = React.ComponentPropsWithoutRef<"p">;

interface TextProps extends RootProps {
  centered?: boolean;
  variant?: TextVariant;
  size?: keyof typeof sizes;
  children?: React.ReactNode;
}

const Text: React.FC<TextProps> = ({
  style,
  centered,
  variant = "default",
  size = "md",
  children,
  ...props
}) => {
  return (
    <ReactEmailText
      style={{
        textAlign: centered ? "center" : "inherit",
        ...variants[variant],
        ...sizes[size],
        ...style,
      }}
      {...props}
    >
      {children}
    </ReactEmailText>
  );
};

export { Text, type TextVariant, type TextProps };

Lists

Bullet List Example

Centered Vertical List

Combined Lists

Different Sized Bullet List

Different Sized Items

Horizontal List

Nested Bullet Lists

Small List

Styled Title List

Themed List