update usage (icons + size-)

This commit is contained in:
Maze Winther 2026-01-23 21:25:51 +01:00
parent c6deceaa89
commit cd0a8d020e
58 changed files with 209 additions and 200 deletions

View File

@ -1665,18 +1665,18 @@ create-icon.tsx
export function createIcon({ definition }: CreateIconParams)
index.tsx
export const GoogleIcon
export const GithubIcon
export const VercelIcon
export const DataBuddyIcon
export const MarbleIcon
export const BackgroundIcon
export const SocialsIcon
export const TransitionUpIcon
export const MenuIcon
export const PencilIcon
export const LeftArrowIcon
export const TrashIcon
export const OcGoogleIcon
export const OcGithubIcon
export const OcVercelIcon
export const OcDataBuddyIcon
export const OcMarbleIcon
export const OcBackgroundIcon
export const OcSocialsIcon
export const OcTransitionUpIcon
export const OcMenuIcon
export const OcPencilIcon
export const OcLeftArrowIcon
export const OcTrashIcon
types.ts
export type IconProps = Omit<
@ -1694,25 +1694,14 @@ types.ts
nodes: IconNode;
}
## packages/ui/src/icons/collections
brand.ts
export const BRAND_COLLECTION
editor.ts
export const EDITOR_COLLECTION
index.ts
export const ICON_COLLECTIONS
ui.ts
export const UI_COLLECTION
## packages/ui/src/icons/registry
brand.ts
export const BRAND_ICONS
editor.ts
export const EDITOR_ICONS
index.ts
export const ICON_DEFINITIONS

View File

