Themes

Learn how to use Rocketship themes in your Astro project

experimental

To use themes, create a Layout.astro file and wrap the <slot /> element with the <Theme> tags.

Layout.astro

<Theme>
<slot />
</Theme>

Theme.astro file

---
type ColorName = "gray" | "gold" | "bronze" | "brown" | "yellow" | "amber" | "orange" | "tomato" | "red" | "ruby" | "crimson" | "pink" | "plum" | "purple" | "violet" | "iris" | "indigo" | "blue" | "cyan" | "teal" | "jade" | "green" | "grass" | "lime" | "mint" | "sky";

export interface Props {
  accentColor?: ColorName;
  radius?: "sm" | "md" | "lg" | "full";
  colors?: ColorName[];
}

const { accentColor = "indigo", radius = "lg", colors } = Astro.props;

const themeStyles = ["rs-theme", accentColor ? `rs-theme--accent-${accentColor}` : "rs-theme--accent-default", `rs-theme--radius-${radius}`].filter(Boolean).join(" ");

const defaultColors: ColorName[] = ["gray", "red", "blue", "green", "cyan", "teal", "indigo", "tomato", "orange", "purple", "pink", "yellow", "amber", "gold", "bronze", "brown", "ruby", "crimson", "plum", "violet", "iris", "jade", "grass", "lime", "mint", "sky"];

const selectedColors = colors || defaultColors;

