diff --git a/packages/ui/src/Colors.mdx b/packages/ui/src/Colors.mdx
new file mode 100644
index 0000000000..316f688d59
--- /dev/null
+++ b/packages/ui/src/Colors.mdx
@@ -0,0 +1,10 @@
+import { Meta, Canvas } from '@storybook/blocks';
+import * as ColorsStories from './Colors.stories';
+
+
+
+# Colors
+
+Below are the colors we use at Penumbra. We deliberately do not include RGB/hex values for our colors, as they should be used via tokens — e.g., `text.primary`, `neutral.light`, `destructive.main`, etc. — to ensure consistency.
+
+
diff --git a/packages/ui/src/Colors.stories.tsx b/packages/ui/src/Colors.stories.tsx
new file mode 100644
index 0000000000..6c196f59ec
--- /dev/null
+++ b/packages/ui/src/Colors.stories.tsx
@@ -0,0 +1,108 @@
+import type { Meta, StoryObj } from '@storybook/react';
+import { Grid } from './Grid';
+import { Technical } from './Typography';
+import styled from 'styled-components';
+import {
+ type ColorVariant,
+ type Color as TColor,
+ type TextColorVariant,
+} from './ThemeProvider/theme';
+import { Fragment } from 'react';
+import { media } from './utils/media';
+
+const meta: Meta = {};
+export default meta;
+
+const Label = styled.div`
+ display: flex;
+ height: 100%;
+
+ ${media.tablet`
+ align-items: center;
+ `}
+`;
+
+const Variants = styled.div`
+ display: grid;
+ gap: ${props => props.theme.spacing(4)};
+ grid-template-columns: 1fr;
+
+ ${media.tablet`
+ grid-template-columns: repeat(4, 1fr);
+ `}
+`;
+
+type VariantProps =
+ | {
+ $color: 'text';
+ $colorVariant: TextColorVariant;
+ }
+ | {
+ $color: Exclude;
+ $colorVariant: ColorVariant;
+ };
+
+const Variant = styled.div`
+ background-color: ${props =>
+ props.$color === 'text' ? 'transparent' : props.theme.color[props.$color][props.$colorVariant]};
+ border-radius: ${props => props.theme.borderRadius.xl};
+ color: ${props =>
+ props.$color === 'text'
+ ? props.theme.color.text[props.$colorVariant]
+ : props.$colorVariant === 'contrast' || props.$colorVariant === 'light'
+ ? props.theme.color[props.$color].dark
+ : props.theme.color.text.primary};
+ padding: ${props => props.theme.spacing(2)};
+`;
+
+const BASE_COLORS: Exclude[] = [
+ 'neutral',
+ 'primary',
+ 'secondary',
+ 'unshield',
+ 'destructive',
+ 'caution',
+ 'success',
+];
+
+const Color = >({ color }: { color: T }) => (
+
+
+
+
+
+
+ {color === 'text'
+ ? (['primary', 'secondary', 'disabled', 'special'] as const).map(variant => (
+
+ {variant}
+
+ ))
+ : (['main', 'light', 'dark', 'contrast'] as const).map(variant => (
+
+ {variant}
+
+ ))}
+
+
+
+);
+
+export const ColorGrid: StoryObj = {
+ tags: ['!dev'],
+ render: function Render() {
+ return (
+ <>
+
+
+
+ {BASE_COLORS.map(color => (
+
+ ))}
+
+ >
+ );
+ },
+};