@ -60,7 +60,7 @@ function AuthorList({ authors }: { authors: Author[] }) {
<div className="flex items-center gap-2">
{authors.map((author) => (
<div key={author.id} className="flex items-center gap-2">
<Avatar className="h-6 w-6 shadow-sm">
<Avatar className="size-6 shadow-sm">
<AvatarImage src={author.image} alt={author.name} />
<AvatarFallback className="text-xs">
{author.name.charAt(0).toUpperCase()}

View File

@ -1,4 +1,4 @@
import { GithubIcon } from "@opencut/ui/icons";
import { OcGithubIcon } from "@opencut/ui/icons";
import { ExternalLink } from "lucide-react";
import type { Metadata } from "next";
import Link from "next/link";
@ -101,7 +101,7 @@ export default async function ContributorsPage() {
function StatItem({ value, label }: { value: number; label: string }) {
return (
<div className="flex items-center gap-2">
<div className="bg-foreground h-2 w-2 rounded-full" />
<div className="bg-foreground size-2 rounded-full" />
<span className="font-medium">{value}</span>
<span className="text-muted-foreground">{label}</span>
</div>
@ -187,7 +187,7 @@ function AllContributorsSection({
className="opacity-100 transition-opacity hover:opacity-70"
>
<div className="flex flex-col items-center gap-2 p-2">
<Avatar className="h-16 w-16">
<Avatar className="size-16">
<AvatarImage
src={contributor.avatar_url}
alt={`${contributor.login}'s avatar`}
@ -214,8 +214,8 @@ function EmptyState() {
return (
<div className="flex flex-col gap-8 py-20 text-center">
<div className="flex flex-col gap-6">
<div className="bg-muted/50 mx-auto flex h-20 w-20 items-center justify-center rounded-full">
<GithubIcon className="text-muted-foreground h-8 w-8" />
<div className="bg-muted/50 mx-auto flex size-20 items-center justify-center rounded-full">
<OcGithubIcon className="text-muted-foreground size-8" />
</div>
<div className="flex flex-col gap-3">
<h3 className="text-xl font-medium">No contributors found</h3>
@ -231,9 +231,9 @@ function EmptyState() {
rel="noopener noreferrer"
>
<Button variant="outline" className="gap-2">
<GithubIcon className="h-4 w-4" />
<OcGithubIcon />
View on GitHub
<ExternalLink className="h-4 w-4" />
<ExternalLink />
</Button>
</Link>
</div>
@ -259,8 +259,8 @@ function ExternalToolsSection() {
>
<Card className="h-full">
<CardContent className="flex h-full flex-col gap-4 p-6 text-center">
<div className="bg-muted/50 mx-auto flex h-12 w-12 items-center justify-center rounded-full">
<tool.icon className="h-6 w-6" />
<div className="bg-muted/50 mx-auto flex size-12 items-center justify-center rounded-full">
<tool.icon className="size-6" />
</div>
<div className="flex flex-1 flex-col gap-2">
<h3 className="text-lg font-semibold">{tool.name}</h3>

View File

@ -40,7 +40,7 @@ function EditorLayout() {
return (
<ResizablePanelGroup
direction="vertical"
className="h-full w-full gap-[0.18rem]"
className="size-full gap-[0.18rem]"
onLayout={(sizes) => {
setPanel("mainContent", sizes[0] ?? panels.mainContent);
setPanel("timeline", sizes[1] ?? panels.timeline);
@ -54,7 +54,7 @@ function EditorLayout() {
>
<ResizablePanelGroup
direction="horizontal"
className="h-full w-full gap-[0.19rem] px-3"
className="size-full gap-[0.19rem] px-3"
onLayout={(sizes) => {
setPanel("tools", sizes[0] ?? panels.tools);
setPanel("preview", sizes[1] ?? panels.preview);

View File

@ -171,7 +171,7 @@ export default function ProjectsPage() {
size="sm"
onClick={handleCancelSelection}
>
<X className="size-4!" />
<X />
Cancel
</Button>
{selectedProjects.size > 0 && (
@ -180,7 +180,7 @@ export default function ProjectsPage() {
size="sm"
onClick={() => setIsBulkDeleteDialogOpen(true)}
>
<Trash2 className="size-4!" />
<Trash2 />
Delete ({selectedProjects.size})
</Button>
)}
@ -210,7 +210,7 @@ export default function ProjectsPage() {
{isSelectionMode ? (
<div className="flex items-center gap-2">
<Button variant="outline" onClick={handleCancelSelection}>
<X className="size-4!" />
<X />
Cancel
</Button>
<Button
@ -218,7 +218,7 @@ export default function ProjectsPage() {
disabled={selectedProjects.size === 0}
onClick={() => setIsBulkDeleteDialogOpen(true)}
>
<Trash2 className="size-4!" />
<Trash2 />
Delete {selectedProjects.size} projects
</Button>
</div>
@ -429,7 +429,7 @@ function ProjectCard({
className="object-cover"
/>
) : (
<div className="bg-muted/50 flex h-full w-full items-center justify-center">
<div className="bg-muted/50 flex size-full items-center justify-center">
<Video className="text-muted-foreground size-12 shrink-0" />
</div>
)}
@ -562,7 +562,7 @@ function ProjectsLoader() {
<div className="flex flex-col gap-1.5 px-0 pt-5">
<Skeleton className="bg-muted/50 h-4 w-3/4" />
<div className="flex items-center gap-1.5">
<Skeleton className="bg-muted/50 h-4 w-4" />
<Skeleton className="bg-muted/50 size-4" />
<Skeleton className="bg-muted/50 h-4 w-24" />
</div>
</div>
@ -575,7 +575,7 @@ function ProjectsLoader() {
function CreateButton({ onClick }: { onClick?: () => void }) {
return (
<Button className="flex" onClick={onClick}>
<Plus className="size-4!" />
<Plus />
<span className="text-sm font-medium">New project</span>
</Button>
);

View File

@ -110,7 +110,7 @@ export default function ProjectsPage() {
href="/projects"
className="flex items-center gap-3 rounded-2xl bg-blue-50/50 px-4 py-3 text-sm font-medium text-[#00A3FF]"
>
<LayoutGrid className="h-5 w-5" />
<LayoutGrid className="size-5" />
Projects
</a>
<div className="px-4 pt-6 pb-2">
@ -122,14 +122,14 @@ export default function ProjectsPage() {
href="/projects"
className="flex items-center gap-3 rounded-2xl px-4 py-3 text-sm font-medium text-slate-500 hover:bg-slate-50 hover:text-slate-900"
>
<Folder className="h-5 w-5 text-slate-400" />
<Folder className="size-5 text-slate-400" />
Marketing
</a>
<a
href="/projects"
className="flex items-center gap-3 rounded-2xl px-4 py-3 text-sm font-medium text-slate-500 hover:bg-slate-50 hover:text-slate-900"
>
<Folder className="h-5 w-5 text-slate-400" />
<Folder className="size-5 text-slate-400" />
Social media
</a>
</nav>
@ -143,7 +143,7 @@ export default function ProjectsPage() {
<div className="flex items-center gap-4">
<div className="group relative">
<Search className="absolute top-1/2 left-3.5 h-4 w-4 -translate-y-1/2 text-slate-400" />
<Search className="absolute top-1/2 left-3.5 size-4 -translate-y-1/2 text-slate-400" />
<input
type="text"
placeholder="Search..."
@ -157,7 +157,7 @@ export default function ProjectsPage() {
className="rounded-full bg-slate-100 p-2 text-slate-900"
aria-label="Grid view"
>
<LayoutGrid className="h-4 w-4" aria-hidden="true">
<LayoutGrid className="size-4" aria-hidden="true">
<title>Grid view</title>
</LayoutGrid>
</button>
@ -166,7 +166,7 @@ export default function ProjectsPage() {
className="rounded-full p-2 text-slate-400 hover:text-slate-600"
aria-label="List view"
>
<List className="h-4 w-4" aria-hidden="true">
<List className="size-4" aria-hidden="true">
<title>List view</title>
</List>
</button>
@ -176,7 +176,7 @@ export default function ProjectsPage() {
type="button"
className="flex items-center gap-2 rounded-full bg-[#00A3FF] px-5 py-2.5 text-sm font-semibold text-white hover:bg-[#008BE0] active:scale-95"
>
<Plus className="h-4 w-4" />
<Plus className="size-4" />
New project
</button>
</div>
@ -226,7 +226,7 @@ export default function ProjectsPage() {
<div className="project-select-wrapper absolute top-4 left-4 z-20">
<input
type="checkbox"
className="custom-checkbox project-select h-6 w-6 cursor-pointer shadow-md"
className="custom-checkbox project-select size-6 cursor-pointer shadow-md"
checked={isSelected}
onChange={({ currentTarget }) => {
toggleProjectSelection({
@ -243,7 +243,7 @@ export default function ProjectsPage() {
className="rounded-full bg-white/90 p-2 text-slate-600 backdrop-blur-sm hover:bg-white hover:text-[#00A3FF]"
aria-label="Project menu"
>
<MoreHorizontal className="h-4 w-4" aria-hidden="true">
<MoreHorizontal className="size-4" aria-hidden="true">
<title>Project menu</title>
</MoreHorizontal>
</button>

View File

@ -51,7 +51,7 @@ function SponsorCard({ sponsor }: { sponsor: Sponsor }) {
href={sponsor.url}
target="_blank"
rel="noopener noreferrer"
className="h-full w-full"
className="size-full"
>
<Card className="h-full">
<CardContent className="flex h-full flex-col justify-center gap-8 p-8">
@ -67,7 +67,7 @@ function SponsorCard({ sponsor }: { sponsor: Sponsor }) {
<h3 className="text-xl font-semibold group-hover:underline">
{sponsor.name}
</h3>
<ExternalLink className="text-muted-foreground h-4 w-4" />
<ExternalLink className="text-muted-foreground size-4" />
</div>
<p className="text-muted-foreground">{sponsor.description}</p>
</div>

View File

@ -28,7 +28,7 @@ export function MediaDragOverlay({
return (
<button
className="bg-foreground/5 hover:bg-foreground/10 flex h-full w-full flex-col items-center justify-center gap-4 rounded-lg p-8 text-center transition-all duration-200"
className="bg-foreground/5 hover:bg-foreground/10 flex size-full flex-col items-center justify-center gap-4 rounded-lg p-8 text-center transition-all duration-200"
type="button"
disabled={isProcessing || !onClick}
onClick={(event) => handleClick({ event })}

View File

@ -48,7 +48,7 @@ export function TabBar() {
<div className="relative flex">
<div
ref={scrollRef}
className="scrollbar-hidden relative flex h-full w-full flex-col items-center justify-start gap-5 overflow-y-auto px-4 py-4"
className="scrollbar-hidden relative flex size-full flex-col items-center justify-start gap-5 overflow-y-auto px-4 py-4"
>
{TAB_KEYS.map((tabKey) => {
const tab = tabs[tabKey];

View File

@ -342,7 +342,7 @@ export function MediaView() {
</div>
</div>
<div className="scrollbar-thin h-full w-full overflow-y-auto pt-1">
<div className="scrollbar-thin size-full overflow-y-auto pt-1">
<div className="w-full flex-1 p-3 pt-0">
{isDragOver || filteredMediaItems.length === 0 ? (
<MediaDragOverlay

View File

@ -407,7 +407,7 @@ function SavedSoundsView() {
return (
<div className="bg-panel flex h-full flex-col items-center justify-center gap-3 p-4">
<HeartIcon
className="text-muted-foreground h-10 w-10"
className="text-muted-foreground size-10"
strokeWidth={1.5}
/>
<div className="flex flex-col gap-2 text-center">
@ -524,7 +524,7 @@ function AudioItem({ sound, isPlaying, onPlay }: AudioItemProps) {
className="flex min-w-0 flex-1 items-center gap-3 text-left"
onClick={handleClick}
>
<div className="bg-accent relative flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded-md">
<div className="bg-accent relative flex size-12 shrink-0 items-center justify-center overflow-hidden rounded-md">
<div className="from-primary/20 absolute inset-0 bg-gradient-to-br to-transparent" />
{isPlaying ? (
<PauseIcon className="size-5" />

View File

@ -151,7 +151,7 @@ function EmptyView({ message }: { message: string }) {
return (
<div className="bg-panel flex h-full flex-col items-center justify-center gap-3 p-4">
<StickerIcon
className="text-muted-foreground h-10 w-10"
className="text-muted-foreground size-10"
strokeWidth={1.5}
/>
<div className="flex flex-col gap-2 text-center">
@ -342,7 +342,7 @@ function StickersContentView({ category }: { category: StickerCategory }) {
<button
type="button"
onClick={clearRecentStickers}
className="hover:bg-accent ml-auto flex h-5 w-5 items-center justify-center rounded p-0"
className="hover:bg-accent ml-auto flex size-5 items-center justify-center rounded p-0"
>
<X className="text-muted-foreground size-3" />
</button>
@ -376,7 +376,7 @@ function StickersContentView({ category }: { category: StickerCategory }) {
/>
) : (
<div className="flex items-center justify-center py-8">
<Loader2 className="text-muted-foreground h-6 w-6 animate-spin" />
<Loader2 className="text-muted-foreground size-6 animate-spin" />
</div>
)}
</div>
@ -489,7 +489,7 @@ function CollectionItem({ title, subtitle, onClick }: CollectionItemProps) {
<p className="font-medium">{title}</p>
<p className="text-muted-foreground text-xs">{subtitle}</p>
</div>
<ArrowRight className="size-4" />
<ArrowRight />
</Button>
);
}
@ -522,13 +522,13 @@ function StickerItem({
const collectionPrefix = iconName.split(":")[0];
const preview = imageError ? (
<div className="flex h-full w-full items-center justify-center p-2">
<div className="flex size-full items-center justify-center p-2">
<span className="text-muted-foreground text-center text-xs break-all">
{displayName}
</span>
</div>
) : (
<div className="flex h-full w-full items-center justify-center p-4">
<div className="flex size-full items-center justify-center p-4">
<Image
src={
hostIndex === 0
@ -542,7 +542,7 @@ function StickerItem({
alt={displayName}
width={64}
height={64}
className="h-full w-full object-contain"
className="size-full object-contain"
style={
capSize
? {

View File

@ -181,7 +181,7 @@ export function DraggableItem({
ratio={1}
className="ring-primary relative overflow-hidden rounded-md shadow-2xl ring-3"
>
<div className="h-full w-full [&_img]:h-full [&_img]:w-full [&_img]:rounded-none [&_img]:object-cover">
<div className="size-full [&_img]:size-full [&_img]:rounded-none [&_img]:object-cover">
{preview}
</div>
{shouldShowPlusOnDrag && (
@ -222,7 +222,7 @@ function PlusButton({
}}
title={tooltipText}
>
<Plus className="size-4!" />
<Plus />
</Button>
);

View File

@ -1,13 +1,7 @@
"use client";
import { Button } from "../ui/button";
import {
ChevronDown,
ArrowLeft,
SquarePen,
Trash,
Loader2,
} from "lucide-react";
import { ChevronDown } from "lucide-react";
import { KeyboardShortcutsHelp } from "../keyboard-shortcuts-help";
import { useState } from "react";
import {
@ -27,7 +21,7 @@ import { ThemeToggle } from "../theme-toggle";
import { SOCIAL_LINKS } from "@/constants/site-constants";
import { toast } from "sonner";
import { useEditor } from "@/hooks/use-editor";
import { PencilIcon } from "@opencut/ui/icons";
import { OcLeftArrowIcon, OcPencilIcon, OcTrashIcon } from "@opencut/ui/icons";
export function EditorHeader() {
return (
@ -125,18 +119,14 @@ function ProjectDropdown() {
onClick={handleExit}
disabled={isExiting}
>
{isExiting ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<ArrowLeft className="h-4 w-4" />
)}
<OcLeftArrowIcon className="size-4" />
Projects
</DropdownMenuItem>
<DropdownMenuItem
className="flex items-center gap-1.5"
onClick={() => setIsRenameDialogOpen(true)}
>
<PencilIcon className="h-4 w-4" />
<OcPencilIcon className="size-4" />
Rename project
</DropdownMenuItem>
<DropdownMenuItem
@ -144,7 +134,7 @@ function ProjectDropdown() {
className="flex items-center gap-1.5"
onClick={() => setIsDeleteDialogOpen(true)}
>
<Trash className="h-4 w-4" />
<OcTrashIcon className="size-4" />
Delete Project
</DropdownMenuItem>
<DropdownMenuSeparator />
@ -155,7 +145,7 @@ function ProjectDropdown() {
rel="noopener noreferrer"
className="flex items-center gap-1.5"
>
<FaDiscord className="h-4 w-4" />
<FaDiscord className="size-4" />
Discord
</Link>
</DropdownMenuItem>

View File

@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import { TransitionUpIcon } from "@opencut/ui/icons";
import { OcTransitionUpIcon } from "@opencut/ui/icons";
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
import { Button } from "../ui/button";
import { Label } from "../ui/label";
@ -53,9 +53,9 @@ export function ExportButton() {
}}
>
<div className="relative flex items-center gap-1.5 rounded-[0.8rem] bg-linear-270 from-[#2567EC] to-[#37B6F7] px-4 py-1 shadow-[0_1px_3px_0px_rgba(0,0,0,0.65)]">
<TransitionUpIcon className="z-50" />
<OcTransitionUpIcon className="z-50" />
<span className="z-50 text-[0.875rem]">Export</span>
<div className="absolute top-0 left-0 z-10 flex h-full w-full items-center justify-center rounded-[0.8rem] bg-linear-to-t from-white/0 to-white/50">
<div className="absolute top-0 left-0 z-10 flex size-full items-center justify-center rounded-[0.8rem] bg-linear-to-t from-white/0 to-white/50">
<div className="absolute top-[0.08rem] z-50 h-[calc(100%-2px)] w-[calc(100%-2px)] rounded-[0.8rem] bg-linear-270 from-[#2567EC] to-[#37B6F7]"></div>
</div>
</div>
@ -240,7 +240,7 @@ function ExportPopover({
</div>
<Button onClick={handleExport} className="w-full gap-2">
<Download className="h-4 w-4" />
<Download className="size-4" />
Export
</Button>
</>

View File

@ -9,7 +9,7 @@ function TikTokGuide() {
<Image
src="/platform-guides/tiktok-blueprint.png"
alt="TikTok layout guide"
className="absolute inset-0 h-full w-full object-contain"
className="absolute inset-0 size-full object-contain"
draggable={false}
fill
/>

View File

@ -36,7 +36,7 @@ export function MigrationDialog() {
</DialogHeader>
<div className="flex items-center justify-center py-4">
<Loader2 className="text-muted-foreground h-8 w-8 animate-spin" />
<Loader2 className="text-muted-foreground size-8 animate-spin" />
</div>
</DialogContent>
</Dialog>

View File

@ -131,7 +131,7 @@ function NextButton({
return (
<Button onClick={onClick} variant="default" className="w-full">
{children}
<ArrowRightIcon className="h-4 w-4" />
<ArrowRightIcon className="size-4" />
</Button>
);
}

View File

@ -52,7 +52,7 @@ function EmptyView() {
return (
<div className="bg-panel flex h-full flex-col items-center justify-center gap-3 p-4">
<SquareSlashIcon
className="text-muted-foreground h-10 w-10"
className="text-muted-foreground size-10"
strokeWidth={1.5}
/>
<div className="flex flex-col gap-2 text-center">

View File

@ -159,7 +159,7 @@ export function ScenesView({ children }: { children: React.ReactNode }) {
<div className="flex items-center gap-2">
{((isSelectMode && selectedScenes.has(scene.id)) ||
(!isSelectMode && currentScene?.id === scene.id)) && (
<Check className="h-4 w-4" />
<Check className="size-4" />
)}
</div>
</Button>

View File

@ -260,7 +260,7 @@ export function Timeline() {
className="bg-panel z-100 w-28 shrink-0 overflow-y-auto border-r"
style={{ paddingTop: TIMELINE_CONSTANTS.PADDING_TOP }}
>
<ScrollArea className="h-full w-full" ref={trackLabelsScrollRef}>
<ScrollArea className="size-full" ref={trackLabelsScrollRef}>
<div className="flex flex-col gap-1">
{tracks.map((track) => (
<div
@ -344,7 +344,7 @@ export function Timeline() {
/>
<ScrollArea
className="h-full w-full"
className="size-full"
ref={tracksScrollRef}
onMouseDown={(event) => {
const isDirectTarget = event.target === event.currentTarget;

View File

@ -56,7 +56,7 @@ export function Footer() {
target="_blank"
rel="noopener noreferrer"
>
<FaGithub className="h-5 w-5" />
<FaGithub className="size-5" />
</Link>
<Link
href={SOCIAL_LINKS.x}
@ -64,7 +64,7 @@ export function Footer() {
target="_blank"
rel="noopener noreferrer"
>
<RiTwitterXLine className="h-5 w-5" />
<RiTwitterXLine className="size-5" />
</Link>
<Link
href={SOCIAL_LINKS.discord}
@ -72,7 +72,7 @@ export function Footer() {
target="_blank"
rel="noopener noreferrer"
>
<RiDiscordFill className="h-5 w-5" />
<RiDiscordFill className="size-5" />
</Link>
</div>
</div>

View File

@ -1,5 +1,5 @@
import { Button } from "./ui/button";
import { GithubIcon } from "@opencut/ui/icons";
import { OcGithubIcon } from "@opencut/ui/icons";
import { ExternalLink } from "lucide-react";
import Link from "next/link";
import { SOCIAL_LINKS } from "@/constants/site-constants";
@ -24,7 +24,7 @@ export function GitHubContributeSection({
rel="noopener noreferrer"
>
<Button className="w-full" size="lg">
<GithubIcon className="h-4 w-4" />
<OcGithubIcon className="size-4" />
Start contributing
</Button>
</Link>
@ -34,7 +34,7 @@ export function GitHubContributeSection({
rel="noopener noreferrer"
>
<Button variant="outline" className="w-full" size="lg">
<ExternalLink className="h-4 w-4" />
<ExternalLink className="size-4" />
Report issues
</Button>
</Link>

View File

@ -7,12 +7,13 @@ import { Button } from "./ui/button";
import { ArrowRight } from "lucide-react";
import Image from "next/image";
import { ThemeToggle } from "./theme-toggle";
import { GithubIcon, MenuIcon } from "@opencut/ui/icons";
import { OcGithubIcon, OcMenuIcon } from "@opencut/ui/icons";
import { cn } from "@/utils/ui";
import { DEFAULT_LOGO_URL, SOCIAL_LINKS } from "@/constants/site-constants";
export function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const closeMenu = () => setIsMenuOpen(false);
const links = [
{
@ -61,20 +62,20 @@ export function Header() {
className="flex items-center justify-center p-0"
onClick={() => setIsMenuOpen(!isMenuOpen)}
>
<MenuIcon size={30} />
<OcMenuIcon size={30} />
</Button>
</div>
<div className="hidden items-center gap-3 md:flex">
<Link href={SOCIAL_LINKS.github}>
<Button className="bg-background text-sm" variant="outline">
<GithubIcon className="h-4 w-4" />
<OcGithubIcon className="size-4" />
31k+
</Button>
</Link>
<Link href="/projects">
<Button className="text-sm">
Projects
<ArrowRight className="h-4 w-4" />
<ArrowRight className="size-4" />
</Button>
</Link>
<ThemeToggle />
@ -86,9 +87,24 @@ export function Header() {
"transition-opacity duration-150",
isMenuOpen && "pointer-events-auto opacity-100",
)}
onClick={() => setIsMenuOpen(false)}
>
<div className="relative h-full">
<button
type="button"
aria-label="Close menu"
className="absolute inset-0"
onClick={closeMenu}
onKeyDown={(event) => {
if (
event.key === "Enter" ||
event.key === " " ||
event.key === "Escape"
) {
event.preventDefault();
closeMenu();
}
}}
/>
<nav className="flex flex-col gap-3 px-6 pt-[5rem]">
{links.map((link, index) => (
<motion.div

View File

@ -113,7 +113,7 @@ export function KeyboardShortcutsHelp() {
<DialogContent className="flex max-h-[80vh] max-w-2xl flex-col p-0">
<DialogHeader className="flex-shrink-0 p-6 pb-0">
<DialogTitle className="flex items-center gap-2">
<Keyboard className="h-5 w-5" />
<Keyboard className="size-5" />
Keyboard Shortcuts
</DialogTitle>
<DialogDescription>

View File

@ -113,7 +113,7 @@ export function Handlebars({ children }: HandlebarsProps) {
return (
<div className="flex justify-center gap-4 leading-16">
<div ref={containerRef} className="relative mt-0.5 -rotate-[2.76deg]">
<div className="absolute inset-0 z-10 flex h-full w-full justify-between rounded-2xl border border-yellow-500">
<div className="absolute inset-0 z-10 flex size-full justify-between rounded-2xl border border-yellow-500">
<div
ref={leftHandleRef}
className="bg-background absolute left-0 z-20 flex h-full w-7 cursor-ew-resize touch-none items-center justify-center rounded-full border border-yellow-500 select-none"
@ -154,7 +154,7 @@ export function Handlebars({ children }: HandlebarsProps) {
</div>
<span
className="relative z-0 inline-flex h-full w-full items-center justify-center rounded-2xl px-9 will-change-auto"
className="relative z-0 inline-flex size-full items-center justify-center rounded-2xl px-9 will-change-auto"
style={{
mask: `linear-gradient(90deg,
rgba(255, 255, 255, 0) 0%,

View File

@ -90,7 +90,7 @@ export function EditorProvider({ projectId, children }: EditorProviderProps) {
return (
<div className="bg-background flex h-screen w-screen items-center justify-center">
<div className="flex flex-col items-center gap-4">
<Loader2 className="text-muted-foreground h-8 w-8 animate-spin" />
<Loader2 className="text-muted-foreground size-8 animate-spin" />
<p className="text-muted-foreground text-sm">Loading project...</p>
</div>
</div>
@ -101,7 +101,7 @@ export function EditorProvider({ projectId, children }: EditorProviderProps) {
return (
<div className="bg-background flex h-screen w-screen items-center justify-center">
<div className="flex flex-col items-center gap-4">
<Loader2 className="text-muted-foreground h-8 w-8 animate-spin" />
<Loader2 className="text-muted-foreground size-8 animate-spin" />
<p className="text-muted-foreground text-sm">Exiting project...</p>
</div>
</div>

View File

@ -34,7 +34,7 @@ const AccordionTrigger = React.forwardRef<
{...props}
>
{children}
<ChevronDown className="text-muted-foreground h-4 w-4 shrink-0 transition-transform duration-200" />
<ChevronDown className="text-muted-foreground size-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));

View File

@ -12,7 +12,7 @@ const Avatar = React.forwardRef<
<AvatarPrimitive.Root
ref={ref}
className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
"relative flex size-10 shrink-0 overflow-hidden rounded-full",
className,
)}
{...props}
@ -26,7 +26,7 @@ const AvatarImage = React.forwardRef<
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn("aspect-square h-full w-full", className)}
className={cn("aspect-square size-full", className)}
{...props}
/>
));
@ -38,10 +38,10 @@ const AvatarFallback = React.forwardRef<
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"bg-muted flex h-full w-full items-center justify-center rounded-full",
className,
)}
className={cn(
"bg-muted flex size-full items-center justify-center rounded-full",
className,
)}
{...props}
/>
));

View File

@ -80,7 +80,7 @@ const BreadcrumbSeparator = ({
<li
role="presentation"
aria-hidden="true"
className={cn("[&>svg]:h-3.5 [&>svg]:w-3.5", className)}
className={cn("[&>svg]:size-3.5", className)}
{...props}
>
{children ?? <ChevronRight />}
@ -95,10 +95,10 @@ const BreadcrumbEllipsis = ({
<span
role="presentation"
aria-hidden="true"
className={cn("flex h-9 w-9 items-center justify-center", className)}
className={cn("flex size-9 items-center justify-center", className)}
{...props}
>
<MoreHorizontal className="h-4 w-4" />
<MoreHorizontal className="size-4" />
<span className="sr-only">More</span>
</span>
);

View File

@ -30,7 +30,7 @@ const buttonVariants = cva(
default: "h-9 px-4 py-2",
sm: "h-8 rounded-full px-3 text-xs",
lg: "h-10 rounded-full p-5",
icon: "h-7 w-7",
icon: "size-7",
},
},
defaultVariants: {

View File

@ -27,7 +27,7 @@ function Calendar({
nav: "space-x-1 flex items-center",
nav_button: cn(
buttonVariants({ variant: "outline" }),
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
"size-7 bg-transparent p-0 opacity-50 hover:opacity-100",
),
nav_button_previous: "absolute left-1",
nav_button_next: "absolute right-1",
@ -44,7 +44,7 @@ function Calendar({
),
day: cn(
buttonVariants({ variant: "text" }),
"h-8 w-8 p-0 font-normal aria-selected:opacity-100",
"size-8 p-0 font-normal aria-selected:opacity-100",
),
day_range_start: "day-range-start",
day_range_end: "day-range-end",
@ -60,8 +60,8 @@ function Calendar({
...classNames,
}}
components={{
IconLeft: ({ ...props }) => <ChevronLeft className="h-4 w-4" />,
IconRight: ({ ...props }) => <ChevronRight className="h-4 w-4" />,
IconLeft: ({ ...props }) => <ChevronLeft className="size-4" />,
IconRight: ({ ...props }) => <ChevronRight className="size-4" />,
}}
{...props}
/>

View File

@ -206,7 +206,7 @@ const CarouselPrevious = React.forwardRef<
variant={variant}
size={size}
className={cn(
"absolute h-8 w-8 rounded-full",
"absolute size-8 rounded-full",
orientation === "horizontal"
? "top-1/2 -left-12 -translate-y-1/2"
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
@ -216,7 +216,7 @@ const CarouselPrevious = React.forwardRef<
onClick={scrollPrev}
{...props}
>
<ArrowLeft className="h-4 w-4" />
<ArrowLeft className="size-4" />
<span className="sr-only">Previous slide</span>
</Button>
);
@ -235,7 +235,7 @@ const CarouselNext = React.forwardRef<
variant={variant}
size={size}
className={cn(
"absolute h-8 w-8 rounded-full",
"absolute size-8 rounded-full",
orientation === "horizontal"
? "top-1/2 -right-12 -translate-y-1/2"
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
@ -245,7 +245,7 @@ const CarouselNext = React.forwardRef<
onClick={scrollNext}
{...props}
>
<ArrowRight className="h-4 w-4" />
<ArrowRight className="size-4" />
<span className="sr-only">Next slide</span>
</Button>
);

View File

@ -199,7 +199,7 @@ const ChartTooltipContent = React.forwardRef<
<div
key={item.dataKey}
className={cn(
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:size-2.5",
indicator === "dot" && "items-center",
)}
>
@ -215,7 +215,7 @@ const ChartTooltipContent = React.forwardRef<
className={cn(
"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
{
"h-2.5 w-2.5": indicator === "dot",
"size-2.5": indicator === "dot",
"w-1": indicator === "line",
"w-0 border-[1.5px] border-dashed bg-transparent":
indicator === "dashed",
@ -298,14 +298,14 @@ const ChartLegendContent = React.forwardRef<
<div
key={item.value}
className={cn(
"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3",
"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:size-3",
)}
>
{itemConfig?.icon && !hideIcon ? (
<itemConfig.icon />
) : (
<div
className="h-2 w-2 shrink-0 rounded-[2px]"
className="size-2 shrink-0 rounded-[2px]"
style={{
backgroundColor: item.color,
}}

View File

@ -13,7 +13,7 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer border-primary focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground h-4 w-4 shrink-0 rounded-sm border shadow-sm focus-visible:ring-1 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
"peer border-primary focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground size-4 shrink-0 rounded-sm border shadow-sm focus-visible:ring-1 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
@ -21,7 +21,7 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")}
>
<Check className="h-4 w-4" />
<Check className="size-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));

View File

@ -14,7 +14,7 @@ const Command = React.forwardRef<
<CommandPrimitive
ref={ref}
className={cn(
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
"bg-popover text-popover-foreground flex size-full flex-col overflow-hidden rounded-md",
className,
)}
{...props}
@ -26,7 +26,7 @@ const CommandDialog = ({ children, ...props }: DialogProps) => {
return (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0">
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:size-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:size-5">
{children}
</Command>
</DialogContent>
@ -39,7 +39,7 @@ const CommandInput = React.forwardRef<
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>(({ className, ...props }, ref) => (
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<Search className="mr-2 size-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
ref={ref}
className={cn(

View File

@ -121,9 +121,9 @@ const ContextMenuCheckboxItem = React.forwardRef<
checked={checked}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<span className="absolute left-2 flex size-3.5 items-center justify-center">
<ContextMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
<Check className="size-4" />
</ContextMenuPrimitive.ItemIndicator>
</span>
{children}
@ -143,9 +143,9 @@ const ContextMenuRadioItem = React.forwardRef<
className={cn(contextMenuItemVariants({ variant }), "pr-2 pl-8", className)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<span className="absolute left-2 flex size-3.5 items-center justify-center">
<ContextMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
<Circle className="size-2 fill-current" />
</ContextMenuPrimitive.ItemIndicator>
</span>
{children}

View File

@ -50,7 +50,7 @@ const DialogContent = React.forwardRef<
>
{children}
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 cursor-pointer opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<X className="h-4 w-4" />
<X className="size-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>

View File

@ -136,9 +136,9 @@ const DropdownMenuCheckboxItem = React.forwardRef<
{...props}
>
{children}
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
<span className="absolute right-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
<Check className="size-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
</DropdownMenuPrimitive.CheckboxItem>
@ -162,9 +162,9 @@ const DropdownMenuRadioItem = React.forwardRef<
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<span className="absolute left-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
<Circle className="size-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}

View File

@ -74,7 +74,7 @@ export function InputWithBack({
}}
transition={smoothTransition}
>
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
<Search className="text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2" />
<Input
placeholder={placeholder}
className="bg-panel-accent w-full pl-9"

View File

@ -101,9 +101,9 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
aria-label={showPassword ? "Hide password" : "Show password"}
>
{showPassword ? (
<Eye className="h-4 w-4" />
<Eye className="size-4" />
) : (
<EyeOff className="h-4 w-4" />
<EyeOff className="size-4" />
)}
</Button>
)}

View File

@ -62,7 +62,7 @@ const MenubarSubTrigger = React.forwardRef<
{...props}
>
{children}
<ChevronRight className="ml-auto h-4 w-4" />
<ChevronRight className="ml-auto size-4" />
</MenubarPrimitive.SubTrigger>
));
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
@ -138,9 +138,9 @@ const MenubarCheckboxItem = React.forwardRef<
checked={checked}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<span className="absolute left-2 flex size-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
<Check className="size-4" />
</MenubarPrimitive.ItemIndicator>
</span>
{children}
@ -160,9 +160,9 @@ const MenubarRadioItem = React.forwardRef<
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<span className="absolute left-2 flex size-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator>
<Circle className="h-4 w-4 fill-current" />
<Circle className="size-4 fill-current" />
</MenubarPrimitive.ItemIndicator>
</span>
{children}

View File

@ -109,7 +109,7 @@ const NavigationMenuIndicator = React.forwardRef<
)}
{...props}
>
<div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
<div className="bg-border relative top-[60%] size-2 rotate-45 rounded-tl-sm shadow-md" />
</NavigationMenuPrimitive.Indicator>
));
NavigationMenuIndicator.displayName =

View File

@ -69,7 +69,7 @@ const PaginationPrevious = ({
className={cn("gap-1 pl-2.5", className)}
{...props}
>
<ChevronLeft className="h-4 w-4" />
<ChevronLeft className="size-4" />
<span>Previous</span>
</PaginationLink>
);
@ -86,7 +86,7 @@ const PaginationNext = ({
{...props}
>
<span>Next</span>
<ChevronRight className="h-4 w-4" />
<ChevronRight className="size-4" />
</PaginationLink>
);
PaginationNext.displayName = "PaginationNext";
@ -97,10 +97,10 @@ const PaginationEllipsis = ({
}: React.ComponentProps<"span">) => (
<span
aria-hidden
className={cn("flex h-9 w-9 items-center justify-center", className)}
className={cn("flex size-9 items-center justify-center", className)}
{...props}
>
<MoreHorizontal className="h-4 w-4" />
<MoreHorizontal className="size-4" />
<span className="sr-only">More pages</span>
</span>
);

View File

@ -98,7 +98,7 @@ const CountrySelect = ({
/>
<ChevronsUpDown
className={cn(
"-mr-2 size-4 opacity-50",
"-mr-2 opacity-50",
disabled ? "hidden" : "opacity-100",
)}
/>

View File

@ -18,7 +18,7 @@ const Progress = React.forwardRef<
{...props}
>
<ProgressPrimitive.Indicator
className="bg-foreground h-full w-full flex-1 transition-all"
className="bg-foreground size-full flex-1 transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>

View File

@ -28,13 +28,13 @@ const RadioGroupItem = React.forwardRef<
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"border-primary text-primary focus-visible:ring-ring aspect-square h-4 w-4 rounded-full border shadow-sm focus:outline-hidden focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50",
"border-primary text-primary focus-visible:ring-ring aspect-square size-4 rounded-full border shadow-sm focus:outline-hidden focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
>
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<Circle className="fill-primary h-3.5 w-3.5" />
<Circle className="fill-primary size-3.5" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
);

View File

@ -10,7 +10,7 @@ const ResizablePanelGroup = ({
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
<ResizablePrimitive.PanelGroup
className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
"flex size-full data-[panel-group-direction=vertical]:flex-col",
className,
)}
{...props}

View File

@ -60,7 +60,7 @@ const SelectScrollUpButton = React.forwardRef<
)}
{...props}
>
<ChevronUp className="h-4 w-4" />
<ChevronUp className="size-4" />
</SelectPrimitive.ScrollUpButton>
));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
@ -77,7 +77,7 @@ const SelectScrollDownButton = React.forwardRef<
)}
{...props}
>
<ChevronDown className="h-4 w-4" />
<ChevronDown className="size-4" />
</SelectPrimitive.ScrollDownButton>
));
SelectScrollDownButton.displayName =
@ -142,9 +142,9 @@ const SelectItem = React.forwardRef<
className={cn(selectItemVariants({ variant }), className)}
{...props}
>
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
<span className="absolute right-2 flex size-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
<Check className="size-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>

View File

@ -198,7 +198,7 @@ function Sidebar({
<SheetTitle>Sidebar</SheetTitle>
<SheetDescription>Displays the mobile sidebar.</SheetDescription>
</SheetHeader>
<div className="flex h-full w-full flex-col">{children}</div>
<div className="flex size-full flex-col">{children}</div>
</SheetContent>
</Sheet>
);
@ -243,7 +243,7 @@ function Sidebar({
<div
data-sidebar="sidebar"
data-slot="sidebar-inner"
className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex size-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
>
{children}
</div>

View File

@ -20,7 +20,7 @@ const Slider = React.forwardRef<
<SliderPrimitive.Track className="bg-primary/20 relative h-1.5 w-full grow overflow-hidden rounded-full">
<SliderPrimitive.Range className="bg-primary absolute h-full" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className="border-primary/50 bg-background focus-visible:ring-ring block h-4 w-4 rounded-full border shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50" />
<SliderPrimitive.Thumb className="border-primary/50 bg-background focus-visible:ring-ring block size-4 rounded-full border shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
));
Slider.displayName = SliderPrimitive.Root.displayName;

View File

@ -19,7 +19,7 @@ const Switch = React.forwardRef<
>
<SwitchPrimitives.Thumb
className={cn(
"bg-background pointer-events-none block h-4 w-4 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
"bg-background pointer-events-none block size-4 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
)}
/>
</SwitchPrimitives.Root>

View File

@ -83,7 +83,7 @@ const ToastClose = React.forwardRef<
toast-close=""
{...props}
>
<X className="h-4 w-4" />
<X className="size-4" />
</ToastPrimitives.Close>
));
ToastClose.displayName = ToastPrimitives.Close.displayName;

View File

@ -1,4 +1,4 @@
import { DataBuddyIcon, MarbleIcon, VercelIcon } from "@opencut/ui/icons";
import { OcDataBuddyIcon, OcMarbleIcon, OcVercelIcon } from "@opencut/ui/icons";
export const SITE_URL = "https://opencut.app";
@ -25,19 +25,19 @@ export const EXTERNAL_TOOLS: ExternalTool[] = [
description:
"Modern headless CMS for content management and the blog for OpenCut",
url: "https://marblecms.com?utm_source=opencut",
icon: MarbleIcon,
icon: OcMarbleIcon,
},
{
name: "Vercel",
description: "Platform where we deploy and host OpenCut",
url: "https://vercel.com?utm_source=opencut",
icon: VercelIcon,
icon: OcVercelIcon,
},
{
name: "Databuddy",
description: "GDPR compliant analytics and user insights for OpenCut",
url: "https://databuddy.cc?utm_source=opencut",
icon: DataBuddyIcon,
icon: OcDataBuddyIcon,
},
];

View File

@ -37,8 +37,8 @@ export const TIMELINE_CONSTANTS = {
} as const;
export const TRACK_ICONS: Record<TrackType, React.ReactNode> = {
video: <Video className="text-muted-foreground h-4 w-4 shrink-0" />,
text: <TypeIcon className="text-muted-foreground h-4 w-4 shrink-0" />,
audio: <Music className="text-muted-foreground h-4 w-4 shrink-0" />,
sticker: <Sticker className="text-muted-foreground h-4 w-4 shrink-0" />,
video: <Video className="text-muted-foreground size-4 shrink-0" />,
text: <TypeIcon className="text-muted-foreground size-4 shrink-0" />,
audio: <Music className="text-muted-foreground size-4 shrink-0" />,
sticker: <Sticker className="text-muted-foreground size-4 shrink-0" />,
} as const;

View File

@ -1,51 +1,51 @@
import { createIcon } from "./create-icon";
import { ICON_DEFINITIONS } from "./registry";
export const GoogleIcon = createIcon({
export const OcGoogleIcon = createIcon({
definition: ICON_DEFINITIONS.google,
});
export const GithubIcon = createIcon({
export const OcGithubIcon = createIcon({
definition: ICON_DEFINITIONS.github,
});
export const VercelIcon = createIcon({
export const OcVercelIcon = createIcon({
definition: ICON_DEFINITIONS.vercel,
});
export const DataBuddyIcon = createIcon({
export const OcDataBuddyIcon = createIcon({
definition: ICON_DEFINITIONS.databuddy,
});
export const MarbleIcon = createIcon({
export const OcMarbleIcon = createIcon({
definition: ICON_DEFINITIONS.marble,
});
export const BackgroundIcon = createIcon({
export const OcBackgroundIcon = createIcon({
definition: ICON_DEFINITIONS.background,
});
export const SocialsIcon = createIcon({
export const OcSocialsIcon = createIcon({
definition: ICON_DEFINITIONS.socials,
});
export const TransitionUpIcon = createIcon({
export const OcTransitionUpIcon = createIcon({
definition: ICON_DEFINITIONS.transitionUp,
});
export const MenuIcon = createIcon({
export const OcMenuIcon = createIcon({
definition: ICON_DEFINITIONS.menu,
});
export const PencilIcon = createIcon({
export const OcPencilIcon = createIcon({
definition: ICON_DEFINITIONS.pencil,
});
export const LeftArrowIcon = createIcon({
export const OcLeftArrowIcon = createIcon({
definition: ICON_DEFINITIONS.leftArrow,
});
export const TrashIcon = createIcon({
export const OcTrashIcon = createIcon({
definition: ICON_DEFINITIONS.trash,
});

View File

@ -1,8 +1,10 @@
import type { IconDefinition } from "../types";
import { BRAND_ICONS } from "./brand";
import { UI_ICONS } from "./ui";
import { EDITOR_ICONS } from "./editor";
export const ICON_DEFINITIONS = {
...BRAND_ICONS,
...UI_ICONS,
...EDITOR_ICONS,
} satisfies Record<string, IconDefinition>;

View File

@ -15,8 +15,20 @@ Review every point below carefully for files to ensure they follow consistent co
13. Booleans must be named like `isSomething` or `hasSomething` or `shouldSomething`. Not `something` or `somethingIs`.
14. No text in docs or UI ever uses title case. Example: `Hello World` is wrong. It should be `Hello world`.
15. Use `size-10` instead of `h-10 w-10` when the width and height are the same.
16. For components that need to subscribe to data from the editor api (`src/core`, `src/managers`), use the `useEditor` hook.
17. In react components: store/manager methods should not be passed as props to sub-components. If a sub-component can access the same methods, it should do so. Example:
16. When using `size-` on an SVG (lucide, react-icons, @opencut/ui/icons, etc.) inside of a <Button> (not <buttom>), make sure to use the `!` modifier to ensure the size is applied correctly. This is becuase the <Button> component has a default size of `size-4` that can only be overridden with the `!` modifier. That also means, don't do `!size-4` since that's the default size.
- Example:
```tsx
<Button>
<PlusIcon className="!size-6" /> // This is correct ✅
<PlusIcon className="size-6" /> // This is wrong ❌
<PlusIcon className="!size-4" /> // This is wrong ❌
<span>Add</span>
</Button>
```
17. For components that need to subscribe to data from the editor api (`src/core`, `src/managers`), use the `useEditor` hook.
18. In react components: store/manager methods should not be passed as props to sub-components. If a sub-component can access the same methods, it should do so. Example:
```tsx
import { useTimelineStore } from "@/stores/timeline-store";
@ -41,7 +53,7 @@ Review every point below carefully for files to ensure they follow consistent co
```
```
18. Components render UI. Domain logic (data transformations, business rules, state mutations) lives in hooks, utilities, or managers. Simple interaction logic (gesture detection, modifier keys) can stay in components if not too many lines of code/complex.
19. Components render UI. Domain logic (data transformations, business rules, state mutations) lives in hooks, utilities, or managers. Simple interaction logic (gesture detection, modifier keys) can stay in components if not too many lines of code/complex.
19. Readability matters more than short names in the age of AI coding. Do not shorten names for the sake of "typing less". Nobody is typing code these days. AI agents are. Hence, clarity and readability are the most important things. Example: "element" is better than "el".