const colorScales: Record<ColorName, string[]> = {
  sky: ["hsl(193, 100%, 98.8%)", "hsl(193, 100%, 97.3%)", "hsl(193, 99%, 94.7%)", "hsl(193, 91.4%, 91.4%)", "hsl(194, 82%, 86.6%)", "hsl(194, 74.1%, 79.5%)", "hsl(194, 72.3%, 69.6%)", "hsl(193, 77.9%, 53.9%)", "hsl(193, 98%, 70%)", "hsl(193, 87%, 66.5%)", "hsl(195, 100%, 31.5%)", "hsl(195, 100%, 13%)"],
  red: ["hsl(359, 100%, 99.4%)", "hsl(359, 100%, 98.6%)", "hsl(360, 100%, 96.8%)", "hsl(360, 97.9%, 94.8%)", "hsl(360, 90.2%, 91.9%)", "hsl(360, 81.7%, 87.8%)", "hsl(359, 74.2%, 81.7%)", "hsl(359, 69.5%, 74.3%)", "hsl(358, 75%, 59%)", "hsl(358, 69.4%, 55.2%)", "hsl(358, 65%, 48.7%)", "hsl(354, 50%, 14.6%)"],
  ruby: ["hsl(348, 100%, 99.4%)", "hsl(348, 100%, 98.6%)", "hsl(347, 100%, 96.7%)", "hsl(347, 100%, 94.7%)", "hsl(347, 89.6%, 92%)", "hsl(347, 81%, 88%)", "hsl(346, 74.6%, 82.3%)", "hsl(345, 70.6%, 75%)", "hsl(345, 82.7%, 60.6%)", "hsl(345, 75.3%, 56.7%)", "hsl(345, 71.2%, 50.4%)", "hsl(344, 50%, 14.6%)"],
  plum: ["hsl(292, 90%, 99.4%)", "hsl(300, 100%, 98.6%)", "hsl(299, 71.2%, 96.4%)", "hsl(299, 62%, 93.8%)", "hsl(298, 56.1%, 90.5%)", "hsl(296, 51.3%, 85.8%)", "hsl(295, 48.2%, 78.9%)", "hsl(292, 47.7%, 70.8%)", "hsl(292, 45%, 51%)", "hsl(292, 50.2%, 46.9%)", "hsl(292, 60%, 42.5%)", "hsl(291, 66%, 14%)"],
  pink: ["hsl(322, 100%, 99.4%)", "hsl(323, 100%, 98.4%)", "hsl(323, 86.3%, 96.5%)", "hsl(323, 78.7%, 94.2%)", "hsl(323, 72.2%, 91.1%)", "hsl(323, 66.3%, 86.6%)", "hsl(323, 62%, 80.1%)", "hsl(323, 60.3%, 72.4%)", "hsl(322, 65%, 54.5%)", "hsl(322, 63.9%, 50.7%)", "hsl(322, 75%, 46%)", "hsl(320, 70%, 13.5%)"],
  gray: ["hsl(0, 0%, 99%)", "hsl(0, 0%, 97.3%)", "hsl(0, 0%, 95.1%)", "hsl(0, 0%, 93%)", "hsl(0, 0%, 90.9%)", "hsl(0, 0%, 88.7%)", "hsl(0, 0%, 85.8%)", "hsl(0, 0%, 78%)", "hsl(0, 0%, 56.1%)", "hsl(0, 0%, 52.3%)", "hsl(0, 0%, 43.5%)", "hsl(0, 0%, 9%)"],
  gold: ["hsl(50, 20%, 99%)", "hsl(47, 52%, 96.1%)", "hsl(46, 38.2%, 93.7%)", "hsl(44, 32.7%, 90.1%)", "hsl(43, 29.9%, 85.7%)", "hsl(41, 28.3%, 79.8%)", "hsl(39, 27.6%, 71.9%)", "hsl(36, 27.2%, 61.8%)", "hsl(36, 20%, 49.5%)", "hsl(36, 19.8%, 45.7%)", "hsl(36, 20%, 39%)", "hsl(36, 16%, 20%)"],
  iris: ["hsl(240, 65%, 99.4%)", "hsl(240, 100%, 99%)", "hsl(241, 97%, 97.3%)", "hsl(241, 91.5%, 95.3%)", "hsl(242, 85.4%, 92.7%)", "hsl(243, 77.6%, 88.8%)", "hsl(245, 70.7%, 82.8%)", "hsl(247, 66.6%, 75.1%)", "hsl(248, 53%, 58%)", "hsl(247, 46.6%, 53.7%)", "hsl(245, 41%, 47%)", "hsl(243, 54%, 20%)"],
  cyan: ["hsl(185, 60%, 98.7%)", "hsl(185, 73.3%, 97.1%)", "hsl(186, 70.2%, 94.4%)", "hsl(186, 63.8%, 90.6%)", "hsl(187, 58.3%, 85.4%)", "hsl(188, 54.6%, 78.4%)", "hsl(189, 53.7%, 68.7%)", "hsl(189, 60.3%, 52.5%)", "hsl(190, 95%, 39%)", "hsl(191, 91.2%, 36.8%)", "hsl(192, 85%, 31%)", "hsl(192, 88%, 12.5%)"],
  teal: ["hsl(165, 60%, 98.8%)", "hsl(169, 64.7%, 96.7%)", "hsl(169, 59.8%, 94%)", "hsl(169, 53.1%, 90.2%)", "hsl(170, 47.1%, 85%)", "hsl(170, 42.6%, 77.9%)", "hsl(170, 39.9%, 68.1%)", "hsl(172, 42.1%, 52.5%)", "hsl(173, 80%, 36%)", "hsl(173, 83.4%, 32.5%)", "hsl(174, 90%, 25.2%)", "hsl(170, 50%, 12.5%)"],
  blue: ["hsl(206, 100%, 99.2%)", "hsl(210, 100%, 98%)", "hsl(209, 100%, 96.5%)", "hsl(210, 98.8%, 94%)", "hsl(209, 95%, 90.1%)", "hsl(209, 81.2%, 84.5%)", "hsl(208, 77.5%, 76.9%)", "hsl(206, 81.9%, 65.3%)", "hsl(206, 100%, 50%)", "hsl(208, 100%, 47.3%)", "hsl(211, 100%, 43.2%)", "hsl(211, 100%, 15%)"],
  jade: ["hsl(152, 61.8%, 97.5%)", "hsl(150, 54.2%, 95.5%)", "hsl(151, 49.3%, 92.4%)", "hsl(151, 44.5%, 88.4%)", "hsl(152, 39.8%, 83.1%)", "hsl(153, 35.6%, 76%)", "hsl(154, 32.9%, 66.2%)", "hsl(155, 34.3%, 52%)", "hsl(155, 40%, 40%)", "hsl(156, 42%, 37%)", "hsl(157, 46%, 30%)", "hsl(155, 45%, 11.8%)"],
  mint: ["hsl(165, 80%, 98.8%)", "hsl(164, 88.2%, 96.7%)", "hsl(164, 76.6%, 93.3%)", "hsl(165, 68.8%, 89.5%)", "hsl(165, 60.6%, 84.5%)", "hsl(165, 53.5%, 76.9%)", "hsl(166, 50.7%, 66.1%)", "hsl(168, 52.8%, 51%)", "hsl(167, 65%, 66%)", "hsl(167, 59.3%, 63.1%)", "hsl(172, 72%, 28.5%)", "hsl(172, 70%, 12%)"],
  lime: ["hsl(85, 50%, 98.7%)", "hsl(85, 66.7%, 96.5%)", "hsl(85, 76%, 92.3%)", "hsl(84, 75.3%, 87.5%)", "hsl(84, 71.5%, 81.9%)", "hsl(82, 65%, 74.6%)", "hsl(79, 53%, 61.8%)", "hsl(76, 61.7%, 45.1%)", "hsl(81, 67%, 50%)", "hsl(80, 68.3%, 46.9%)", "hsl(75, 80%, 26%)", "hsl(78, 70%, 11.5%)"],
  brown: ["hsl(30, 40%, 99.1%)", "hsl(30, 50%, 97.6%)", "hsl(30, 52.5%, 94.6%)", "hsl(30, 53%, 91.2%)", "hsl(29, 52.9%, 86.8%)", "hsl(29, 52.5%, 80.9%)", "hsl(29, 51.5%, 72.8%)", "hsl(28, 50%, 63.1%)", "hsl(28, 34%, 51%)", "hsl(27, 31.8%, 47.6%)", "hsl(25, 30%, 41%)", "hsl(20, 30%, 19%)"],
  amber: ["hsl(39, 70%, 99%)", "hsl(40, 100%, 96.5%)", "hsl(44, 100%, 91.7%)", "hsl(43, 100%, 86.8%)", "hsl(42, 100%, 81.8%)", "hsl(42, 100%, 75.8%)", "hsl(41, 100%, 69%)", "hsl(39, 100%, 57%)", "hsl(39, 100%, 50%)", "hsl(38, 100%, 46.1%)", "hsl(36, 100%, 36.1%)", "hsl(35, 100%, 15.5%)"],
  grass: ["hsl(116, 50%, 98.9%)", "hsl(120, 60%, 97.1%)", "hsl(120, 53.6%, 94.8%)", "hsl(121, 47.5%, 91.4%)", "hsl(122, 42.6%, 86.5%)", "hsl(124, 39%, 79.7%)", "hsl(126, 37.1%, 70.2%)", "hsl(131, 38.1%, 56.3%)", "hsl(131, 41%, 46.5%)", "hsl(132, 43.1%, 42.2%)", "hsl(133, 50%, 32.5%)", "hsl(130, 30%, 14.9%)"],
  green: ["hsl(136, 50%, 98.9%)", "hsl(138, 62.5%, 96.9%)", "hsl(139, 55.2%, 94.5%)", "hsl(140, 48.7%, 91%)", "hsl(141, 43.7%, 86%)", "hsl(143, 40.3%, 79%)", "hsl(146, 38.5%, 69%)", "hsl(151, 40.2%, 54.1%)", "hsl(151, 55%, 41.5%)", "hsl(152, 57.5%, 37.6%)", "hsl(153, 67%, 28.5%)", "hsl(155, 40%, 14%)"],
  purple: ["hsl(280, 65%, 99.4%)", "hsl(276, 100%, 99%)", "hsl(276, 83.1%, 97%)", "hsl(275, 76.4%, 94.7%)", "hsl(275, 70.8%, 91.8%)", "hsl(274, 65.4%, 87.8%)", "hsl(273, 61%, 81.7%)", "hsl(272, 60%, 73.5%)", "hsl(272, 51%, 54%)", "hsl(272, 46.8%, 50.3%)", "hsl(272, 50%, 45.8%)", "hsl(272, 66%, 16%)"],
  bronze: ["hsl(15, 30%, 99.1%)", "hsl(17, 63.6%, 97.8%)", "hsl(17, 42.1%, 95.2%)", "hsl(17, 35.2%, 92.1%)", "hsl(17, 31.5%, 88.2%)", "hsl(17, 29%, 83.2%)", "hsl(17, 26.9%, 75.6%)", "hsl(17, 25.1%, 66.5%)", "hsl(17, 20%, 54%)", "hsl(17, 18.1%, 50.1%)", "hsl(17, 16%, 44%)", "hsl(17, 13%, 22%)"],
  orange: ["hsl(24, 70%, 99%)", "hsl(24, 83.3%, 97.6%)", "hsl(24, 100%, 95.3%)", "hsl(25, 100%, 92.2%)", "hsl(25, 100%, 88.2%)", "hsl(25, 100%, 82.8%)", "hsl(24, 100%, 75.3%)", "hsl(24, 94.5%, 64.3%)", "hsl(24, 94%, 50%)", "hsl(24, 100%, 46.5%)", "hsl(24, 100%, 37%)", "hsl(15, 60%, 17%)"],
  yellow: ["hsl(60, 54%, 98.5%)", "hsl(52, 100%, 95.5%)", "hsl(55, 100%, 90.9%)", "hsl(54, 100%, 86.6%)", "hsl(52, 97.9%, 82%)", "hsl(50, 89.4%, 76.1%)", "hsl(47, 80.4%, 68%)", "hsl(48, 100%, 46.1%)", "hsl(53, 92%, 50%)", "hsl(50, 100%, 48.5%)", "hsl(42, 100%, 29%)", "hsl(40, 55%, 13.5%)"],
  tomato: ["hsl(10, 100%, 99.4%)", "hsl(8, 100%, 98.4%)", "hsl(8, 100%, 96.6%)", "hsl(8, 100%, 94.3%)", "hsl(8, 92.8%, 91%)", "hsl(9, 84.7%, 86.3%)", "hsl(10, 77.3%, 79.5%)", "hsl(10, 71.6%, 71%)", "hsl(10, 78%, 54%)", "hsl(10, 71.5%, 50%)", "hsl(10, 82%, 43.5%)", "hsl(10, 50%, 13.5%)"],
  violet: ["hsl(255, 65%, 99.4%)", "hsl(252, 100%, 99%)", "hsl(252, 96.9%, 97.4%)", "hsl(252, 91.5%, 95.5%)", "hsl(252, 85.1%, 93%)", "hsl(252, 77.8%, 89.4%)", "hsl(252, 71%, 83.7%)", "hsl(252, 68.6%, 76.3%)", "hsl(252, 56%, 57.5%)", "hsl(251, 48.1%, 53.5%)", "hsl(250, 43%, 48%)", "hsl(254, 60%, 18.5%)"],
  crimson: ["hsl(332, 100%, 99.4%)", "hsl(330, 100%, 98.4%)", "hsl(331, 85.6%, 96.6%)", "hsl(331, 78.1%, 94.2%)", "hsl(332, 72.1%, 91.1%)", "hsl(333, 67%, 86.7%)", "hsl(335, 63.5%, 80.4%)", "hsl(336, 62.3%, 72.9%)", "hsl(336, 80%, 57.8%)", "hsl(336, 73.7%, 53.5%)", "hsl(336, 75%, 47.2%)", "hsl(340, 65%, 14.5%)"],
  indigo: ["hsl(225, 60%, 99%)", "hsl(223, 100%, 98%)", "hsl(223, 98%, 95%)", "hsl(223, 92%, 90%)", "hsl(224, 87%, 84%)", "hsl(224, 81%, 75%)", "hsl(225, 77%, 65%)", "hsl(226, 75%, 55%)", "hsl(226, 70%, 50%)", "hsl(227, 64%, 45%)", "hsl(228, 67%, 40%)", "hsl(226, 50%, 30%)"],
};

