--- version: 1.0.0-beta.6 --- # Icons URL: /docs/icons Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/icons.mdx @vapor-ui/icons 라이브러리에서 제공하는 아이콘입니다. 아이콘을 클릭해 import 문을 복사할 수 있습니다. *** title: Icons description: | @vapor-ui/icons 라이브러리에서 제공하는 아이콘입니다. 아이콘을 클릭해 import 문을 복사할 수 있습니다. ------------------------------ ## Basic Icons | Icon Name | Import Statement | | --------------------------------------- | ------------------------------------------------------------------------- | | `AchievementIcon` | `import { AchievementIcon } from '@vapor-ui/icons'` | | `AddUserIcon` | `import { AddUserIcon } from '@vapor-ui/icons'` | | `AfghanistanColorIcon` | `import { AfghanistanColorIcon } from '@vapor-ui/icons'` | | `AiGoormeeIcon` | `import { AiGoormeeIcon } from '@vapor-ui/icons'` | | `AiSmartieIcon` | `import { AiSmartieIcon } from '@vapor-ui/icons'` | | `AirplayIcon` | `import { AirplayIcon } from '@vapor-ui/icons'` | | `AlbaniaColorIcon` | `import { AlbaniaColorIcon } from '@vapor-ui/icons'` | | `AlgeriaColorIcon` | `import { AlgeriaColorIcon } from '@vapor-ui/icons'` | | `AlgorithmIcon` | `import { AlgorithmIcon } from '@vapor-ui/icons'` | | `AndorraColorIcon` | `import { AndorraColorIcon } from '@vapor-ui/icons'` | | `AngolaColorIcon` | `import { AngolaColorIcon } from '@vapor-ui/icons'` | | `AntiguaAndBarbudaColorIcon` | `import { AntiguaAndBarbudaColorIcon } from '@vapor-ui/icons'` | | `AppleIcon` | `import { AppleIcon } from '@vapor-ui/icons'` | | `ArgentinaColorIcon` | `import { ArgentinaColorIcon } from '@vapor-ui/icons'` | | `ArmeniaColorIcon` | `import { ArmeniaColorIcon } from '@vapor-ui/icons'` | | `ArrowDownCircleIcon` | `import { ArrowDownCircleIcon } from '@vapor-ui/icons'` | | `AssignmentIcon` | `import { AssignmentIcon } from '@vapor-ui/icons'` | | `AustraliaColorIcon` | `import { AustraliaColorIcon } from '@vapor-ui/icons'` | | `AustriaColorIcon` | `import { AustriaColorIcon } from '@vapor-ui/icons'` | | `AwsIcon` | `import { AwsIcon } from '@vapor-ui/icons'` | | `AzerbaijanColorIcon` | `import { AzerbaijanColorIcon } from '@vapor-ui/icons'` | | `AzureIcon` | `import { AzureIcon } from '@vapor-ui/icons'` | | `BahamasColorIcon` | `import { BahamasColorIcon } from '@vapor-ui/icons'` | | `BahrainColorIcon` | `import { BahrainColorIcon } from '@vapor-ui/icons'` | | `BangladeshColorIcon` | `import { BangladeshColorIcon } from '@vapor-ui/icons'` | | `BarbadosColorIcon` | `import { BarbadosColorIcon } from '@vapor-ui/icons'` | | `BedIcon` | `import { BedIcon } from '@vapor-ui/icons'` | | `BelarusColorIcon` | `import { BelarusColorIcon } from '@vapor-ui/icons'` | | `BelgiumColorIcon` | `import { BelgiumColorIcon } from '@vapor-ui/icons'` | | `BelizeColorIcon` | `import { BelizeColorIcon } from '@vapor-ui/icons'` | | `BellOffIcon` | `import { BellOffIcon } from '@vapor-ui/icons'` | | `BellOnIcon` | `import { BellOnIcon } from '@vapor-ui/icons'` | | `BeninColorIcon` | `import { BeninColorIcon } from '@vapor-ui/icons'` | | `BhutanColorIcon` | `import { BhutanColorIcon } from '@vapor-ui/icons'` | | `BitbucketIcon` | `import { BitbucketIcon } from '@vapor-ui/icons'` | | `BlogColorIcon` | `import { BlogColorIcon } from '@vapor-ui/icons'` | | `BlogIcon` | `import { BlogIcon } from '@vapor-ui/icons'` | | `BoliviaColorIcon` | `import { BoliviaColorIcon } from '@vapor-ui/icons'` | | `BookIcon` | `import { BookIcon } from '@vapor-ui/icons'` | | `BookmarkIcon` | `import { BookmarkIcon } from '@vapor-ui/icons'` | | `BosniaAndHerzegovinaColorIcon` | `import { BosniaAndHerzegovinaColorIcon } from '@vapor-ui/icons'` | | `BotswanaColorIcon` | `import { BotswanaColorIcon } from '@vapor-ui/icons'` | | `BottomPlayerIcon` | `import { BottomPlayerIcon } from '@vapor-ui/icons'` | | `BranchIcon` | `import { BranchIcon } from '@vapor-ui/icons'` | | `BrazilColorIcon` | `import { BrazilColorIcon } from '@vapor-ui/icons'` | | `BreakpointIcon` | `import { BreakpointIcon } from '@vapor-ui/icons'` | | `BruneiColorIcon` | `import { BruneiColorIcon } from '@vapor-ui/icons'` | | `BuildIcon` | `import { BuildIcon } from '@vapor-ui/icons'` | | `BulgariaColorIcon` | `import { BulgariaColorIcon } from '@vapor-ui/icons'` | | `BurkinaFasoColorIcon` | `import { BurkinaFasoColorIcon } from '@vapor-ui/icons'` | | `BurundiColorIcon` | `import { BurundiColorIcon } from '@vapor-ui/icons'` | | `CafeIcon` | `import { CafeIcon } from '@vapor-ui/icons'` | | `CakeIcon` | `import { CakeIcon } from '@vapor-ui/icons'` | | `CalculatorIcon` | `import { CalculatorIcon } from '@vapor-ui/icons'` | | `CalendarIcon` | `import { CalendarIcon } from '@vapor-ui/icons'` | | `CallIcon` | `import { CallIcon } from '@vapor-ui/icons'` | | `CambodiaColorIcon` | `import { CambodiaColorIcon } from '@vapor-ui/icons'` | | `CameraIcon` | `import { CameraIcon } from '@vapor-ui/icons'` | | `CameroonColorIcon` | `import { CameroonColorIcon } from '@vapor-ui/icons'` | | `CampIcon` | `import { CampIcon } from '@vapor-ui/icons'` | | `CanadaColorIcon` | `import { CanadaColorIcon } from '@vapor-ui/icons'` | | `CapeVerdeColorIcon` | `import { CapeVerdeColorIcon } from '@vapor-ui/icons'` | | `CaptionIcon` | `import { CaptionIcon } from '@vapor-ui/icons'` | | `CarIcon` | `import { CarIcon } from '@vapor-ui/icons'` | | `CardsIcon` | `import { CardsIcon } from '@vapor-ui/icons'` | | `CaretDownIcon` | `import { CaretDownIcon } from '@vapor-ui/icons'` | | `CaretLeftIcon` | `import { CaretLeftIcon } from '@vapor-ui/icons'` | | `CaretRightIcon` | `import { CaretRightIcon } from '@vapor-ui/icons'` | | `CaretUpIcon` | `import { CaretUpIcon } from '@vapor-ui/icons'` | | `CentralAfricanRepublicColorIcon` | `import { CentralAfricanRepublicColorIcon } from '@vapor-ui/icons'` | | `CertificateIcon` | `import { CertificateIcon } from '@vapor-ui/icons'` | | `ChadColorIcon` | `import { ChadColorIcon } from '@vapor-ui/icons'` | | `ChapterIcon` | `import { ChapterIcon } from '@vapor-ui/icons'` | | `ChartPieIcon` | `import { ChartPieIcon } from '@vapor-ui/icons'` | | `ChatgptIcon` | `import { ChatgptIcon } from '@vapor-ui/icons'` | | `CheckCircleIcon` | `import { CheckCircleIcon } from '@vapor-ui/icons'` | | `CheckboxIcon` | `import { CheckboxIcon } from '@vapor-ui/icons'` | | `ChileColorIcon` | `import { ChileColorIcon } from '@vapor-ui/icons'` | | `ChinaColorIcon` | `import { ChinaColorIcon } from '@vapor-ui/icons'` | | `ChromeColorIcon` | `import { ChromeColorIcon } from '@vapor-ui/icons'` | | `ChromeIcon` | `import { ChromeIcon } from '@vapor-ui/icons'` | | `ClassIcon` | `import { ClassIcon } from '@vapor-ui/icons'` | | `CodeBlockIcon` | `import { CodeBlockIcon } from '@vapor-ui/icons'` | | `CodevisorIcon` | `import { CodevisorIcon } from '@vapor-ui/icons'` | | `CollaborationIcon` | `import { CollaborationIcon } from '@vapor-ui/icons'` | | `ColombiaColorIcon` | `import { ColombiaColorIcon } from '@vapor-ui/icons'` | | `ComorosColorIcon` | `import { ComorosColorIcon } from '@vapor-ui/icons'` | | `ComponentIcon` | `import { ComponentIcon } from '@vapor-ui/icons'` | | `ContainerIcon` | `import { ContainerIcon } from '@vapor-ui/icons'` | | `ContainerRunIcon` | `import { ContainerRunIcon } from '@vapor-ui/icons'` | | `ContainerShareIcon` | `import { ContainerShareIcon } from '@vapor-ui/icons'` | | `ContainerStopIcon` | `import { ContainerStopIcon } from '@vapor-ui/icons'` | | `ContainerToImageIcon` | `import { ContainerToImageIcon } from '@vapor-ui/icons'` | | `ControlCommonIcon` | `import { ControlCommonIcon } from '@vapor-ui/icons'` | | `CookIslandsColorIcon` | `import { CookIslandsColorIcon } from '@vapor-ui/icons'` | | `CopyIcon` | `import { CopyIcon } from '@vapor-ui/icons'` | | `CostaRicaColorIcon` | `import { CostaRicaColorIcon } from '@vapor-ui/icons'` | | `CouponIcon` | `import { CouponIcon } from '@vapor-ui/icons'` | | `CourseHistoryIcon` | `import { CourseHistoryIcon } from '@vapor-ui/icons'` | | `CourseIcon` | `import { CourseIcon } from '@vapor-ui/icons'` | | `CpuIcon` | `import { CpuIcon } from '@vapor-ui/icons'` | | `CreditCardIcon` | `import { CreditCardIcon } from '@vapor-ui/icons'` | | `CroatiaColorIcon` | `import { CroatiaColorIcon } from '@vapor-ui/icons'` | | `CubaColorIcon` | `import { CubaColorIcon } from '@vapor-ui/icons'` | | `CursorshareoffIcon` | `import { CursorshareoffIcon } from '@vapor-ui/icons'` | | `CursorshareonIcon` | `import { CursorshareonIcon } from '@vapor-ui/icons'` | | `CyprusColorIcon` | `import { CyprusColorIcon } from '@vapor-ui/icons'` | | `CzechRepublicColorIcon` | `import { CzechRepublicColorIcon } from '@vapor-ui/icons'` | | `DarkIcon` | `import { DarkIcon } from '@vapor-ui/icons'` | | `DashboardIcon` | `import { DashboardIcon } from '@vapor-ui/icons'` | | `DatabaseIcon` | `import { DatabaseIcon } from '@vapor-ui/icons'` | | `DebugContinueIcon` | `import { DebugContinueIcon } from '@vapor-ui/icons'` | | `DebugIcon` | `import { DebugIcon } from '@vapor-ui/icons'` | | `DemocraticRepublicOfTheCongoColorIcon` | `import { DemocraticRepublicOfTheCongoColorIcon } from '@vapor-ui/icons'` | | `DenmarkColorIcon` | `import { DenmarkColorIcon } from '@vapor-ui/icons'` | | `DeployPushIcon` | `import { DeployPushIcon } from '@vapor-ui/icons'` | | `DetailViewIcon` | `import { DetailViewIcon } from '@vapor-ui/icons'` | | `DiscIcon` | `import { DiscIcon } from '@vapor-ui/icons'` | | `DiscordColorIcon` | `import { DiscordColorIcon } from '@vapor-ui/icons'` | | `DiscordIcon` | `import { DiscordIcon } from '@vapor-ui/icons'` | | `DiscussionIcon` | `import { DiscussionIcon } from '@vapor-ui/icons'` | | `DiskIcon` | `import { DiskIcon } from '@vapor-ui/icons'` | | `DislikeIcon` | `import { DislikeIcon } from '@vapor-ui/icons'` | | `DislikeThumbIcon` | `import { DislikeThumbIcon } from '@vapor-ui/icons'` | | `DividerIcon` | `import { DividerIcon } from '@vapor-ui/icons'` | | `DjiboutiColorIcon` | `import { DjiboutiColorIcon } from '@vapor-ui/icons'` | | `DockerIcon` | `import { DockerIcon } from '@vapor-ui/icons'` | | `DocktoBottomIcon` | `import { DocktoBottomIcon } from '@vapor-ui/icons'` | | `DocumentViewerIcon` | `import { DocumentViewerIcon } from '@vapor-ui/icons'` | | `DominicaColorIcon` | `import { DominicaColorIcon } from '@vapor-ui/icons'` | | `DominicanRepublicColorIcon` | `import { DominicanRepublicColorIcon } from '@vapor-ui/icons'` | | `DotIcon` | `import { DotIcon } from '@vapor-ui/icons'` | | `DownloadIcon` | `import { DownloadIcon } from '@vapor-ui/icons'` | | `DragIndicatorIcon` | `import { DragIndicatorIcon } from '@vapor-ui/icons'` | | `EastTimorColorIcon` | `import { EastTimorColorIcon } from '@vapor-ui/icons'` | | `EcuadorColorIcon` | `import { EcuadorColorIcon } from '@vapor-ui/icons'` | | `EditIcon` | `import { EditIcon } from '@vapor-ui/icons'` | | `EgyptColorIcon` | `import { EgyptColorIcon } from '@vapor-ui/icons'` | | `ElSalvadorColorIcon` | `import { ElSalvadorColorIcon } from '@vapor-ui/icons'` | | `EquatorialGuineaColorIcon` | `import { EquatorialGuineaColorIcon } from '@vapor-ui/icons'` | | `EraserIcon` | `import { EraserIcon } from '@vapor-ui/icons'` | | `EritreaColorIcon` | `import { EritreaColorIcon } from '@vapor-ui/icons'` | | `ErrorCircleIcon` | `import { ErrorCircleIcon } from '@vapor-ui/icons'` | | `EstoniaColorIcon` | `import { EstoniaColorIcon } from '@vapor-ui/icons'` | | `EswatiniColorIcon` | `import { EswatiniColorIcon } from '@vapor-ui/icons'` | | `EthiopiaColorIcon` | `import { EthiopiaColorIcon } from '@vapor-ui/icons'` | | `ExamIcon` | `import { ExamIcon } from '@vapor-ui/icons'` | | `ExamListIcon` | `import { ExamListIcon } from '@vapor-ui/icons'` | | `ExamReportIcon` | `import { ExamReportIcon } from '@vapor-ui/icons'` | | `ExploreIcon` | `import { ExploreIcon } from '@vapor-ui/icons'` | | `ExportIcon` | `import { ExportIcon } from '@vapor-ui/icons'` | | `ExportImageIcon` | `import { ExportImageIcon } from '@vapor-ui/icons'` | | `FacebookColorIcon` | `import { FacebookColorIcon } from '@vapor-ui/icons'` | | `FacebookIcon` | `import { FacebookIcon } from '@vapor-ui/icons'` | | `FigmaColorIcon` | `import { FigmaColorIcon } from '@vapor-ui/icons'` | | `FigmaIcon` | `import { FigmaIcon } from '@vapor-ui/icons'` | | `FijiColorIcon` | `import { FijiColorIcon } from '@vapor-ui/icons'` | | `FileAddIcon` | `import { FileAddIcon } from '@vapor-ui/icons'` | | `FileDeleteIcon` | `import { FileDeleteIcon } from '@vapor-ui/icons'` | | `FileIcon` | `import { FileIcon } from '@vapor-ui/icons'` | | `FilenewIcon` | `import { FilenewIcon } from '@vapor-ui/icons'` | | `FilterIcon` | `import { FilterIcon } from '@vapor-ui/icons'` | | `FinlandColorIcon` | `import { FinlandColorIcon } from '@vapor-ui/icons'` | | `FirefoxColorIcon` | `import { FirefoxColorIcon } from '@vapor-ui/icons'` | | `FlagIcon` | `import { FlagIcon } from '@vapor-ui/icons'` | | `FlaskIcon` | `import { FlaskIcon } from '@vapor-ui/icons'` | | `FlightIcon` | `import { FlightIcon } from '@vapor-ui/icons'` | | `FoldIcon` | `import { FoldIcon } from '@vapor-ui/icons'` | | `FolderIcon` | `import { FolderIcon } from '@vapor-ui/icons'` | | `FolderNewIcon` | `import { FolderNewIcon } from '@vapor-ui/icons'` | | `FolderSearchIcon` | `import { FolderSearchIcon } from '@vapor-ui/icons'` | | `ForkIcon` | `import { ForkIcon } from '@vapor-ui/icons'` | | `FranceColorIcon` | `import { FranceColorIcon } from '@vapor-ui/icons'` | | `FunctionIcon` | `import { FunctionIcon } from '@vapor-ui/icons'` | | `GabonColorIcon` | `import { GabonColorIcon } from '@vapor-ui/icons'` | | `GambiaColorIcon` | `import { GambiaColorIcon } from '@vapor-ui/icons'` | | `GameIcon` | `import { GameIcon } from '@vapor-ui/icons'` | | `GcpIcon` | `import { GcpIcon } from '@vapor-ui/icons'` | | `GeorgiaColorIcon` | `import { GeorgiaColorIcon } from '@vapor-ui/icons'` | | `GermanyColorIcon` | `import { GermanyColorIcon } from '@vapor-ui/icons'` | | `GhanaColorIcon` | `import { GhanaColorIcon } from '@vapor-ui/icons'` | | `GitIcon` | `import { GitIcon } from '@vapor-ui/icons'` | | `GithubColorIcon` | `import { GithubColorIcon } from '@vapor-ui/icons'` | | `GithubIcon` | `import { GithubIcon } from '@vapor-ui/icons'` | | `GitlabIcon` | `import { GitlabIcon } from '@vapor-ui/icons'` | | `GoogleCalendarIcon` | `import { GoogleCalendarIcon } from '@vapor-ui/icons'` | | `GoogleColorIcon` | `import { GoogleColorIcon } from '@vapor-ui/icons'` | | `GoogleDrawingIcon` | `import { GoogleDrawingIcon } from '@vapor-ui/icons'` | | `GoogleIcon` | `import { GoogleIcon } from '@vapor-ui/icons'` | | `GooglePresentationIcon` | `import { GooglePresentationIcon } from '@vapor-ui/icons'` | | `GoogleSpreadsheetIcon` | `import { GoogleSpreadsheetIcon } from '@vapor-ui/icons'` | | `GoormduinoIcon` | `import { GoormduinoIcon } from '@vapor-ui/icons'` | | `GpuIcon` | `import { GpuIcon } from '@vapor-ui/icons'` | | `GreeceColorIcon` | `import { GreeceColorIcon } from '@vapor-ui/icons'` | | `GrenadaColorIcon` | `import { GrenadaColorIcon } from '@vapor-ui/icons'` | | `GroupIcon` | `import { GroupIcon } from '@vapor-ui/icons'` | | `GuatemalaColorIcon` | `import { GuatemalaColorIcon } from '@vapor-ui/icons'` | | `GuestIcon` | `import { GuestIcon } from '@vapor-ui/icons'` | | `GuineaBissauColorIcon` | `import { GuineaBissauColorIcon } from '@vapor-ui/icons'` | | `GuineaColorIcon` | `import { GuineaColorIcon } from '@vapor-ui/icons'` | | `GuyanaColorIcon` | `import { GuyanaColorIcon } from '@vapor-ui/icons'` | | `HaitiColorIcon` | `import { HaitiColorIcon } from '@vapor-ui/icons'` | | `HeartIcon` | `import { HeartIcon } from '@vapor-ui/icons'` | | `HelpCircleIcon` | `import { HelpCircleIcon } from '@vapor-ui/icons'` | | `HelpIcon` | `import { HelpIcon } from '@vapor-ui/icons'` | | `HighlightViewIcon` | `import { HighlightViewIcon } from '@vapor-ui/icons'` | | `HomeIcon` | `import { HomeIcon } from '@vapor-ui/icons'` | | `HondurasColorIcon` | `import { HondurasColorIcon } from '@vapor-ui/icons'` | | `HourglassIcon` | `import { HourglassIcon } from '@vapor-ui/icons'` | | `HungaryColorIcon` | `import { HungaryColorIcon } from '@vapor-ui/icons'` | | `IcelandColorIcon` | `import { IcelandColorIcon } from '@vapor-ui/icons'` | | `IdCardIcon` | `import { IdCardIcon } from '@vapor-ui/icons'` | | `IdeShareIcon` | `import { IdeShareIcon } from '@vapor-ui/icons'` | | `ImageIcon` | `import { ImageIcon } from '@vapor-ui/icons'` | | `ImagePackIcon` | `import { ImagePackIcon } from '@vapor-ui/icons'` | | `ImageToContainerIcon` | `import { ImageToContainerIcon } from '@vapor-ui/icons'` | | `ImportIcon` | `import { ImportIcon } from '@vapor-ui/icons'` | | `IndiaColorIcon` | `import { IndiaColorIcon } from '@vapor-ui/icons'` | | `IndonesiaColorIcon` | `import { IndonesiaColorIcon } from '@vapor-ui/icons'` | | `InfoCircleIcon` | `import { InfoCircleIcon } from '@vapor-ui/icons'` | | `InstagramColorIcon` | `import { InstagramColorIcon } from '@vapor-ui/icons'` | | `InstagramIcon` | `import { InstagramIcon } from '@vapor-ui/icons'` | | `IntelliSenseClassIcon` | `import { IntelliSenseClassIcon } from '@vapor-ui/icons'` | | `IntelliSenseColorIcon` | `import { IntelliSenseColorIcon } from '@vapor-ui/icons'` | | `IntelliSenseConstantIcon` | `import { IntelliSenseConstantIcon } from '@vapor-ui/icons'` | | `IntelliSenseEnumIcon` | `import { IntelliSenseEnumIcon } from '@vapor-ui/icons'` | | `IntelliSenseEventIcon` | `import { IntelliSenseEventIcon } from '@vapor-ui/icons'` | | `IntelliSenseFunctionIcon` | `import { IntelliSenseFunctionIcon } from '@vapor-ui/icons'` | | `IntelliSenseInterfaceIcon` | `import { IntelliSenseInterfaceIcon } from '@vapor-ui/icons'` | | `IntelliSenseModuleIcon` | `import { IntelliSenseModuleIcon } from '@vapor-ui/icons'` | | `IntelliSenseNullIcon` | `import { IntelliSenseNullIcon } from '@vapor-ui/icons'` | | `IntelliSenseOperatorIcon` | `import { IntelliSenseOperatorIcon } from '@vapor-ui/icons'` | | `IntelliSensePropertyIcon` | `import { IntelliSensePropertyIcon } from '@vapor-ui/icons'` | | `IntelliSenseSnippetIcon` | `import { IntelliSenseSnippetIcon } from '@vapor-ui/icons'` | | `IntelliSenseStructureIcon` | `import { IntelliSenseStructureIcon } from '@vapor-ui/icons'` | | `IntelliSenseTextIcon` | `import { IntelliSenseTextIcon } from '@vapor-ui/icons'` | | `IntelliSenseUnitIcon` | `import { IntelliSenseUnitIcon } from '@vapor-ui/icons'` | | `IntelliSenseValueIcon` | `import { IntelliSenseValueIcon } from '@vapor-ui/icons'` | | `IntellijColorIcon` | `import { IntellijColorIcon } from '@vapor-ui/icons'` | | `IranColorIcon` | `import { IranColorIcon } from '@vapor-ui/icons'` | | `IraqColorIcon` | `import { IraqColorIcon } from '@vapor-ui/icons'` | | `IrelandColorIcon` | `import { IrelandColorIcon } from '@vapor-ui/icons'` | | `IsraelColorIcon` | `import { IsraelColorIcon } from '@vapor-ui/icons'` | | `ItalicIcon` | `import { ItalicIcon } from '@vapor-ui/icons'` | | `ItalyColorIcon` | `import { ItalyColorIcon } from '@vapor-ui/icons'` | | `IvoryCoastColorIcon` | `import { IvoryCoastColorIcon } from '@vapor-ui/icons'` | | `JamaicaColorIcon` | `import { JamaicaColorIcon } from '@vapor-ui/icons'` | | `JapanColorIcon` | `import { JapanColorIcon } from '@vapor-ui/icons'` | | `JiraIcon` | `import { JiraIcon } from '@vapor-ui/icons'` | | `JordanColorIcon` | `import { JordanColorIcon } from '@vapor-ui/icons'` | | `JupyterColorIcon` | `import { JupyterColorIcon } from '@vapor-ui/icons'` | | `JupyterlabColorIcon` | `import { JupyterlabColorIcon } from '@vapor-ui/icons'` | | `JupyterlabIcon` | `import { JupyterlabIcon } from '@vapor-ui/icons'` | | `KakaoIcon` | `import { KakaoIcon } from '@vapor-ui/icons'` | | `KazakhstanColorIcon` | `import { KazakhstanColorIcon } from '@vapor-ui/icons'` | | `KenyaColorIcon` | `import { KenyaColorIcon } from '@vapor-ui/icons'` | | `KeyboardIcon` | `import { KeyboardIcon } from '@vapor-ui/icons'` | | `KeyboardTabIcon` | `import { KeyboardTabIcon } from '@vapor-ui/icons'` | | `KidIcon` | `import { KidIcon } from '@vapor-ui/icons'` | | `KiribatiColorIcon` | `import { KiribatiColorIcon } from '@vapor-ui/icons'` | | `KosovoColorIcon` | `import { KosovoColorIcon } from '@vapor-ui/icons'` | | `KrampolineIcon` | `import { KrampolineIcon } from '@vapor-ui/icons'` | | `KubernatesIcon` | `import { KubernatesIcon } from '@vapor-ui/icons'` | | `KuwaitColorIcon` | `import { KuwaitColorIcon } from '@vapor-ui/icons'` | | `KyrgyzstanColorIcon` | `import { KyrgyzstanColorIcon } from '@vapor-ui/icons'` | | `LaosColorIcon` | `import { LaosColorIcon } from '@vapor-ui/icons'` | | `LatviaColorIcon` | `import { LatviaColorIcon } from '@vapor-ui/icons'` | | `LebanonColorIcon` | `import { LebanonColorIcon } from '@vapor-ui/icons'` | | `LesothoColorIcon` | `import { LesothoColorIcon } from '@vapor-ui/icons'` | | `LiberiaColorIcon` | `import { LiberiaColorIcon } from '@vapor-ui/icons'` | | `LibyaColorIcon` | `import { LibyaColorIcon } from '@vapor-ui/icons'` | | `LiechtensteinColorIcon` | `import { LiechtensteinColorIcon } from '@vapor-ui/icons'` | | `LightIcon` | `import { LightIcon } from '@vapor-ui/icons'` | | `LightbulbIcon` | `import { LightbulbIcon } from '@vapor-ui/icons'` | | `LightningIcon` | `import { LightningIcon } from '@vapor-ui/icons'` | | `LikeIcon` | `import { LikeIcon } from '@vapor-ui/icons'` | | `LikeThumbIcon` | `import { LikeThumbIcon } from '@vapor-ui/icons'` | | `LinkedinIcon` | `import { LinkedinIcon } from '@vapor-ui/icons'` | | `ListIcon` | `import { ListIcon } from '@vapor-ui/icons'` | | `ListNumberedIcon` | `import { ListNumberedIcon } from '@vapor-ui/icons'` | | `LithuaniaColorIcon` | `import { LithuaniaColorIcon } from '@vapor-ui/icons'` | | `LiveLessonIcon` | `import { LiveLessonIcon } from '@vapor-ui/icons'` | | `LocationIcon` | `import { LocationIcon } from '@vapor-ui/icons'` | | `LockIcon` | `import { LockIcon } from '@vapor-ui/icons'` | | `LuxembourgColorIcon` | `import { LuxembourgColorIcon } from '@vapor-ui/icons'` | | `MadagascarColorIcon` | `import { MadagascarColorIcon } from '@vapor-ui/icons'` | | `MagicWandIcon` | `import { MagicWandIcon } from '@vapor-ui/icons'` | | `MailIcon` | `import { MailIcon } from '@vapor-ui/icons'` | | `MalawiColorIcon` | `import { MalawiColorIcon } from '@vapor-ui/icons'` | | `MalaysiaColorIcon` | `import { MalaysiaColorIcon } from '@vapor-ui/icons'` | | `MaldivesColorIcon` | `import { MaldivesColorIcon } from '@vapor-ui/icons'` | | `MaliColorIcon` | `import { MaliColorIcon } from '@vapor-ui/icons'` | | `MaltaColorIcon` | `import { MaltaColorIcon } from '@vapor-ui/icons'` | | `MarkModeIcon` | `import { MarkModeIcon } from '@vapor-ui/icons'` | | `MarkdownIcon` | `import { MarkdownIcon } from '@vapor-ui/icons'` | | `MarshallIslandsColorIcon` | `import { MarshallIslandsColorIcon } from '@vapor-ui/icons'` | | `MauritaniaColorIcon` | `import { MauritaniaColorIcon } from '@vapor-ui/icons'` | | `MauritiusColorIcon` | `import { MauritiusColorIcon } from '@vapor-ui/icons'` | | `MediumIcon` | `import { MediumIcon } from '@vapor-ui/icons'` | | `MemoIcon` | `import { MemoIcon } from '@vapor-ui/icons'` | | `MemoryIcon` | `import { MemoryIcon } from '@vapor-ui/icons'` | | `MessageIcon` | `import { MessageIcon } from '@vapor-ui/icons'` | | `MethodIcon` | `import { MethodIcon } from '@vapor-ui/icons'` | | `MexicoColorIcon` | `import { MexicoColorIcon } from '@vapor-ui/icons'` | | `MicOffIcon` | `import { MicOffIcon } from '@vapor-ui/icons'` | | `MicOnIcon` | `import { MicOnIcon } from '@vapor-ui/icons'` | | `MicronesiaColorIcon` | `import { MicronesiaColorIcon } from '@vapor-ui/icons'` | | `MinusBoxIcon` | `import { MinusBoxIcon } from '@vapor-ui/icons'` | | `MoldovaColorIcon` | `import { MoldovaColorIcon } from '@vapor-ui/icons'` | | `MonacoColorIcon` | `import { MonacoColorIcon } from '@vapor-ui/icons'` | | `MongoliaColorIcon` | `import { MongoliaColorIcon } from '@vapor-ui/icons'` | | `MontenegroColorIcon` | `import { MontenegroColorIcon } from '@vapor-ui/icons'` | | `MoroccoColorIcon` | `import { MoroccoColorIcon } from '@vapor-ui/icons'` | | `MovieIcon` | `import { MovieIcon } from '@vapor-ui/icons'` | | `MozambiqueColorIcon` | `import { MozambiqueColorIcon } from '@vapor-ui/icons'` | | `MyanmarColorIcon` | `import { MyanmarColorIcon } from '@vapor-ui/icons'` | | `MysqlColorIcon` | `import { MysqlColorIcon } from '@vapor-ui/icons'` | | `MysqlIcon` | `import { MysqlIcon } from '@vapor-ui/icons'` | | `NamibiaColorIcon` | `import { NamibiaColorIcon } from '@vapor-ui/icons'` | | `NauruColorIcon` | `import { NauruColorIcon } from '@vapor-ui/icons'` | | `NaverIcon` | `import { NaverIcon } from '@vapor-ui/icons'` | | `NaverblogColorIcon` | `import { NaverblogColorIcon } from '@vapor-ui/icons'` | | `NaverblogIcon` | `import { NaverblogIcon } from '@vapor-ui/icons'` | | `NepalColorIcon` | `import { NepalColorIcon } from '@vapor-ui/icons'` | | `NetherlandsColorIcon` | `import { NetherlandsColorIcon } from '@vapor-ui/icons'` | | `NetworkIcon` | `import { NetworkIcon } from '@vapor-ui/icons'` | | `NewZealandColorIcon` | `import { NewZealandColorIcon } from '@vapor-ui/icons'` | | `NextIcon` | `import { NextIcon } from '@vapor-ui/icons'` | | `NicaraguaColorIcon` | `import { NicaraguaColorIcon } from '@vapor-ui/icons'` | | `NigerColorIcon` | `import { NigerColorIcon } from '@vapor-ui/icons'` | | `NigeriaColorIcon` | `import { NigeriaColorIcon } from '@vapor-ui/icons'` | | `NiueColorIcon` | `import { NiueColorIcon } from '@vapor-ui/icons'` | | `NoImageIcon` | `import { NoImageIcon } from '@vapor-ui/icons'` | | `NoUserIcon` | `import { NoUserIcon } from '@vapor-ui/icons'` | | `NorthMacedoniaColorIcon` | `import { NorthMacedoniaColorIcon } from '@vapor-ui/icons'` | | `NorwayColorIcon` | `import { NorwayColorIcon } from '@vapor-ui/icons'` | | `NoticeBoardIcon` | `import { NoticeBoardIcon } from '@vapor-ui/icons'` | | `NoticeCircleIcon` | `import { NoticeCircleIcon } from '@vapor-ui/icons'` | | `NotionIcon` | `import { NotionIcon } from '@vapor-ui/icons'` | | `ObjectIcon` | `import { ObjectIcon } from '@vapor-ui/icons'` | | `OmanColorIcon` | `import { OmanColorIcon } from '@vapor-ui/icons'` | | `OpenFileIcon` | `import { OpenFileIcon } from '@vapor-ui/icons'` | | `OpenFolderIcon` | `import { OpenFolderIcon } from '@vapor-ui/icons'` | | `OperaColorIcon` | `import { OperaColorIcon } from '@vapor-ui/icons'` | | `OrganizationIcon` | `import { OrganizationIcon } from '@vapor-ui/icons'` | | `PakistanColorIcon` | `import { PakistanColorIcon } from '@vapor-ui/icons'` | | `PalauColorIcon` | `import { PalauColorIcon } from '@vapor-ui/icons'` | | `PanamaColorIcon` | `import { PanamaColorIcon } from '@vapor-ui/icons'` | | `PanelOpenIcon` | `import { PanelOpenIcon } from '@vapor-ui/icons'` | | `PapuaNewGuineaColorIcon` | `import { PapuaNewGuineaColorIcon } from '@vapor-ui/icons'` | | `ParaguayColorIcon` | `import { ParaguayColorIcon } from '@vapor-ui/icons'` | | `ParentsIcon` | `import { ParentsIcon } from '@vapor-ui/icons'` | | `PauseIcon` | `import { PauseIcon } from '@vapor-ui/icons'` | | `PaycoIcon` | `import { PaycoIcon } from '@vapor-ui/icons'` | | `PaypalColorIcon` | `import { PaypalColorIcon } from '@vapor-ui/icons'` | | `PcIcon` | `import { PcIcon } from '@vapor-ui/icons'` | | `PdfIcon` | `import { PdfIcon } from '@vapor-ui/icons'` | | `PeruColorIcon` | `import { PeruColorIcon } from '@vapor-ui/icons'` | | `PhilippinesColorIcon` | `import { PhilippinesColorIcon } from '@vapor-ui/icons'` | | `PhoneIcon` | `import { PhoneIcon } from '@vapor-ui/icons'` | | `PinSetIcon` | `import { PinSetIcon } from '@vapor-ui/icons'` | | `PipetteIcon` | `import { PipetteIcon } from '@vapor-ui/icons'` | | `PlansIcon` | `import { PlansIcon } from '@vapor-ui/icons'` | | `PlayIcon` | `import { PlayIcon } from '@vapor-ui/icons'` | | `PlugInIcon` | `import { PlugInIcon } from '@vapor-ui/icons'` | | `PlugOutIcon` | `import { PlugOutIcon } from '@vapor-ui/icons'` | | `PlusBoxIcon` | `import { PlusBoxIcon } from '@vapor-ui/icons'` | | `PolandColorIcon` | `import { PolandColorIcon } from '@vapor-ui/icons'` | | `PortforwardingIcon` | `import { PortforwardingIcon } from '@vapor-ui/icons'` | | `PortugalColorIcon` | `import { PortugalColorIcon } from '@vapor-ui/icons'` | | `PowerIcon` | `import { PowerIcon } from '@vapor-ui/icons'` | | `PreIcon` | `import { PreIcon } from '@vapor-ui/icons'` | | `PresentScreenIcon` | `import { PresentScreenIcon } from '@vapor-ui/icons'` | | `PreviewIcon` | `import { PreviewIcon } from '@vapor-ui/icons'` | | `PrintIcon` | `import { PrintIcon } from '@vapor-ui/icons'` | | `ProductHuntColorIcon` | `import { ProductHuntColorIcon } from '@vapor-ui/icons'` | | `ProgrammingIcon` | `import { ProgrammingIcon } from '@vapor-ui/icons'` | | `ProjectIcon` | `import { ProjectIcon } from '@vapor-ui/icons'` | | `ProjectOpenIcon` | `import { ProjectOpenIcon } from '@vapor-ui/icons'` | | `ProjectSettingIcon` | `import { ProjectSettingIcon } from '@vapor-ui/icons'` | | `PropertyIcon` | `import { PropertyIcon } from '@vapor-ui/icons'` | | `PsychologyIcon` | `import { PsychologyIcon } from '@vapor-ui/icons'` | | `PublishIcon` | `import { PublishIcon } from '@vapor-ui/icons'` | | `QatarColorIcon` | `import { QatarColorIcon } from '@vapor-ui/icons'` | | `QnAIcon` | `import { QnAIcon } from '@vapor-ui/icons'` | | `QuoteIcon` | `import { QuoteIcon } from '@vapor-ui/icons'` | | `ReferenceIcon` | `import { ReferenceIcon } from '@vapor-ui/icons'` | | `RemoteIcon` | `import { RemoteIcon } from '@vapor-ui/icons'` | | `RemoteOffIcon` | `import { RemoteOffIcon } from '@vapor-ui/icons'` | | `ReplaceIcon` | `import { ReplaceIcon } from '@vapor-ui/icons'` | | `RepublicOfTheCongoColorIcon` | `import { RepublicOfTheCongoColorIcon } from '@vapor-ui/icons'` | | `ResultManagementIcon` | `import { ResultManagementIcon } from '@vapor-ui/icons'` | | `RomaniaColorIcon` | `import { RomaniaColorIcon } from '@vapor-ui/icons'` | | `RouteIcon` | `import { RouteIcon } from '@vapor-ui/icons'` | | `RstudioColorIcon` | `import { RstudioColorIcon } from '@vapor-ui/icons'` | | `RunIcon` | `import { RunIcon } from '@vapor-ui/icons'` | | `RussiaColorIcon` | `import { RussiaColorIcon } from '@vapor-ui/icons'` | | `RwandaColorIcon` | `import { RwandaColorIcon } from '@vapor-ui/icons'` | | `SaintKittsAndNevisColorIcon` | `import { SaintKittsAndNevisColorIcon } from '@vapor-ui/icons'` | | `SaintLuciaColorIcon` | `import { SaintLuciaColorIcon } from '@vapor-ui/icons'` | | `SaintVincentAndTheGrenadinesColorIcon` | `import { SaintVincentAndTheGrenadinesColorIcon } from '@vapor-ui/icons'` | | `SamoaColorIcon` | `import { SamoaColorIcon } from '@vapor-ui/icons'` | | `SanMarinoColorIcon` | `import { SanMarinoColorIcon } from '@vapor-ui/icons'` | | `SaoTomeAndPrincipeColorIcon` | `import { SaoTomeAndPrincipeColorIcon } from '@vapor-ui/icons'` | | `SaudiArabiaColorIcon` | `import { SaudiArabiaColorIcon } from '@vapor-ui/icons'` | | `SaveAsIcon` | `import { SaveAsIcon } from '@vapor-ui/icons'` | | `SaveIcon` | `import { SaveIcon } from '@vapor-ui/icons'` | | `SavingIcon` | `import { SavingIcon } from '@vapor-ui/icons'` | | `SbomIcon` | `import { SbomIcon } from '@vapor-ui/icons'` | | `SchoolIcon` | `import { SchoolIcon } from '@vapor-ui/icons'` | | `SendIcon` | `import { SendIcon } from '@vapor-ui/icons'` | | `SenegalColorIcon` | `import { SenegalColorIcon } from '@vapor-ui/icons'` | | `SentryIcon` | `import { SentryIcon } from '@vapor-ui/icons'` | | `SerbiaColorIcon` | `import { SerbiaColorIcon } from '@vapor-ui/icons'` | | `SettingIcon` | `import { SettingIcon } from '@vapor-ui/icons'` | | `SeychellesColorIcon` | `import { SeychellesColorIcon } from '@vapor-ui/icons'` | | `ShareIcon` | `import { ShareIcon } from '@vapor-ui/icons'` | | `ShoppingCartIcon` | `import { ShoppingCartIcon } from '@vapor-ui/icons'` | | `SideNavIcon` | `import { SideNavIcon } from '@vapor-ui/icons'` | | `SierraLeoneColorIcon` | `import { SierraLeoneColorIcon } from '@vapor-ui/icons'` | | `SingaporeColorIcon` | `import { SingaporeColorIcon } from '@vapor-ui/icons'` | | `SlackColorIcon` | `import { SlackColorIcon } from '@vapor-ui/icons'` | | `SlackIcon` | `import { SlackIcon } from '@vapor-ui/icons'` | | `SlotIcon` | `import { SlotIcon } from '@vapor-ui/icons'` | | `SlovakiaColorIcon` | `import { SlovakiaColorIcon } from '@vapor-ui/icons'` | | `SloveniaColorIcon` | `import { SloveniaColorIcon } from '@vapor-ui/icons'` | | `SolomonIslandsColorIcon` | `import { SolomonIslandsColorIcon } from '@vapor-ui/icons'` | | `SomaliaColorIcon` | `import { SomaliaColorIcon } from '@vapor-ui/icons'` | | `SoundOffIcon` | `import { SoundOffIcon } from '@vapor-ui/icons'` | | `SoundOnIcon` | `import { SoundOnIcon } from '@vapor-ui/icons'` | | `SourcecodeIcon` | `import { SourcecodeIcon } from '@vapor-ui/icons'` | | `SouthAfricaColorIcon` | `import { SouthAfricaColorIcon } from '@vapor-ui/icons'` | | `SouthKoreaColorIcon` | `import { SouthKoreaColorIcon } from '@vapor-ui/icons'` | | `SouthSudanColorIcon` | `import { SouthSudanColorIcon } from '@vapor-ui/icons'` | | `SpainColorIcon` | `import { SpainColorIcon } from '@vapor-ui/icons'` | | `SplitIcon` | `import { SplitIcon } from '@vapor-ui/icons'` | | `SriLankaColorIcon` | `import { SriLankaColorIcon } from '@vapor-ui/icons'` | | `SshIcon` | `import { SshIcon } from '@vapor-ui/icons'` | | `StarIcon` | `import { StarIcon } from '@vapor-ui/icons'` | | `StopIcon` | `import { StopIcon } from '@vapor-ui/icons'` | | `StorageIcon` | `import { StorageIcon } from '@vapor-ui/icons'` | | `StorybookColorIcon` | `import { StorybookColorIcon } from '@vapor-ui/icons'` | | `StorybookIcon` | `import { StorybookIcon } from '@vapor-ui/icons'` | | `StripeColorIcon` | `import { StripeColorIcon } from '@vapor-ui/icons'` | | `StripeIcon` | `import { StripeIcon } from '@vapor-ui/icons'` | | `StruckIcon` | `import { StruckIcon } from '@vapor-ui/icons'` | | `StudentManagementIcon` | `import { StudentManagementIcon } from '@vapor-ui/icons'` | | `SudanColorIcon` | `import { SudanColorIcon } from '@vapor-ui/icons'` | | `SurinameColorIcon` | `import { SurinameColorIcon } from '@vapor-ui/icons'` | | `SwedenColorIcon` | `import { SwedenColorIcon } from '@vapor-ui/icons'` | | `SwitzerlandColorIcon` | `import { SwitzerlandColorIcon } from '@vapor-ui/icons'` | | `SyllabusIcon` | `import { SyllabusIcon } from '@vapor-ui/icons'` | | `SyriaColorIcon` | `import { SyriaColorIcon } from '@vapor-ui/icons'` | | `TabletIcon` | `import { TabletIcon } from '@vapor-ui/icons'` | | `TaegukColorIcon` | `import { TaegukColorIcon } from '@vapor-ui/icons'` | | `TaegukIcon` | `import { TaegukIcon } from '@vapor-ui/icons'` | | `TajikistanColorIcon` | `import { TajikistanColorIcon } from '@vapor-ui/icons'` | | `TakeoffIcon` | `import { TakeoffIcon } from '@vapor-ui/icons'` | | `TanzaniaColorIcon` | `import { TanzaniaColorIcon } from '@vapor-ui/icons'` | | `TestIcon` | `import { TestIcon } from '@vapor-ui/icons'` | | `ThailandColorIcon` | `import { ThailandColorIcon } from '@vapor-ui/icons'` | | `TimeIcon` | `import { TimeIcon } from '@vapor-ui/icons'` | | `TogoColorIcon` | `import { TogoColorIcon } from '@vapor-ui/icons'` | | `TongaColorIcon` | `import { TongaColorIcon } from '@vapor-ui/icons'` | | `TrashIcon` | `import { TrashIcon } from '@vapor-ui/icons'` | | `TreeCollapseIcon` | `import { TreeCollapseIcon } from '@vapor-ui/icons'` | | `TrelloIcon` | `import { TrelloIcon } from '@vapor-ui/icons'` | | `TrinidadAndTobagoColorIcon` | `import { TrinidadAndTobagoColorIcon } from '@vapor-ui/icons'` | | `TunisiaColorIcon` | `import { TunisiaColorIcon } from '@vapor-ui/icons'` | | `TurkeyColorIcon` | `import { TurkeyColorIcon } from '@vapor-ui/icons'` | | `TurkmenistanColorIcon` | `import { TurkmenistanColorIcon } from '@vapor-ui/icons'` | | `TuvaluColorIcon` | `import { TuvaluColorIcon } from '@vapor-ui/icons'` | | `TwoFileIcon` | `import { TwoFileIcon } from '@vapor-ui/icons'` | | `UgandaColorIcon` | `import { UgandaColorIcon } from '@vapor-ui/icons'` | | `UkraineColorIcon` | `import { UkraineColorIcon } from '@vapor-ui/icons'` | | `UnitedArabEmiratesColorIcon` | `import { UnitedArabEmiratesColorIcon } from '@vapor-ui/icons'` | | `UnitedKingdomColorIcon` | `import { UnitedKingdomColorIcon } from '@vapor-ui/icons'` | | `UnitedStatesColorIcon` | `import { UnitedStatesColorIcon } from '@vapor-ui/icons'` | | `UnlockIcon` | `import { UnlockIcon } from '@vapor-ui/icons'` | | `UploadIcon` | `import { UploadIcon } from '@vapor-ui/icons'` | | `UppercaseIcon` | `import { UppercaseIcon } from '@vapor-ui/icons'` | | `UruguayColorIcon` | `import { UruguayColorIcon } from '@vapor-ui/icons'` | | `UserCheckIcon` | `import { UserCheckIcon } from '@vapor-ui/icons'` | | `UserIcon` | `import { UserIcon } from '@vapor-ui/icons'` | | `UserMoveIcon` | `import { UserMoveIcon } from '@vapor-ui/icons'` | | `UserSearchIcon` | `import { UserSearchIcon } from '@vapor-ui/icons'` | | `UzbekistanColorIcon` | `import { UzbekistanColorIcon } from '@vapor-ui/icons'` | | `VanuatuColorIcon` | `import { VanuatuColorIcon } from '@vapor-ui/icons'` | | `VariableIcon` | `import { VariableIcon } from '@vapor-ui/icons'` | | `VaticanCityColorIcon` | `import { VaticanCityColorIcon } from '@vapor-ui/icons'` | | `VenezuelaColorIcon` | `import { VenezuelaColorIcon } from '@vapor-ui/icons'` | | `VideocamOffIcon` | `import { VideocamOffIcon } from '@vapor-ui/icons'` | | `VideocamOnIcon` | `import { VideocamOnIcon } from '@vapor-ui/icons'` | | `VietnamColorIcon` | `import { VietnamColorIcon } from '@vapor-ui/icons'` | | `ViewModuleIcon` | `import { ViewModuleIcon } from '@vapor-ui/icons'` | | `ViewOffIcon` | `import { ViewOffIcon } from '@vapor-ui/icons'` | | `ViewOnIcon` | `import { ViewOnIcon } from '@vapor-ui/icons'` | | `VscodeColorIcon` | `import { VscodeColorIcon } from '@vapor-ui/icons'` | | `VscodeIcon` | `import { VscodeIcon } from '@vapor-ui/icons'` | | `WarningIcon` | `import { WarningIcon } from '@vapor-ui/icons'` | | `WordMatchIcon` | `import { WordMatchIcon } from '@vapor-ui/icons'` | | `XIcon` | `import { XIcon } from '@vapor-ui/icons'` | | `YemenColorIcon` | `import { YemenColorIcon } from '@vapor-ui/icons'` | | `YoutubeColorIcon` | `import { YoutubeColorIcon } from '@vapor-ui/icons'` | | `YoutubeIcon` | `import { YoutubeIcon } from '@vapor-ui/icons'` | | `ZambiaColorIcon` | `import { ZambiaColorIcon } from '@vapor-ui/icons'` | | `ZimbabweColorIcon` | `import { ZimbabweColorIcon } from '@vapor-ui/icons'` | ## Outline Icons | Icon Name | Import Statement | | -------------------------------------- | ------------------------------------------------------------------------ | | `AccessibilityOutlineIcon` | `import { AccessibilityOutlineIcon } from '@vapor-ui/icons'` | | `AchievementOutlineIcon` | `import { AchievementOutlineIcon } from '@vapor-ui/icons'` | | `AddCartOutlineIcon` | `import { AddCartOutlineIcon } from '@vapor-ui/icons'` | | `AddUserOutlineIcon` | `import { AddUserOutlineIcon } from '@vapor-ui/icons'` | | `AiGoormeeOutlineIcon` | `import { AiGoormeeOutlineIcon } from '@vapor-ui/icons'` | | `AiSmartieOutlineIcon` | `import { AiSmartieOutlineIcon } from '@vapor-ui/icons'` | | `AichatOutlineIcon` | `import { AichatOutlineIcon } from '@vapor-ui/icons'` | | `AirplayOutlineIcon` | `import { AirplayOutlineIcon } from '@vapor-ui/icons'` | | `AlgorithmOutlineIcon` | `import { AlgorithmOutlineIcon } from '@vapor-ui/icons'` | | `AlignCenterOutlineIcon` | `import { AlignCenterOutlineIcon } from '@vapor-ui/icons'` | | `AlignJustifyOutlineIcon` | `import { AlignJustifyOutlineIcon } from '@vapor-ui/icons'` | | `AlignLeftOutlineIcon` | `import { AlignLeftOutlineIcon } from '@vapor-ui/icons'` | | `AlignRightOutlineIcon` | `import { AlignRightOutlineIcon } from '@vapor-ui/icons'` | | `AnalysisOutlineIcon` | `import { AnalysisOutlineIcon } from '@vapor-ui/icons'` | | `ArrowDownOutlineIcon` | `import { ArrowDownOutlineIcon } from '@vapor-ui/icons'` | | `ArrowUpOutlineIcon` | `import { ArrowUpOutlineIcon } from '@vapor-ui/icons'` | | `AssignmentOutlineIcon` | `import { AssignmentOutlineIcon } from '@vapor-ui/icons'` | | `AttachFileOutlineIcon` | `import { AttachFileOutlineIcon } from '@vapor-ui/icons'` | | `AttemptOutlineIcon` | `import { AttemptOutlineIcon } from '@vapor-ui/icons'` | | `AutoCodeOutlineIcon` | `import { AutoCodeOutlineIcon } from '@vapor-ui/icons'` | | `BackPageOutlineIcon` | `import { BackPageOutlineIcon } from '@vapor-ui/icons'` | | `BackUpOutlineIcon` | `import { BackUpOutlineIcon } from '@vapor-ui/icons'` | | `BedOutlineIcon` | `import { BedOutlineIcon } from '@vapor-ui/icons'` | | `BellOffOutlineIcon` | `import { BellOffOutlineIcon } from '@vapor-ui/icons'` | | `BellOnOutlineIcon` | `import { BellOnOutlineIcon } from '@vapor-ui/icons'` | | `BlankOutlineIcon` | `import { BlankOutlineIcon } from '@vapor-ui/icons'` | | `BlockOutlineIcon` | `import { BlockOutlineIcon } from '@vapor-ui/icons'` | | `BoldOutlineIcon` | `import { BoldOutlineIcon } from '@vapor-ui/icons'` | | `BookOutlineIcon` | `import { BookOutlineIcon } from '@vapor-ui/icons'` | | `BookmarkOutlineIcon` | `import { BookmarkOutlineIcon } from '@vapor-ui/icons'` | | `BottomPlayerOutlineIcon` | `import { BottomPlayerOutlineIcon } from '@vapor-ui/icons'` | | `BranchOutlineIcon` | `import { BranchOutlineIcon } from '@vapor-ui/icons'` | | `BuildOutlineIcon` | `import { BuildOutlineIcon } from '@vapor-ui/icons'` | | `BulletlistOutlineIcon` | `import { BulletlistOutlineIcon } from '@vapor-ui/icons'` | | `CafeOutlineIcon` | `import { CafeOutlineIcon } from '@vapor-ui/icons'` | | `CakeOutlineIcon` | `import { CakeOutlineIcon } from '@vapor-ui/icons'` | | `CalculatorOutlineIcon` | `import { CalculatorOutlineIcon } from '@vapor-ui/icons'` | | `CalendarOutlineIcon` | `import { CalendarOutlineIcon } from '@vapor-ui/icons'` | | `CallOutlineIcon` | `import { CallOutlineIcon } from '@vapor-ui/icons'` | | `CameraOutlineIcon` | `import { CameraOutlineIcon } from '@vapor-ui/icons'` | | `CampOutlineIcon` | `import { CampOutlineIcon } from '@vapor-ui/icons'` | | `CaptionOutlineIcon` | `import { CaptionOutlineIcon } from '@vapor-ui/icons'` | | `CarOutlineIcon` | `import { CarOutlineIcon } from '@vapor-ui/icons'` | | `CardsOutlineIcon` | `import { CardsOutlineIcon } from '@vapor-ui/icons'` | | `CertificateOutlineIcon` | `import { CertificateOutlineIcon } from '@vapor-ui/icons'` | | `ChapterOutlineIcon` | `import { ChapterOutlineIcon } from '@vapor-ui/icons'` | | `ChartOutlineIcon` | `import { ChartOutlineIcon } from '@vapor-ui/icons'` | | `ChartPieOutlineIcon` | `import { ChartPieOutlineIcon } from '@vapor-ui/icons'` | | `CheckCartOutlineIcon` | `import { CheckCartOutlineIcon } from '@vapor-ui/icons'` | | `CheckCircleOutlineIcon` | `import { CheckCircleOutlineIcon } from '@vapor-ui/icons'` | | `ChecklistOutlineIcon` | `import { ChecklistOutlineIcon } from '@vapor-ui/icons'` | | `ChevronDoubleLeftOutlineIcon` | `import { ChevronDoubleLeftOutlineIcon } from '@vapor-ui/icons'` | | `ChevronDoubleRightOutlineIcon` | `import { ChevronDoubleRightOutlineIcon } from '@vapor-ui/icons'` | | `ChevronDownOutlineIcon` | `import { ChevronDownOutlineIcon } from '@vapor-ui/icons'` | | `ChevronLeftOutlineIcon` | `import { ChevronLeftOutlineIcon } from '@vapor-ui/icons'` | | `ChevronRightOutlineIcon` | `import { ChevronRightOutlineIcon } from '@vapor-ui/icons'` | | `ChevronUpOutlineIcon` | `import { ChevronUpOutlineIcon } from '@vapor-ui/icons'` | | `CloseOutlineIcon` | `import { CloseOutlineIcon } from '@vapor-ui/icons'` | | `CodeBlockOutlineIcon` | `import { CodeBlockOutlineIcon } from '@vapor-ui/icons'` | | `CollaborationOutlineIcon` | `import { CollaborationOutlineIcon } from '@vapor-ui/icons'` | | `CollapseOutlineIcon` | `import { CollapseOutlineIcon } from '@vapor-ui/icons'` | | `CommitOutlineIcon` | `import { CommitOutlineIcon } from '@vapor-ui/icons'` | | `ConfirmOutlineIcon` | `import { ConfirmOutlineIcon } from '@vapor-ui/icons'` | | `ContainerOutlineIcon` | `import { ContainerOutlineIcon } from '@vapor-ui/icons'` | | `ContainerRunOutlineIcon` | `import { ContainerRunOutlineIcon } from '@vapor-ui/icons'` | | `ContainerShareOutlineIcon` | `import { ContainerShareOutlineIcon } from '@vapor-ui/icons'` | | `ContainerStopOutlineIcon` | `import { ContainerStopOutlineIcon } from '@vapor-ui/icons'` | | `ControlCommonOutlineIcon` | `import { ControlCommonOutlineIcon } from '@vapor-ui/icons'` | | `CopyAsMarkdownOutlineIcon` | `import { CopyAsMarkdownOutlineIcon } from '@vapor-ui/icons'` | | `CopyOutlineIcon` | `import { CopyOutlineIcon } from '@vapor-ui/icons'` | | `CorrectOutlineIcon` | `import { CorrectOutlineIcon } from '@vapor-ui/icons'` | | `CouponOutlineIcon` | `import { CouponOutlineIcon } from '@vapor-ui/icons'` | | `CourseOutlineIcon` | `import { CourseOutlineIcon } from '@vapor-ui/icons'` | | `CpuOutlineIcon` | `import { CpuOutlineIcon } from '@vapor-ui/icons'` | | `CreateBranchOutlineIcon` | `import { CreateBranchOutlineIcon } from '@vapor-ui/icons'` | | `CreditCardOutlineIcon` | `import { CreditCardOutlineIcon } from '@vapor-ui/icons'` | | `DarkOutlineIcon` | `import { DarkOutlineIcon } from '@vapor-ui/icons'` | | `DashboardOutlineIcon` | `import { DashboardOutlineIcon } from '@vapor-ui/icons'` | | `DatabaseOutlineIcon` | `import { DatabaseOutlineIcon } from '@vapor-ui/icons'` | | `DebugOutlineIcon` | `import { DebugOutlineIcon } from '@vapor-ui/icons'` | | `DeployOutlineIcon` | `import { DeployOutlineIcon } from '@vapor-ui/icons'` | | `DeployPushOutlineIcon` | `import { DeployPushOutlineIcon } from '@vapor-ui/icons'` | | `DetailViewOutlineIcon` | `import { DetailViewOutlineIcon } from '@vapor-ui/icons'` | | `DiscOutlineIcon` | `import { DiscOutlineIcon } from '@vapor-ui/icons'` | | `DiscardOutlineIcon` | `import { DiscardOutlineIcon } from '@vapor-ui/icons'` | | `DiscussionOutlineIcon` | `import { DiscussionOutlineIcon } from '@vapor-ui/icons'` | | `DislikeOutlineIcon` | `import { DislikeOutlineIcon } from '@vapor-ui/icons'` | | `DislikeThumbOutlineIcon` | `import { DislikeThumbOutlineIcon } from '@vapor-ui/icons'` | | `DividerOutlineIcon` | `import { DividerOutlineIcon } from '@vapor-ui/icons'` | | `DocktoBottomOutlineIcon` | `import { DocktoBottomOutlineIcon } from '@vapor-ui/icons'` | | `DocumentViewerOutlineIcon` | `import { DocumentViewerOutlineIcon } from '@vapor-ui/icons'` | | `DollarOutlineIcon` | `import { DollarOutlineIcon } from '@vapor-ui/icons'` | | `DownloadOutlineIcon` | `import { DownloadOutlineIcon } from '@vapor-ui/icons'` | | `EditOutlineIcon` | `import { EditOutlineIcon } from '@vapor-ui/icons'` | | `EnterOutlineIcon` | `import { EnterOutlineIcon } from '@vapor-ui/icons'` | | `EqualOutlineIcon` | `import { EqualOutlineIcon } from '@vapor-ui/icons'` | | `EraserOutlineIcon` | `import { EraserOutlineIcon } from '@vapor-ui/icons'` | | `ErrorCircleOutlineIcon` | `import { ErrorCircleOutlineIcon } from '@vapor-ui/icons'` | | `ExamListOutlineIcon` | `import { ExamListOutlineIcon } from '@vapor-ui/icons'` | | `ExamOutlineIcon` | `import { ExamOutlineIcon } from '@vapor-ui/icons'` | | `ExamReportOutlineIcon` | `import { ExamReportOutlineIcon } from '@vapor-ui/icons'` | | `ExpandOutlineIcon` | `import { ExpandOutlineIcon } from '@vapor-ui/icons'` | | `ExploreOutlineIcon` | `import { ExploreOutlineIcon } from '@vapor-ui/icons'` | | `ExportOutlineIcon` | `import { ExportOutlineIcon } from '@vapor-ui/icons'` | | `FileAddOutlineIcon` | `import { FileAddOutlineIcon } from '@vapor-ui/icons'` | | `FileDeleteOutlineIcon` | `import { FileDeleteOutlineIcon } from '@vapor-ui/icons'` | | `FileEditOutlineIcon` | `import { FileEditOutlineIcon } from '@vapor-ui/icons'` | | `FileNewOutlineIcon` | `import { FileNewOutlineIcon } from '@vapor-ui/icons'` | | `FileOutlineIcon` | `import { FileOutlineIcon } from '@vapor-ui/icons'` | | `FilterOutlineIcon` | `import { FilterOutlineIcon } from '@vapor-ui/icons'` | | `FlagOutlineIcon` | `import { FlagOutlineIcon } from '@vapor-ui/icons'` | | `FoldOutlineIcon` | `import { FoldOutlineIcon } from '@vapor-ui/icons'` | | `FolderNewOutlineIcon` | `import { FolderNewOutlineIcon } from '@vapor-ui/icons'` | | `FolderOutlineIcon` | `import { FolderOutlineIcon } from '@vapor-ui/icons'` | | `FolderSearchOutlineIcon` | `import { FolderSearchOutlineIcon } from '@vapor-ui/icons'` | | `ForkOutlineIcon` | `import { ForkOutlineIcon } from '@vapor-ui/icons'` | | `FormatColorTextOutlineIcon` | `import { FormatColorTextOutlineIcon } from '@vapor-ui/icons'` | | `ForwardPageOutlineIcon` | `import { ForwardPageOutlineIcon } from '@vapor-ui/icons'` | | `FunctionOutlineIcon` | `import { FunctionOutlineIcon } from '@vapor-ui/icons'` | | `FunctionsOutlineIcon` | `import { FunctionsOutlineIcon } from '@vapor-ui/icons'` | | `GameOutlineIcon` | `import { GameOutlineIcon } from '@vapor-ui/icons'` | | `GiftOutlineIcon` | `import { GiftOutlineIcon } from '@vapor-ui/icons'` | | `GitMergeOutlineIcon` | `import { GitMergeOutlineIcon } from '@vapor-ui/icons'` | | `GlobalOutlineIcon` | `import { GlobalOutlineIcon } from '@vapor-ui/icons'` | | `GoogleDrawingOutlineIcon` | `import { GoogleDrawingOutlineIcon } from '@vapor-ui/icons'` | | `GooglePresentationOutlineIcon` | `import { GooglePresentationOutlineIcon } from '@vapor-ui/icons'` | | `GoogleSpreadsheetOutlineIcon` | `import { GoogleSpreadsheetOutlineIcon } from '@vapor-ui/icons'` | | `GroupOutlineIcon` | `import { GroupOutlineIcon } from '@vapor-ui/icons'` | | `HardBreakOutlineIcon` | `import { HardBreakOutlineIcon } from '@vapor-ui/icons'` | | `Heading1OutlineIcon` | `import { Heading1OutlineIcon } from '@vapor-ui/icons'` | | `Heading2OutlineIcon` | `import { Heading2OutlineIcon } from '@vapor-ui/icons'` | | `Heading3OutlineIcon` | `import { Heading3OutlineIcon } from '@vapor-ui/icons'` | | `Heading4OutlineIcon` | `import { Heading4OutlineIcon } from '@vapor-ui/icons'` | | `HeartOutlineIcon` | `import { HeartOutlineIcon } from '@vapor-ui/icons'` | | `HelpCircleOutlineIcon` | `import { HelpCircleOutlineIcon } from '@vapor-ui/icons'` | | `HighlightViewOutlineIcon` | `import { HighlightViewOutlineIcon } from '@vapor-ui/icons'` | | `HistoryOutlineIcon` | `import { HistoryOutlineIcon } from '@vapor-ui/icons'` | | `HomeOutlineIcon` | `import { HomeOutlineIcon } from '@vapor-ui/icons'` | | `IdCardOutlineIcon` | `import { IdCardOutlineIcon } from '@vapor-ui/icons'` | | `ImageOutlineIcon` | `import { ImageOutlineIcon } from '@vapor-ui/icons'` | | `ImagePackOutlineIcon` | `import { ImagePackOutlineIcon } from '@vapor-ui/icons'` | | `ImageToContainerOutlineIcon` | `import { ImageToContainerOutlineIcon } from '@vapor-ui/icons'` | | `ImportOutlineIcon` | `import { ImportOutlineIcon } from '@vapor-ui/icons'` | | `InOutlineIcon` | `import { InOutlineIcon } from '@vapor-ui/icons'` | | `IndentDecreaseOutlineIcon` | `import { IndentDecreaseOutlineIcon } from '@vapor-ui/icons'` | | `IndentIncreaseOutlineIcon` | `import { IndentIncreaseOutlineIcon } from '@vapor-ui/icons'` | | `InfiniteOutlineIcon` | `import { InfiniteOutlineIcon } from '@vapor-ui/icons'` | | `InfoCircleOutlineIcon` | `import { InfoCircleOutlineIcon } from '@vapor-ui/icons'` | | `InputSettingOutlineIcon` | `import { InputSettingOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseEnumOutlineIcon` | `import { IntelliSenseEnumOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseEventOutlineIcon` | `import { IntelliSenseEventOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseFieldOutlineIcon` | `import { IntelliSenseFieldOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseModuleOutlineIcon` | `import { IntelliSenseModuleOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSensePropertyOutlineIcon` | `import { IntelliSensePropertyOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseReferenceOutlineIcon` | `import { IntelliSenseReferenceOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseSnippetOutlineIcon` | `import { IntelliSenseSnippetOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseTypeParameterOutlineIcon` | `import { IntelliSenseTypeParameterOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseUnitOutlineIcon` | `import { IntelliSenseUnitOutlineIcon } from '@vapor-ui/icons'` | | `IntelliSenseVariableOutlineIcon` | `import { IntelliSenseVariableOutlineIcon } from '@vapor-ui/icons'` | | `KeyboardOutlineIcon` | `import { KeyboardOutlineIcon } from '@vapor-ui/icons'` | | `KidOutlineIcon` | `import { KidOutlineIcon } from '@vapor-ui/icons'` | | `LightOutlineIcon` | `import { LightOutlineIcon } from '@vapor-ui/icons'` | | `LightbulbOutlineIcon` | `import { LightbulbOutlineIcon } from '@vapor-ui/icons'` | | `LightningOutlineIcon` | `import { LightningOutlineIcon } from '@vapor-ui/icons'` | | `LikeOutlineIcon` | `import { LikeOutlineIcon } from '@vapor-ui/icons'` | | `LikeThumbOutlineIcon` | `import { LikeThumbOutlineIcon } from '@vapor-ui/icons'` | | `LineSpacingOutlineIcon` | `import { LineSpacingOutlineIcon } from '@vapor-ui/icons'` | | `LineStyleOutlineIcon` | `import { LineStyleOutlineIcon } from '@vapor-ui/icons'` | | `LinearScaleOutlineIcon` | `import { LinearScaleOutlineIcon } from '@vapor-ui/icons'` | | `LinkOffOutlineIcon` | `import { LinkOffOutlineIcon } from '@vapor-ui/icons'` | | `LinkOutlineIcon` | `import { LinkOutlineIcon } from '@vapor-ui/icons'` | | `LiveLessonOutlineIcon` | `import { LiveLessonOutlineIcon } from '@vapor-ui/icons'` | | `LocationOutlineIcon` | `import { LocationOutlineIcon } from '@vapor-ui/icons'` | | `LockOutlineIcon` | `import { LockOutlineIcon } from '@vapor-ui/icons'` | | `LongTextOutlineIcon` | `import { LongTextOutlineIcon } from '@vapor-ui/icons'` | | `MagicWandOutlineIcon` | `import { MagicWandOutlineIcon } from '@vapor-ui/icons'` | | `MailOutlineIcon` | `import { MailOutlineIcon } from '@vapor-ui/icons'` | | `ManagementOutlineIcon` | `import { ManagementOutlineIcon } from '@vapor-ui/icons'` | | `MarkModeOutlineIcon` | `import { MarkModeOutlineIcon } from '@vapor-ui/icons'` | | `MarkdownOutlineIcon` | `import { MarkdownOutlineIcon } from '@vapor-ui/icons'` | | `MemoOutlineIcon` | `import { MemoOutlineIcon } from '@vapor-ui/icons'` | | `MenuOutlineIcon` | `import { MenuOutlineIcon } from '@vapor-ui/icons'` | | `MergeUpOutlineIcon` | `import { MergeUpOutlineIcon } from '@vapor-ui/icons'` | | `MessageOutlineIcon` | `import { MessageOutlineIcon } from '@vapor-ui/icons'` | | `MethodOutlineIcon` | `import { MethodOutlineIcon } from '@vapor-ui/icons'` | | `MicOffOutlineIcon` | `import { MicOffOutlineIcon } from '@vapor-ui/icons'` | | `MicOnOutlineIcon` | `import { MicOnOutlineIcon } from '@vapor-ui/icons'` | | `MinusBoxOutlineIcon` | `import { MinusBoxOutlineIcon } from '@vapor-ui/icons'` | | `MinusOutlineIcon` | `import { MinusOutlineIcon } from '@vapor-ui/icons'` | | `MoreCommonOutlineIcon` | `import { MoreCommonOutlineIcon } from '@vapor-ui/icons'` | | `MovieOutlineIcon` | `import { MovieOutlineIcon } from '@vapor-ui/icons'` | | `NetfficeOutlineIcon` | `import { NetfficeOutlineIcon } from '@vapor-ui/icons'` | | `NetworkOutlineIcon` | `import { NetworkOutlineIcon } from '@vapor-ui/icons'` | | `NextOutlineIcon` | `import { NextOutlineIcon } from '@vapor-ui/icons'` | | `NoImageOutlineIcon` | `import { NoImageOutlineIcon } from '@vapor-ui/icons'` | | `NoUserOutlineIcon` | `import { NoUserOutlineIcon } from '@vapor-ui/icons'` | | `NoticeBoardOutlineIcon` | `import { NoticeBoardOutlineIcon } from '@vapor-ui/icons'` | | `NoticeCircleOutlineIcon` | `import { NoticeCircleOutlineIcon } from '@vapor-ui/icons'` | | `NumberlistOutlineIcon` | `import { NumberlistOutlineIcon } from '@vapor-ui/icons'` | | `OpenFileOutlineIcon` | `import { OpenFileOutlineIcon } from '@vapor-ui/icons'` | | `OpenFolderOutlineIcon` | `import { OpenFolderOutlineIcon } from '@vapor-ui/icons'` | | `OpenInNewOutlineIcon` | `import { OpenInNewOutlineIcon } from '@vapor-ui/icons'` | | `OutOutlineIcon` | `import { OutOutlineIcon } from '@vapor-ui/icons'` | | `PandasOutlineIcon` | `import { PandasOutlineIcon } from '@vapor-ui/icons'` | | `PanelOpenOutlineIcon` | `import { PanelOpenOutlineIcon } from '@vapor-ui/icons'` | | `PauseOutlineIcon` | `import { PauseOutlineIcon } from '@vapor-ui/icons'` | | `PcOutlineIcon` | `import { PcOutlineIcon } from '@vapor-ui/icons'` | | `PdfOutlineIcon` | `import { PdfOutlineIcon } from '@vapor-ui/icons'` | | `PhoneOutlineIcon` | `import { PhoneOutlineIcon } from '@vapor-ui/icons'` | | `PinSetOutlineIcon` | `import { PinSetOutlineIcon } from '@vapor-ui/icons'` | | `PlansOutlineIcon` | `import { PlansOutlineIcon } from '@vapor-ui/icons'` | | `PlayOutlineIcon` | `import { PlayOutlineIcon } from '@vapor-ui/icons'` | | `PlaylistOutlineIcon` | `import { PlaylistOutlineIcon } from '@vapor-ui/icons'` | | `PlusBoxOutlineIcon` | `import { PlusBoxOutlineIcon } from '@vapor-ui/icons'` | | `PlusOutlineIcon` | `import { PlusOutlineIcon } from '@vapor-ui/icons'` | | `PortforwardingOutlineIcon` | `import { PortforwardingOutlineIcon } from '@vapor-ui/icons'` | | `PreOutlineIcon` | `import { PreOutlineIcon } from '@vapor-ui/icons'` | | `PresentScreenOutlineIcon` | `import { PresentScreenOutlineIcon } from '@vapor-ui/icons'` | | `PresetOutlineIcon` | `import { PresetOutlineIcon } from '@vapor-ui/icons'` | | `PreviewOutlineIcon` | `import { PreviewOutlineIcon } from '@vapor-ui/icons'` | | `PriceOutlineIcon` | `import { PriceOutlineIcon } from '@vapor-ui/icons'` | | `PrintOutlineIcon` | `import { PrintOutlineIcon } from '@vapor-ui/icons'` | | `ProgrammingOutlineIcon` | `import { ProgrammingOutlineIcon } from '@vapor-ui/icons'` | | `ProjectOutlineIcon` | `import { ProjectOutlineIcon } from '@vapor-ui/icons'` | | `ProjectSettingOutlineIcon` | `import { ProjectSettingOutlineIcon } from '@vapor-ui/icons'` | | `PsychologyOutlineIcon` | `import { PsychologyOutlineIcon } from '@vapor-ui/icons'` | | `PublishOutlineIcon` | `import { PublishOutlineIcon } from '@vapor-ui/icons'` | | `PullOutlineIcon` | `import { PullOutlineIcon } from '@vapor-ui/icons'` | | `QnAOutlineIcon` | `import { QnAOutlineIcon } from '@vapor-ui/icons'` | | `QrcodeOutlineIcon` | `import { QrcodeOutlineIcon } from '@vapor-ui/icons'` | | `QuoteOutlineIcon` | `import { QuoteOutlineIcon } from '@vapor-ui/icons'` | | `ReferenceOutlineIcon` | `import { ReferenceOutlineIcon } from '@vapor-ui/icons'` | | `RefreshOutlineIcon` | `import { RefreshOutlineIcon } from '@vapor-ui/icons'` | | `RegexOutlineIcon` | `import { RegexOutlineIcon } from '@vapor-ui/icons'` | | `ReloadOutlineIcon` | `import { ReloadOutlineIcon } from '@vapor-ui/icons'` | | `RemoteOffOutlineIcon` | `import { RemoteOffOutlineIcon } from '@vapor-ui/icons'` | | `RemoteOutlineIcon` | `import { RemoteOutlineIcon } from '@vapor-ui/icons'` | | `ReplyOutlineIcon` | `import { ReplyOutlineIcon } from '@vapor-ui/icons'` | | `RestaurantOutlineIcon` | `import { RestaurantOutlineIcon } from '@vapor-ui/icons'` | | `ResultManagementOutlineIcon` | `import { ResultManagementOutlineIcon } from '@vapor-ui/icons'` | | `RouteOutlineIcon` | `import { RouteOutlineIcon } from '@vapor-ui/icons'` | | `RunOutlineIcon` | `import { RunOutlineIcon } from '@vapor-ui/icons'` | | `SaveAsOutlineIcon` | `import { SaveAsOutlineIcon } from '@vapor-ui/icons'` | | `SaveOutlineIcon` | `import { SaveOutlineIcon } from '@vapor-ui/icons'` | | `SavingOutlineIcon` | `import { SavingOutlineIcon } from '@vapor-ui/icons'` | | `SchoolOutlineIcon` | `import { SchoolOutlineIcon } from '@vapor-ui/icons'` | | `SearchOutlineIcon` | `import { SearchOutlineIcon } from '@vapor-ui/icons'` | | `SendOutlineIcon` | `import { SendOutlineIcon } from '@vapor-ui/icons'` | | `SettingOutlineIcon` | `import { SettingOutlineIcon } from '@vapor-ui/icons'` | | `ShareOutlineIcon` | `import { ShareOutlineIcon } from '@vapor-ui/icons'` | | `ShoppingCartOutlineIcon` | `import { ShoppingCartOutlineIcon } from '@vapor-ui/icons'` | | `ShortTextOutlineIcon` | `import { ShortTextOutlineIcon } from '@vapor-ui/icons'` | | `ShortcutOutlineIcon` | `import { ShortcutOutlineIcon } from '@vapor-ui/icons'` | | `SideNavOutlineIcon` | `import { SideNavOutlineIcon } from '@vapor-ui/icons'` | | `SignalPowerOutlineIcon` | `import { SignalPowerOutlineIcon } from '@vapor-ui/icons'` | | `SlashOutlineIcon` | `import { SlashOutlineIcon } from '@vapor-ui/icons'` | | `SoundOffOutlineIcon` | `import { SoundOffOutlineIcon } from '@vapor-ui/icons'` | | `SoundOnOutlineIcon` | `import { SoundOnOutlineIcon } from '@vapor-ui/icons'` | | `SpinnerOutlineIcon` | `import { SpinnerOutlineIcon } from '@vapor-ui/icons'` | | `SplitHorizontalOutlineIcon` | `import { SplitHorizontalOutlineIcon } from '@vapor-ui/icons'` | | `SplitVerticalOutlineIcon` | `import { SplitVerticalOutlineIcon } from '@vapor-ui/icons'` | | `StarOutlineIcon` | `import { StarOutlineIcon } from '@vapor-ui/icons'` | | `StepInOutlineIcon` | `import { StepInOutlineIcon } from '@vapor-ui/icons'` | | `StepOutOutlineIcon` | `import { StepOutOutlineIcon } from '@vapor-ui/icons'` | | `StepOverOutlineIcon` | `import { StepOverOutlineIcon } from '@vapor-ui/icons'` | | `StopOutlineIcon` | `import { StopOutlineIcon } from '@vapor-ui/icons'` | | `StrikeOutlineIcon` | `import { StrikeOutlineIcon } from '@vapor-ui/icons'` | | `StruckOutlineIcon` | `import { StruckOutlineIcon } from '@vapor-ui/icons'` | | `StudentManagementOutlineIcon` | `import { StudentManagementOutlineIcon } from '@vapor-ui/icons'` | | `SyllabusOutlineIcon` | `import { SyllabusOutlineIcon } from '@vapor-ui/icons'` | | `TableFilterOutlineIcon` | `import { TableFilterOutlineIcon } from '@vapor-ui/icons'` | | `TableOutlineIcon` | `import { TableOutlineIcon } from '@vapor-ui/icons'` | | `TabletOutlineIcon` | `import { TabletOutlineIcon } from '@vapor-ui/icons'` | | `TerminalConnectOutlineIcon` | `import { TerminalConnectOutlineIcon } from '@vapor-ui/icons'` | | `TerminalOutlineIcon` | `import { TerminalOutlineIcon } from '@vapor-ui/icons'` | | `TerminalWindowOutlineIcon` | `import { TerminalWindowOutlineIcon } from '@vapor-ui/icons'` | | `TestOutlineIcon` | `import { TestOutlineIcon } from '@vapor-ui/icons'` | | `TextColorOutlineIcon` | `import { TextColorOutlineIcon } from '@vapor-ui/icons'` | | `TextOutlineIcon` | `import { TextOutlineIcon } from '@vapor-ui/icons'` | | `TextScanOutlineIcon` | `import { TextScanOutlineIcon } from '@vapor-ui/icons'` | | `TimeOutlineIcon` | `import { TimeOutlineIcon } from '@vapor-ui/icons'` | | `TransferOutlineIcon` | `import { TransferOutlineIcon } from '@vapor-ui/icons'` | | `TranslateOutlineIcon` | `import { TranslateOutlineIcon } from '@vapor-ui/icons'` | | `TrashOutlineIcon` | `import { TrashOutlineIcon } from '@vapor-ui/icons'` | | `UnderlineOutlineIcon` | `import { UnderlineOutlineIcon } from '@vapor-ui/icons'` | | `UndoOutlineIcon` | `import { UndoOutlineIcon } from '@vapor-ui/icons'` | | `UnlockOutlineIcon` | `import { UnlockOutlineIcon } from '@vapor-ui/icons'` | | `UploadOutlineIcon` | `import { UploadOutlineIcon } from '@vapor-ui/icons'` | | `UserCheckOutlineIcon` | `import { UserCheckOutlineIcon } from '@vapor-ui/icons'` | | `UserMoveOutlineIcon` | `import { UserMoveOutlineIcon } from '@vapor-ui/icons'` | | `UserOutlineIcon` | `import { UserOutlineIcon } from '@vapor-ui/icons'` | | `UserSearchOutlineIcon` | `import { UserSearchOutlineIcon } from '@vapor-ui/icons'` | | `VideocamOffOutlineIcon` | `import { VideocamOffOutlineIcon } from '@vapor-ui/icons'` | | `VideocamOnOutlineIcon` | `import { VideocamOnOutlineIcon } from '@vapor-ui/icons'` | | `ViewExpandOutlineIcon` | `import { ViewExpandOutlineIcon } from '@vapor-ui/icons'` | | `ViewModuleOutlineIcon` | `import { ViewModuleOutlineIcon } from '@vapor-ui/icons'` | | `ViewOffOutlineIcon` | `import { ViewOffOutlineIcon } from '@vapor-ui/icons'` | | `ViewOnOutlineIcon` | `import { ViewOnOutlineIcon } from '@vapor-ui/icons'` | | `ViewShrinkOutlineIcon` | `import { ViewShrinkOutlineIcon } from '@vapor-ui/icons'` | | `WarningOutlineIcon` | `import { WarningOutlineIcon } from '@vapor-ui/icons'` | | `WordSearchOutlineIcon` | `import { WordSearchOutlineIcon } from '@vapor-ui/icons'` | | `ZoomInOutlineIcon` | `import { ZoomInOutlineIcon } from '@vapor-ui/icons'` | | `ZoomOutOutlineIcon` | `import { ZoomOutOutlineIcon } from '@vapor-ui/icons'` | --- version: 1.0.0-beta.6 --- # Welcome, Vapor UI URL: /docs Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/index.mdx Vapor는 구름의 세 번째 디자인 시스템으로, 다양한 서브 패키지들로 구성되어 있습니다. 각 서브 패키지는 다음과 같은 역할을 수행합니다. *** title: Welcome, Vapor UI description: Vapor는 구름의 세 번째 디자인 시스템으로, 다양한 서브 패키지들로 구성되어 있습니다. 각 서브 패키지는 다음과 같은 역할을 수행합니다. ------------------------------------------------------------------------------------------- --- version: 1.0.0-beta.6 --- # Codemod URL: /docs/getting-started/codemod Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/codemod.mdx Vapor UI v1 마이그레이션을 자동으로 수행하는 CLI 도구 *** title: Codemod description: Vapor UI v1 마이그레이션을 자동으로 수행하는 CLI 도구 ------------------------------------------------- `@vapor-ui/codemod`를 사용하면 `@vapor-ui/core` v1의 breaking changes를 자동으로 마이그레이션할 수 있습니다. ## 시작하기 전에 `@vapor-ui/core`에서 import한 컴포넌트만 변환됩니다. 다른 라이브러리의 동일한 이름의 컴포넌트는 변환되지 않습니다. * **Git 상태 확인**: uncommitted changes가 있으면 실행되지 않습니다. `--force` 옵션으로 우회할 수 있습니다. * **Dry Run 권장**: `--dry` 옵션으로 변경 사항을 먼저 확인하세요. *** ## 빠른 시작 별도 설치 없이 `npx`로 실행합니다: ```bash npx @vapor-ui/codemod v1/migrate ./src ``` 이 명령어는 아래의 모든 변환을 한 번에 적용합니다. ### 옵션 | 옵션 | 설명 | | -------------------- | ---------------------------------------- | | `--dry` | 변경 사항을 미리보기만 하고 파일에 적용하지 않음 | | `--force` | Git 안전 검사를 우회하고 강제 실행 | | `--parser ` | 파서 지정: `babel`, `ts`, `tsx` (기본값: `tsx`) | | `--extensions ` | 변환할 파일 확장자 (기본값: `tsx,ts,jsx,js`) | *** ## 변환 목록 ### `loop` → `loopFocus` 포커스 루프 동작을 제어하는 prop 이름이 변경됩니다. **대상 컴포넌트:** `Menu`, `Tabs` ```tsx // Before Open ... // After Open ... ``` ```tsx // Before ... // After ... ``` *** ### `trackAnchor` → `disableAnchorTracking` 앵커 추적 prop이 부정형으로 변경됩니다. boolean 값이 반전됩니다. **대상 컴포넌트:** `Popover`, `Menu`, `Tooltip` ```tsx // Before Content // After Content ``` ```tsx // Before ... // After ... ``` 표현식에는 `!` 연산자가 자동으로 추가됩니다: ```tsx // Before // After ``` *** ### `hoverable` → `disableHoverablePopup` Tooltip 팝업의 hover 가능 여부를 제어하는 prop이 부정형으로 변경됩니다. boolean 값이 반전됩니다. **대상 컴포넌트:** `Tooltip` ```tsx // Before Hover me Content // After Hover me Content ``` ```tsx // Before // After ``` *** ### Hover props를 `Root`에서 `Trigger`로 이동 hover 관련 props가 `Root`에서 `Trigger`로 이동합니다. **대상 컴포넌트 및 props:** | Prop | Menu | Popover | Tooltip | | ------------- | :--: | :-----: | :-----: | | `openOnHover` | O | O | - | | `delay` | O | O | O | | `closeDelay` | O | O | O | **Menu:** ```tsx // Before Open ... // After Open ... ``` **Popover:** ```tsx // Before Hover Content // After Hover Content ``` **Tooltip:** ```tsx // Before Hover Content // After Hover Content ``` *** ### `onClearErrors` 제거 `Form.Root`에서 `onClearErrors` prop이 제거됩니다. v1에서는 `errors` prop으로 전달한 에러가 필드 값 변경 시 자동으로 클리어됩니다. **대상 컴포넌트:** `Form` ```tsx // Before { setErrors((prev) => { const next = { ...prev }; Object.keys(clearedErrors).forEach((name) => delete next[name]); return next; }); }} > // After ``` *** ### `selected` → `current` 현재 선택된 링크를 나타내는 prop 이름이 Breadcrumb API와 일관성을 맞추기 위해 변경됩니다. **대상 컴포넌트:** `NavigationMenu` ```tsx // Before Home // After Home ``` ```tsx // Before Dashboard // After Dashboard ``` *** ## 고급 사용법 ### 여러 변환이 적용되는 경우 ```tsx // Before import { Menu, Tooltip } from '@vapor-ui/core'; function App() { return ( <> Menu Item 1 Item 2 Hover me Tooltip content ); } // After import { Menu, Tooltip } from '@vapor-ui/core'; function App() { return ( <> Menu Item 1 Item 2 Hover me Tooltip content ); } ``` ### Alias import 처리 alias로 import한 컴포넌트도 올바르게 변환됩니다: ```tsx // Before import { Menu as VaporMenu } from '@vapor-ui/core'; Open // After Open ``` *** ## 수동 마이그레이션 codemod로 자동 변환할 수 없는 항목입니다. 직접 검색하여 수정하세요. ### `data-selected` → `data-active` CSS 선택자에서 사용되는 data attribute가 변경됩니다. **대상 컴포넌트:** `Tabs`, `NavigationMenu` 기존 Tabs는 상태 이름이 `selected`, `highlighted`, `active`가 혼재되어 있어 "현재 활성 탭"이 무엇인지 직관적이지 않았습니다. v1에서는 `data-active`로 통일합니다. ```css /* Before */ [data-selected] { background-color: var(--color-primary); } /* After */ [data-active] { background-color: var(--color-primary); } ``` CSS 선택자는 컴포넌트 import와 무관하게 사용되므로 codemod로 자동 변환할 수 없습니다. `data-selected`를 검색하여 직접 수정하세요. --- version: 1.0.0-beta.6 --- # ESLint Plugin URL: /docs/getting-started/eslint Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/eslint.mdx ESLint Plugin Vapor를 사용하여 접근성 규칙을 자동으로 검사하고 코드 품질을 향상시키세요. *** title: ESLint Plugin description: ESLint Plugin Vapor를 사용하여 접근성 규칙을 자동으로 검사하고 코드 품질을 향상시키세요. ----------------------------------------------------------------------- **ESLint Plugin Vapor**는 Vapor UI 컴포넌트의 **접근성 규칙을 자동으로 검사**하여 더 나은 사용자 경험을 보장합니다. ## Why * Vapor UI 컴포넌트를 사용할 때 자주 발생하는 접근성 문제들을 **개발 단계에서 미리 발견**할 수 있습니다. * 수동으로 검토하기 어려운 접근성 가이드라인을 **자동으로 체크**합니다. 이제 개발자는 더 나은 코드를 작성하는 데에만 집중할 수 있습니다. * 웹사이트의 전반적인 사용자 경험을 향상시키고, 더 넓은 사용자층에게 다가갈 수 있습니다. ## Installation 프로젝트에서 사용 중인 패키지 매니저로 플러그인을 설치하세요. `eslint-plugin-vapor`는 eslint-plugin-jsx-a11y, typescript-eslint와 함께 사용할 수 있습니다. ```package-install npm install --save-dev eslint-plugin-vapor eslint-plugin-jsx-a11y typescript-eslint ``` ## Configuration ### Flat Config ESLint 9.0+ 버전을 사용하는 경우, `eslint.config.js` 파일에 다음과 같이 설정하세요: ```js import vapor from 'eslint-plugin-vapor'; export default [ { plugins: { vapor, }, rules: { 'vapor/icon-button-has-aria-label': 'error', 'vapor/navigation-has-aria-label': 'error', }, }, // 또는 recommended 설정 사용 vapor.configs.recommended, ]; ``` ### Legacy Config ESLint 8.x 버전을 사용하는 경우, `.eslintrc.js` 파일에 다음과 같이 설정하세요: ```js module.exports = { plugins: ['vapor'], extends: ['plugin:vapor/legacy'], // 또는 개별 규칙 설정 rules: { 'vapor/icon-button-has-aria-label': 'error', 'vapor/navigation-has-aria-label': 'error', }, }; ``` ## Rules ### icon-button-has-aria-label `IconButton` 컴포넌트에 `aria-label` 속성이 있는지 검사합니다. ```tsx // ❌ // ✅ ``` ### navigation-has-aria-label `NavigationMenu.Root`와 `Breadcrumb.Root` 컴포넌트에 `aria-label` 속성이 있는지 검사합니다. ```tsx // ❌ ... ... // ✅ ... ... ``` ### alt-text-on-avatar `Avatar` 컴포넌트를 이미지로 사용할 때, `src`와 `alt` 속성이 있는지 검사합니다. ```tsx // ❌ // ✅ ``` ### should-have-title-on-dialog `Dialog` 컴포넌트에 `Dialog.Title`, 혹은 `aria-label` 속성이 포함되어 있는지 검사합니다. ```tsx // ❌ ... // ✅ 정보 입력 ... // 또는 ... ``` --- version: 1.0.0-beta.6 --- # Installation URL: /docs/getting-started/installation Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/installation.mdx Vapor UI를 프로젝트에 설치하고 첫 컴포넌트를 사용해보세요. *** title: Installation description: Vapor UI를 프로젝트에 설치하고 첫 컴포넌트를 사용해보세요. ------------------------------------------------- 이 문서를 완료하면 Vapor UI 패키지를 설치하고, 첫 번째 컴포넌트를 화면에 렌더링할 수 있습니다. ## 사전 준비 다음 환경이 필요합니다. | 요구사항 | 버전 | | :------ | :---- | | React | 17 이상 | | Node.js | 16 이상 | ## 1단계: 패키지 설치 패키지 매니저를 사용하여 Vapor UI를 설치합니다. ```package-install npm install @vapor-ui/core @vapor-ui/icons ``` ## 2단계: Portal 설정 Vapor UI는 Dialog, Popover 같은 팝업 컴포넌트에 Portal을 사용합니다. Portal 컴포넌트가 항상 페이지 최상단에 표시되도록 애플리케이션 레이아웃 루트에 다음 스타일을 추가합니다. ```tsx title="layout.tsx"
{children}
``` ```css title="styles.css" .root { isolation: isolate; } ``` 이 스타일은 `.root` 요소에 별도의 stacking context를 생성합니다. 이를 통해 팝업이 항상 페이지 콘텐츠 위에 표시되며, 다른 스타일의 `z-index` 속성과 충돌하지 않습니다. ## 3단계: 컴포넌트 사용 컴포넌트를 import하여 사용합니다. ```json doc-gen:file { "file": "./src/components/demo/examples/assemble-component.tsx", "codeblock": true } ``` ## 다음 단계 * [테마 설정하기](/theme/theme-provider) - 라이트/다크 모드 및 커스텀 테마 설정 방법 * [컴포넌트 살펴보기](./overview#components) - 다양한 UI 컴포넌트 사용법 --- version: 1.0.0-beta.6 --- # LLMs.txt URL: /docs/getting-started/llms-txt Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/llms-txt.mdx Cursor 등 AI 도구에서 Vapor Design System 문서를 활용하는 방법 *** title: LLMs.txt description: Cursor 등 AI 도구에서 Vapor Design System 문서를 활용하는 방법 ------------------------------------------------------------- 이 문서에서는 LLMs.txt 파일의 구성과 AI 도구에서 활용하는 방법을 설명합니다. ## LLMs.txt 개요 LLMs.txt는 LLM(Large Language Model)이 Vapor Design System 문서를 이해하도록 구조화한 텍스트 파일입니다. 컨텍스트 창이 제한된 AI 도구에서 핵심 정보를 빠르게 파악할 수 있습니다. ## 파일 구성 | 파일명 | 설명 | | ------------- | ------------------------------------- | | llms.txt | 전체 라우트 및 카테고리 개요를 포함한 메인 인덱스 파일 | | llms-full.txt | 모든 문서(컴포넌트, 가이드, API 등)를 포함한 전체 문서 세트 | ### 인덱스 파일 * [llms.txt](/llms.txt): 각 문서에 대한 요약과 링크를 포함합니다. * [llms-full.txt](/llms-full.txt): 모든 내용을 포함하며 큰 컨텍스트 워크플로우에 적합합니다. ### 문서 경로 **가이드** * [/docs/getting-started/installation.mdx](/docs/getting-started/installation.mdx): 설치 가이드 **디자인 토큰** * [/docs/tokens/color.mdx](/docs/tokens/color.mdx): 색상 시스템 * [/docs/tokens/size.mdx](/docs/tokens/size.mdx): 크기 및 여백 * [/docs/tokens/typography.mdx](/docs/tokens/typography.mdx): 타이포그래피 시스템 **테마** * [/theme/theme-provider.mdx](/theme/theme-provider.mdx): 테마 설정 가이드 **컴포넌트** * [/docs/components/\[component-name\].mdx](/docs/components/avatar.mdx): 컴포넌트별 사용법과 API (예: Avatar) ## AI 도구에서 사용 Cursor 등 LLM 기반 코드 도구에서 LLMs.txt 파일을 활용하려면 `@Docs` 기능을 사용합니다. * [Cursor @Docs 문서](https://docs.cursor.com/context/@-symbols/@-docs) --- version: 1.0.0-beta.6 --- # Overview URL: /docs/getting-started/overview Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/overview.mdx 빠른 개발과 일관된 디자인을 위한 Vapor UI 디자인 시스템을 살펴보세요. *** title: Overview description: 빠른 개발과 일관된 디자인을 위한 Vapor UI 디자인 시스템을 살펴보세요. -------------------------------------------------------- 이 문서에서는 Vapor UI의 핵심 기능과 제공하는 컴포넌트 목록을 확인할 수 있습니다. ## Vapor UI 소개 Vapor UI는 개발자 경험과 디자인 일관성을 모두 만족시키는 React 컴포넌트 라이브러리입니다. 구름에서 개발한 세 번째 디자인 시스템으로, 실제 프로덕션에서 검증된 컴포넌트들을 제공합니다. ## 핵심 기능 * **모듈화된 구조**: 필요한 패키지만 선택적으로 설치하여 번들 크기를 최적화합니다. * **TypeScript 지원**: 모든 컴포넌트에 타입 정의가 포함되어 자동 완성과 타입 검사를 지원합니다. * **접근성 내장**: WCAG 2.1 AA 수준의 웹 접근성을 기본으로 제공합니다. * **Tailwind CSS 통합**: Tailwind 유틸리티 클래스로 컴포넌트를 빠르게 커스터마이징할 수 있습니다. * **다크 모드**: 라이트/다크 테마 자동 전환 시스템을 제공합니다. ## 적합한 프로젝트 Vapor UI는 다음과 같은 프로젝트에서 효과적으로 활용할 수 있습니다. * 빠른 프로토타이핑이 필요한 스타트업과 신규 프로젝트 * 일관된 디자인 시스템을 구축하려는 중대형 팀 * 접근성을 중요시하는 공공 서비스나 글로벌 서비스 * TypeScript 환경의 모던 React 프로젝트 * 디자인과 개발 간 협업이 중요한 조직 *** ## Components --- version: 1.0.0-beta.6 --- # Design Principles URL: /docs/getting-started/principles Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/principles.mdx Vapor UI의 컴포넌트 아키텍처와 개발 철학을 이끄는 핵심 디자인 원칙 *** title: Design Principles description: Vapor UI의 컴포넌트 아키텍처와 개발 철학을 이끄는 핵심 디자인 원칙 ------------------------------------------------------ 이 문서에서는 Vapor UI의 설계 철학과 6가지 핵심 원칙을 설명합니다. 이 원칙들을 이해하면 컴포넌트를 더 효과적으로 활용할 수 있습니다. ## 1. Preset 기반의 컴파운드 패턴 Vapor UI는 합성 컴포넌트 패턴을 채택하여 편의성과 유연성을 함께 제공합니다. 빠른 구현이 필요할 때는 Preset 컴포넌트를, 세밀한 제어가 필요할 때는 Primitive 컴포넌트를 사용합니다. ```tsx // Preset 패턴 (빠르고 간편) Trigger Contents // Primitive 패턴 (완전한 제어) Trigger Contents ``` 이 접근법의 장점은 다음과 같습니다. * **빠른 시작**: Preset 컴포넌트로 즉시 구현할 수 있습니다. * **세밀한 제어**: Primitive 컴포넌트로 커스텀 동작을 구현할 수 있습니다. * **혼합 사용**: 같은 애플리케이션에서 두 패턴을 함께 사용할 수 있습니다. ## 2. 접근성 Vapor UI는 [Base UI](https://base-ui.com/react/overview/quick-start)를 기반으로 [WCAG 2.2](https://www.w3.org/TR/WCAG22/) AA를 준수합니다. [키보드 네비게이션](https://www.w3.org/TR/WCAG22/#keyboard-accessible)과 [포커스 표시](https://www.w3.org/WAI/WCAG22/Understanding/focus-appearance)를 기본으로 지원합니다. ### 접근성 기능 * **Base UI 통합**: ARIA 속성, 키보드 내비게이션, 스크린 리더를 자동으로 지원합니다. * **색상 대비 준수**: 자체 개발한 Color Generator가 WCAG AA/AAA 대비 비율을 보장합니다. * **수학적 디자인 토큰**: 일관된 시각적 위계를 위해 수학적 비율로 생성된 토큰을 사용합니다. ```tsx // 적절한 ARIA 속성과 키보드 처리가 자동으로 포함됨 설정 열기 {/* 포커스 관리와 ESC 키 처리가 내장됨 */} ``` ### Color Generator 시스템 Color Generator는 지각적 색상 모델을 사용하여 접근성을 충족하는 색상 팔레트를 생성합니다. ```tsx // 색상이 자동으로 대비 요구사항을 충족함 Primary Success Warning ``` ## 3. 일관된 네이밍 규칙 모든 컴포넌트는 일관된 네이밍 규칙을 따릅니다. 이 규칙을 통해 컴포넌트 사용법을 예측할 수 있습니다. * **독립 컴포넌트**: 단일 이름을 사용합니다. * **합성 컴포넌트**: Dot Notation 표기법을 사용합니다. ```tsx // 단일 컴포넌트 상태 // 합성 컴포넌트 프로젝트 상태 현재 개발 진행상황 섹션 1 섹션 2 섹션 3 ``` ## 4. 예측 가능한 속성 명명 컴포넌트 속성은 시각적 옵션과 논리적 상태를 기반으로 체계적인 규칙을 따릅니다. ### 시각적 옵션 ```tsx // 크기 변형은 일관된 스케일을 따름 ... // After ... ``` **Why this change:** * Maintains Figma-React design system parity (SSOT principle) * Follows "React Props = Figma Variants" architectural principle * Aligns with Vapor UI's 4-layer component architecture (Container, Interaction, Contents, Slot) * Layout concerns should be handled by parent containers, not component props ## 1.0.0-beta.6 It contains the same code as the previous version. Please refer to that version. ## 1.0.0-beta.5 ### Button * update horizontal padding for small size (`050 (4px)` -> `100 (8px)`) ([#323](https://github.com/goorm-dev/vapor-ui/pull/323)) - Thanks [@agetbase](https://github.com/agetbase)! ### Checkbox * fix checkbox borderRadius sync error ([#267](https://github.com/goorm-dev/vapor-ui/pull/267)) - Thanks [@SimYunSup](https://github.com/SimYunSup)! ### Field * add default layout styles to field.label ([#289](https://github.com/goorm-dev/vapor-ui/pull/289)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Form * add new `Form` component ([#256](https://github.com/goorm-dev/vapor-ui/pull/256)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Icon Button * Fixed a CSS dependency order issue where `IconButton` styles loaded before `Button` styles, causing incorrect style inheritance. ### Radio * adjust indicator size to account for border ([#291](https://github.com/goorm-dev/vapor-ui/pull/291)) - Thanks [@SimYunSup](https://github.com/SimYunSup)! ### Radio Card * add new component `RadioCard` ([#284](https://github.com/goorm-dev/vapor-ui/pull/284)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Radio Group * synchronize the aria-labelledby with the recieved id prop ([#327](https://github.com/goorm-dev/vapor-ui/pull/327)) - Thanks [@noahchoii](https://github.com/noahchoii)! * replace layout styles into layout component like VStack, HStack ([#288](https://github.com/goorm-dev/vapor-ui/pull/288)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Text Input * add component layer ([#253](https://github.com/goorm-dev/vapor-ui/pull/253)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Theme * add ThemeScope component and migrate to data-attribute based theming ([#278](https://github.com/goorm-dev/vapor-ui/pull/278)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Theme Provider * remove ThemeScript and simplify ThemeProvider ([#240](https://github.com/goorm-dev/vapor-ui/pull/240)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Etc. * enabled CSS tree shaking ([#298](https://github.com/goorm-dev/vapor-ui/pull/298)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * Component CSS is now automatically imported by each component file. * add white foreground variant to foreground recipe ([#305](https://github.com/goorm-dev/vapor-ui/pull/305)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! * export component with namespace ([#276](https://github.com/goorm-dev/vapor-ui/pull/276)) - Thanks [@noahchoii](https://github.com/noahchoii)! * migrate to base-ui beta v4 ([#292](https://github.com/goorm-dev/vapor-ui/pull/292)) - Thanks [@noahchoii](https://github.com/noahchoii)! * change components interface ([#360](https://github.com/goorm-dev/vapor-ui/pull/360)) - Thanks [@noahchoii](https://github.com/noahchoii)! * missing component exports in entry file ([#248](https://github.com/goorm-dev/vapor-ui/pull/248)) - Thanks [@noahchoii](https://github.com/noahchoii)! * add uilitiy css props ([#326](https://github.com/goorm-dev/vapor-ui/pull/326)) - Thanks [@noahchoii](https://github.com/noahchoii)! * rename `CombinedContent` to `Content` ([#247](https://github.com/goorm-dev/vapor-ui/pull/247)) - Thanks [@noahchoii](https://github.com/noahchoii)! * unify cascade layers under `vapor` namespace ([#334](https://github.com/goorm-dev/vapor-ui/pull/334)) - Thanks [@noahchoii](https://github.com/noahchoii)! * standardize state attributes for form components ([#282](https://github.com/goorm-dev/vapor-ui/pull/282)) - Thanks [@noahchoii](https://github.com/noahchoii)! * feat: rename color tokens ([#261](https://github.com/goorm-dev/vapor-ui/pull/261)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * prevent loading font while building CSS ([#265](https://github.com/goorm-dev/vapor-ui/pull/265)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * correct background color of interaction layer in dark mode ([#335](https://github.com/goorm-dev/vapor-ui/pull/335)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Updated Dependencies * @vapor-ui/icons\@1.0.0-beta.5 ## 0.6.0 ### Callout * add flex layout for icons and text alignment ([#181](https://github.com/goorm-dev/vapor-ui/pull/181)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Collapsible * add new `Collapsible` component ([#197](https://github.com/goorm-dev/vapor-ui/pull/197)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Field * add new `Field` components ([#224](https://github.com/goorm-dev/vapor-ui/pull/224)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Input Group * add new `InputGroup` component ([#230](https://github.com/goorm-dev/vapor-ui/pull/230)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Multi Select * add new `MultiSelect` component ([#225](https://github.com/goorm-dev/vapor-ui/pull/225)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Navigation Menu * Migrate `Nav` to `NavigationMenu` ([#211](https://github.com/goorm-dev/vapor-ui/pull/211)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Popover * add new `Popover` component ([#156](https://github.com/goorm-dev/vapor-ui/pull/156)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Select * add new `Select` component ([#222](https://github.com/goorm-dev/vapor-ui/pull/222)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Sheet * add new `Sheet` component ([#187](https://github.com/goorm-dev/vapor-ui/pull/187)) - Thanks [@noahchoii](https://github.com/noahchoii)! * edit spacing style implementation ([#238](https://github.com/goorm-dev/vapor-ui/pull/238)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Tabs * add new `Tabs` component ([#157](https://github.com/goorm-dev/vapor-ui/pull/157)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Textarea * Add new `Textarea` component ([#209](https://github.com/goorm-dev/vapor-ui/pull/209)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Tooltip * eidt tooltip offset ([#212](https://github.com/goorm-dev/vapor-ui/pull/212)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Etc. * change the overlay component interface ([#195](https://github.com/goorm-dev/vapor-ui/pull/195)) - Thanks [@noahchoii](https://github.com/noahchoii)! * remove `Label` sub-component from all form elements ([#204](https://github.com/goorm-dev/vapor-ui/pull/204)) - Thanks [@noahchoii](https://github.com/noahchoii)! * migrate to `Base UI` ([#186](https://github.com/goorm-dev/vapor-ui/pull/186)) - Thanks [@noahchoii](https://github.com/noahchoii)! * support readonly props in all of form elements ([#208](https://github.com/goorm-dev/vapor-ui/pull/208)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! * fix svg rendering issue on safari ([#237](https://github.com/goorm-dev/vapor-ui/pull/237)) - Thanks [@noahchoii](https://github.com/noahchoii)! * remove active style when provided readonly ([#246](https://github.com/goorm-dev/vapor-ui/pull/246)) - Thanks [@noahchoii](https://github.com/noahchoii)! * ensure focus styles take precedence over hover styles ([#200](https://github.com/goorm-dev/vapor-ui/pull/200)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Updated Dependencies * @vapor-ui/icons\@0.4.0 ## 0.5.0 ### Avatar * align CSS variable with build identifiers config ([#176](https://github.com/goorm-dev/vapor-ui/pull/176)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Breadcrumb * add new `Breadcrumb` component ([#151](https://github.com/goorm-dev/vapor-ui/pull/151)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Button * add `no-wrap` CSS properties ([#114](https://github.com/goorm-dev/vapor-ui/pull/114)) - Thanks [@jun094](https://github.com/jun094)! ### Menu * add new `Menu` component ([#147](https://github.com/goorm-dev/vapor-ui/pull/147)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Radio Group * add background-color(white) to RadioGroup Indicator ([#146](https://github.com/goorm-dev/vapor-ui/pull/146)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Tooltip * add new `Tooltip` component ([#150](https://github.com/goorm-dev/vapor-ui/pull/150)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Etc. * enhance vanillaExtractPlugin identifiers ([#161](https://github.com/goorm-dev/vapor-ui/pull/161)) - Thanks [@noahchoii](https://github.com/noahchoii)! * remove hover state when used touchscreen ([#158](https://github.com/goorm-dev/vapor-ui/pull/158)) - Thanks [@noahchoii](https://github.com/noahchoii)! * add `VComponentProps` ([#168](https://github.com/goorm-dev/vapor-ui/pull/168)) - Thanks [@noahchoii](https://github.com/noahchoii)! * add `box-shadow` tokens ([#143](https://github.com/goorm-dev/vapor-ui/pull/143)) - Thanks [@noahchoii](https://github.com/noahchoii)! * enhance vanillaExtractPlugin identifiers for better debugging ([#149](https://github.com/goorm-dev/vapor-ui/pull/149)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Updated Dependencies * @vapor-ui/icons\@1.0.0 ## 0.4.0 ### Badge * align text to center ([#137](https://github.com/goorm-dev/vapor-ui/pull/137)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Radio Group * remove incorrectly injected props ([#125](https://github.com/goorm-dev/vapor-ui/pull/125)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Etc. * change CSS layer names to `theme`, `reset`, `components`, and `utilities` ([#138](https://github.com/goorm-dev/vapor-ui/pull/138)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * add Tailwind CSS v4 preset ([#98](https://github.com/goorm-dev/vapor-ui/pull/98)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * improve DX by overhauling CSS bundling strategy ([#121](https://github.com/goorm-dev/vapor-ui/pull/121)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * add foreground mixin to style entry point ([#142](https://github.com/goorm-dev/vapor-ui/pull/142)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Updated Dependencies * @vapor-ui/icons\@0.2.0 ## 0.3.1 ### Theme Provider * add `primaryColor` props for user custom ([#87](https://github.com/goorm-dev/vapor-ui/pull/87)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ## 0.3.0 ### Etc. * remove sprinkles on each components ([#88](https://github.com/goorm-dev/vapor-ui/pull/88)) - Thanks [@noahchoii](https://github.com/noahchoii)! * correct CSS layer priority ([#94](https://github.com/goorm-dev/vapor-ui/pull/94)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ## 0.2.1 ### Theme Provider * support RSC ([#82](https://github.com/goorm-dev/vapor-ui/pull/82)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ## 0.2.0 ### Callout * add new `Callout` component ([#67](https://github.com/goorm-dev/vapor-ui/pull/67)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Checkbox * add new `Checkbox` Component ([#58](https://github.com/goorm-dev/vapor-ui/pull/58)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Dialog * edit dialog animation style ([#72](https://github.com/goorm-dev/vapor-ui/pull/72)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Radio Group * add new `RadioGroup` component ([#76](https://github.com/goorm-dev/vapor-ui/pull/76)) - Thanks [@noahchoii](https://github.com/noahchoii)! ### Switch * add new `Switch` component - Thanks [@noahchoii](https://github.com/noahchoii)! ### Etc. * remove `@vapor-ui/icons` for resolving storybook build error ([#57](https://github.com/goorm-dev/vapor-ui/pull/57)) - Thanks [@noahchoii](https://github.com/noahchoii)! * prevent code splitting while tsup build ([#81](https://github.com/goorm-dev/vapor-ui/pull/81)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * resolve circular dependency in vanilla-extract ([#73](https://github.com/goorm-dev/vapor-ui/pull/73)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * optimize build system for component bundling ([#73](https://github.com/goorm-dev/vapor-ui/pull/73)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ## 0.1.0 ### Etc. * create package ([#48](https://github.com/goorm-dev/vapor-ui/pull/48)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! --- version: 1.0.0-beta.6 --- # Css Generator URL: /docs/getting-started/releases/css-generator Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/releases/css-generator.md @vapor-ui/css-generator 패키지의 릴리즈 노트입니다. *** title: Css Generator description: '@vapor-ui/css-generator 패키지의 릴리즈 노트입니다.' ------------------------------------------------------ # @vapor-ui/css-generator ## 1.0.0-beta.8 ### Tokens * **BREAKING CHANGE**: rename `color-background-canvas` token to `color-canvas` ([#378](https://github.com/goorm-dev/vapor-ui/pull/378)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! The canvas background token has been renamed for better semantic clarity and consistency: * Token name: `color-background-canvas` → `color-canvas` * CSS variable: `--vapor-color-background-canvas` → `--vapor-color-canvas` **Migration required:** * Update all references from `color-background-canvas` to `color-canvas` * Replace CSS variables from `--vapor-color-background-canvas` to `--vapor-color-canvas` ### Updated Dependencies * @vapor-ui/color-generator\@1.0.0-beta.8 ## 1.0.0-beta.7 ### Updated Dependencies * @vapor-ui/color-generator\@1.0.0-beta.7 ## 1.0.0-beta.6 ### Etc. * feat: update color generator & color palette ([#337](https://github.com/goorm-dev/vapor-ui/pull/337)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Updated Dependencies * @vapor-ui/color-generator\@1.0.0-beta.6 ## 1.0.0-beta.5 ### Theme * feat(theme): Add ThemeScope component and migrate to data-attribute based theming ([#278](https://github.com/goorm-dev/vapor-ui/pull/278)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Etc. * feat: create @vapor-ui/color-generator & @vapor-ui/css-generator ([#234](https://github.com/goorm-dev/vapor-ui/pull/234)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! * feat: update color tokens ([#261](https://github.com/goorm-dev/vapor-ui/pull/261)) - Thanks [@ZeroChoi2781](https://github.com/ZeroChoi2781)! ### Updated Dependencies * @vapor-ui/color-generator\@1.0.0 --- version: 1.0.0-beta.6 --- # ESLint URL: /docs/getting-started/releases/eslint-plugin-vapor Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/releases/eslint-plugin-vapor.md eslint-plugin-vapor 패키지의 릴리즈 노트입니다. *** title: ESLint description: 'eslint-plugin-vapor 패키지의 릴리즈 노트입니다.' -------------------------------------------------- # eslint-plugin-vapor ## 1.0.0 ### Eslint Plugin Vapor * create new `eslint-plugin-vapor` for accessibilities ([#457](https://github.com/goorm-dev/vapor-ui/pull/457)) - Thanks [@noahchoii](https://github.com/noahchoii)! --- version: 1.0.0-beta.6 --- # Icons URL: /docs/getting-started/releases/icons Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/docs/getting-started/releases/icons.md @vapor-ui/icons 패키지의 릴리즈 노트입니다. *** title: Icons description: '@vapor-ui/icons 패키지의 릴리즈 노트입니다.' ---------------------------------------------- # @vapor-ui/icons ## 1.0.0 ### Etc. * Sync icons from Figma and remove deleted HeadingOutlineIcon ([#430](https://github.com/goorm-dev/vapor-ui/pull/430)) - Thanks [@github-actions](https://github.com/apps/github-actions)! * Update icons from Figma ([#449](https://github.com/goorm-dev/vapor-ui/pull/449)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **Updated Symbol Icons:** `VscodeColorIcon` **New Symbol Icons:** `SouthKoreaColorIcon`, and 195 other country icons ## 1.0.0-beta.7 ### Icon Base * remove iconType ([#231](https://github.com/goorm-dev/vapor-ui/pull/231)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Etc. * Update icons from Figma ([#406](https://github.com/goorm-dev/vapor-ui/pull/406)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **Updated Basic Icons:** `Heading2OutlineIcon`, `StrikeOutlineIcon`, `ChecklistOutlineIcon`, `Heading3OutlineIcon`, `Heading4OutlineIcon`, `Heading1OutlineIcon` ## 1.0.0-beta.6 ### Etc. * clone elements & enhance customizability ([#359](https://github.com/goorm-dev/vapor-ui/pull/359)) - Thanks [@noahchoii](https://github.com/noahchoii)! * Add new icons from Figma ([#396](https://github.com/goorm-dev/vapor-ui/pull/396)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **New:** `ChecklistOutlineIcon`, `StrikeOutlineIcon`, `Heading3OutlineIcon`, `Heading2OutlineIcon`, `Heading1OutlineIcon`, `Heading4OutlineIcon` ## 1.0.0-beta.5 ### Etc. * Add new icons from Figma ([#264](https://github.com/goorm-dev/vapor-ui/pull/264)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **New:** `DocktoBottomIcon`, `SideNavIcon`, `SideNavOutlineIcon`, `DocktoBottomOutlineIcon` **Updated:** * Basic Icons: `PanelOpenIcon`, `PanelOpenOutlineIcon` * Update icons from Figma ([#285](https://github.com/goorm-dev/vapor-ui/pull/285)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **Updated:** `TreeCollapseIcon` ## 0.4.0 ### Icon Base * adjust prop precedence for dimensions(width, height, size) ([#182](https://github.com/goorm-dev/vapor-ui/pull/182)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! ### Etc. * Add new icons from Figma ([#207](https://github.com/goorm-dev/vapor-ui/pull/207)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **New:** `MediumIcon` **Updated:** * Symbol Icons: `FirefoxColorIcon` * update icons from Figma ([#217](https://github.com/goorm-dev/vapor-ui/pull/217)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **Updated:** `TerminalWindowOutlineIcon` ## 0.3.0 ### Etc. * add new icons from Figma ([#179](https://github.com/goorm-dev/vapor-ui/pull/179)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **New:** `LinearScaleOutlineIcon` **Updated:** * Basic Icons: `PlayIcon`, `ReplaceIcon`, `ClassIcon`, `ArrowUpOutlineIcon`, `ArrowDownOutlineIcon`, `TerminalOutlineIcon`, `ViewShrinkOutlineIcon`, `FolderSearchIcon`, `StarOutlineIcon`, `PriceOutlineIcon`, `HistoryOutlineIcon`, `CardsOutlineIcon`, `ZoomOutOutlineIcon`, `IntelliSensePropertyOutlineIcon`, `CorrectOutlineIcon`, `ChevronDoubleRightOutlineIcon`, `AutoCodeOutlineIcon`, `ChapterOutlineIcon` * Symbol Icons: `RstudioColorIcon` * add new icons from Figma ([#198](https://github.com/goorm-dev/vapor-ui/pull/198)) - Thanks [@github-actions](https://github.com/apps/github-actions)! **New:** `SidenavIcon` ## 0.2.0 ### Etc. * add new icons and update existing icon components ([#119](https://github.com/goorm-dev/vapor-ui/pull/119)) - Thanks [@MaxLee-dev](https://github.com/MaxLee-dev)! **New Icons Added** * `AlignJustifyOutlineIcon`, `CopyAsMarkdownOutlineIcon`, `IndentDecreaseOutlineIcon`, `SlotIcon`, `TextScanOutlineIcon` **Updated** * Updated approximately 190 existing icons with refined SVG paths and improved rendering * Minor coordinate adjustments for better visual consistency * Enhanced clipPath definitions where needed ## 0.1.0 ### Minor Changes * 68b001c: create avatar , badge , box , button , card , dialog , flex , grid , h-stack , icon-button, nav , text-input , text , theme-provider , v-stack --- version: 1.0.0-beta.6 --- # Form URL: /blocks/form Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/blocks/form.mdx 여러 개의 입력 단위를 하나로 묶어 사용자로부터 정보를 수집하는 폼 영역 *** title: Form description: 여러 개의 입력 단위를 하나로 묶어 사용자로부터 정보를 수집하는 폼 영역 previewImageUrl: /images/form-preview\.svg ------------------------------------------ ### Type: Login ```tsx import './login-form.css'; import { Button, Checkbox, Field, Form, HStack, Text, TextInput, VStack } from '@vapor-ui/core'; export default function LoginForm() { return ( event.preventDefault()} />} > 이메일 이메일을 입력해주세요. 유효한 이메일 형식이 아닙니다. 비밀번호 8~16자, 대소문자 영문, 특수문자 포함 비밀번호를 입력해주세요. 유효한 비밀번호 형식이 아닙니다. 자동 로그인 ); } ``` ```css .input-label { color: var(--vapor-color-foreground-normal-100, #525463); font-size: var(--vapor-typography-fontSize-050, 0.75rem); font-weight: var(--vapor-typography-fontWeight-500); line-height: var(--vapor-typography-lineHeight-050, 1.125rem); /* 150% */ letter-spacing: var(--vapor-typography-letterSpacing-000, 0); } .checkbox-label { color: var(--vapor-color-foreground-normal-100, #2b2d36); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } .helper-text { color: var(--vapor-color-foreground-hint, #6c6e7e); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } ``` ### Type: SignUp ```tsx import './signup-form.css'; import { useState } from 'react'; import { Box, Button, Checkbox, Field, Form, HStack, IconButton, Select, Text, TextInput, VStack, } from '@vapor-ui/core'; import { ChevronRightOutlineIcon } from '@vapor-ui/icons'; const jobs = [ { label: '개발자', value: 'developer' }, { label: '디자이너', value: 'designer' }, { label: '프로덕트 매니저', value: 'product-manager' }, { label: '기타', value: 'etc' }, ]; export default function SignupForm() { const [passwordCheck, setPasswordCheck] = useState(''); // const passwordCheck = useRef(''); return ( event.preventDefault()} />} > } flexDirection="column" className="input-label" > 이메일 이메일을 입력해주세요. 유효한 이메일 형식이 아닙니다. } flexDirection="column" className="input-label" > 비밀번호 setPasswordCheck(value)} required pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\W_]).{8,16}" /> 8~16자, 대소문자 영문, 숫자, 특수문자 포함 비밀번호를 입력해주세요. 유효한 비밀번호 형식이 아닙니다. } flexDirection="column" className="input-label" > 비밀번호 확인 8~16자, 대소문자 영문, 특수문자 포함 비밀번호를 입력해주세요. 비밀번호를 다시 확인해주세요. } flexDirection="column" className="input-label" > 이름 이름을 입력해주세요. } flexDirection="column" className="input-label" > 직업 {jobs.map((job) => ( {job.label} ))} } alignItems="center" className="checkbox-label" > 필수 약관에 모두 동의 } alignItems="center" className="checkbox-label" > 이용 약관 동의 } alignItems="center" className="checkbox-label" > 개인 정보 수집 이용 동의 이미 계정이 있으세요? ); } ``` ```css .input-label { color: var(--vapor-color-foreground-normal-100, #525463); font-size: var(--vapor-typography-fontSize-050, 0.75rem); font-weight: var(--vapor-typography-fontWeight-500); line-height: var(--vapor-typography-lineHeight-050, 1.125rem); /* 150% */ letter-spacing: var(--vapor-typography-letterSpacing-000, 0); } .checkbox-label { color: var(--vapor-color-foreground-normal-100, #2b2d36); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } .helper-text { color: var(--vapor-color-foreground-hint, #6c6e7e); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } ``` ### Type: Authentication ```tsx import { Children, cloneElement, isValidElement, useState } from 'react'; import './authentication-form.css'; import { Button, Field, Form, Select, Text, TextInput, VStack } from '@vapor-ui/core'; const codes = { '+82': '🇰🇷 +82', '+1': '🇺🇸 +1', '+34': '🇪🇸 +34', '+33': '🇫🇷 +33', '+39': '🇮🇹 +39', '+44': '🇬🇧 +44', '+81': '🇯🇵 +81', '+86': '🇨🇳 +86', '+7': '🇷🇺 +7', }; export default function AuthenticationForm() { const [phoneNumber, setPhoneNumber] = useState(''); const handleChange = (e: React.ChangeEvent) => { setPhoneNumber(e.target.value); }; const regex = /^[0-9\s-()]{6,20}$/; return ( e.preventDefault()} />} > 핸드폰 번호 {Object.entries(codes).map(([value, label]) => ( {label} ))} 핸드폰 번호를 입력해주세요. 올바른 핸드폰 번호를 입력해주세요. 인증번호 인증번호를 입력해주세요. ); } interface GroupProps { attached?: boolean; children?: React.ReactNode; } const Group = ({ attached = false, children: childrenProp }: GroupProps) => { const children = Children.map(childrenProp, (child, index) => { if (!isValidElement(child)) return; return cloneElement(child as React.ReactElement, { style: { '--group-index': index, ...child.props.style }, ...(index === 0 ? { 'data-first-item': '' } : {}), ...(index === Children.count(childrenProp) - 1 ? { 'data-last-item': '' } : {}), }); }); return (
{children}
); }; ``` ```css .input-label { color: var(--vapor-color-foreground-normal-100, #525463); font-size: var(--vapor-typography-fontSize-050, 0.75rem); font-weight: var(--vapor-typography-fontWeight-500); line-height: var(--vapor-typography-lineHeight-050, 1.125rem); /* 150% */ letter-spacing: var(--vapor-typography-letterSpacing-000, 0); } .group { display: flex; align-items: center; gap: 0; &.attached { & > [data-first-item] { border-right: none; border-top-right-radius: 0; border-bottom-right-radius: 0; } & > [data-last-item] { border: 1px solid var(--vapor-color-border-normal, #d1d2d8); border-top-left-radius: 0; border-bottom-left-radius: 0; } & > *:not([data-first-item]):not([data-last-item]) { border: 1px solid var(--vapor-color-border-normal, #d1d2d8); border-right: none; border-radius: 0; } } } ```
### Type: Research ```tsx import './research-form.css'; import { Button, Checkbox, Field, Form, HStack, MultiSelect, Radio, RadioGroup, Select, Switch, Text, TextInput, VStack, } from '@vapor-ui/core'; const jobs = [ { label: '프론트엔드 개발자', value: 'frontend-engineer' }, { label: '백엔드 개발자', value: 'backend-engineer' }, { label: '풀스택 개발자', value: 'fullstack-engineer' }, { label: '모바일 앱 개발자', value: 'app-engineer' }, { label: 'DevOps/클라우드 엔지니어', value: 'devops-engineer' }, ]; const stacks = [ { label: 'HTML/CSS', value: 'html-css' }, { label: 'JavaScript', value: 'javascript' }, { label: 'React', value: 'react' }, { label: 'Vue.js', value: 'vue' }, { label: 'Next.js', value: 'nextjs' }, ]; export default function ResearchForm() { return ( event.preventDefault()} />} > 기본 정보를 입력해주세요. 이름 이름을 입력해주세요. 직업 {jobs.map((job) => ( {job.label} ))} 스택 {stacks.map((stack) => ( {stack.label} ))} 만족도를 선택해주세요. 매우 만족 보통 불만족 좋았던 강의는 무엇인가요? 중복 선택 가능 멘토님 강연 능력 주제(협업 및 커뮤니케이션 스킬) 전반적인 강의 내용 세미나 자료 기타 개인 정보 수신 동의 }> 서비스 메일 수신 동의 }> 이벤트성 광고 수신 동의 ); } ``` ```css .input-label { color: var(--vapor-color-foreground-normal-100, #525463); font-size: var(--vapor-typography-fontSize-050, 0.75rem); font-weight: var(--vapor-typography-fontWeight-500); line-height: var(--vapor-typography-lineHeight-050, 1.125rem); /* 150% */ letter-spacing: var(--vapor-typography-letterSpacing-000, 0); } .checkbox-label { color: var(--vapor-color-foreground-normal-100, #2b2d36); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } .radio-label { color: var(--vapor-color-foreground-normal-100, #2b2d36); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } ``` ### Type: Filter ```tsx import './filter-form.css'; import type { FormEvent } from 'react'; import { useCallback, useRef, useState } from 'react'; import { Box, Button, Checkbox, Collapsible, Field, Form, HStack, Radio, RadioGroup, Text, VStack, } from '@vapor-ui/core'; import { ChevronDownOutlineIcon, RefreshOutlineIcon } from '@vapor-ui/icons'; // 초기값 정의 type FormData = typeof FORM_SCHEME; const FORM_SCHEME = { view: 'recent', sort: { feedback: false, buttons: false, 'data-display': false, overlay: false, inputs: false, navigation: false, utils: false, }, packs: { 'goorm-dev/vapor-core': false, 'goorm-dev/vapor-component': false, 'vapor-ui/core': false, }, status: { active: false, inactive: false, draft: false }, tag: { ui: false, 'open-source': false, performance: false }, }; export default function FilterForm() { const formRef = useRef(null); const [formData, setFormData] = useState({ view: FORM_SCHEME.view, sort: { ...FORM_SCHEME.sort }, packs: { ...FORM_SCHEME.packs }, status: { ...FORM_SCHEME.status }, tag: { ...FORM_SCHEME.tag }, }); const getFieldValues = useCallback( (fieldName: T): FormData[T] => formData[fieldName], [formData], ); const updateFormData = useCallback( (fieldName: keyof FormData, key: string, checked: boolean) => { setFormData((prev) => { const field = prev[fieldName]; if (typeof field !== 'object') return prev; return { ...prev, [fieldName]: { ...field, [key]: checked } }; }); }, [], ); // 라디오 버튼 변경 핸들러 const handleRadioChange = useCallback((fieldName: keyof FormData, value: string) => { setFormData((prev) => ({ ...prev, [fieldName]: value })); }, []); // 체크박스 변경 핸들러 const handleCheckboxChange = useCallback( (fieldName: keyof FormData, key: string) => (checked: boolean) => { updateFormData(fieldName, key, checked); }, [updateFormData], ); const selectedSortCount = Object.values(getFieldValues('sort')).filter(Boolean).length; const handleReset = (event: FormEvent) => { event.preventDefault(); setFormData({ view: FORM_SCHEME.view, sort: { ...FORM_SCHEME.sort }, packs: { ...FORM_SCHEME.packs }, status: { ...FORM_SCHEME.status }, tag: { ...FORM_SCHEME.tag }, }); }; return ( }> Filter } border="none" marginY="$150" height="1px" width="100%" backgroundColor="$gray-300" /> View }> handleRadioChange('view', value as string) } > Recent Most Popular Sort {selectedSortCount} }> Feedback Buttons Data Display Overlay Inputs Navigation Utils Package }> goorm-dev/vapor-core goorm-dev/vapor-component vapor-ui/core Status }> Active Inactive Draft Tag }> UI Open Source Performance ); } ``` ```css .checkbox-label { color: var(--vapor-color-foreground-normal-100, #2b2d36); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } .radio-label { color: var(--vapor-color-foreground-normal-100, #2b2d36); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } .collapsible-trigger { width: 100%; display: flex; align-items: center; justify-content: space-between; transition: transform 150ms ease; } .trigger-icon { transition: transform 150ms ease; &:where([data-open] &) { transform: rotate(180deg); } &:where([data-closed] &) { transform: rotate(0); } } ``` ### Type: BottomSheetFilter ```tsx import './sheet-form.css'; import type { FormEvent } from 'react'; import { useCallback, useState } from 'react'; import { Button, Checkbox, Field, Form, Sheet, Tabs, VStack } from '@vapor-ui/core'; import { RefreshOutlineIcon } from '@vapor-ui/icons'; type FormData = typeof FORM_SCHEME; const FORM_SCHEME = { sort: { feedback: false, buttons: true, 'data-display': false, overlay: false, inputs: true, navigation: false, utils: false, }, packs: { 'goorm-dev/vapor-core': true, 'goorm-dev/vapor-component': false, 'vapor-ui/core': false, }, status: { active: true, inactive: false, draft: false, }, tag: { ui: true, 'open-source': false, performance: false, }, }; export default function SheetForm() { const [formData, setFormData] = useState(() => { return { sort: { ...FORM_SCHEME.sort }, packs: { ...FORM_SCHEME.packs }, status: { ...FORM_SCHEME.status }, tag: { ...FORM_SCHEME.tag }, }; }); const getFieldValues = useCallback( (fieldName: T): FormData[T] => formData[fieldName], [formData], ); const updateFormData = useCallback( (fieldName: keyof FormData, key: string, checked: boolean) => { setFormData((prev) => { const field = prev[fieldName]; if (typeof field !== 'object') return prev; return { ...prev, [fieldName]: { ...field, [key]: checked } }; }); }, [], ); const handleCheckboxChange = useCallback( (fieldName: keyof FormData, key: string) => (checked: boolean) => { updateFormData(fieldName, key, checked); }, [updateFormData], ); const handleReset = useCallback((event: FormEvent) => { event.preventDefault(); setFormData({ sort: { ...FORM_SCHEME.sort }, packs: { ...FORM_SCHEME.packs }, status: { ...FORM_SCHEME.status }, tag: { ...FORM_SCHEME.tag }, }); }, []); return ( } > }>Open Filter } className={'popup'} > Filter Sort Package Status Tag {/* Sort */} Feedback Buttons Data Display Overlay Inputs Navigation Utils {/* Package */} goorm-dev/vapor-core goorm-dev/vapor-component vapor-ui/core {/* Status */} Active Inactive Draft {/* Tag */} UI Open Source Performance }> Apply ); } ``` ```css .checkbox-label { color: var(--vapor-color-foreground-normal-100, #2b2d36); font-size: var(--vapor-typography-fontSize-075, 0.875rem); font-weight: var(--vapor-typography-fontWeight-400); line-height: var(--vapor-typography-lineHeight-075, 1.375rem); /* 157.143% */ letter-spacing: var(--vapor-typography-letterSpacing-100, -0.00625rem); } .popup { border-top-left-radius: var(--vapor-size-borderRadius-300); border-top-right-radius: var(--vapor-size-borderRadius-300); } .tabs { height: 100%; } .tabs-list { padding-inline: 0; } .tabs-panel { padding-block: var(--vapor-size-space-200); } .header { padding: var(--vapor-size-space-250) var(--vapor-size-space-200) 0; } .body { padding-inline: var(--vapor-size-space-200); } .footer { gap: var(--vapor-size-space-100); padding-top: var(--vapor-size-space-100); } .refresh-button { flex-shrink: 0; } .apply-button { flex-shrink: 0; flex-grow: 1; } ``` --- version: 1.0.0-beta.6 --- # Navbar URL: /blocks/nav-bar Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/blocks/nav-bar.mdx 사용자의 액션에 대한 피드백 혹은 서비스에 대한 메시지를 제공할 때 사용할 수 있습니다. 상황에 따라 컬러와 좌측 아이콘, 닫기 버튼을 적절히 사용합니다. *** title: Navbar description: 사용자의 액션에 대한 피드백 혹은 서비스에 대한 메시지를 제공할 때 사용할 수 있습니다. 상황에 따라 컬러와 좌측 아이콘, 닫기 버튼을 적절히 사용합니다. previewImageUrl: /images/nav-bar-preview\.svg --------------------------------------------- ### Left Aligned Navbar ```tsx import './block.css'; import type { ComponentProps } from 'react'; import { Avatar, Collapsible, HStack, IconButton, NavigationMenu, Sheet } from '@vapor-ui/core'; import { BellOnIcon, ChevronDownOutlineIcon, CloseOutlineIcon, MenuOutlineIcon, } from '@vapor-ui/icons'; export default function Block1() { return ( Features Pricing Templates }> } > }> }> } > } > Features Container SBOM Pricing Templates ); } const LogoSvg = (props: ComponentProps<'svg'>) => { return ( ); }; ``` ```css .navbar-desktop { display: inherit; @media (max-width: 767px) { display: none; } } .navbar-mobile { display: none; @media (max-width: 767px) { display: inherit; } } .logo { flex-shrink: 0; } .vertical-navigation-menu { width: 100%; } .collapsible-trigger { width: 100%; justify-content: space-between; } .link-item { justify-content: flex-start; } .nested-link-item { justify-content: flex-start; padding-left: var(--vapor-size-space-250); } ``` ### Center Aligned Navbar ```tsx import './block.css'; import type { ComponentProps } from 'react'; import { Avatar, Collapsible, HStack, IconButton, NavigationMenu, Sheet } from '@vapor-ui/core'; import { BellOnIcon, ChevronDownOutlineIcon, CloseOutlineIcon, MenuOutlineIcon, } from '@vapor-ui/icons'; export default function Block2() { return ( Features Pricing Templates }> } > }> }> } > } > Features Container SBOM Pricing Templates ); } const LogoSvg = (props: ComponentProps<'svg'>) => { return ( ); }; ``` ```css .navbar-desktop { display: inherit; @media (max-width: 767px) { display: none; } } .navbar-mobile { display: none; @media (max-width: 767px) { display: inherit; } } .logo { flex-shrink: 0; } .vertical-navigation-menu { width: 100%; } .collapsible-trigger { width: 100%; justify-content: space-between; } .link-item { justify-content: flex-start; } .nested-link-item { justify-content: flex-start; padding-left: var(--vapor-size-space-250); } ``` ### Right Aligned Navbar ```tsx import './block.css'; import type { ComponentProps } from 'react'; import { Avatar, Collapsible, HStack, IconButton, NavigationMenu, Sheet } from '@vapor-ui/core'; import { BellOnIcon, ChevronDownOutlineIcon, CloseOutlineIcon, MenuOutlineIcon, } from '@vapor-ui/icons'; export default function Block3() { return ( Features Pricing Templates }> } > } > }> } > } > Features Container SBOM Pricing Templates ); } const LogoSvg = (props: ComponentProps<'svg'>) => { return ( ); }; ``` ```css .navbar-desktop { display: inherit; @media (max-width: 767px) { display: none; } } .navbar-mobile { display: none; @media (max-width: 767px) { display: inherit; } } .logo { flex-shrink: 0; } .vertical-navigation-menu { width: 100%; } .collapsible-trigger { width: 100%; justify-content: space-between; } .link-item { justify-content: flex-start; } .nested-link-item { justify-content: flex-start; padding-left: var(--vapor-size-space-250); } ``` ### Navbar with Login Button ```tsx import './block.css'; import type { ComponentProps } from 'react'; import { Button, Collapsible, HStack, IconButton, NavigationMenu, Sheet } from '@vapor-ui/core'; import { ChevronDownOutlineIcon, CloseOutlineIcon, MenuOutlineIcon } from '@vapor-ui/icons'; export default function Block4() { return ( Features Pricing Templates } > }> } > } > Features Container SBOM Pricing Templates ); } const LogoSvg = (props: ComponentProps<'svg'>) => { return ( ); }; ``` ```css .navbar-desktop { display: inherit; @media (max-width: 767px) { display: none; } } .navbar-mobile { display: none; @media (max-width: 767px) { display: inherit; } } .logo { flex-shrink: 0; } .vertical-navigation-menu { width: 100%; } .collapsible-trigger { width: 100%; justify-content: space-between; } .link-item { justify-content: flex-start; } .nested-link-item { justify-content: flex-start; padding-left: var(--vapor-size-space-250); } ``` ### Logo Centered Navbar ```tsx import './logo.css'; import type { ComponentProps } from 'react'; import { Button, HStack } from '@vapor-ui/core'; export default function Block5() { return ( ); } const LogoSvg = (props: ComponentProps<'svg'>) => { return ( ); }; ``` ```css .logo { flex-shrink: 0; } ``` ### Page Navigation Navbar ```tsx import './logo.css'; import type { ComponentProps } from 'react'; import { HStack, IconButton } from '@vapor-ui/core'; import { BackPageOutlineIcon, ForwardPageOutlineIcon } from '@vapor-ui/icons'; export default function Block6() { return ( ); } const LogoSvg = (props: ComponentProps<'svg'>) => { return ( ); }; ``` ```css .logo { flex-shrink: 0; } ``` --- version: 1.0.0-beta.6 --- # Table URL: /blocks/table Source: https://raw.githubusercontent.com/goorm-dev/vapor-ui/refs/heads/main/apps/website/content/blocks/table.mdx 데이터의 구조화된 표현을 제공하는 데 사용됩니다. *** title: Table description: 데이터의 구조화된 표현을 제공하는 데 사용됩니다. previewImageUrl: /images/table-preview\.svg ------------------------------------------- 이 문서는 대량의 데이터를 다루는 Data Table의 구현 예시를 안내합니다. Data Table은 데이터를 효율적으로 시각화하고 관리하는 강력한 도구이지만, 내부적으로 복잡한 상태 관리와 로직을 필요로 합니다. 이러한 기능을 컴포넌트 내부에 강결합하면 유지보수가 어렵고 확장성이 떨어지는 문제가 발생할 수 있습니다. 이에 따라 Vapor UI의 Table 컴포넌트는 순수한 뷰(View) 역할에 집중하여 기본적인 구조와 스타일을 제공합니다. 이 문서에서는 `@tanstack/react-table`과 같은 Headless UI 라이브러리를 활용하여 다양한 기능을 유연하게 구현하는 방법을 예시로 제공합니다. ### Basic ```tsx import { Badge, Table } from '@vapor-ui/core'; const datas = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const activeness: Record = { active: 'success', inactive: 'hint', }; export default function Basic() { return ( Name Status Role Last Active {datas.map((data, index) => ( {data.name} {data.status.toUpperCase()} {data.role} {data['last-active']} ))} ); } ``` ### Checkbox ```tsx import { useMemo, useState } from 'react'; import { type ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import { Badge, Card, Checkbox, Table } from '@vapor-ui/core'; export default function Basic() { const [rowSelection, setRowSelection] = useState({}); const columns = useMemo[]>( () => [ { id: 'select', header: ({ table }) => ( table.toggleAllRowsSelected(value)} style={{ justifySelf: 'center' }} /> ), cell: ({ row }) => ( row.toggleSelected(value)} style={{ justifySelf: 'center' }} /> ), }, { header: 'Name', accessorKey: 'name', }, { header: 'Status', accessorKey: 'status', cell: ({ getValue }) => { const status = getValue(); return ( {status.toUpperCase()} ); }, }, { header: 'Role', accessorKey: 'role', }, { header: 'Last Active', accessorKey: 'last-active', }, ], [], ); const table = useReactTable({ data: datas, columns, state: { rowSelection }, enableRowSelection: true, onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), }); return ( {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => { return ( {row.getVisibleCells().map((cell) => { return ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ); })} ); })} ); } type Data = { name: string; status: 'active' | 'inactive'; role: string; 'last-active': string; }; const datas: Data[] = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const activeness: Record = { active: 'success', inactive: 'hint', }; ``` ### Ordering ```tsx import { useMemo, useState } from 'react'; import { type ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import { Badge, Box, Card, Table } from '@vapor-ui/core'; export default function Ordering() { const [rowSelection, setRowSelection] = useState({}); const columns = useMemo[]>( () => [ { id: 'select', header: () => ID, cell: ({ row }) => {row.index + 1}, }, { header: 'Name', accessorKey: 'name', }, { header: 'Status', accessorKey: 'status', cell: ({ getValue }) => { const status = getValue(); return ( {status.toUpperCase()} ); }, }, { header: 'Role', accessorKey: 'role', }, { header: 'Last Active', accessorKey: 'last-active', }, ], [], ); const table = useReactTable({ data: datas, columns, state: { rowSelection }, enableRowSelection: true, onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), }); return ( {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => { return ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ); })} ); } type Data = { name: string; status: 'active' | 'inactive'; role: string; 'last-active': string; }; const datas: Data[] = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const activeness: Record = { active: 'success', inactive: 'hint', }; ``` ### Sticky ```tsx import type { CSSProperties } from 'react'; import { useMemo, useState } from 'react'; import type { Column, Table as TanstackTable } from '@tanstack/react-table'; import { type ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import { Badge, Box, Card, Table } from '@vapor-ui/core'; export default function Basic() { const [rowSelection, setRowSelection] = useState({}); const columns = useMemo[]>( () => [ { header: () => ID, accessorKey: 'id', cell: ({ row }) => {row.index + 1}, }, { header: 'Name', accessorKey: 'name', cell: ({ row }) => {row.getValue('name')}, }, { header: 'Status', accessorKey: 'status', cell: ({ row }) => { const status = row.getValue('status'); return ( {status.toUpperCase()} ); }, }, { header: 'Role', accessorKey: 'role', }, { header: 'Last Active', accessorKey: 'last-active', }, ], [], ); const table = useReactTable({ data: datas, columns, state: { rowSelection, columnPinning: { left: ['id', 'name'] } }, enableRowSelection: true, onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), }); return ( {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( columnSizingHandler(thElem, table, header.column) } backgroundColor="$gray-050" style={{ ...getCommonPinningStyles(header.column) }} > {flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => { return ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ); })} ); } type Data = { name: string; status: 'active' | 'inactive'; role: string; 'last-active': string; }; const datas: Data[] = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const getCommonPinningStyles = (column: Column): CSSProperties => { const isPinned = column.getIsPinned(); const lastPinnedColumn = isPinned === 'left' && column.getIsLastColumn('left'); return { boxShadow: lastPinnedColumn ? '-3px 0 0 0 rgba(0, 0, 0, 0.06) inset' : undefined, left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined, position: isPinned ? 'sticky' : 'unset', zIndex: isPinned ? 1 : undefined, }; }; const activeness: Record = { active: 'success', inactive: 'hint', }; const columnSizingHandler = ( thElem: HTMLTableCellElement | null, table: TanstackTable, column: Column, ) => { if (!thElem) return; if (table.getState().columnSizing[column.id] !== undefined) return; if (table.getState().columnSizing[column.id] === thElem.getBoundingClientRect().width) return; table.setColumnSizing((prevSizes) => ({ ...prevSizes, [column.id]: thElem.getBoundingClientRect().width, })); }; ``` ### Collapsed ```tsx import type { CSSProperties } from 'react'; import { useMemo, useState } from 'react'; import { makeStateUpdater } from '@tanstack/react-table'; import type { Column, ColumnDef, OnChangeFn, RowData, TableFeature, Table as TanstackTable, Updater, } from '@tanstack/react-table'; import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import { Badge, Box, Card, HStack, IconButton, Table } from '@vapor-ui/core'; import { ChevronDoubleLeftOutlineIcon, ChevronDoubleRightOutlineIcon } from '@vapor-ui/icons'; export default function Collapsed() { const columns = useMemo[]>( () => [ { header: () => ID, accessorKey: 'id', cell: ({ row }) => {row.index + 1}, }, { header: ({ column }) => { const isCollapsed = column.getIsCollapsed(); const IconElement = isCollapsed ? ChevronDoubleRightOutlineIcon : ChevronDoubleLeftOutlineIcon; return ( {isCollapsed ? '' : 'Name'} column.toggleCollapsed()} > ); }, accessorKey: 'name', cell: ({ row, column }) => { const isCollapsed = column.getIsCollapsed(); return ( {row.getValue('name')} ); }, }, { header: 'Status', accessorKey: 'status', cell: ({ row }) => { const status = row.getValue('status'); return ( {status.toUpperCase()} ); }, }, { header: () => Role, accessorKey: 'role', }, { header: () => Last Active, accessorKey: 'last-active', }, ], [], ); const [columnCollapsed, setColumnCollapsed] = useState(['name']); // 초기에 접힐 컬럼들 const table = useReactTable({ _features: [ColumnCollapsedFeature], data: datas, columns, state: { columnPinning: { left: ['id', 'name'] }, columnCollapsed, }, enableRowSelection: true, getCoreRowModel: getCoreRowModel(), onColumnCollapsedChange: setColumnCollapsed, }); return ( {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( columnSizingHandler(thElem, table, header.column) } backgroundColor="$gray-050" style={{ ...getCommonPinningStyles(header.column) }} > {flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => { return ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ); })} ); } /* -----------------------------------------------------------------------------------------------*/ type Data = { name: string; status: 'active' | 'inactive'; role: string; 'last-active': string; }; const datas: Data[] = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const getCommonPinningStyles = (column: Column): CSSProperties => { const isPinned = column.getIsPinned(); const lastPinnedColumn = isPinned === 'left' && column.getIsLastColumn('left'); return { boxShadow: lastPinnedColumn ? '-3px 0 0 0 rgba(0, 0, 0, 0.06) inset' : undefined, left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined, position: isPinned ? 'sticky' : 'unset', zIndex: isPinned ? 1 : undefined, }; }; const activeness: Record = { active: 'success', inactive: 'hint', }; const columnSizingHandler = ( thElem: HTMLTableCellElement | null, table: TanstackTable, column: Column, ) => { if (!thElem) return; const currentSize = table.getState().columnSizing[column.id]; const elementWidth = thElem.getBoundingClientRect().width; if (currentSize === elementWidth) return; table.setColumnSizing((prevSizes) => ({ ...prevSizes, [column.id]: elementWidth, })); }; /* -----------------------------------------------------------------------------------------------*/ export type ColumnCollapsedState = string[]; export interface ColumnCollapsedTableState { columnCollapsed: ColumnCollapsedState; } export interface ColumnCollapsedOptions { enableColumnCollapsed?: boolean; onColumnCollapsedChange?: OnChangeFn; } export interface ColumnCollapsedColumnInstance { getIsCollapsed: () => boolean; toggleCollapsed: () => void; } declare module '@tanstack/react-table' { interface TableState extends ColumnCollapsedTableState {} // eslint-disable-next-line @typescript-eslint/no-unused-vars interface TableOptionsResolved extends ColumnCollapsedOptions {} // eslint-disable-next-line @typescript-eslint/no-unused-vars interface Column extends ColumnCollapsedColumnInstance {} } export const ColumnCollapsedFeature: TableFeature = { getInitialState: (state): ColumnCollapsedTableState => { return { columnCollapsed: [], ...state, }; }, getDefaultOptions: ( table: TanstackTable, ): ColumnCollapsedOptions => { return { enableColumnCollapsed: true, onColumnCollapsedChange: makeStateUpdater('columnCollapsed', table), }; }, createColumn: ( column: Column, table: TanstackTable, ): void => { column.getIsCollapsed = () => { return table.getState().columnCollapsed?.includes(column.id) ?? false; }; column.toggleCollapsed = () => { const currentState = column.getIsCollapsed(); const updater: Updater = (old) => { if (currentState) return old.filter((id) => id !== column.id); return [...old, column.id]; }; table.options.onColumnCollapsedChange?.(updater); }; }, }; ``` ### Sort ```tsx import { useMemo, useState } from 'react'; import type { SortingState } from '@tanstack/react-table'; import { type ColumnDef, flexRender, getCoreRowModel, getSortedRowModel, useReactTable, } from '@tanstack/react-table'; import { Badge, Box, Card, HStack, IconButton, Table } from '@vapor-ui/core'; import { ControlCommonIcon } from '@vapor-ui/icons'; export default function Sort() { const columns = useMemo[]>( () => [ { id: 'index', header: 'ID', accessorFn: (_, index) => index + 1, cell: ({ getValue }) => {String(getValue() ?? '.')}, }, { header: 'Name', accessorKey: 'name', cell: (info) => info.getValue(), }, { accessorKey: 'status', cell: ({ getValue }) => { const status = getValue(); return ( {status.toUpperCase()} ); }, }, { accessorKey: 'role', cell: (info) => info.getValue(), }, { accessorKey: 'last-active', cell: (info) => info.getValue(), sortingFn: 'datetime', }, ], [], ); const [sorting, setSorting] = useState([]); const table = useReactTable({ data: datas, columns, state: { sorting }, enableRowSelection: true, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), onSortingChange: setSorting, }); return ( {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => { return ( {row.getVisibleCells().map((cell) => { return ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ); })} ); })} ); } type Data = { name: string; status: 'active' | 'inactive'; role: string; 'last-active': string; }; const datas: Data[] = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const activeness: Record = { active: 'success', inactive: 'hint', }; ``` ### Scroll ```tsx import { useMemo, useState } from 'react'; import { type ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import { Badge, Box, Card, Table } from '@vapor-ui/core'; export default function Scroll() { const [rowSelection, setRowSelection] = useState({}); const columns = useMemo[]>( () => [ { accessorKey: 'id', header: () => ID, cell: ({ row }) => {row.index + 1}, }, { header: 'Name', accessorKey: 'name', cell: ({ row }) => {row.getValue('name')}, }, { header: 'Status', accessorKey: 'status', cell: ({ row }) => { const status = row.getValue('status'); return ( {status.toUpperCase()} ); }, }, { header: () => 'Role', accessorKey: 'role', }, { header: () => 'Last Active', accessorKey: 'last-active', }, ], [], ); const table = useReactTable({ data: datas, columns, state: { rowSelection, columnPinning: { left: ['id', 'name'] } }, enableRowSelection: true, onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), }); return ( {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => { return ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ); })} ); } type Data = { name: string; status: 'active' | 'inactive'; role: string; 'last-active': string; }; const datas: Data[] = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const activeness: Record = { active: 'success', inactive: 'hint', }; ``` ### Filter ```tsx import { useMemo, useState } from 'react'; import type { ColumnFiltersState, Row } from '@tanstack/react-table'; import { type ColumnDef, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, useReactTable, } from '@tanstack/react-table'; import { Badge, Box, Button, Card, HStack, MultiSelect, Select, Table, Text, TextInput, } from '@vapor-ui/core'; import { PlusOutlineIcon, SearchOutlineIcon } from '@vapor-ui/icons'; // eslint-disable-next-line @typescript-eslint/no-explicit-any const customFilterFn = (row: Row, columnId: string, filterValue: any) => { if (!filterValue || filterValue.length === 0) return true; const cellValue = row.getValue(columnId) as string; return filterValue.includes(cellValue); }; export default function Scroll() { const columns = useMemo[]>( () => [ { header: () => ID, accessorKey: 'id', size: 0, // prevent cumulative layout shift cell: ({ row }) => {row.index + 1}, }, { header: 'Name', accessorKey: 'name', size: 0, // prevent cumulative layout shift cell: ({ row }) =>
{row.getValue('name')}
, }, { header: 'Status', accessorKey: 'status', cell: ({ row }) => { const status = row.getValue('status'); return ( {status.toUpperCase()} ); }, filterFn: customFilterFn, }, { header: 'Role', accessorKey: 'role', filterFn: customFilterFn, }, { header: 'Last Active', accessorKey: 'last-active', }, ], [], ); const [columnFilters, setColumnFilters] = useState([]); const table = useReactTable({ data: datas, columns, state: { columnFilters }, enableRowSelection: true, getCoreRowModel: getCoreRowModel(), getFilteredRowModel: getFilteredRowModel(), getPaginationRowModel: getPaginationRowModel(), onColumnFiltersChange: setColumnFilters, }); return ( 출석부 table.getColumn('name')?.setFilterValue(value) } /> { table.getColumn('status')?.setFilterValue(value); }} content={ <> Active Inactive } /> table.getColumn('role')?.setFilterValue(value) } content={ <> Designer Developer } /> col.getIsVisible()) .map((col) => col.id)} content={table .getAllColumns() .filter((column) => column.getCanHide()) .map((column) => ( column.toggleVisibility()} > {column.id} ))} /> {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.length ? ( table.getRowModel().rows.map((row) => { return ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ); }) ) : ( 검색 결과가 없습니다. )} table.setPageSize(Number(value))} > {(value) => `${value}개씩 보기`} {[5, 10, 20, 30, 40, 50].map((pageSize) => ( {pageSize} ))} ); } type Data = { name: string; status: 'active' | 'inactive'; role: string; 'last-active': string; }; const datas: Data[] = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const activeness: Record = { active: 'success', inactive: 'hint', }; /* -----------------------------------------------------------------------------------------------*/ interface FilterSelectProps extends React.ComponentProps { triggerLabel: string; content: React.ReactNode; } const FilterSelect = ({ content, triggerLabel, ...props }: FilterSelectProps) => { return ( } style={{ width: 'unset' }} > {triggerLabel} }> {content} ); }; ```
### Pagination ```tsx import { useMemo, useState } from 'react'; import type { ColumnFiltersState, Row } from '@tanstack/react-table'; import { type ColumnDef, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, useReactTable, } from '@tanstack/react-table'; import { Badge, Button, Card, HStack, MultiSelect, Pagination, Select, Table, Text, TextInput, } from '@vapor-ui/core'; import { PlusOutlineIcon, SearchOutlineIcon } from '@vapor-ui/icons'; // eslint-disable-next-line @typescript-eslint/no-explicit-any const customFilterFn = (row: Row, columnId: string, filterValue: any) => { if (!filterValue || filterValue.length === 0) return true; const cellValue = row.getValue(columnId) as string; return filterValue.includes(cellValue); }; export default function WithPagination() { const columns = useMemo[]>( () => [ { header: () =>
ID
, accessorKey: 'id', size: 0, // prevent cumulative layout shift cell: ({ row }) =>
{row.index + 1}
, }, { header: 'Name', accessorKey: 'name', size: 0, // prevent cumulative layout shift cell: ({ row }) =>
{row.getValue('name')}
, }, { header: 'Status', accessorKey: 'status', cell: ({ row }) => { const status = row.getValue('status'); return ( {status.toUpperCase()} ); }, filterFn: customFilterFn, }, { header: 'Role', accessorKey: 'role', filterFn: customFilterFn, }, { header: 'Last Active', accessorKey: 'last-active', }, ], [], ); const [columnFilters, setColumnFilters] = useState([]); const table = useReactTable({ data: datas, columns, state: { columnFilters }, enableRowSelection: true, getCoreRowModel: getCoreRowModel(), getFilteredRowModel: getFilteredRowModel(), getPaginationRowModel: getPaginationRowModel(), onColumnFiltersChange: setColumnFilters, }); return ( 출석부 table.getColumn('name')?.setFilterValue(value) } /> { table.getColumn('status')?.setFilterValue(value); }} content={ <> Active Inactive } /> table.getColumn('role')?.setFilterValue(value) } content={ <> Designer Developer } /> col.getIsVisible()) .map((col) => col.id)} content={table .getAllColumns() .filter((column) => column.getCanHide()) .map((column) => ( column.toggleVisibility()} > {column.id} ))} /> {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.length ? ( table.getRowModel().rows.map((row) => { return ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ); }) ) : ( 검색 결과가 없습니다. )} table.setPageIndex(page - 1)} > table.setPageSize(Number(value))} > {(value) => `${value}개씩 보기`} {[5, 10, 20, 30, 40, 50].map((pageSize) => ( {pageSize} ))} ); } type Data = { name: string; status: 'active' | 'inactive'; role: string; 'last-active': string; }; const datas: Data[] = [ { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, { name: 'Olivia Park', status: 'active', role: 'designer', 'last-active': '2 hours ago' }, { name: 'Ethan Kim', status: 'active', role: 'developer', 'last-active': '3 days ago' }, { name: 'Mia Choi', status: 'inactive', role: 'developer', 'last-active': '10 minutes ago' }, { name: 'Noah Lee', status: 'active', role: 'designer', 'last-active': '1 day ago' }, { name: 'Ava Jung', status: 'active', role: 'developer', 'last-active': '5 days ago' }, { name: 'Liam Han', status: 'inactive', role: 'developer', 'last-active': '5 days ago' }, { name: 'Emma Seo', status: 'active', role: 'designer', 'last-active': '7 days ago' }, { name: 'Mason Yoo', status: 'active', role: 'designer', 'last-active': '30 minutes ago' }, { name: 'Sophia Lim', status: 'inactive', role: 'designer', 'last-active': '4 hours ago' }, { name: 'Lucas Park', status: 'active', role: 'developer', 'last-active': '1 hour ago' }, ]; const activeness: Record = { active: 'success', inactive: 'hint', }; /* -----------------------------------------------------------------------------------------------*/ interface FilterSelectProps extends React.ComponentProps { triggerLabel: string; content: React.ReactNode; } const FilterSelect = ({ content, triggerLabel, ...props }: FilterSelectProps) => { return ( } style={{ width: 'unset' }} > {triggerLabel} }> {content} ); }; ```