Openstatus www.openstatus.dev
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: cli card (#1276)

* feat: cli card

* ci: apply automated fixes

* chore: typo

* fix: typo

* ci: apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

authored by

Maximilian Kaske
autofix-ci[bot]
and committed by
GitHub
ff935d91 b45e6016

+104
+2
apps/web/src/app/page.tsx
··· 1 1 import { MarketingLayout } from "@/components/layout/marketing-layout"; 2 2 import { AlertCard } from "@/components/marketing/alert/card"; 3 + import { CLICard } from "@/components/marketing/cli/card"; 3 4 import { Hero } from "@/components/marketing/hero"; 4 5 import { BottomCTA, MiddleCTA } from "@/components/marketing/in-between-cta"; 5 6 import { LatestChangelogs } from "@/components/marketing/lastest-changelogs"; ··· 21 22 <MiddleCTA /> 22 23 <StatusPageCard /> 23 24 <AlertCard /> 25 + <CLICard /> 24 26 <BottomCTA /> 25 27 <LatestChangelogs /> 26 28 </div>
+32
apps/web/src/components/marketing/cli/card.tsx
··· 1 + import { cardConfig } from "@/config/features"; 2 + import { 3 + CardContainer, 4 + CardContent, 5 + CardFeature, 6 + CardFeatureContainer, 7 + CardHeader, 8 + CardIcon, 9 + CardTitle, 10 + } from "../card"; 11 + import { Terminal } from "./terminal"; 12 + 13 + export function CLICard() { 14 + const { icon, title, features } = cardConfig.cli; 15 + return ( 16 + <CardContainer> 17 + <CardHeader> 18 + <CardIcon icon={icon} /> 19 + <CardTitle>{title}</CardTitle> 20 + </CardHeader> 21 + <CardContent> 22 + <Terminal /> 23 + <CardFeatureContainer> 24 + {features?.map((feature, i) => ( 25 + // biome-ignore lint/suspicious/noArrayIndexKey: <explanation> 26 + <CardFeature key={i} {...feature} /> 27 + ))} 28 + </CardFeatureContainer> 29 + </CardContent> 30 + </CardContainer> 31 + ); 32 + }
+45
apps/web/src/components/marketing/cli/terminal.tsx
··· 1 + "use client"; 2 + 3 + import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; 4 + import { cn } from "@/lib/utils"; 5 + import { Button } from "@openstatus/ui"; 6 + import { CheckIcon, CopyIcon } from "lucide-react"; 7 + import type React from "react"; 8 + 9 + const command = "openstatus monitors trigger 420"; 10 + 11 + export function Terminal({ className, ...props }: React.ComponentProps<"pre">) { 12 + const { copy, isCopied } = useCopyToClipboard(); 13 + 14 + function handleCopy() { 15 + copy(command, { withToast: true }); 16 + } 17 + 18 + return ( 19 + <div className="flex items-center w-full"> 20 + <pre 21 + className={cn( 22 + "bg-muted/50 w-full rounded-lg px-4 py-2 flex items-center gap-2 border", 23 + className, 24 + )} 25 + {...props} 26 + > 27 + <code className="text-sm"> 28 + <span className="text-muted-foreground">$</span> {command} 29 + </code> 30 + <Button 31 + variant="ghost" 32 + size="icon" 33 + onClick={handleCopy} 34 + className="ml-auto -mr-2 hover:bg-transparent" 35 + > 36 + {isCopied ? ( 37 + <CheckIcon className="size-4" /> 38 + ) : ( 39 + <CopyIcon className="size-4" /> 40 + )} 41 + </Button> 42 + </pre> 43 + </div> 44 + ); 45 + }
+25
apps/web/src/config/features.ts apps/web/src/config/features.tsx
··· 1 1 import type { ValidIcon } from "@/components/icons"; 2 + import { Terminal } from "@/components/marketing/cli/terminal"; 2 3 3 4 export type Feature = { 4 5 icon: ValidIcon; ··· 99 100 catchline: "Get alerted.", 100 101 description: 101 102 "Get notified via Email, SMS, Slack, Discord,... before your users do.", 103 + }, 104 + ], 105 + }, 106 + cli: { 107 + icon: "terminal", 108 + title: "CLI", 109 + features: [ 110 + { 111 + icon: "sparkles", 112 + catchline: "No ClickOps", 113 + description: ( 114 + <p> 115 + Use your config file to manage or trigger your monitors. Never leave 116 + your terminal.{" "} 117 + <a 118 + className="text-foreground" 119 + href="https://docs.openstatus.dev/cli/getting-started/" 120 + target="_blank" 121 + rel="noreferrer" 122 + > 123 + Learn more 124 + </a> 125 + </p> 126 + ), 102 127 }, 103 128 ], 104 129 },