const generateStyles = () => {
  const styles = `
    :root {
      ${selectedColors.map(color => 
        colorScales[color].map((hsl, i) => `--${color}-${i + 1}: ${hsl};`).join("\n")
      ).join("\n")}
      ${["radius", "space"].map(prop => 
        [...Array(3)].map((_, i) => `--rs-${prop}-${i + 1}: ${(i + 1) * 0.125}rem;`).join("\n")
      ).join("\n")}
      ${[...Array(6)].map((_, i) => `--rs-space-${i + 4}: ${(i + 2) * 8}px;`).join("\n")}
    }

    .rs-theme {
      ${[...Array(12)].map((_, i) => `--rs-theme-accent-${i + 1}: var(--${accentColor}-${i + 1});`).join("\n")}
      --rs-theme-accent-contrast: ${["yellow", "amber", "gold"].includes(accentColor) ? "black" : "white"};
    }

    ${selectedColors.map(color => `
      .rs-theme--accent-${color} {
        ${[...Array(12)].map((_, i) => `--rs-theme-accent-${i + 1}: var(--${color}-${i + 1});`).join("\n")}
        --rs-theme-accent-contrast: ${["yellow", "amber", "gold"].includes(color) ? "black" : "white"};
      }
    `).join("\n")}

    ${["sm", "md", "lg", "full"].map((size, i) => 
      `.rs-theme--radius-${size} { --rs-theme-radius: ${size === "full" ? "9999px" : `var(--rs-radius-${i + 1})`}; }`
    ).join("\n")}
  `;

  return styles;

};

---

<div class={themeStyles}>
  <slot />
</div>

<style is:global set:html={generateStyles()}></style>

The colors are inspired by Radix UI’s color scales.