Takazudo Modular Styleguide

Shared/NewsThumb

All Variants
Default
Detail
Grid
List
Single Digit
Triple Digit

Component Source

news-thumb.tsx

import type { FunctionComponent } from 'preact';
interface NewsThumbProps {
  volume: number;
  type: 'grid' | 'list' | 'detail';
}

/**
 * NewsThumb component for newsletter article thumbnails
 * Displays a stylized "NEWS {volume}" thumbnail with diagonal lines
 */
export const NewsThumb: FunctionComponent<NewsThumbProps> = ({ volume, type }) => {
  // Base styles for all variants
  const baseStyles =
    'relative overflow-hidden bg-zd-literal-black text-zd-literal-white flex flex-col items-center justify-center w-full aspect-square';

  // Type-specific text sizes - volume number DOMINATES 80-90% of space
  const textSizes = {
    grid: {
      news: 'text-[1rem] xl:text-[1.3rem] 2xl:text-[1.8rem]',
      volume: 'text-[3rem] md:text-[2rem] lg:text-[4.5rem] xl:text-[6rem]',
    },
    list: {
      news: 'text-[0.6rem] md:text-[1rem]',
      volume: 'text-[2rem] md:text-[3rem]',
    },
    detail: {
      news: 'text-[3rem]',
      volume: 'text-[5rem] sm:text-[10rem] md:text-[13rem] lg:text-[8rem] xl:text-[14rem]',
    },
  };

  const sizes = textSizes[type];

  return (
    <div className={baseStyles}>
      <div className={'absolute inset-0 border-[2px] border-zd-white'} />

      {/* inside text bg */}
      <div
        className={
          'absolute top-[20%] bottom-[20%] right-[10%] left-[10%] select-none z-10 bg-zd-literal-black'
        }
      />

      {/* news + volume */}
      <div className={'select-none z-20 text-center'}>
        <div
          className={`${sizes.news} tracking-[0.2rem] font-normal uppercase pl-[.6rem] pb-[.1rem]`}
        >
          News
        </div>

        <div className={`${sizes.volume} font-medium leading-none pb-[.6rem]`}>{volume}</div>
      </div>

      {/* Bold diagonal line 1 (top-left to bottom-right) */}
      <div className={'absolute top-0 left-0 w-[141%] transform rotate-45 origin-top-left'}>
        <div className={'w-full h-0 border-t-[2px] border-zd-white mt-[-1px]'} />
      </div>

      {/* Bold diagonal line 2 (top-right to bottom-left) */}
      <div className={'absolute top-0 right-0 w-[141%] transform -rotate-45 origin-top-right'}>
        <div className={'w-full h-0 border-t-[2px] border-zd-white mt-[-1px]'} />
      </div>
    </div>
  );
};

Story Source

news-thumb.stories.tsx

import { NewsThumb } from './news-thumb';
import type { ControlsMap } from '../../sub-packages/styleguide-v2/src/data/control-types';

/**
 * NewsThumb Component
 *
 * Stylized thumbnail for newsletter articles displaying
 * "NEWS" with a volume number and diagonal line decorations.
 *
 * Features:
 * - Three size variants: grid, list, detail
 * - Bold diagonal lines for visual interest
 * - Responsive typography
 */
export const meta = {
  title: 'Shared/NewsThumb',
};

export const controls: ControlsMap = {
  volume: { type: 'number', default: 42, min: 1, max: 999 },
  type: { type: 'select', default: 'grid', options: ['grid', 'list', 'detail'] },
};

/**
 * Default - controllable via props panel
 */
export const Default = {
  args: { volume: 42, type: 'grid' },
  render: ({ volume, type }: { volume: number; type: 'grid' | 'list' | 'detail' }) => (
    <div className="w-[200px]">
      <NewsThumb volume={volume} type={type} />
    </div>
  ),
};

/**
 * Grid variant - used in article grids
 */
export const Grid = () => (
  <div className="w-[200px]">
    <NewsThumb volume={42} type="grid" />
  </div>
);

/**
 * List variant - used in article lists
 */
export const List = () => (
  <div className="w-[100px]">
    <NewsThumb volume={42} type="list" />
  </div>
);

/**
 * Detail variant - used on article detail pages
 */
export const Detail = () => (
  <div className="w-[300px]">
    <NewsThumb volume={42} type="detail" />
  </div>
);

/**
 * Single digit volume
 */
export const SingleDigit = () => (
  <div className="w-[200px]">
    <NewsThumb volume={5} type="grid" />
  </div>
);

/**
 * Triple digit volume
 */
export const TripleDigit = () => (
  <div className="w-[200px]">
    <NewsThumb volume={123} type="grid" />
  </div>
);

/**
 * All variants side by side
 */
export const AllVariants = () => (
  <div className="flex items-end gap-hgap-md">
    <div className="w-[100px]">
      <p className="text-muted text-xs mb-vgap-xs text-center">List</p>
      <NewsThumb volume={42} type="list" />
    </div>
    <div className="w-[200px]">
      <p className="text-muted text-xs mb-vgap-xs text-center">Grid</p>
      <NewsThumb volume={42} type="grid" />
    </div>
    <div className="w-[300px]">
      <p className="text-muted text-xs mb-vgap-xs text-center">Detail</p>
      <NewsThumb volume={42} type="detail" />
    </div>
  </div>
);