Concorde
BETA

TodayIcon

Icono de calendario para la navegación lateral del sidebar.

<TodayIcon size={32} state="default" />
<TodayIcon size={32} state="hover" />
<TodayIcon size={32} state="active" />

Instalación

$ npx github:AaronCoorahua/ConcordeV2#cli add todayicon

Uso

import TodayIcon from "@/src/components/TodayIcon";

// Autónomo — trackea hover/active solo
<TodayIcon size={24} />

// Controlado — el padre pasa el estado
<TodayIcon size={24} state="hover" />

Ejemplos

Estados

Default (gradiente púrpura diagonal), hover (gradiente naranja), active (blanco sólido).

default
hover
active
<TodayIcon size={28} state="default" />
<TodayIcon size={28} state="hover" />
<TodayIcon size={28} state="active" />

Tamaños

Acepta cualquier número de px. Default 24.

<TodayIcon size={16} />
<TodayIcon size={24} />
<TodayIcon size={32} />
<TodayIcon size={40} />

Interactivo (sin prop state)

Sin el prop state, el icono trackea sus propios eventos de mouse. Hovea o haz click para ver la transición.

<TodayIcon size={32} />

API

PropTipoDefault
size
Ancho y alto del SVG en px.
number24
state
Estado visual controlado. Omitir para modo autónomo (mouse tracking interno).
"default" | "hover" | "active"
title
Texto accesible. Sin él el icono es decorativo (aria-hidden).
string
className
Clases extra sobre el <svg>.
string""

Código del componente

Ver TodayIcon.tsx completo · self-contained · zero deps
TodayIcon.tsx
"use client";

import { useId, useState } from "react";
import type { JSX } from "react";

export interface TodayIconProps {
  size?: number;
  /** Controlled visual state — omit to let the icon track its own hover/active */
  state?: "default" | "hover" | "active";
  title?: string;
  className?: string;
}

export default function TodayIcon({ size = 24, state: controlled, title, className = "" }: TodayIconProps): JSX.Element {
  const uid = useId().replace(/:/g, "-");
  const [hovered, setHovered] = useState(false);
  const [pressed,  setPressed]  = useState(false);

  const resolved = controlled ?? (pressed ? "active" : hovered ? "hover" : "default");
  const isActive = resolved === "active";
  const isHover  = resolved === "hover";
  const paint    = isActive ? "white" : `url(#${uid}g)`;

  const handlers = controlled ? {} : {
    onMouseEnter: () => setHovered(true),
    onMouseLeave: () => { setHovered(false); setPressed(false); },
    onMouseDown:  () => setPressed(true),
    onMouseUp:    () => setPressed(false),
  };

  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 24 24"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      className={className}
      role={title ? "img" : undefined}
      aria-hidden={title ? undefined : true}
      style={{ flexShrink: 0 }}
      {...handlers}
    >
      {title && <title>{title}</title>}

      {!isActive && (
        <defs>
          {isHover ? (
            <linearGradient id={`${uid}g`} x1="12" y1="1" x2="12" y2="21" gradientUnits="userSpaceOnUse">
              <stop stopColor="#FF9639"/>
              <stop offset="0.4" stopColor="#EF852E"/>
              <stop offset="1" stopColor="#BE3D00"/>
            </linearGradient>
          ) : (
            <linearGradient id={`${uid}g`} x1="5.58549" y1="-11.674" x2="29.3422" y2="-4.95314" gradientUnits="userSpaceOnUse">
              <stop stopColor="#CFBAFF"/>
              <stop offset="0.35" stopColor="white"/>
              <stop offset="0.65" stopColor="#AE8EFF"/>
              <stop offset="1" stopColor="#CFBAFF"/>
            </linearGradient>
          )}
        </defs>
      )}

      <path
        d="M9 1V3H15V1H17V3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H7V1H9ZM20 11H4V19H20V11ZM11 13V17H6V13H11ZM7 5H4V9H20V5H17V7H15V5H9V7H7V5Z"
        fill={paint}
      />
    </svg>
  );
}