mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Implement new color themes (#7592)
This commit is contained in:
parent
e853916513
commit
6709e719c1
230 changed files with 2729 additions and 2576 deletions
5
.changeset/thin-animals-smell.md
Normal file
5
.changeset/thin-animals-smell.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'hive': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
added light mode to console
|
||||||
|
|
@ -161,7 +161,7 @@ module.exports = {
|
||||||
rules: {
|
rules: {
|
||||||
// conflicts with official prettier-plugin-tailwindcss and tailwind v3
|
// conflicts with official prettier-plugin-tailwindcss and tailwind v3
|
||||||
'better-tailwindcss/enforce-consistent-class-order': 'off',
|
'better-tailwindcss/enforce-consistent-class-order': 'off',
|
||||||
'better-tailwindcss/enforce-canonical-classes': 'warn',
|
'better-tailwindcss/enforce-canonical-classes': 'off',
|
||||||
// keeping classes in one line helps prettier-plugin-tailwindcss
|
// keeping classes in one line helps prettier-plugin-tailwindcss
|
||||||
// enable wrapping in text editors to make classes human readable
|
// enable wrapping in text editors to make classes human readable
|
||||||
'better-tailwindcss/enforce-consistent-line-wrapping': 'off',
|
'better-tailwindcss/enforce-consistent-line-wrapping': 'off',
|
||||||
|
|
@ -214,10 +214,6 @@ module.exports = {
|
||||||
{
|
{
|
||||||
ignore: [
|
ignore: [
|
||||||
'drag-none',
|
'drag-none',
|
||||||
// Tailwind v4 semantic colors from @theme in index.css
|
|
||||||
// Regex patterns to match all utility variants (bg-*, text-*, border-*, etc.)
|
|
||||||
// Includes optional opacity modifier (/40, /60, etc.)
|
|
||||||
'(bg|text|border|ring|outline|shadow|from|via|to|fill|stroke|caret|accent|divide|placeholder)-(background|foreground|card|card-foreground|popover|popover-foreground|primary|primary-foreground|secondary|secondary-foreground|muted|muted-foreground|accent|accent-foreground|destructive|destructive-foreground|border|input|ring|sidebar|sidebar-background|sidebar-foreground|sidebar-primary|sidebar-primary-foreground|sidebar-accent|sidebar-accent-foreground|sidebar-border|sidebar-ring|chart-1|chart-2)(/.*)?',
|
|
||||||
// Animation utilities (from index.css, replaces tailwindcss-animate)
|
// Animation utilities (from index.css, replaces tailwindcss-animate)
|
||||||
'animate-in',
|
'animate-in',
|
||||||
'animate-out',
|
'animate-out',
|
||||||
|
|
|
||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -36,6 +36,9 @@
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||||
"git.mergeEditor": false,
|
"git.mergeEditor": false,
|
||||||
|
"tailwindCSS.experimental.configFile": {
|
||||||
|
"packages/web/app/src/index.css": "packages/web/app/**"
|
||||||
|
},
|
||||||
"tailwindCSS.classFunctions": ["cva", "cx", "cn", "clsx"],
|
"tailwindCSS.classFunctions": ["cva", "cx", "cn", "clsx"],
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,12 @@
|
||||||
<html lang="en" class="dark">
|
<html lang="en" class="dark">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="preconnect" href="https://rsms.me/" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,400..700;1,400..700&display=swap"
|
||||||
|
/>
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/svg+xml"
|
type="image/svg+xml"
|
||||||
|
|
@ -22,7 +26,7 @@
|
||||||
<script src="/__env.js"></script>
|
<script src="/__env.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="font-sans text-white" id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -426,7 +426,7 @@ export function AdminStats({
|
||||||
<DataWrapper query={query} organizationSlug={null}>
|
<DataWrapper query={query} organizationSlug={null}>
|
||||||
{({ data }) => (
|
{({ data }) => (
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
<div className="flex justify-between rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
<div className="border-neutral-5 bg-neutral-2/50 flex justify-between rounded-md border p-5">
|
||||||
<OverallStat label="Users" value={overall.users} />
|
<OverallStat label="Users" value={overall.users} />
|
||||||
<OverallStat label="Organizations" value={overall.organizations} />
|
<OverallStat label="Organizations" value={overall.organizations} />
|
||||||
<OverallStat label="Projects" value={overall.projects} />
|
<OverallStat label="Projects" value={overall.projects} />
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ export function AuthCardStack(props: { children: React.ReactNode }) {
|
||||||
export function AuthOrSeparator() {
|
export function AuthOrSeparator() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-row items-center justify-between gap-x-4">
|
<div className="flex flex-row items-center justify-between gap-x-4">
|
||||||
<div className="h-[1px] w-full bg-gray-700" />
|
<div className="bg-neutral-4 h-px w-full" />
|
||||||
<div className="text-center text-gray-400">or</div>
|
<div className="text-neutral-9 text-center">or</div>
|
||||||
<div className="h-[1px] w-full bg-gray-700" />
|
<div className="bg-neutral-4 h-px w-full" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ export function Label({ className, children, ...props }: ComponentProps<'span'>)
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-block rounded-sm bg-white/10 px-2 py-1 text-xs font-medium tracking-widest text-yellow-300',
|
'bg-accent_10 text-accent inline-block rounded-sm px-2 py-1 text-xs font-medium tracking-widest',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -36,15 +36,15 @@ export const Page = ({
|
||||||
<div className={cn('relative flex h-full flex-col', className)}>
|
<div className={cn('relative flex h-full flex-col', className)}>
|
||||||
<div className="flex shrink-0 flex-row items-center justify-between p-4">
|
<div className="flex shrink-0 flex-row items-center justify-between p-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-xl font-bold text-white">{title}</h2>
|
<h2 className="text-neutral-1 text-xl font-bold">{title}title</h2>
|
||||||
<span className="mt-2 text-sm text-gray-300">{subtitle}</span>
|
<span className="text-neutral-8 mt-2 text-sm">{subtitle}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center space-x-2">{actions}</div>
|
<div className="flex flex-row items-center space-x-2">{actions}</div>
|
||||||
</div>
|
</div>
|
||||||
{noPadding ? (
|
{noPadding ? (
|
||||||
children
|
children
|
||||||
) : (
|
) : (
|
||||||
<div className={cn('px-4 pb-4 text-white', scrollable ? 'grow overflow-y-auto' : 'h-full')}>
|
<div className={cn('px-4 pb-4', scrollable ? 'grow overflow-y-auto' : 'h-full')}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -54,17 +54,17 @@ export const Page = ({
|
||||||
|
|
||||||
export const Section = {
|
export const Section = {
|
||||||
Title: ({ className, children, ...props }: ComponentProps<'h3'>): ReactElement => (
|
Title: ({ className, children, ...props }: ComponentProps<'h3'>): ReactElement => (
|
||||||
<h3 className={cn('text-base font-bold text-white', className)} {...props}>
|
<h3 className={cn('text-neutral-11 text-base font-bold', className)} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</h3>
|
</h3>
|
||||||
),
|
),
|
||||||
BigTitle: ({ className, children, ...props }: ComponentProps<'h2'>): ReactElement => (
|
BigTitle: ({ className, children, ...props }: ComponentProps<'h2'>): ReactElement => (
|
||||||
<h2 className={cn('text-base font-bold text-white', className)} {...props}>
|
<h2 className={cn('text-neutral-11 text-base font-bold', className)} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</h2>
|
</h2>
|
||||||
),
|
),
|
||||||
Subtitle: ({ className, children, ...props }: ComponentProps<'div'>): ReactElement => (
|
Subtitle: ({ className, children, ...props }: ComponentProps<'div'>): ReactElement => (
|
||||||
<div className={cn('text-sm text-gray-300', className)} {...props}>
|
<div className={cn('text-neutral-10 text-sm', className)} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
|
@ -86,7 +86,7 @@ export function Scale({
|
||||||
{new Array(size).fill(null).map((_, i) => (
|
{new Array(size).fill(null).map((_, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className={cn('h-4 w-1', value >= i * (max / size) ? 'bg-emerald-400' : 'bg-gray-200')}
|
className={cn('h-4 w-1', value >= i * (max / size) ? 'bg-emerald-400' : 'bg-neutral-10')}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export function ErrorComponent(props: { error: any; message?: string }) {
|
||||||
<p>{commonErrorStrings.reported}</p>
|
<p>{commonErrorStrings.reported}</p>
|
||||||
<p>
|
<p>
|
||||||
{commonErrorStrings.track}{' '}
|
{commonErrorStrings.track}{' '}
|
||||||
<Button variant="link" className="h-auto p-0 text-orange-500" asChild>
|
<Button variant="link" className="h-auto p-0" asChild>
|
||||||
<a href="mailto:support@graphql-hive.com">{commonErrorStrings.link}</a>
|
<a href="mailto:support@graphql-hive.com">{commonErrorStrings.link}</a>
|
||||||
</Button>
|
</Button>
|
||||||
.
|
.
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,14 @@ export function GetStartedProgress(props: {
|
||||||
props.className,
|
props.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="text-sm font-medium">Get Started</div>
|
<div className="text-neutral-11 text-sm font-medium">Get Started</div>
|
||||||
<div className="text-xs text-gray-500">
|
<div className="text-neutral-10 text-xs">
|
||||||
{remaining} remaining task{remaining > 1 ? 's' : ''}
|
{remaining} remaining task{remaining > 1 ? 's' : ''}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="relative mt-1 h-[5px] w-full overflow-hidden rounded-sm bg-gray-800">
|
<div className="bg-accent_30 relative mt-1 h-[5px] w-full overflow-hidden rounded-sm">
|
||||||
<div
|
<div
|
||||||
className="h-full bg-orange-500"
|
className="bg-accent_80 h-full"
|
||||||
style={{ width: `${(completed / total) * 100}%` }}
|
style={{ width: `${(completed / total) * 100}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -100,19 +100,19 @@ function Task({
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative block rounded-lg border border-gray-800 bg-gray-900 p-4 hover:bg-gray-800',
|
'border-neutral-5 hover:bg-neutral-5 bg-neutral-4 relative block rounded-lg border p-4',
|
||||||
completed ? 'opacity-70' : null,
|
completed ? 'opacity-70' : null,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-start space-x-3">
|
<div className="flex items-start space-x-3">
|
||||||
{completed ? (
|
{completed ? (
|
||||||
<CircleCheck className="size-5 text-orange-500" />
|
<CircleCheck className="text-accent size-5" />
|
||||||
) : (
|
) : (
|
||||||
<Circle className="size-5 text-orange-500" />
|
<Circle className="text-neutral-2 size-5" />
|
||||||
)}
|
)}
|
||||||
<div className="w-0 flex-1">
|
<div className="w-0 flex-1">
|
||||||
<p className="font-medium leading-5 text-white">{title}</p>
|
<p className="text-neutral-12 font-medium leading-5">{title}</p>
|
||||||
<p className="text-muted-foreground mt-1 text-sm">{description}</p>
|
<p className="text-neutral-10 mt-1 text-sm">{description}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
import { PrimaryNavigationLink } from '@/components/navigation/primary-navigation-link';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
||||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||||
import { Link, useRouter } from '@tanstack/react-router';
|
import { useRouter } from '@tanstack/react-router';
|
||||||
|
|
||||||
const OrganizationSelector_OrganizationConnectionFragment = graphql(`
|
const OrganizationSelector_OrganizationConnectionFragment = graphql(`
|
||||||
fragment OrganizationSelector_OrganizationConnectionFragment on OrganizationConnection {
|
fragment OrganizationSelector_OrganizationConnectionFragment on OrganizationConnection {
|
||||||
|
|
@ -27,18 +28,18 @@ export function OrganizationSelector(props: {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!organizations) {
|
if (!organizations) {
|
||||||
return <div className="h-5 w-48 animate-pulse rounded-full bg-gray-800" />;
|
return <div className="bg-neutral-5 h-5 w-48 animate-pulse rounded-full" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.isOIDCUser) {
|
if (props.isOIDCUser) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<PrimaryNavigationLink
|
||||||
to="/$organizationSlug"
|
linkProps={{
|
||||||
params={{ organizationSlug: props.currentOrganizationSlug }}
|
to: '/$organizationSlug',
|
||||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
params: { organizationSlug: props.currentOrganizationSlug },
|
||||||
>
|
}}
|
||||||
{props.currentOrganizationSlug}
|
linkText={props.currentOrganizationSlug}
|
||||||
</Link>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import { useForm, UseFormReturn } from 'react-hook-form';
|
||||||
import { useMutation, useQuery } from 'urql';
|
import { useMutation, useQuery } from 'urql';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { NotFoundContent } from '@/components/common/not-found-content';
|
import { NotFoundContent } from '@/components/common/not-found-content';
|
||||||
|
import { Header } from '@/components/navigation/header';
|
||||||
|
import { SecondaryNavigation } from '@/components/navigation/secondary-navigation';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
|
|
@ -123,26 +125,22 @@ export function OrganizationLayout({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header>
|
<Header>
|
||||||
<div className="h-(--header-height) container flex items-center justify-between">
|
<div className="flex flex-row items-center gap-4">
|
||||||
<div className="flex flex-row items-center gap-4">
|
<HiveLink className="size-8" />
|
||||||
<HiveLink className="size-8" />
|
<OrganizationSelector
|
||||||
<OrganizationSelector
|
isOIDCUser={query.data?.me.provider === AuthProviderType.Oidc}
|
||||||
isOIDCUser={query.data?.me.provider === AuthProviderType.Oidc}
|
currentOrganizationSlug={props.organizationSlug}
|
||||||
currentOrganizationSlug={props.organizationSlug}
|
organizations={query.data?.organizations ?? null}
|
||||||
organizations={query.data?.organizations ?? null}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<UserMenu
|
|
||||||
me={query.data?.me ?? null}
|
|
||||||
currentOrganizationSlug={props.organizationSlug}
|
|
||||||
organizations={query.data?.organizations ?? null}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
<UserMenu
|
||||||
<div className="h-(--tabs-navbar-height) relative border-b border-gray-800">
|
me={query.data?.me ?? null}
|
||||||
|
currentOrganizationSlug={props.organizationSlug}
|
||||||
|
organizations={query.data?.organizations ?? null}
|
||||||
|
/>
|
||||||
|
</Header>
|
||||||
|
<SecondaryNavigation>
|
||||||
<div className="container flex items-center justify-between">
|
<div className="container flex items-center justify-between">
|
||||||
{currentOrganization ? (
|
{currentOrganization ? (
|
||||||
<Tabs value={page} className="min-w-[600px]">
|
<Tabs value={page} className="min-w-[600px]">
|
||||||
|
|
@ -198,19 +196,14 @@ export function OrganizationLayout({
|
||||||
</Tabs>
|
</Tabs>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-row gap-x-8 border-b-2 border-b-transparent px-4 py-3">
|
<div className="flex flex-row gap-x-8 border-b-2 border-b-transparent px-4 py-3">
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{currentOrganization?.viewerCanCreateProject ? (
|
{currentOrganization?.viewerCanCreateProject ? (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button onClick={toggleModalOpen} variant="link" data-cy="new-project-button">
|
||||||
onClick={toggleModalOpen}
|
|
||||||
variant="link"
|
|
||||||
className="text-orange-500"
|
|
||||||
data-cy="new-project-button"
|
|
||||||
>
|
|
||||||
<PlusIcon size={16} className="mr-2" />
|
<PlusIcon size={16} className="mr-2" />
|
||||||
New project
|
New project
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -224,8 +217,8 @@ export function OrganizationLayout({
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</SecondaryNavigation>
|
||||||
<div className="container min-h-[var(--content-height)] pb-7">
|
<div className="min-h-(--content-height) container pb-7">
|
||||||
{currentOrganization ? (
|
{currentOrganization ? (
|
||||||
<>
|
<>
|
||||||
<ProPlanBilling organization={currentOrganization} />
|
<ProPlanBilling organization={currentOrganization} />
|
||||||
|
|
@ -297,15 +290,15 @@ function ProjectTypeCard(props: {
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="[&:has([data-state=checked])>div]:border-primary cursor-pointer">
|
<FormLabel className="[&:has([data-state=checked])>div]:border-accent_80 cursor-pointer">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<RadioGroupItem value={props.type} className="sr-only" />
|
<RadioGroupItem value={props.type} className="sr-only" />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<div className="border-muted hover:border-accent hover:bg-accent flex items-center gap-4 rounded-md border-2 p-4">
|
<div className="border-neutral-5 hover:border-neutral-2 flex items-center gap-4 rounded-md border p-4">
|
||||||
<Slot className="size-8 text-gray-400">{props.icon}</Slot>
|
<Slot className="text-neutral-12 size-8">{props.icon}</Slot>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-sm font-medium">{props.title}</span>
|
<span className="text-neutral-12 text-sm font-medium">{props.title}</span>
|
||||||
<p className="text-sm text-gray-400">{props.description}</p>
|
<p className="text-neutral-11 text-sm">{props.description}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
|
@ -427,7 +420,9 @@ export function CreateProjectModalContent(props: {
|
||||||
description="Single GraphQL schema developed as a monolith"
|
description="Single GraphQL schema developed as a monolith"
|
||||||
icon={
|
icon={
|
||||||
<BoxIcon
|
<BoxIcon
|
||||||
className={cn(field.value === ProjectType.Single && 'text-white')}
|
className={cn(
|
||||||
|
field.value === ProjectType.Single && 'text-neutral-12',
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
@ -437,7 +432,9 @@ export function CreateProjectModalContent(props: {
|
||||||
description="Project developed according to Apollo Federation specification"
|
description="Project developed according to Apollo Federation specification"
|
||||||
icon={
|
icon={
|
||||||
<BlocksIcon
|
<BlocksIcon
|
||||||
className={cn(field.value === ProjectType.Federation && 'text-white')}
|
className={cn(
|
||||||
|
field.value === ProjectType.Federation && 'text-neutral-12',
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
@ -447,7 +444,9 @@ export function CreateProjectModalContent(props: {
|
||||||
description="Project that stitches together multiple GraphQL APIs"
|
description="Project that stitches together multiple GraphQL APIs"
|
||||||
icon={
|
icon={
|
||||||
<FoldVerticalIcon
|
<FoldVerticalIcon
|
||||||
className={cn(field.value === ProjectType.Stitching && 'text-white')}
|
className={cn(
|
||||||
|
field.value === ProjectType.Stitching && 'text-neutral-12',
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
import { PrimaryNavigationLink } from '@/components/navigation/primary-navigation-link';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
||||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||||
import { Link, useRouter } from '@tanstack/react-router';
|
import { useRouter } from '@tanstack/react-router';
|
||||||
|
|
||||||
const ProjectSelector_OrganizationConnectionFragment = graphql(`
|
const ProjectSelector_OrganizationConnectionFragment = graphql(`
|
||||||
fragment ProjectSelector_OrganizationConnectionFragment on OrganizationConnection {
|
fragment ProjectSelector_OrganizationConnectionFragment on OrganizationConnection {
|
||||||
|
|
@ -43,19 +44,19 @@ export function ProjectSelector(props: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{currentOrganization ? (
|
{currentOrganization ? (
|
||||||
<Link
|
<PrimaryNavigationLink
|
||||||
to="/$organizationSlug"
|
linkProps={{
|
||||||
params={{ organizationSlug: props.currentOrganizationSlug }}
|
to: '/$organizationSlug',
|
||||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
params: { organizationSlug: props.currentOrganizationSlug },
|
||||||
>
|
}}
|
||||||
{currentOrganization.slug}
|
linkText={currentOrganization.slug}
|
||||||
</Link>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-5 w-48 max-w-[200px] animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-48 max-w-[200px] animate-pulse rounded-full" />
|
||||||
)}
|
)}
|
||||||
{projectEdges?.length && currentProject ? (
|
{projectEdges?.length && currentProject ? (
|
||||||
<>
|
<>
|
||||||
<div className="italic text-gray-500">/</div>
|
<div className="text-neutral-10 italic">/</div>
|
||||||
<Select
|
<Select
|
||||||
value={props.currentProjectSlug}
|
value={props.currentProjectSlug}
|
||||||
onValueChange={id => {
|
onValueChange={id => {
|
||||||
|
|
@ -87,7 +88,7 @@ export function ProjectSelector(props: {
|
||||||
</Select>
|
</Select>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-5 w-48 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-48 animate-pulse rounded-full" />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import { ReactNode } from 'react';
|
||||||
import { useForm, UseFormReturn } from 'react-hook-form';
|
import { useForm, UseFormReturn } from 'react-hook-form';
|
||||||
import { useMutation, useQuery } from 'urql';
|
import { useMutation, useQuery } from 'urql';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import { Header } from '@/components/navigation/header';
|
||||||
|
import { SecondaryNavigation } from '@/components/navigation/secondary-navigation';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
|
|
@ -86,32 +88,30 @@ export function ProjectLayout({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header>
|
<Header>
|
||||||
<div className="h-(--header-height) container flex items-center justify-between">
|
<div className="flex flex-row items-center gap-4">
|
||||||
<div className="flex flex-row items-center gap-4">
|
<HiveLink className="size-8" />
|
||||||
<HiveLink className="size-8" />
|
<ProjectSelector
|
||||||
<ProjectSelector
|
currentOrganizationSlug={props.organizationSlug}
|
||||||
currentOrganizationSlug={props.organizationSlug}
|
currentProjectSlug={props.projectSlug}
|
||||||
currentProjectSlug={props.projectSlug}
|
organizations={query.data?.organizations ?? null}
|
||||||
organizations={query.data?.organizations ?? null}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<UserMenu
|
|
||||||
me={me ?? null}
|
|
||||||
currentOrganizationSlug={props.organizationSlug}
|
|
||||||
organizations={query.data?.organizations ?? null}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
<div>
|
||||||
|
<UserMenu
|
||||||
|
me={me ?? null}
|
||||||
|
currentOrganizationSlug={props.organizationSlug}
|
||||||
|
organizations={query.data?.organizations ?? null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Header>
|
||||||
{query.fetching === false &&
|
{query.fetching === false &&
|
||||||
query.stale === false &&
|
query.stale === false &&
|
||||||
(currentProject === null || currentOrganization === null) ? (
|
(currentProject === null || currentOrganization === null) ? (
|
||||||
<ResourceNotFoundComponent title="404 - This project does not seem to exist." />
|
<ResourceNotFoundComponent title="404 - This project does not seem to exist." />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="h-(--tabs-navbar-height) relative border-b border-gray-800">
|
<SecondaryNavigation>
|
||||||
<div className="container flex items-center justify-between">
|
<div className="container flex items-center justify-between">
|
||||||
{currentOrganization && currentProject ? (
|
{currentOrganization && currentProject ? (
|
||||||
<Tabs value={page}>
|
<Tabs value={page}>
|
||||||
|
|
@ -155,13 +155,13 @@ export function ProjectLayout({
|
||||||
</Tabs>
|
</Tabs>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-row gap-x-8 border-b-2 border-b-transparent px-4 py-3">
|
<div className="flex flex-row gap-x-8 border-b-2 border-b-transparent px-4 py-3">
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{currentProject?.viewerCanCreateTarget ? (
|
{currentProject?.viewerCanCreateTarget ? (
|
||||||
<Button onClick={toggleModalOpen} variant="link" className="text-orange-500">
|
<Button onClick={toggleModalOpen} variant="link">
|
||||||
<PlusIcon size={16} className="mr-2" />
|
<PlusIcon size={16} className="mr-2" />
|
||||||
New target
|
New target
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -173,8 +173,8 @@ export function ProjectLayout({
|
||||||
toggleModalOpen={toggleModalOpen}
|
toggleModalOpen={toggleModalOpen}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</SecondaryNavigation>
|
||||||
<div className="container min-h-[var(--content-height)] pb-7">
|
<div className="min-h-(--content-height) container pb-7">
|
||||||
<div className={className}>{children}</div>
|
<div className={className}>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
import { PrimaryNavigationLink } from '@/components/navigation/primary-navigation-link';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
||||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||||
import { Link, useRouter } from '@tanstack/react-router';
|
import { useRouter } from '@tanstack/react-router';
|
||||||
|
|
||||||
const TargetSelector_OrganizationConnectionFragment = graphql(`
|
const TargetSelector_OrganizationConnectionFragment = graphql(`
|
||||||
fragment TargetSelector_OrganizationConnectionFragment on OrganizationConnection {
|
fragment TargetSelector_OrganizationConnectionFragment on OrganizationConnection {
|
||||||
|
|
@ -53,34 +54,32 @@ export function TargetSelector(props: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{currentOrganization ? (
|
{currentOrganization ? (
|
||||||
<Link
|
<PrimaryNavigationLink
|
||||||
to="/$organizationSlug"
|
linkProps={{
|
||||||
params={{
|
to: '/$organizationSlug',
|
||||||
organizationSlug: currentOrganization.slug,
|
params: { organizationSlug: currentOrganization.slug },
|
||||||
}}
|
}}
|
||||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
linkText={currentOrganization.slug}
|
||||||
>
|
/>
|
||||||
{currentOrganization.slug}
|
|
||||||
</Link>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="h-5 w-48 max-w-[200px] animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-48 max-w-[200px] animate-pulse rounded-full" />
|
||||||
)}
|
)}
|
||||||
<div className="italic text-gray-500">/</div>
|
<div className="text-neutral-10 italic">/</div>
|
||||||
{currentOrganization && currentProject ? (
|
{currentOrganization && currentProject ? (
|
||||||
<Link
|
<PrimaryNavigationLink
|
||||||
to="/$organizationSlug/$projectSlug"
|
linkProps={{
|
||||||
params={{
|
to: '/$organizationSlug/$projectSlug',
|
||||||
organizationSlug: props.currentOrganizationSlug,
|
params: {
|
||||||
projectSlug: props.currentProjectSlug,
|
organizationSlug: props.currentOrganizationSlug,
|
||||||
|
projectSlug: props.currentProjectSlug,
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
linkText={currentProject.slug}
|
||||||
>
|
/>
|
||||||
{currentProject.slug}
|
|
||||||
</Link>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="h-5 w-48 max-w-[200px] animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-48 max-w-[200px] animate-pulse rounded-full" />
|
||||||
)}
|
)}
|
||||||
<div className="italic text-gray-500">/</div>
|
<div className="text-neutral-10 italic">/</div>
|
||||||
{targetEdges?.length && currentOrganization && currentProject && currentTarget ? (
|
{targetEdges?.length && currentOrganization && currentProject && currentTarget ? (
|
||||||
<>
|
<>
|
||||||
<Select
|
<Select
|
||||||
|
|
@ -112,7 +111,7 @@ export function TargetSelector(props: {
|
||||||
</Select>
|
</Select>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-5 w-48 max-w-[200px] animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-48 max-w-[200px] animate-pulse rounded-full" />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { createContext, ReactElement, ReactNode, useContext, useMemo, useState } from 'react';
|
import { createContext, ReactElement, ReactNode, useContext, useMemo, useState } from 'react';
|
||||||
import { LinkIcon } from 'lucide-react';
|
import { LinkIcon } from 'lucide-react';
|
||||||
import { useQuery } from 'urql';
|
import { useQuery } from 'urql';
|
||||||
|
import { Header } from '@/components/navigation/header';
|
||||||
|
import { SecondaryNavigation } from '@/components/navigation/secondary-navigation';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
|
|
@ -156,26 +158,24 @@ export const TargetLayout = ({
|
||||||
projectSlug={props.projectSlug}
|
projectSlug={props.projectSlug}
|
||||||
targetSlug={props.targetSlug}
|
targetSlug={props.targetSlug}
|
||||||
>
|
>
|
||||||
<header>
|
<Header>
|
||||||
<div className="h-(--header-height) container flex items-center justify-between">
|
<div className="flex flex-row items-center gap-4">
|
||||||
<div className="flex flex-row items-center gap-4">
|
<HiveLink className="size-8" />
|
||||||
<HiveLink className="size-8" />
|
<TargetSelector
|
||||||
<TargetSelector
|
organizations={query.data?.organizations ?? null}
|
||||||
organizations={query.data?.organizations ?? null}
|
currentOrganizationSlug={props.organizationSlug}
|
||||||
currentOrganizationSlug={props.organizationSlug}
|
currentProjectSlug={props.projectSlug}
|
||||||
currentProjectSlug={props.projectSlug}
|
currentTargetSlug={props.targetSlug}
|
||||||
currentTargetSlug={props.targetSlug}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<UserMenu
|
|
||||||
me={me ?? null}
|
|
||||||
currentOrganizationSlug={props.organizationSlug}
|
|
||||||
organizations={query.data?.organizations ?? null}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
<div>
|
||||||
|
<UserMenu
|
||||||
|
me={me ?? null}
|
||||||
|
currentOrganizationSlug={props.organizationSlug}
|
||||||
|
organizations={query.data?.organizations ?? null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Header>
|
||||||
|
|
||||||
{query.fetching === false &&
|
{query.fetching === false &&
|
||||||
query.stale === false &&
|
query.stale === false &&
|
||||||
|
|
@ -183,7 +183,7 @@ export const TargetLayout = ({
|
||||||
<ResourceNotFoundComponent title="404 - This project does not seem to exist." />
|
<ResourceNotFoundComponent title="404 - This project does not seem to exist." />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="h-(--tabs-navbar-height) relative border-b border-gray-800">
|
<SecondaryNavigation>
|
||||||
<div className="container flex items-center justify-between">
|
<div className="container flex items-center justify-between">
|
||||||
{currentOrganization && currentProject && currentTarget ? (
|
{currentOrganization && currentProject && currentTarget ? (
|
||||||
<Tabs className="flex h-full grow flex-col" value={page}>
|
<Tabs className="flex h-full grow flex-col" value={page}>
|
||||||
|
|
@ -323,9 +323,9 @@ export const TargetLayout = ({
|
||||||
</Tabs>
|
</Tabs>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-row gap-x-8 border-b-2 border-b-transparent px-4 py-3">
|
<div className="flex flex-row gap-x-8 border-b-2 border-b-transparent px-4 py-3">
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{currentTarget && isCDNEnabled && (
|
{currentTarget && isCDNEnabled && (
|
||||||
|
|
@ -333,7 +333,7 @@ export const TargetLayout = ({
|
||||||
<Button
|
<Button
|
||||||
onClick={toggleModalOpen}
|
onClick={toggleModalOpen}
|
||||||
variant="link"
|
variant="link"
|
||||||
className="hidden whitespace-nowrap text-orange-500 md:flex"
|
className="hidden whitespace-nowrap md:flex"
|
||||||
>
|
>
|
||||||
<LinkIcon size={16} className="mr-2" />
|
<LinkIcon size={16} className="mr-2" />
|
||||||
Connect to CDN
|
Connect to CDN
|
||||||
|
|
@ -348,10 +348,8 @@ export const TargetLayout = ({
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</SecondaryNavigation>
|
||||||
<div className={cn('container min-h-[var(--content-height)] pb-7', className)}>
|
<div className={cn('min-h-(--content-height) container pb-7', className)}>{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</TargetReferenceProvider>
|
</TargetReferenceProvider>
|
||||||
|
|
|
||||||
11
packages/web/app/src/components/navigation/header.tsx
Normal file
11
packages/web/app/src/components/navigation/header.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
type HeaderProps = {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Header({ children }: HeaderProps) {
|
||||||
|
return (
|
||||||
|
<div className="h-(--header-height) bg-neutral-3">
|
||||||
|
<header className="container flex h-full items-center justify-between">{children}</header>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { Link, LinkProps } from '@tanstack/react-router';
|
||||||
|
|
||||||
|
type PrimaryNavigationLinkProps = {
|
||||||
|
linkText: string;
|
||||||
|
linkProps: Pick<LinkProps, 'to' | 'params'>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function PrimaryNavigationLink({ linkProps, linkText }: PrimaryNavigationLinkProps) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={linkProps.to}
|
||||||
|
params={linkProps.params}
|
||||||
|
className="text-neutral-11 max-w-[200px] shrink-0 truncate font-medium"
|
||||||
|
>
|
||||||
|
{linkText}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
type SecondaryNavigationProps = {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SecondaryNavigation({ children }: SecondaryNavigationProps) {
|
||||||
|
return (
|
||||||
|
<div className="h-(--tabs-navbar-height) border-neutral-5 bg-neutral-3 relative border-b">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -44,8 +44,8 @@ export const PermissionScopeItem = <
|
||||||
data-cy={props.dataCy}
|
data-cy={props.dataCy}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div className="font-semibold text-white">{props.scope.name}</div>
|
<div className="text-neutral-12 font-semibold">{props.scope.name}</div>
|
||||||
<div className="text-xs text-gray-400">{props.scope.description}</div>
|
<div className="text-neutral-10 text-xs">{props.scope.description}</div>
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<Select
|
||||||
disabled={!props.canManageScope || props.disabled}
|
disabled={!props.canManageScope || props.disabled}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ const planCollection: {
|
||||||
href="https://the-guild.dev"
|
href="https://the-guild.dev"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="font-medium text-orange-500 transition-colors hover:underline"
|
className="text-neutral-2 font-medium transition-colors hover:underline"
|
||||||
>
|
>
|
||||||
The Guild
|
The Guild
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -84,16 +84,16 @@ function Plan(plan: {
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
${plan.price}
|
${plan.price}
|
||||||
<span className="text-sm text-gray-500">/mo</span>
|
<span className="text-neutral-10 text-sm">/mo</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-500">{plan.description}</div>
|
<div className="text-neutral-10 text-sm">{plan.description}</div>
|
||||||
<div className="mt-6 flex flex-col gap-2">
|
<div className="mt-6 flex flex-col gap-2">
|
||||||
{plan.features.map((feature, i) => (
|
{plan.features.map((feature, i) => (
|
||||||
<div key={i}>
|
<div key={i}>
|
||||||
<Section.Subtitle className="flex items-center gap-1">
|
<Section.Subtitle className="flex items-center gap-1">
|
||||||
<CheckIcon className="h-5 w-auto text-gray-500" />
|
<CheckIcon className="text-neutral-10 h-5 w-auto" />
|
||||||
{feature}
|
{feature}
|
||||||
</Section.Subtitle>
|
</Section.Subtitle>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -102,8 +102,8 @@ function Plan(plan: {
|
||||||
</div>
|
</div>
|
||||||
{plan.footer && (
|
{plan.footer && (
|
||||||
<div>
|
<div>
|
||||||
<div className="mx-auto my-4 w-9/12 border-b border-gray-800" />
|
<div className="border-neutral-5 mx-auto my-4 w-9/12 border-b" />
|
||||||
<div className="text-xs text-gray-300">{plan.footer}</div>
|
<div className="text-neutral-11 text-xs">{plan.footer}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ function PriceEstimationTable(props: {
|
||||||
<TBody>
|
<TBody>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Td>
|
<Td>
|
||||||
Base price <span className="text-gray-500">(unlimited seats)</span>
|
Base price <span className="text-neutral-10">(unlimited seats)</span>
|
||||||
</Td>
|
</Td>
|
||||||
<Td align="right" />
|
<Td align="right" />
|
||||||
<Td align="right">{CurrencyFormatter.format(plan.basePrice ?? 0)}</Td>
|
<Td align="right">{CurrencyFormatter.format(plan.basePrice ?? 0)}</Td>
|
||||||
|
|
@ -46,7 +46,7 @@ function PriceEstimationTable(props: {
|
||||||
{includedOperationsInMillions > 0 && (
|
{includedOperationsInMillions > 0 && (
|
||||||
<Tr>
|
<Tr>
|
||||||
<Td>
|
<Td>
|
||||||
Included Operations <span className="text-gray-500">(free)</span>
|
Included Operations <span className="text-neutral-10">(free)</span>
|
||||||
</Td>
|
</Td>
|
||||||
<Td align="right">{includedOperationsInMillions}M</Td>
|
<Td align="right">{includedOperationsInMillions}M</Td>
|
||||||
<Td align="right">{CurrencyFormatter.format(0)}</Td>
|
<Td align="right">{CurrencyFormatter.format(0)}</Td>
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export function RoleSelector<T>(props: {
|
||||||
>
|
>
|
||||||
{props.defaultRole?.name ?? 'Select role'}
|
{props.defaultRole?.name ?? 'Select role'}
|
||||||
</span>
|
</span>
|
||||||
<ChevronDownIcon className="text-muted-foreground ml-2 size-4" />
|
<ChevronDownIcon className="text-neutral-10 ml-2 size-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-[400px] p-0" align="end">
|
<PopoverContent className="w-[400px] p-0" align="end">
|
||||||
|
|
@ -81,7 +81,7 @@ export function RoleSelector<T>(props: {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>None</p>
|
<p>None</p>
|
||||||
<p className="text-muted-foreground text-sm">Do not assign a role</p>
|
<p className="text-neutral-10 text-sm">Do not assign a role</p>
|
||||||
</CommandItem>
|
</CommandItem>
|
||||||
) : null}
|
) : null}
|
||||||
{props.roles.map(role => {
|
{props.roles.map(role => {
|
||||||
|
|
@ -118,7 +118,7 @@ export function RoleSelector<T>(props: {
|
||||||
disabled={!isActive}
|
disabled={!isActive}
|
||||||
>
|
>
|
||||||
<p>{role.name}</p>
|
<p>{role.name}</p>
|
||||||
<p className="text-muted-foreground text-sm">{role.description}</p>
|
<p className="text-neutral-10 text-sm">{role.description}</p>
|
||||||
</CommandItem>
|
</CommandItem>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>{reason}</TooltipContent>
|
<TooltipContent>{reason}</TooltipContent>
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ function MemberInvitationForm(props: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="text-red-500">Viewer role not found in organization member roles</div>
|
<div className="text-red-500">Viewer role not found in organization member roles</div>
|
||||||
<div className="text-gray-400">Please contact support.</div>
|
<div className="text-neutral-10">Please contact support.</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -190,7 +190,7 @@ function MemberInvitationForm(props: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="text-red-500">Viewer role not found in organization member roles</div>
|
<div className="text-red-500">Viewer role not found in organization member roles</div>
|
||||||
<div className="text-gray-400">Please contact support.</div>
|
<div className="text-neutral-10">Please contact support.</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -423,13 +423,13 @@ function Invitation(props: {
|
||||||
<td className="truncate py-3 text-center text-sm" title={invitation.role.name}>
|
<td className="truncate py-3 text-center text-sm" title={invitation.role.name}>
|
||||||
{invitation.role.name}
|
{invitation.role.name}
|
||||||
</td>
|
</td>
|
||||||
<td className="py-3 text-center text-sm text-gray-400">
|
<td className="text-neutral-10 py-3 text-center text-sm">
|
||||||
{DateFormatter.format(new Date(invitation.expiresAt))}
|
{DateFormatter.format(new Date(invitation.expiresAt))}
|
||||||
</td>
|
</td>
|
||||||
<td className="py-3 text-right text-sm">
|
<td className="py-3 text-right text-sm">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="ghost" className="data-[state=open]:bg-muted flex size-8 p-0">
|
<Button variant="ghost" className="data-[state=open]:bg-neutral-3 flex size-8 p-0">
|
||||||
<MoreHorizontalIcon className="size-4" />
|
<MoreHorizontalIcon className="size-4" />
|
||||||
<span className="sr-only">Open menu</span>
|
<span className="sr-only">Open menu</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -494,7 +494,7 @@ export function OrganizationInvitations(props: {
|
||||||
/>
|
/>
|
||||||
</SubPageLayoutHeader>
|
</SubPageLayoutHeader>
|
||||||
{organization.invitations.edges.length > 0 ? (
|
{organization.invitations.edges.length > 0 ? (
|
||||||
<table className="w-full table-fixed divide-y-[1px] divide-gray-500/20">
|
<table className="divide-neutral-10/20 w-full table-fixed divide-y">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="w-[100px] py-3 text-left text-sm font-semibold sm:w-auto">Email</th>
|
<th className="w-[100px] py-3 text-left text-sm font-semibold sm:w-auto">Email</th>
|
||||||
|
|
@ -503,7 +503,7 @@ export function OrganizationInvitations(props: {
|
||||||
<th className="w-12 py-3 text-right text-sm font-semibold" />
|
<th className="w-12 py-3 text-right text-sm font-semibold" />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="max-w-full divide-y-[1px] divide-gray-500/20">
|
<tbody className="divide-neutral-10/20 max-w-full divide-y">
|
||||||
{organization.invitations.edges.map(edge => (
|
{organization.invitations.edges.map(edge => (
|
||||||
<Invitation
|
<Invitation
|
||||||
key={edge.node.id}
|
key={edge.node.id}
|
||||||
|
|
@ -517,10 +517,10 @@ export function OrganizationInvitations(props: {
|
||||||
) : (
|
) : (
|
||||||
<div className="flex h-[250px] shrink-0 items-center justify-center rounded-md border border-dashed">
|
<div className="flex h-[250px] shrink-0 items-center justify-center rounded-md border border-dashed">
|
||||||
<div className="mx-auto flex max-w-[420px] flex-col items-center justify-center text-center">
|
<div className="mx-auto flex max-w-[420px] flex-col items-center justify-center text-center">
|
||||||
<MailQuestionIcon className="text-muted-foreground size-10" />
|
<MailQuestionIcon className="text-neutral-10 size-10" />
|
||||||
|
|
||||||
<h3 className="mt-4 text-lg font-semibold">No invitations</h3>
|
<h3 className="mt-4 text-lg font-semibold">No invitations</h3>
|
||||||
<p className="text-muted-foreground mb-4 mt-2 text-sm">
|
<p className="text-neutral-10 mb-4 mt-2 text-sm">
|
||||||
Invitations to join this organization will appear here.
|
Invitations to join this organization will appear here.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ const OrganizationMemberRow = memo(function OrganizationMemberRow(props: {
|
||||||
</td>
|
</td>
|
||||||
<td className="grow overflow-hidden py-3 text-sm font-medium">
|
<td className="grow overflow-hidden py-3 text-sm font-medium">
|
||||||
<h3 className="line-clamp-1 font-medium">{member.user.displayName}</h3>
|
<h3 className="line-clamp-1 font-medium">{member.user.displayName}</h3>
|
||||||
<h4 className="text-xs text-gray-400">{member.user.email}</h4>
|
<h4 className="text-neutral-10 text-xs">{member.user.email}</h4>
|
||||||
</td>
|
</td>
|
||||||
<td className="relative py-3 text-center text-sm">
|
<td className="relative py-3 text-center text-sm">
|
||||||
{member.isOwner ? (
|
{member.isOwner ? (
|
||||||
|
|
@ -199,7 +199,7 @@ const OrganizationMemberRow = memo(function OrganizationMemberRow(props: {
|
||||||
{member.viewerCanRemove && (
|
{member.viewerCanRemove && (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="ghost" className="data-[state=open]:bg-muted flex size-8 p-0">
|
<Button variant="ghost" className="data-[state=open]:bg-neutral-3 flex size-8 p-0">
|
||||||
<MoreHorizontalIcon className="size-4" />
|
<MoreHorizontalIcon className="size-4" />
|
||||||
<span className="sr-only">Open menu</span>
|
<span className="sr-only">Open menu</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -264,7 +264,7 @@ function MemberRole(props: {
|
||||||
{organization.viewerCanAssignUserRoles && (
|
{organization.viewerCanAssignUserRoles && (
|
||||||
<Sheet.Sheet open={isOpen} onOpenChange={isOpen => setIsOpen(isOpen)}>
|
<Sheet.Sheet open={isOpen} onOpenChange={isOpen => setIsOpen(isOpen)}>
|
||||||
<Sheet.SheetTrigger asChild>
|
<Sheet.SheetTrigger asChild>
|
||||||
<button className="font-medium text-orange-500 transition-colors hover:underline">
|
<button className="text-neutral-2 font-medium transition-colors hover:underline">
|
||||||
change
|
change
|
||||||
</button>
|
</button>
|
||||||
</Sheet.SheetTrigger>
|
</Sheet.SheetTrigger>
|
||||||
|
|
@ -377,7 +377,7 @@ export function OrganizationMembers(props: {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</SubPageLayoutHeader>
|
</SubPageLayoutHeader>
|
||||||
<table className="w-full table-auto divide-y-[1px] divide-gray-500/20">
|
<table className="divide-neutral-10/20 w-full table-auto divide-y-[1px]">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th colSpan={2} className="relative select-none py-3 text-left text-sm font-semibold">
|
<th colSpan={2} className="relative select-none py-3 text-left text-sm font-semibold">
|
||||||
|
|
@ -389,14 +389,14 @@ export function OrganizationMembers(props: {
|
||||||
<th className="w-12 py-3 text-right text-sm font-semibold" />
|
<th className="w-12 py-3 text-right text-sm font-semibold" />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y-[1px] divide-gray-500/20">
|
<tbody className="divide-neutral-10/20 divide-y-[1px]">
|
||||||
{members.length === 0 ? (
|
{members.length === 0 ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={4} className="py-16">
|
<td colSpan={4} className="py-16">
|
||||||
<div className="flex flex-col items-center justify-center px-4">
|
<div className="flex flex-col items-center justify-center px-4">
|
||||||
<h3 className="mb-2 text-lg font-semibold text-gray-100">No members found</h3>
|
<h3 className="text-neutral-11 mb-2 text-lg font-semibold">No members found</h3>
|
||||||
|
|
||||||
<p className="max-w-sm text-center text-sm text-gray-200">
|
<p className="text-neutral-10 max-w-sm text-center text-sm">
|
||||||
{`No results for "${searchValue}". Try adjusting your search term.`}
|
{`No results for "${searchValue}". Try adjusting your search term.`}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -415,7 +415,7 @@ export function OrganizationMembers(props: {
|
||||||
</table>
|
</table>
|
||||||
{/* Pagination Controls */}
|
{/* Pagination Controls */}
|
||||||
<div className="mt-4 flex items-center justify-between">
|
<div className="mt-4 flex items-center justify-between">
|
||||||
<div className="text-sm text-gray-500">
|
<div className="text-neutral-10 text-sm">
|
||||||
Page {currentPage + 1}
|
Page {currentPage + 1}
|
||||||
{searchValue && members.length > 0 && ` - showing results for "${searchValue}"`}
|
{searchValue && members.length > 0 && ` - showing results for "${searchValue}"`}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ export function MemberRolePicker(props: {
|
||||||
selectedRoleId={selectedRoleId}
|
selectedRoleId={selectedRoleId}
|
||||||
onSelectRoleId={roleId => setSelectedRoleId(roleId)}
|
onSelectRoleId={roleId => setSelectedRoleId(roleId)}
|
||||||
/>
|
/>
|
||||||
<p className="text-muted-foreground mt-2 text-sm">
|
<p className="text-neutral-10 mt-2 text-sm">
|
||||||
The role assigned to the user that will grant permissions.
|
The role assigned to the user that will grant permissions.
|
||||||
</p>
|
</p>
|
||||||
{selectedRole && (
|
{selectedRole && (
|
||||||
|
|
@ -136,7 +136,7 @@ export function MemberRolePicker(props: {
|
||||||
<Heading size="lg" className="mb-1 text-sm">
|
<Heading size="lg" className="mb-1 text-sm">
|
||||||
Assigned Resources
|
Assigned Resources
|
||||||
</Heading>
|
</Heading>
|
||||||
<p className="text-muted-foreground mt-2 text-sm">
|
<p className="text-neutral-10 mt-2 text-sm">
|
||||||
Specify the resources on which the permissions will be granted.
|
Specify the resources on which the permissions will be granted.
|
||||||
</p>
|
</p>
|
||||||
<ResourceSelector
|
<ResourceSelector
|
||||||
|
|
|
||||||
|
|
@ -145,8 +145,8 @@ export function PermissionSelector(props: PermissionSelectorProps) {
|
||||||
(needsDependency || !permission.isAssignableByViewer) && 'opacity-30',
|
(needsDependency || !permission.isAssignableByViewer) && 'opacity-30',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="font-semibold text-white">{permission.title}</div>
|
<div className="text-neutral-12 font-semibold">{permission.title}</div>
|
||||||
<div className="text-xs text-gray-400">{permission.description}</div>
|
<div className="text-neutral-11 text-xs">{permission.description}</div>
|
||||||
</div>
|
</div>
|
||||||
{permission.isAssignableByViewer === false ? (
|
{permission.isAssignableByViewer === false ? (
|
||||||
<div className="flex grow justify-end">
|
<div className="flex grow justify-end">
|
||||||
|
|
|
||||||
|
|
@ -811,7 +811,7 @@ export function ResourceSelector(props: {
|
||||||
{/** Projects Content */}
|
{/** Projects Content */}
|
||||||
{showProjectsTab && (
|
{showProjectsTab && (
|
||||||
<div className="flex h-full flex-1 flex-col overflow-auto border pt-2">
|
<div className="flex h-full flex-1 flex-col overflow-auto border pt-2">
|
||||||
<div className="text-muted-foreground mb-1 px-2 text-xs uppercase">
|
<div className="text-neutral-10 mb-1 px-2 text-xs uppercase">
|
||||||
access granted
|
access granted
|
||||||
</div>
|
</div>
|
||||||
{projectState.selected.length ? (
|
{projectState.selected.length ? (
|
||||||
|
|
@ -838,7 +838,7 @@ export function ResourceSelector(props: {
|
||||||
) : (
|
) : (
|
||||||
<div className="px-2 text-xs">None selected</div>
|
<div className="px-2 text-xs">None selected</div>
|
||||||
)}
|
)}
|
||||||
<div className="text-muted-foreground mb-1 mt-3 px-2 text-xs uppercase">
|
<div className="text-neutral-10 mb-1 mt-3 px-2 text-xs uppercase">
|
||||||
not selected
|
not selected
|
||||||
</div>
|
</div>
|
||||||
{projectState.notSelected.length ? (
|
{projectState.notSelected.length ? (
|
||||||
|
|
@ -864,18 +864,18 @@ export function ResourceSelector(props: {
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{targetState === null ? (
|
{targetState === null ? (
|
||||||
<div className="text-muted-foreground px-2 text-sm">
|
<div className="text-neutral-10 px-2 text-sm">
|
||||||
Select a project for adjusting the target access.
|
Select a project for adjusting the target access.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{targetState.selection === '*' ? (
|
{targetState.selection === '*' ? (
|
||||||
<div className="text-muted-foreground px-2 text-xs">
|
<div className="text-neutral-10 px-2 text-xs">
|
||||||
Access to all targets of project granted.
|
Access to all targets of project granted.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="text-muted-foreground mb-1 px-2 text-xs uppercase">
|
<div className="text-neutral-10 mb-1 px-2 text-xs uppercase">
|
||||||
access granted
|
access granted
|
||||||
</div>
|
</div>
|
||||||
{targetState.selection.selected.length ? (
|
{targetState.selection.selected.length ? (
|
||||||
|
|
@ -910,7 +910,7 @@ export function ResourceSelector(props: {
|
||||||
) : (
|
) : (
|
||||||
<div className="px-2 text-xs">None selected</div>
|
<div className="px-2 text-xs">None selected</div>
|
||||||
)}
|
)}
|
||||||
<div className="text-muted-foreground mb-1 mt-3 px-2 text-xs uppercase">
|
<div className="text-neutral-10 mb-1 mt-3 px-2 text-xs uppercase">
|
||||||
Not selected
|
Not selected
|
||||||
</div>
|
</div>
|
||||||
{targetState.selection.notSelected.length ? (
|
{targetState.selection.notSelected.length ? (
|
||||||
|
|
@ -939,26 +939,26 @@ export function ResourceSelector(props: {
|
||||||
<div className="py-2">
|
<div className="py-2">
|
||||||
{projectState.activeProject?.projectSelection.targets.mode ===
|
{projectState.activeProject?.projectSelection.targets.mode ===
|
||||||
GraphQLSchema.ResourceAssignmentModeType.All ? (
|
GraphQLSchema.ResourceAssignmentModeType.All ? (
|
||||||
<div className="text-muted-foreground px-2 text-xs">
|
<div className="text-neutral-10 px-2 text-xs">
|
||||||
Access to all services of projects targets granted.
|
Access to all services of projects targets granted.
|
||||||
</div>
|
</div>
|
||||||
) : serviceState === null ? (
|
) : serviceState === null ? (
|
||||||
<div className="text-muted-foreground px-2 text-xs">
|
<div className="text-neutral-10 px-2 text-xs">
|
||||||
Select a target for adjusting the service access.
|
Select a target for adjusting the service access.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{serviceState === 'none' ? (
|
{serviceState === 'none' ? (
|
||||||
<div className="text-muted-foreground px-2 text-xs">
|
<div className="text-neutral-10 px-2 text-xs">
|
||||||
Project is monolithic and has no services.
|
Project is monolithic and has no services.
|
||||||
</div>
|
</div>
|
||||||
) : serviceState.selection === '*' ? (
|
) : serviceState.selection === '*' ? (
|
||||||
<div className="text-muted-foreground px-2 text-xs">
|
<div className="text-neutral-10 px-2 text-xs">
|
||||||
Access to all services in target granted.
|
Access to all services in target granted.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="text-muted-foreground mb-1 px-2 text-xs uppercase">
|
<div className="text-neutral-10 mb-1 px-2 text-xs uppercase">
|
||||||
access granted
|
access granted
|
||||||
</div>
|
</div>
|
||||||
{serviceState.selection.selected.length ? (
|
{serviceState.selection.selected.length ? (
|
||||||
|
|
@ -973,7 +973,7 @@ export function ResourceSelector(props: {
|
||||||
) : (
|
) : (
|
||||||
<div className="px-2 text-xs">None</div>
|
<div className="px-2 text-xs">None</div>
|
||||||
)}
|
)}
|
||||||
<div className="text-muted-foreground mb-1 mt-3 px-2 text-xs uppercase">
|
<div className="text-neutral-10 mb-1 mt-3 px-2 text-xs uppercase">
|
||||||
Not selected
|
Not selected
|
||||||
</div>
|
</div>
|
||||||
{serviceState.selection.notSelected.map(serviceName => (
|
{serviceState.selection.notSelected.map(serviceName => (
|
||||||
|
|
@ -1066,22 +1066,22 @@ export function ResourceSelector(props: {
|
||||||
<div className="py-2">
|
<div className="py-2">
|
||||||
{projectState.activeProject?.projectSelection.targets.mode ===
|
{projectState.activeProject?.projectSelection.targets.mode ===
|
||||||
GraphQLSchema.ResourceAssignmentModeType.All ? (
|
GraphQLSchema.ResourceAssignmentModeType.All ? (
|
||||||
<div className="text-muted-foreground px-2 text-xs">
|
<div className="text-neutral-10 px-2 text-xs">
|
||||||
Access to all apps of projects targets granted.
|
Access to all apps of projects targets granted.
|
||||||
</div>
|
</div>
|
||||||
) : appsState === null ? (
|
) : appsState === null ? (
|
||||||
<div className="text-muted-foreground px-2 text-xs">
|
<div className="text-neutral-10 px-2 text-xs">
|
||||||
Select a target for adjusting the apps access.
|
Select a target for adjusting the apps access.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{appsState.selection === '*' ? (
|
{appsState.selection === '*' ? (
|
||||||
<div className="text-muted-foreground px-2 text-xs">
|
<div className="text-neutral-10 px-2 text-xs">
|
||||||
Access to all apps in target granted.
|
Access to all apps in target granted.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="text-muted-foreground mb-1 px-2 text-xs uppercase">
|
<div className="text-neutral-10 mb-1 px-2 text-xs uppercase">
|
||||||
access granted
|
access granted
|
||||||
</div>
|
</div>
|
||||||
{appsState.selection.selected.length ? (
|
{appsState.selection.selected.length ? (
|
||||||
|
|
@ -1096,7 +1096,7 @@ export function ResourceSelector(props: {
|
||||||
) : (
|
) : (
|
||||||
<div className="px-2 text-xs">None</div>
|
<div className="px-2 text-xs">None</div>
|
||||||
)}
|
)}
|
||||||
<div className="text-muted-foreground mb-1 mt-3 px-2 text-xs uppercase">
|
<div className="text-neutral-10 mb-1 mt-3 px-2 text-xs uppercase">
|
||||||
Not selected
|
Not selected
|
||||||
</div>
|
</div>
|
||||||
{appsState.selection.notSelected.map(serviceName => (
|
{appsState.selection.notSelected.map(serviceName => (
|
||||||
|
|
@ -1170,7 +1170,7 @@ function RowItem(props: {
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex cursor-pointer items-center space-x-1 px-2 py-1 data-[active=true]:cursor-default data-[active=true]:bg-gray-200 data-[active=true]:text-black"
|
className="data-[active=true]:bg-neutral-10 data-[active=true]:text-neutral-1 flex cursor-pointer items-center space-x-1 px-2 py-1 data-[active=true]:cursor-default"
|
||||||
data-active={props.isActive}
|
data-active={props.isActive}
|
||||||
>
|
>
|
||||||
<span className="grow text-sm" onClick={props.onClick}>
|
<span className="grow text-sm" onClick={props.onClick}>
|
||||||
|
|
@ -1189,7 +1189,7 @@ function RowItem(props: {
|
||||||
<XIcon
|
<XIcon
|
||||||
size={12}
|
size={12}
|
||||||
data-active={props.isActive}
|
data-active={props.isActive}
|
||||||
className="text-muted-foreground data-[active=true]:text-secondary"
|
className="text-neutral-10 data-[active=true]:text-neutral-2"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
|
||||||
|
|
@ -633,7 +633,7 @@ function OrganizationMemberRoleRow(props: {
|
||||||
<TooltipContent side="right">
|
<TooltipContent side="right">
|
||||||
<div className="flex flex-col items-start gap-y-2 p-2">
|
<div className="flex flex-col items-start gap-y-2 p-2">
|
||||||
<div className="font-medium">This role is locked</div>
|
<div className="font-medium">This role is locked</div>
|
||||||
<div className="text-sm text-gray-400">
|
<div className="text-neutral-10 text-sm">
|
||||||
Locked roles are created by the system and cannot be modified or deleted.
|
Locked roles are created by the system and cannot be modified or deleted.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -652,7 +652,7 @@ function OrganizationMemberRoleRow(props: {
|
||||||
<TooltipContent side="right">
|
<TooltipContent side="right">
|
||||||
<div className="flex flex-col items-start gap-y-2 p-2">
|
<div className="flex flex-col items-start gap-y-2 p-2">
|
||||||
<div className="font-medium">Default role for new members</div>
|
<div className="font-medium">Default role for new members</div>
|
||||||
<div className="text-sm text-gray-400">
|
<div className="text-neutral-10 text-sm">
|
||||||
<p>New members will be assigned to this role by default.</p>
|
<p>New members will be assigned to this role by default.</p>
|
||||||
{props.canChangeOIDCDefaultRole ? (
|
{props.canChangeOIDCDefaultRole ? (
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -681,7 +681,7 @@ function OrganizationMemberRoleRow(props: {
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="break-words py-3 text-sm text-gray-400" title={role.description}>
|
<td className="text-neutral-10 break-words py-3 text-sm" title={role.description}>
|
||||||
{role.description}
|
{role.description}
|
||||||
</td>
|
</td>
|
||||||
<td className="py-3 text-center text-sm">
|
<td className="py-3 text-center text-sm">
|
||||||
|
|
@ -690,7 +690,7 @@ function OrganizationMemberRoleRow(props: {
|
||||||
<td className="py-3 text-right text-sm">
|
<td className="py-3 text-right text-sm">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="ghost" className="data-[state=open]:bg-muted flex size-8 p-0">
|
<Button variant="ghost" className="data-[state=open]:bg-neutral-3 flex size-8 p-0">
|
||||||
<MoreHorizontalIcon className="size-4" />
|
<MoreHorizontalIcon className="size-4" />
|
||||||
<span className="sr-only">Open menu</span>
|
<span className="sr-only">Open menu</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -929,7 +929,7 @@ export function OrganizationMemberRoles(props: {
|
||||||
>
|
>
|
||||||
<OrganizationMemberRoleCreateButton organization={organization} />
|
<OrganizationMemberRoleCreateButton organization={organization} />
|
||||||
</SubPageLayoutHeader>
|
</SubPageLayoutHeader>
|
||||||
<table className="w-full table-auto divide-y-[1px] divide-gray-500/20">
|
<table className="divide-neutral-10/20 w-full table-auto divide-y-[1px]">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="min-w-[200px] py-3 text-left text-sm font-semibold">Name</th>
|
<th className="min-w-[200px] py-3 text-left text-sm font-semibold">Name</th>
|
||||||
|
|
@ -938,7 +938,7 @@ export function OrganizationMemberRoles(props: {
|
||||||
<th className="w-12 py-3 text-right text-sm font-semibold" />
|
<th className="w-12 py-3 text-right text-sm font-semibold" />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y-[1px] divide-gray-500/20">
|
<tbody className="divide-neutral-10/20 divide-y-[1px]">
|
||||||
{organization.memberRoles?.edges.map(({ node: role }) => (
|
{organization.memberRoles?.edges.map(({ node: role }) => (
|
||||||
<OrganizationMemberRoleRow
|
<OrganizationMemberRoleRow
|
||||||
organizationSlug={organization.slug}
|
organizationSlug={organization.slug}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ export function AccessTokensSubPage(props: AccessTokensSubPageProps): React.Reac
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
<DocsLink
|
<DocsLink
|
||||||
href="/management/access-tokens"
|
href="/management/access-tokens"
|
||||||
className="text-gray-500 hover:text-gray-300"
|
className="text-neutral-10 hover:text-neutral-11"
|
||||||
>
|
>
|
||||||
Learn more about Access Tokens
|
Learn more about Access Tokens
|
||||||
</DocsLink>
|
</DocsLink>
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,7 @@ export function CreateAccessTokenSheetContent(
|
||||||
'step-4-confirmation': () => (
|
'step-4-confirmation': () => (
|
||||||
<>
|
<>
|
||||||
<Heading>Confirm and create Access Token</Heading>
|
<Heading>Confirm and create Access Token</Heading>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-neutral-10 text-sm">
|
||||||
Please please review the selected permissions and resources to ensure they
|
Please please review the selected permissions and resources to ensure they
|
||||||
align with your intended access needs.
|
align with your intended access needs.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -320,7 +320,7 @@ export function CreateAccessTokenSheetContent(
|
||||||
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p className="text-gray-400">
|
<p className="text-neutral-10">
|
||||||
Granted on {permissionLevelToResourceName(group.level)}:
|
Granted on {permissionLevelToResourceName(group.level)}:
|
||||||
</p>
|
</p>
|
||||||
<ul className="flex list-none flex-wrap gap-1">
|
<ul className="flex list-none flex-wrap gap-1">
|
||||||
|
|
@ -337,7 +337,7 @@ export function CreateAccessTokenSheetContent(
|
||||||
{resolvedResources[group.level].map(id => (
|
{resolvedResources[group.level].map(id => (
|
||||||
<li key={id}>
|
<li key={id}>
|
||||||
<Badge
|
<Badge
|
||||||
className="px-3 py-1 font-mono text-xs text-gray-300"
|
className="text-neutral-11 px-3 py-1 font-mono text-xs"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
>
|
>
|
||||||
{id}
|
{id}
|
||||||
|
|
|
||||||
|
|
@ -89,19 +89,19 @@ export function PermissionDetailView(props: {
|
||||||
))}
|
))}
|
||||||
<div className="w-full space-y-1">
|
<div className="w-full space-y-1">
|
||||||
{group.resolvedResourceIds == null ? (
|
{group.resolvedResourceIds == null ? (
|
||||||
<p className="text-gray-400">
|
<p className="text-neutral-10">
|
||||||
Granted on all {permissionLevelToResourceName(group.level)}
|
Granted on all {permissionLevelToResourceName(group.level)}
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p className="text-gray-400">
|
<p className="text-neutral-10">
|
||||||
Granted on {permissionLevelToResourceName(group.level)}:
|
Granted on {permissionLevelToResourceName(group.level)}:
|
||||||
</p>
|
</p>
|
||||||
<ul className="flex list-none flex-wrap gap-1">
|
<ul className="flex list-none flex-wrap gap-1">
|
||||||
{group.resolvedResourceIds.map(id => (
|
{group.resolvedResourceIds.map(id => (
|
||||||
<li key={id}>
|
<li key={id}>
|
||||||
<Badge
|
<Badge
|
||||||
className="px-3 py-1 font-mono text-xs text-gray-300"
|
className="text-neutral-11 px-3 py-1 font-mono text-xs"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
>
|
>
|
||||||
{id}
|
{id}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ const classes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function FormError({ children }: { children: React.ReactNode }) {
|
function FormError({ children }: { children: React.ReactNode }) {
|
||||||
return <div className="text-destructive text-sm">{children}</div>;
|
return <div className="text-sm text-red-500">{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OIDCIntegrationSection_OrganizationFragment = graphql(`
|
const OIDCIntegrationSection_OrganizationFragment = graphql(`
|
||||||
|
|
@ -488,7 +488,7 @@ function CreateOIDCIntegrationForm(props: {
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="bg-muted border-border rounded-md border p-3">
|
<div className="bg-neutral-3 border-neutral-5 rounded-md border p-3">
|
||||||
<OIDCMetadataFetcher
|
<OIDCMetadataFetcher
|
||||||
onEndpointChange={endpoints => {
|
onEndpointChange={endpoints => {
|
||||||
void formik.setFieldValue('tokenEndpoint', endpoints.token);
|
void formik.setFieldValue('tokenEndpoint', endpoints.token);
|
||||||
|
|
@ -1008,13 +1008,13 @@ function UpdateOIDCIntegrationForm(props: {
|
||||||
<Dialog open={props.isOpen} onOpenChange={props.close}>
|
<Dialog open={props.isOpen} onOpenChange={props.close}>
|
||||||
<DialogContent className="flex max-h-[100vh] w-[960px] max-w-[100%] overflow-y-auto">
|
<DialogContent className="flex max-h-[100vh] w-[960px] max-w-[100%] overflow-y-auto">
|
||||||
<div className={classes.container}>
|
<div className={classes.container}>
|
||||||
<div className="bg-border grid grid-cols-1 gap-[1px] md:grid-cols-2">
|
<div className="bg-neutral-5 grid grid-cols-1 gap-[1px] md:grid-cols-2">
|
||||||
<div className="bg-background py-4 pr-4 md:pt-0">
|
<div className="bg-neutral-3 py-4 pr-4 md:pt-0">
|
||||||
<div className="flex flex-col gap-y-5">
|
<div className="flex flex-col gap-y-5">
|
||||||
<div className={cn(classes.container, 'flex flex-col gap-y-4')}>
|
<div className={cn(classes.container, 'flex flex-col gap-y-4')}>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-lg font-medium">OIDC Provider Instructions</div>
|
<div className="text-lg font-medium">OIDC Provider Instructions</div>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-neutral-10 text-sm">
|
||||||
Configure your OIDC provider with the following settings
|
Configure your OIDC provider with the following settings
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1048,7 +1048,7 @@ function UpdateOIDCIntegrationForm(props: {
|
||||||
<div className="flex items-center justify-between space-x-4">
|
<div className="flex items-center justify-between space-x-4">
|
||||||
<div className="flex flex-col space-y-1 text-sm font-medium leading-none">
|
<div className="flex flex-col space-y-1 text-sm font-medium leading-none">
|
||||||
<p>OIDC-Only Access</p>
|
<p>OIDC-Only Access</p>
|
||||||
<p className="text-muted-foreground text-xs font-normal leading-snug">
|
<p className="text-neutral-10 text-xs font-normal leading-snug">
|
||||||
Restricts organization access to only authenticated OIDC accounts.
|
Restricts organization access to only authenticated OIDC accounts.
|
||||||
<br />
|
<br />
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
|
|
@ -1071,7 +1071,7 @@ function UpdateOIDCIntegrationForm(props: {
|
||||||
<p>Default Member Role</p>
|
<p>Default Member Role</p>
|
||||||
<div className="flex items-start justify-between space-x-4">
|
<div className="flex items-start justify-between space-x-4">
|
||||||
<div className="flex basis-2/3 flex-col md:basis-1/2">
|
<div className="flex basis-2/3 flex-col md:basis-1/2">
|
||||||
<p className="text-muted-foreground text-xs font-normal leading-snug">
|
<p className="text-neutral-10 text-xs font-normal leading-snug">
|
||||||
This role is assigned to new members who sign in via OIDC.{' '}
|
This role is assigned to new members who sign in via OIDC.{' '}
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
Only members with the Admin role can modify it.
|
Only members with the Admin role can modify it.
|
||||||
|
|
@ -1098,12 +1098,12 @@ function UpdateOIDCIntegrationForm(props: {
|
||||||
onSubmit={formik.handleSubmit}
|
onSubmit={formik.handleSubmit}
|
||||||
className={cn(
|
className={cn(
|
||||||
classes.container,
|
classes.container,
|
||||||
'bg-background order-first pb-4 md:order-none md:pl-4',
|
'bg-neutral-3 order-first pb-4 md:order-none md:pl-4',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-lg font-medium">Properties</div>
|
<div className="text-lg font-medium">Properties</div>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-neutral-10 text-sm">
|
||||||
Configure your OIDC provider with the following settings
|
Configure your OIDC provider with the following settings
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1223,7 +1223,7 @@ function UpdateOIDCIntegrationForm(props: {
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1 text-sm font-medium leading-none">
|
<div className="space-y-1 text-sm font-medium leading-none">
|
||||||
<p>Default Resource Assignments</p>
|
<p>Default Resource Assignments</p>
|
||||||
<p className="text-muted-foreground text-xs font-normal leading-snug">
|
<p className="text-neutral-10 text-xs font-normal leading-snug">
|
||||||
This permitted resources for new members who sign in via OIDC.{' '}
|
This permitted resources for new members who sign in via OIDC.{' '}
|
||||||
<span className="font-medium">Only members with the Admin role can modify it.</span>
|
<span className="font-medium">Only members with the Admin role can modify it.</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ export function CreatePersonalAccessTokenSheetContent(
|
||||||
'step-4-confirmation': () => (
|
'step-4-confirmation': () => (
|
||||||
<>
|
<>
|
||||||
<Heading>Confirm and create Access Token</Heading>
|
<Heading>Confirm and create Access Token</Heading>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-neutral-10 text-sm">
|
||||||
Please please review the selected permissions and resources to ensure they
|
Please please review the selected permissions and resources to ensure they
|
||||||
align with your intended access needs.
|
align with your intended access needs.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -313,7 +313,7 @@ export function CreatePersonalAccessTokenSheetContent(
|
||||||
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p className="text-gray-400">
|
<p className="text-neutral-10">
|
||||||
Granted on {permissionLevelToResourceName(group.level)}:
|
Granted on {permissionLevelToResourceName(group.level)}:
|
||||||
</p>
|
</p>
|
||||||
<ul className="flex list-none flex-wrap gap-1">
|
<ul className="flex list-none flex-wrap gap-1">
|
||||||
|
|
@ -330,7 +330,7 @@ export function CreatePersonalAccessTokenSheetContent(
|
||||||
{resolvedResources[group.level].map(id => (
|
{resolvedResources[group.level].map(id => (
|
||||||
<li key={id}>
|
<li key={id}>
|
||||||
<Badge
|
<Badge
|
||||||
className="px-3 py-1 font-mono text-xs text-gray-300"
|
className="text-neutral-11 px-3 py-1 font-mono text-xs"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
>
|
>
|
||||||
{id}
|
{id}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ export function PersonalAccessTokensSubPage(
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
<DocsLink
|
<DocsLink
|
||||||
href="/management/access-tokens"
|
href="/management/access-tokens"
|
||||||
className="text-gray-500 hover:text-gray-300"
|
className="text-neutral-10 hover:text-neutral-11"
|
||||||
>
|
>
|
||||||
Learn more about Access Tokens
|
Learn more about Access Tokens
|
||||||
</DocsLink>
|
</DocsLink>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ const statusVariants = cva('inline-flex items-center text-sm font-semibold', {
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
[SupportTicketStatus.Open]: 'text-yellow-400',
|
[SupportTicketStatus.Open]: 'text-yellow-400',
|
||||||
[SupportTicketStatus.Solved]: 'text-gray-500',
|
[SupportTicketStatus.Solved]: 'text-neutral-10',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|
@ -38,12 +38,9 @@ const priorityVariants = cva(
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
[SupportTicketPriority.Normal]:
|
[SupportTicketPriority.Normal]: 'border-transparent bg-red-400 text-neutral-12',
|
||||||
'border-transparent bg-destructive/40 text-destructive-foreground',
|
[SupportTicketPriority.High]: 'border-transparent bg-red-600 text-neutral-12',
|
||||||
[SupportTicketPriority.High]:
|
[SupportTicketPriority.Urgent]: 'border-transparent bg-red-800 text-neutral-12',
|
||||||
'border-transparent bg-destructive/60 text-destructive-foreground',
|
|
||||||
[SupportTicketPriority.Urgent]:
|
|
||||||
'border-transparent bg-destructive/80 text-destructive-foreground',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export function PolicyConfigBox(props: Props) {
|
||||||
>
|
>
|
||||||
{'title' in props ? (
|
{'title' in props ? (
|
||||||
<>
|
<>
|
||||||
<div className="pb-1 text-xs text-gray-600">{props.title}</div>
|
<div className="text-neutral-8 pb-1 text-xs">{props.title}</div>
|
||||||
<div>{props.children}</div>
|
<div>{props.children}</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ export function PolicyListItem(props: {
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<InfoIcon className="ml-2 inline-block size-4 text-orange-500" />
|
<InfoIcon className="text-neutral-2 ml-2 inline-block size-4" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -89,7 +89,7 @@ export function PolicyListItem(props: {
|
||||||
<div>
|
<div>
|
||||||
<SeverityLevelToggle canTurnOff={props.overridingParentRule} rule={ruleInfo.id} />
|
<SeverityLevelToggle canTurnOff={props.overridingParentRule} rule={ruleInfo.id} />
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grow grid-cols-4 align-middle [&>*]:min-h-[40px] [&>*]:border-l-[1px] [&>*]:border-l-gray-800">
|
<div className="[&>*]:border-l-neutral-5 grid grow grid-cols-4 align-middle [&>*]:min-h-[40px] [&>*]:border-l-[1px]">
|
||||||
{shouldShowRuleConfig && (
|
{shouldShowRuleConfig && (
|
||||||
<PolicyRuleConfig
|
<PolicyRuleConfig
|
||||||
rule={ruleInfo.id}
|
rule={ruleInfo.id}
|
||||||
|
|
@ -101,8 +101,8 @@ export function PolicyListItem(props: {
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{props.overridingParentRule && enabled ? (
|
{props.overridingParentRule && enabled ? (
|
||||||
<div className="mt-4 text-xs font-medium text-gray-400">
|
<div className="text-neutral-10 mt-4 text-xs font-medium">
|
||||||
<p className="mr-2 inline-block text-sm font-medium text-orange-500">!</p>
|
<p className="text-neutral-2 mr-2 inline-block text-sm font-medium">!</p>
|
||||||
You are {severity === RuleInstanceSeverityLevel.Off ? 'disabling' : 'overriding'} a
|
You are {severity === RuleInstanceSeverityLevel.Off ? 'disabling' : 'overriding'} a
|
||||||
rule configured at the organization level
|
rule configured at the organization level
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ function PolicySettingsListForm({
|
||||||
<>
|
<>
|
||||||
{children ? children(props) : null}
|
{children ? children(props) : null}
|
||||||
<div className="flex items-center justify-end">
|
<div className="flex items-center justify-end">
|
||||||
{props.dirty ? <p className="pr-2 text-sm text-gray-500">Unsaved changes</p> : null}
|
{props.dirty ? <p className="text-neutral-10 pr-2 text-sm">Unsaved changes</p> : null}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
disabled={!props.dirty || saving || !props.isValid || !onSave}
|
disabled={!props.dirty || saving || !props.isValid || !onSave}
|
||||||
|
|
@ -127,7 +127,7 @@ function PolicySettingsListForm({
|
||||||
{error}
|
{error}
|
||||||
</Callout>
|
</Callout>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="grid grid-cols-1 divide-y divide-gray-800">
|
<div className="divide-neutral-5 grid grid-cols-1 divide-y">
|
||||||
{availableRules.map(availableRule => (
|
{availableRules.map(availableRule => (
|
||||||
<PolicyListItem
|
<PolicyListItem
|
||||||
disabled={!onSave}
|
disabled={!onSave}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export const PolicyBooleanToggle = (props: {
|
||||||
|
|
||||||
const label = (
|
const label = (
|
||||||
<label
|
<label
|
||||||
className="pb-1 pl-2 font-mono text-xs text-gray-500"
|
className="text-neutral-10 pb-1 pl-2 font-mono text-xs"
|
||||||
htmlFor={`${props.rule}_${props.propertyName}`}
|
htmlFor={`${props.rule}_${props.propertyName}`}
|
||||||
>
|
>
|
||||||
{props.title}
|
{props.title}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ export const PolicyEnumSelect = (props: {
|
||||||
<div>{props.title}</div>
|
<div>{props.title}</div>
|
||||||
{props.tooltip ? (
|
{props.tooltip ? (
|
||||||
<Tooltip content={props.tooltip}>
|
<Tooltip content={props.tooltip}>
|
||||||
<InfoIcon className="ml-2 size-4 text-orange-500" />
|
<InfoIcon className="text-neutral-2 ml-2 size-4" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -47,7 +47,7 @@ export const PolicyEnumSelect = (props: {
|
||||||
}}
|
}}
|
||||||
value={currentValue}
|
value={currentValue}
|
||||||
type="single"
|
type="single"
|
||||||
className="bg-gray-900/50 text-gray-500"
|
className="text-neutral-10 bg-neutral-2/50"
|
||||||
>
|
>
|
||||||
{props.options.map(option => (
|
{props.options.map(option => (
|
||||||
<ToggleGroupItem
|
<ToggleGroupItem
|
||||||
|
|
@ -55,8 +55,8 @@ export const PolicyEnumSelect = (props: {
|
||||||
value={option.value}
|
value={option.value}
|
||||||
title={option.label}
|
title={option.label}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'text-xs hover:text-white',
|
'hover:text-neutral-12 text-xs',
|
||||||
currentValue === option.value && 'bg-gray-800 text-white',
|
currentValue === option.value && 'bg-neutral-5 text-neutral-12',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{option.label}
|
{option.label}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export const PolicyMultiSelect = (props: {
|
||||||
<div>{props.title}</div>
|
<div>{props.title}</div>
|
||||||
{props.tooltip ? (
|
{props.tooltip ? (
|
||||||
<Tooltip content={props.tooltip}>
|
<Tooltip content={props.tooltip}>
|
||||||
<InfoIcon className="ml-2 size-4 text-orange-500" />
|
<InfoIcon className="text-neutral-2 ml-2 size-4" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { ReactElement, useEffect } from 'react';
|
import { ReactElement, useEffect } from 'react';
|
||||||
import type { JSONSchema } from 'json-schema-typed';
|
import type { JSONSchema } from 'json-schema-typed';
|
||||||
|
import { useTheme } from '@/components/theme/theme-provider';
|
||||||
import { Spinner } from '@/components/ui/spinner';
|
import { Spinner } from '@/components/ui/spinner';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import MonacoEditor, { type Monaco } from '@monaco-editor/react';
|
import MonacoEditor, { type Monaco } from '@monaco-editor/react';
|
||||||
|
|
@ -29,6 +30,7 @@ const DEFAULT_VALUE = {
|
||||||
export function NamingConventionConfigEditor(props: {
|
export function NamingConventionConfigEditor(props: {
|
||||||
configJsonSchema: JSONSchema | null;
|
configJsonSchema: JSONSchema | null;
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
|
const { resolvedTheme } = useTheme();
|
||||||
const { config, setConfig, getConfigValue, setConfigAsInvalid, getValidationStatus } =
|
const { config, setConfig, getConfigValue, setConfigAsInvalid, getValidationStatus } =
|
||||||
useConfigurationHelper().ruleConfig('naming-convention');
|
useConfigurationHelper().ruleConfig('naming-convention');
|
||||||
const currentValue = getConfigValue<string | undefined>('');
|
const currentValue = getConfigValue<string | undefined>('');
|
||||||
|
|
@ -63,7 +65,8 @@ export function NamingConventionConfigEditor(props: {
|
||||||
return (
|
return (
|
||||||
<div className="col-span-4">
|
<div className="col-span-4">
|
||||||
<MonacoEditor
|
<MonacoEditor
|
||||||
theme="vs-dark"
|
// this outputs either "vs-light" or "vs-dark"
|
||||||
|
theme={`vs-${resolvedTheme}`}
|
||||||
loading={<Spinner />}
|
loading={<Spinner />}
|
||||||
height="40vh"
|
height="40vh"
|
||||||
beforeMount={handleEditorWillMount}
|
beforeMount={handleEditorWillMount}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export const SeverityLevelToggle = (props: { rule: string; canTurnOff: boolean }
|
||||||
label: 'Warning',
|
label: 'Warning',
|
||||||
icon: (active: boolean) => (
|
icon: (active: boolean) => (
|
||||||
<ExclamationTriangleIcon
|
<ExclamationTriangleIcon
|
||||||
className={clsx(active ? 'text-orange-600' : 'text-gray-600', 'hover:text-orange-600')}
|
className={clsx(active ? 'text-orange-500' : 'text-neutral-8', 'hover:text-orange-500')}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
@ -23,7 +23,7 @@ export const SeverityLevelToggle = (props: { rule: string; canTurnOff: boolean }
|
||||||
label: 'Error',
|
label: 'Error',
|
||||||
icon: (active: boolean) => (
|
icon: (active: boolean) => (
|
||||||
<CrossCircledIcon
|
<CrossCircledIcon
|
||||||
className={clsx(active ? 'text-red-600' : 'text-gray-600', 'hover:text-red-600')}
|
className={clsx(active ? 'text-red-600' : 'text-neutral-8', 'hover:text-red-600')}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
@ -35,7 +35,7 @@ export const SeverityLevelToggle = (props: { rule: string; canTurnOff: boolean }
|
||||||
label: 'Disables a rule defined at the organization level',
|
label: 'Disables a rule defined at the organization level',
|
||||||
icon: (active: boolean) => (
|
icon: (active: boolean) => (
|
||||||
<MinusCircledIcon
|
<MinusCircledIcon
|
||||||
className={clsx(active ? 'text-white' : 'text-gray-600', 'hover:text-white')}
|
className={clsx(active ? 'text-neutral-12' : 'text-neutral-8', 'hover:text-neutral-12')}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
@ -51,7 +51,7 @@ export const SeverityLevelToggle = (props: { rule: string; canTurnOff: boolean }
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
type="single"
|
type="single"
|
||||||
className="bg-gray-900/50 text-gray-500"
|
className="text-neutral-10 bg-neutral-2/50"
|
||||||
>
|
>
|
||||||
{options.map(
|
{options.map(
|
||||||
level =>
|
level =>
|
||||||
|
|
@ -61,8 +61,8 @@ export const SeverityLevelToggle = (props: { rule: string; canTurnOff: boolean }
|
||||||
value={level.value}
|
value={level.value}
|
||||||
title={level.label}
|
title={level.label}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'hover:text-white',
|
'hover:text-neutral-12',
|
||||||
config.severity === level.value && 'bg-gray-800 text-white',
|
config.severity === level.value && 'bg-neutral-5 text-neutral-12',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Tooltip content={level.label}>
|
<Tooltip content={level.label}>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export const PolicyStringInputConfig = (props: {
|
||||||
<div>{props.title}</div>
|
<div>{props.title}</div>
|
||||||
{props.tooltip ? (
|
{props.tooltip ? (
|
||||||
<Tooltip content={props.tooltip}>
|
<Tooltip content={props.tooltip}>
|
||||||
<InfoIcon className="ml-2 size-4 text-orange-500" />
|
<InfoIcon className="text-neutral-2 ml-2 size-4" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ export function ChannelsTable(props: {
|
||||||
/>
|
/>
|
||||||
</Td>
|
</Td>
|
||||||
<Td className="text-ellipsis whitespace-nowrap">{channel.name}</Td>
|
<Td className="text-ellipsis whitespace-nowrap">{channel.name}</Td>
|
||||||
<Td className="max-w-xs truncate text-xs text-gray-400">
|
<Td className="text-neutral-10 max-w-xs truncate text-xs">
|
||||||
{renderChannelEndpoint(channel)}
|
{renderChannelEndpoint(channel)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td className="flex max-w-24 content-end">
|
<Td className="flex max-w-24 content-end">
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export const CreateChannelModal = ({
|
||||||
{mutation.data.addAlertChannel.error.inputErrors.name}
|
{mutation.data.addAlertChannel.error.inputErrors.name}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-neutral-10 text-sm">
|
||||||
This will be displayed on channels list, we recommend to make it self-explanatory.
|
This will be displayed on channels list, we recommend to make it self-explanatory.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -164,7 +164,7 @@ export const CreateChannelModal = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{values.endpoint ? (
|
{values.endpoint ? (
|
||||||
<p className="text-sm text-gray-500">Hive will send alerts to your endpoint.</p>
|
<p className="text-neutral-10 text-sm">Hive will send alerts to your endpoint.</p>
|
||||||
) : (
|
) : (
|
||||||
<a href="https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=newteams%2Cdotnet">
|
<a href="https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=newteams%2Cdotnet">
|
||||||
Follow this guide to set up an incoming webhook connector in MS Teams
|
Follow this guide to set up an incoming webhook connector in MS Teams
|
||||||
|
|
@ -196,7 +196,7 @@ export const CreateChannelModal = ({
|
||||||
{mutation.data.addAlertChannel.error.inputErrors.slackChannel}
|
{mutation.data.addAlertChannel.error.inputErrors.slackChannel}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-neutral-10 text-sm">
|
||||||
Use <Tag>#channel</Tag> or <Tag>@username</Tag> form.
|
Use <Tag>#channel</Tag> or <Tag>@username</Tag> form.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -317,7 +317,7 @@ export function CreateProjectAccessTokenSheetContent(
|
||||||
'step-4-confirmation': () => (
|
'step-4-confirmation': () => (
|
||||||
<>
|
<>
|
||||||
<Heading>Confirm and create Access Token</Heading>
|
<Heading>Confirm and create Access Token</Heading>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-neutral-10 text-sm">
|
||||||
Please please review the selected permissions and resources to ensure they
|
Please please review the selected permissions and resources to ensure they
|
||||||
align with your intended access needs.
|
align with your intended access needs.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -335,7 +335,7 @@ export function CreateProjectAccessTokenSheetContent(
|
||||||
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p className="text-gray-400">
|
<p className="text-neutral-10">
|
||||||
Granted on {permissionLevelToResourceName(group.level)}:
|
Granted on {permissionLevelToResourceName(group.level)}:
|
||||||
</p>
|
</p>
|
||||||
<ul className="flex list-none flex-wrap gap-1">
|
<ul className="flex list-none flex-wrap gap-1">
|
||||||
|
|
@ -352,7 +352,7 @@ export function CreateProjectAccessTokenSheetContent(
|
||||||
{resolvedResources[group.level].map(id => (
|
{resolvedResources[group.level].map(id => (
|
||||||
<li key={id}>
|
<li key={id}>
|
||||||
<Badge
|
<Badge
|
||||||
className="px-3 py-1 font-mono text-xs text-gray-300"
|
className="text-neutral-11 px-3 py-1 font-mono text-xs"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
>
|
>
|
||||||
{id}
|
{id}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ export function ProjectAccessTokensSubPage(
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
<DocsLink
|
<DocsLink
|
||||||
href="/management/access-tokens"
|
href="/management/access-tokens"
|
||||||
className="text-gray-500 hover:text-gray-300"
|
className="text-neutral-10 hover:text-neutral-11"
|
||||||
>
|
>
|
||||||
Learn more about Access Tokens
|
Learn more about Access Tokens
|
||||||
</DocsLink>
|
</DocsLink>
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ const ExternalCompositionStatus = ({
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<UpdateIcon
|
<UpdateIcon
|
||||||
className="size-5 animate-spin cursor-default text-gray-500"
|
className="text-neutral-10 size-5 animate-spin cursor-default"
|
||||||
onClick={e => e.preventDefault()}
|
onClick={e => e.preventDefault()}
|
||||||
/>
|
/>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
@ -295,7 +295,7 @@ export const ExternalCompositionSettings = (props: {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-start gap-y-6">
|
<div className="flex flex-col items-start gap-y-6">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-muted-foreground max-w-2xl text-sm">
|
<p className="text-neutral-10 max-w-2xl text-sm">
|
||||||
For advanced users, you can configure an endpoint for external schema compositions. This
|
For advanced users, you can configure an endpoint for external schema compositions. This
|
||||||
can be used to implement custom composition logic.
|
can be used to implement custom composition logic.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ export function LegacyCompositionSettings(props: {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-start gap-y-6">
|
<div className="flex flex-col items-start gap-y-6">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-neutral-10 text-sm">
|
||||||
Not recommended. Migrate towards using Native Federation v2.
|
Not recommended. Migrate towards using Native Federation v2.
|
||||||
</p>
|
</p>
|
||||||
<ProductUpdatesLink href="2023-10-10-native-federation-2">
|
<ProductUpdatesLink href="2023-10-10-native-federation-2">
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ const IncrementalNativeCompositionSwitch = (props: {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex flex-row items-center gap-x-10 rounded-sm border border-gray-800 bg-gray-800/50 p-4',
|
'border-neutral-5 bg-neutral-5/50 flex flex-row items-center gap-x-10 rounded-sm border p-4',
|
||||||
mutation.fetching && 'animate-pulse',
|
mutation.fetching && 'animate-pulse',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -207,7 +207,7 @@ export function NativeCompositionSettings(props: {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-start gap-y-6">
|
<div className="flex flex-col items-start gap-y-6">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-neutral-10 text-sm">
|
||||||
Recommended for most users. Use native GraphQL Federation v2 composition for your project.
|
Recommended for most users. Use native GraphQL Federation v2 composition for your project.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -220,7 +220,7 @@ export function NativeCompositionSettings(props: {
|
||||||
<div className="font-semibold">Incremental migration</div>
|
<div className="font-semibold">Incremental migration</div>
|
||||||
<Badge variant="outline">experimental</Badge>
|
<Badge variant="outline">experimental</Badge>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-muted-foreground text-sm">
|
<div className="text-neutral-10 text-sm">
|
||||||
Your project is using the experimental incremental migration feature. <br />
|
Your project is using the experimental incremental migration feature. <br />
|
||||||
Migrate targets one by one to the native schema composition.
|
Migrate targets one by one to the native schema composition.
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -266,7 +266,7 @@ export function NativeCompositionSettings(props: {
|
||||||
) : null}
|
) : null}
|
||||||
{projectQuery.data.project.nativeFederationCompatibility.status ===
|
{projectQuery.data.project.nativeFederationCompatibility.status ===
|
||||||
NativeFederationCompatibilityStatusType.Unknown ? (
|
NativeFederationCompatibilityStatusType.Unknown ? (
|
||||||
<FlaskConicalIcon className="size-10 text-orange-500" />
|
<FlaskConicalIcon className="text-neutral-2 size-10" />
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -284,13 +284,13 @@ export function NativeCompositionSettings(props: {
|
||||||
? 'Unclear whether your project is compatible'
|
? 'Unclear whether your project is compatible'
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-muted-foreground text-sm">
|
<div className="text-neutral-10 text-sm">
|
||||||
{projectQuery.data.project.nativeFederationCompatibility.status ===
|
{projectQuery.data.project.nativeFederationCompatibility.status ===
|
||||||
NativeFederationCompatibilityStatusType.Compatible ? (
|
NativeFederationCompatibilityStatusType.Compatible ? (
|
||||||
<>
|
<>
|
||||||
Subgraphs of this project are composed and validated correctly by our{' '}
|
Subgraphs of this project are composed and validated correctly by our{' '}
|
||||||
<a
|
<a
|
||||||
className="text-muted-foreground font-semibold underline-offset-4 hover:underline"
|
className="text-neutral-10 font-semibold underline-offset-4 hover:underline"
|
||||||
href="https://github.com/the-guild-org/federation"
|
href="https://github.com/the-guild-org/federation"
|
||||||
>
|
>
|
||||||
Open Source composition library
|
Open Source composition library
|
||||||
|
|
@ -303,7 +303,7 @@ export function NativeCompositionSettings(props: {
|
||||||
<>
|
<>
|
||||||
Our{' '}
|
Our{' '}
|
||||||
<a
|
<a
|
||||||
className="text-muted-foreground font-semibold underline-offset-4 hover:underline"
|
className="text-neutral-10 font-semibold underline-offset-4 hover:underline"
|
||||||
href="https://github.com/the-guild-org/federation"
|
href="https://github.com/the-guild-org/federation"
|
||||||
>
|
>
|
||||||
Open Source composition library
|
Open Source composition library
|
||||||
|
|
@ -325,7 +325,7 @@ export function NativeCompositionSettings(props: {
|
||||||
Your project appears to lack any subgraphs at the moment, making it impossible for
|
Your project appears to lack any subgraphs at the moment, making it impossible for
|
||||||
us to assess compatibility with our{' '}
|
us to assess compatibility with our{' '}
|
||||||
<a
|
<a
|
||||||
className="text-muted-foreground font-semibold underline-offset-4 hover:underline"
|
className="text-neutral-10 font-semibold underline-offset-4 hover:underline"
|
||||||
href="https://github.com/the-guild-org/federation"
|
href="https://github.com/the-guild-org/federation"
|
||||||
>
|
>
|
||||||
Open Source composition library
|
Open Source composition library
|
||||||
|
|
@ -355,7 +355,7 @@ export function NativeCompositionSettings(props: {
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
<div>
|
<div>
|
||||||
<Button variant="link" className="text-orange-500" asChild>
|
<Button variant="link" asChild>
|
||||||
<a href="https://github.com/the-guild-org/federation?tab=readme-ov-file#compatibility">
|
<a href="https://github.com/the-guild-org/federation?tab=readme-ov-file#compatibility">
|
||||||
Learn more about risks and compatibility with other composition libraries
|
Learn more about risks and compatibility with other composition libraries
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export function Description(props: { description: string }) {
|
||||||
hidden: !isDescriptionsVisible,
|
hidden: !isDescriptionsVisible,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Markdown className={clsx('text-left text-sm text-gray-400')} content={props.description} />
|
<Markdown className={clsx('text-neutral-10 text-left text-sm')} content={props.description} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -62,10 +62,10 @@ export function SchemaExplorerUsageStats(props: {
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
title={`${toDecimal(percentage)}% of all requests`}
|
title={`${toDecimal(percentage)}% of all requests`}
|
||||||
className="relative z-0 mt-1 w-full min-w-[25px] overflow-hidden rounded-sm bg-orange-500/20"
|
className="bg-neutral-2/20 relative z-0 mt-1 w-full min-w-[25px] overflow-hidden rounded-sm"
|
||||||
style={{ width: 50, height: 5 }}
|
style={{ width: 50, height: 5 }}
|
||||||
>
|
>
|
||||||
<div className="z-0 h-full bg-orange-500" style={{ width: `${percentage}%` }} />
|
<div className="bg-neutral-2 z-0 h-full" style={{ width: `${percentage}%` }} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
|
@ -101,7 +101,7 @@ export function SchemaExplorerUsageStats(props: {
|
||||||
<tr key={op.hash}>
|
<tr key={op.hash}>
|
||||||
<td className="px-2 pl-0 text-left">
|
<td className="px-2 pl-0 text-left">
|
||||||
<NextLink
|
<NextLink
|
||||||
className="text-orange-500 hover:text-orange-500 hover:underline hover:underline-offset-2"
|
className="text-neutral-2 hover:text-neutral-2 hover:underline hover:underline-offset-2"
|
||||||
to="/$organizationSlug/$projectSlug/$targetSlug/insights/$operationName/$operationHash"
|
to="/$organizationSlug/$projectSlug/$targetSlug/insights/$operationName/$operationHash"
|
||||||
params={{
|
params={{
|
||||||
organizationSlug: props.organizationSlug,
|
organizationSlug: props.organizationSlug,
|
||||||
|
|
@ -146,7 +146,7 @@ export function SchemaExplorerUsageStats(props: {
|
||||||
{usage.usedByClients.map(clientName => (
|
{usage.usedByClients.map(clientName => (
|
||||||
<li key={clientName} className="font-bold">
|
<li key={clientName} className="font-bold">
|
||||||
<NextLink
|
<NextLink
|
||||||
className="text-orange-500 hover:text-orange-500 hover:underline hover:underline-offset-2"
|
className="text-neutral-2 hover:text-neutral-2 hover:underline hover:underline-offset-2"
|
||||||
to="/$organizationSlug/$projectSlug/$targetSlug/insights/client/$name"
|
to="/$organizationSlug/$projectSlug/$targetSlug/insights/client/$name"
|
||||||
params={{
|
params={{
|
||||||
organizationSlug: props.organizationSlug,
|
organizationSlug: props.organizationSlug,
|
||||||
|
|
@ -219,7 +219,7 @@ export function DeprecationNote(props: {
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent className="min-w-6 max-w-screen-md" side="right" sideOffset={5}>
|
<TooltipContent className="min-w-6 max-w-screen-md" side="right" sideOffset={5}>
|
||||||
<div className="mb-2">Deprecation reason</div>
|
<div className="mb-2">Deprecation reason</div>
|
||||||
<Markdown className="text-gray-400" content={props.deprecationReason} />
|
<Markdown className="text-neutral-10" content={props.deprecationReason} />
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
|
|
@ -245,11 +245,11 @@ export function GraphQLTypeCard(props: {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md border-2 border-gray-900">
|
<div className="border-neutral-5 rounded-md border-2">
|
||||||
<div className="flex flex-row justify-between p-4">
|
<div className="flex flex-row justify-between p-4">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex flex-row items-center gap-2">
|
<div className="flex flex-row items-center gap-2">
|
||||||
<div className="font-normal text-gray-400">{props.kind}</div>
|
<div className="text-neutral-10 font-normal">{props.kind}</div>
|
||||||
<div className="font-semibold">
|
<div className="font-semibold">
|
||||||
<GraphQLTypeAsLink
|
<GraphQLTypeAsLink
|
||||||
organizationSlug={props.organizationSlug}
|
organizationSlug={props.organizationSlug}
|
||||||
|
|
@ -262,7 +262,7 @@ export function GraphQLTypeCard(props: {
|
||||||
{props.description && <Description description={props.description} />}
|
{props.description && <Description description={props.description} />}
|
||||||
</div>
|
</div>
|
||||||
{Array.isArray(props.implements) && props.implements.length > 0 && (
|
{Array.isArray(props.implements) && props.implements.length > 0 && (
|
||||||
<div className="flex flex-row items-center text-sm text-gray-400">
|
<div className="text-neutral-10 flex flex-row items-center text-sm">
|
||||||
<div className="mx-2">implements</div>
|
<div className="mx-2">implements</div>
|
||||||
<div className="flex flex-row gap-2">
|
<div className="flex flex-row gap-2">
|
||||||
{props.implements.map(t => (
|
{props.implements.map(t => (
|
||||||
|
|
@ -312,7 +312,7 @@ export function GraphQLTypeCardListItem(props: {
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'flex flex-row items-center justify-between p-4 text-sm',
|
'flex flex-row items-center justify-between p-4 text-sm',
|
||||||
props.index % 2 ? '' : 'bg-gray-900/50',
|
props.index % 2 ? '' : 'bg-neutral-2/50',
|
||||||
props.className,
|
props.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -343,14 +343,14 @@ export function GraphQLInputFields(props: {
|
||||||
<GraphQLTypeCardListItem key={field.name} index={i}>
|
<GraphQLTypeCardListItem key={field.name} index={i}>
|
||||||
<div>
|
<div>
|
||||||
<div className="flex w-full flex-row items-center justify-between">
|
<div className="flex w-full flex-row items-center justify-between">
|
||||||
<div className="text-gray-400">
|
<div className="text-neutral-10">
|
||||||
<DeprecationNote deprecationReason={field.deprecationReason}>
|
<DeprecationNote deprecationReason={field.deprecationReason}>
|
||||||
<LinkToCoordinatePage
|
<LinkToCoordinatePage
|
||||||
organizationSlug={props.organizationSlug}
|
organizationSlug={props.organizationSlug}
|
||||||
projectSlug={props.projectSlug}
|
projectSlug={props.projectSlug}
|
||||||
targetSlug={props.targetSlug}
|
targetSlug={props.targetSlug}
|
||||||
coordinate={coordinate}
|
coordinate={coordinate}
|
||||||
className="font-semibold text-white"
|
className="text-neutral-12 font-semibold"
|
||||||
>
|
>
|
||||||
{field.name}
|
{field.name}
|
||||||
</LinkToCoordinatePage>
|
</LinkToCoordinatePage>
|
||||||
|
|
@ -414,7 +414,7 @@ export function GraphQLTypeAsLink(props: {
|
||||||
>
|
>
|
||||||
Visit in <span className="font-bold">Explorer</span>
|
Visit in <span className="font-bold">Explorer</span>
|
||||||
</NextLink>
|
</NextLink>
|
||||||
<span className="text-xs text-gray-500"> - displays a full type</span>
|
<span className="text-neutral-10 text-xs"> - displays a full type</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<NextLink
|
<NextLink
|
||||||
|
|
@ -430,7 +430,7 @@ export function GraphQLTypeAsLink(props: {
|
||||||
>
|
>
|
||||||
Visit in <span className="font-bold">Insights</span>
|
Visit in <span className="font-bold">Insights</span>
|
||||||
</NextLink>
|
</NextLink>
|
||||||
<span className="text-xs text-gray-500"> - usage insights</span>
|
<span className="text-neutral-10 text-xs"> - usage insights</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<PopoverArrow />
|
<PopoverArrow />
|
||||||
|
|
@ -488,11 +488,11 @@ export const GraphQLFieldsSkeleton = (props: { count?: number }) => {
|
||||||
{widths.map((width, index) => (
|
{widths.map((width, index) => (
|
||||||
<GraphQLTypeCardListItem key={index} index={index} className="w-full">
|
<GraphQLTypeCardListItem key={index} index={index} className="w-full">
|
||||||
<div className="flex w-full flex-row items-center gap-2">
|
<div className="flex w-full flex-row items-center gap-2">
|
||||||
<Skeleton className={cn('bg-muted my-1 h-4', width)} />
|
<Skeleton className={cn('bg-neutral-3 my-1 h-4', width)} />
|
||||||
<div className="ml-auto flex flex-row items-center gap-2">
|
<div className="ml-auto flex flex-row items-center gap-2">
|
||||||
<Skeleton className="bg-muted my-1 size-4" />
|
<Skeleton className="bg-neutral-3 my-1 size-4" />
|
||||||
<Skeleton className="bg-muted my-1 size-4" />
|
<Skeleton className="bg-neutral-3 my-1 size-4" />
|
||||||
<Skeleton className="bg-muted my-1 size-4" />
|
<Skeleton className="bg-neutral-3 my-1 size-4" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</GraphQLTypeCardListItem>
|
</GraphQLTypeCardListItem>
|
||||||
|
|
@ -503,10 +503,10 @@ export const GraphQLFieldsSkeleton = (props: { count?: number }) => {
|
||||||
|
|
||||||
export const GraphQLTypeCardSkeleton = (props: { children: ReactNode }) => {
|
export const GraphQLTypeCardSkeleton = (props: { children: ReactNode }) => {
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md border-2 border-gray-900">
|
<div className="border-neutral-2 rounded-md border-2">
|
||||||
<div className="flex flex-row justify-between p-4">
|
<div className="flex flex-row justify-between p-4">
|
||||||
<div className="flex flex-row items-center gap-2">
|
<div className="flex flex-row items-center gap-2">
|
||||||
<Skeleton className="bg-muted my-1 h-4 w-32" />
|
<Skeleton className="bg-neutral-3 my-1 h-4 w-32" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>{props.children}</div>
|
<div>{props.children}</div>
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ export function DescriptionsVisibilityFilter() {
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<div className="bg-secondary flex h-[40px] flex-row items-center gap-x-4 rounded-md border px-3">
|
<div className="bg-neutral-2 flex h-[40px] flex-row items-center gap-x-4 rounded-md border px-3">
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="filter-toggle-descriptions" className="text-sm font-normal">
|
<Label htmlFor="filter-toggle-descriptions" className="text-sm font-normal">
|
||||||
Show descriptions
|
Show descriptions
|
||||||
|
|
@ -338,7 +338,7 @@ export function MetadataFilter(props: { options: Array<{ name: string; values: s
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="secondary" className="data-[state=open]:bg-muted">
|
<Button variant="secondary" className="data-[state=open]:bg-neutral-3">
|
||||||
<FilterIcon className="size-4" />
|
<FilterIcon className="size-4" />
|
||||||
Metadata
|
Metadata
|
||||||
<span className="sr-only">Open menu to filter by metadata.</span>
|
<span className="sr-only">Open menu to filter by metadata.</span>
|
||||||
|
|
@ -352,7 +352,7 @@ export function MetadataFilter(props: { options: Array<{ name: string; values: s
|
||||||
<React.Fragment key={name}>
|
<React.Fragment key={name}>
|
||||||
{i > 0 && <DropdownMenuSeparator />}
|
{i > 0 && <DropdownMenuSeparator />}
|
||||||
<DropdownMenuGroup
|
<DropdownMenuGroup
|
||||||
className="flex cursor-pointer overflow-x-hidden text-sm text-gray-400 hover:underline"
|
className="text-neutral-10 flex cursor-pointer overflow-x-hidden text-sm hover:underline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const isChecked = !values.every(value => hasMetadataFilter(name, value));
|
const isChecked = !values.every(value => hasMetadataFilter(name, value));
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ export function GraphQLArguments(props: {
|
||||||
const { isDescriptionsVisible } = useDescriptionsVisibleToggle();
|
const { isDescriptionsVisible } = useDescriptionsVisibleToggle();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="ml-1 text-gray-400">
|
<span className="text-neutral-10 ml-1">
|
||||||
<span>(</span>
|
<span>(</span>
|
||||||
<div className="pl-4 text-gray-300">
|
<div className="text-neutral-11 pl-4">
|
||||||
{args.map(arg => {
|
{args.map(arg => {
|
||||||
const coordinate = `${props.parentCoordinate}.${arg.name}`;
|
const coordinate = `${props.parentCoordinate}.${arg.name}`;
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ export function GraphQLFields(props: {
|
||||||
This field is used but the presented arguments are not.
|
This field is used but the presented arguments are not.
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<span className="mr-1 text-sm text-orange-500">*</span>
|
<span className="text-neutral-2 mr-1 text-sm">*</span>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
@ -83,7 +83,7 @@ export function GraphQLFields(props: {
|
||||||
This field is not deprecated but the presented arguments are.
|
This field is not deprecated but the presented arguments are.
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<span className="mr-1 text-sm text-orange-500">*</span>
|
<span className="text-neutral-2 mr-1 text-sm">*</span>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
@ -112,7 +112,7 @@ export function GraphQLFields(props: {
|
||||||
organizationSlug={props.organizationSlug}
|
organizationSlug={props.organizationSlug}
|
||||||
projectSlug={props.projectSlug}
|
projectSlug={props.projectSlug}
|
||||||
targetSlug={props.targetSlug}
|
targetSlug={props.targetSlug}
|
||||||
className="font-semibold text-gray-300"
|
className="text-neutral-11 font-semibold"
|
||||||
type={field.type}
|
type={field.type}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ function Metadata(props: { supergraphMetadata: Array<{ name: string; content: st
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<MetadataIcon className="my-[5px] cursor-pointer text-white" />
|
<MetadataIcon className="text-neutral-12 my-[5px] cursor-pointer" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -216,7 +216,7 @@ export function SupergraphMetadataList(props: {
|
||||||
}
|
}
|
||||||
contentProps={{ className: 'z-10' }}
|
contentProps={{ className: 'z-10' }}
|
||||||
>
|
>
|
||||||
<span className="flex cursor-pointer items-center pl-1 text-xs font-bold text-white">
|
<span className="text-neutral-12 flex cursor-pointer items-center pl-1 text-xs font-bold">
|
||||||
+ {allItems.length - previewItems.length} more
|
+ {allItems.length - previewItems.length} more
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
|
||||||
|
|
@ -155,8 +155,8 @@ export function ChangesBlock(
|
||||||
): ReactElement | null {
|
): ReactElement | null {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2 className="mb-3 font-bold text-white">{props.title}</h2>
|
<h2 className="text-neutral-2 mb-3 font-bold">{props.title}</h2>
|
||||||
<div className="list-inside list-disc space-y-2 text-sm leading-relaxed">
|
<div className="list-inside list-disc space-y-2 text-sm/relaxed">
|
||||||
{props.changesWithUsage?.map((change, key) => (
|
{props.changesWithUsage?.map((change, key) => (
|
||||||
<ChangeItem
|
<ChangeItem
|
||||||
organizationSlug={props.organizationSlug}
|
organizationSlug={props.organizationSlug}
|
||||||
|
|
@ -228,12 +228,12 @@ function ChangeItem(
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'text-left',
|
'text-left',
|
||||||
(change.approval && 'text-orange-500') ||
|
(change.approval && 'text-neutral-2') ||
|
||||||
(severityLevelMapping[change.severityLevel] ?? 'text-red-400'),
|
(severityLevelMapping[change.severityLevel] ?? 'text-red-400'),
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-white">{labelize(change.message)}</span>
|
<span className="text-neutral-10">{labelize(change.message)}</span>
|
||||||
{change.isSafeBasedOnUsage && (
|
{change.isSafeBasedOnUsage && (
|
||||||
<span className="cursor-pointer text-yellow-500">
|
<span className="cursor-pointer text-yellow-500">
|
||||||
{' '}
|
{' '}
|
||||||
|
|
@ -243,7 +243,7 @@ function ChangeItem(
|
||||||
{'usageStatistics' in change && change.usageStatistics && (
|
{'usageStatistics' in change && change.usageStatistics && (
|
||||||
<>
|
<>
|
||||||
{' '}
|
{' '}
|
||||||
<span className="inline-flex items-center space-x-1 rounded-sm bg-gray-800 px-2 py-1 align-middle font-bold">
|
<span className="bg-neutral-5 inline-flex items-center space-x-1 rounded-sm px-2 py-1 align-middle font-bold">
|
||||||
<PulseIcon className="h-4 stroke-[1px]" />
|
<PulseIcon className="h-4 stroke-[1px]" />
|
||||||
<span className="text-xs">
|
<span className="text-xs">
|
||||||
{change.usageStatistics.topAffectedOperations.length}
|
{change.usageStatistics.topAffectedOperations.length}
|
||||||
|
|
@ -263,7 +263,7 @@ function ChangeItem(
|
||||||
{'affectedAppDeployments' in change && change.affectedAppDeployments?.totalCount ? (
|
{'affectedAppDeployments' in change && change.affectedAppDeployments?.totalCount ? (
|
||||||
<>
|
<>
|
||||||
{' '}
|
{' '}
|
||||||
<span className="inline-flex items-center space-x-1 rounded-sm bg-orange-900/50 px-2 py-1 align-middle font-bold">
|
<span className="inline-flex items-center space-x-1 rounded-sm bg-orange-500 px-2 py-1 align-middle font-bold">
|
||||||
<BoxIcon className="size-4 stroke-[2px]" />
|
<BoxIcon className="size-4 stroke-[2px]" />
|
||||||
<span className="text-xs">
|
<span className="text-xs">
|
||||||
{change.affectedAppDeployments.totalCount}{' '}
|
{change.affectedAppDeployments.totalCount}{' '}
|
||||||
|
|
@ -297,15 +297,15 @@ function ChangeItem(
|
||||||
)}
|
)}
|
||||||
{'usageStatistics' in change && change.usageStatistics && metadata ? (
|
{'usageStatistics' in change && change.usageStatistics && metadata ? (
|
||||||
<div>
|
<div>
|
||||||
<h4 className="mb-1 text-sm font-medium text-white">
|
<h4 className="text-neutral-12 mb-1 text-sm font-medium">
|
||||||
Affected Operations (based on usage)
|
Affected Operations (based on usage)
|
||||||
</h4>
|
</h4>
|
||||||
<div className="mb-2 flex justify-between text-sm text-gray-500">
|
<div className="text-neutral-10 mb-2 flex justify-between text-sm">
|
||||||
<span>
|
<span>
|
||||||
Top 10 operations and clients affected by this change based on usage data.
|
Top 10 operations and clients affected by this change based on usage data.
|
||||||
</span>
|
</span>
|
||||||
{metadata && (
|
{metadata && (
|
||||||
<span className="text-xs text-gray-100">
|
<span className="text-neutral-11 text-xs">
|
||||||
See{' '}
|
See{' '}
|
||||||
{metadata.settings.targets.map((target, index, arr) => (
|
{metadata.settings.targets.map((target, index, arr) => (
|
||||||
<>
|
<>
|
||||||
|
|
@ -319,7 +319,7 @@ function ChangeItem(
|
||||||
) : (
|
) : (
|
||||||
<Link
|
<Link
|
||||||
key={index}
|
key={index}
|
||||||
className="text-orange-500 hover:text-orange-500"
|
className="text-neutral-2 hover:text-neutral-2"
|
||||||
to="/$organizationSlug/$projectSlug/$targetSlug/insights/schema-coordinate/$coordinate"
|
to="/$organizationSlug/$projectSlug/$targetSlug/insights/schema-coordinate/$coordinate"
|
||||||
params={{
|
params={{
|
||||||
organizationSlug: props.organizationSlug,
|
organizationSlug: props.organizationSlug,
|
||||||
|
|
@ -358,7 +358,7 @@ function ChangeItem(
|
||||||
<TableRow key={hash}>
|
<TableRow key={hash}>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger className="text-orange-500 hover:text-orange-500 hover:underline hover:underline-offset-4">
|
<PopoverTrigger className="text-neutral-2 hover:text-neutral-2 hover:underline hover:underline-offset-4">
|
||||||
{hash.substring(0, 4)}_{name}
|
{hash.substring(0, 4)}_{name}
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent side="right">
|
<PopoverContent side="right">
|
||||||
|
|
@ -368,7 +368,7 @@ function ChangeItem(
|
||||||
target.target ? (
|
target.target ? (
|
||||||
<p key={i}>
|
<p key={i}>
|
||||||
<Link
|
<Link
|
||||||
className="text-orange-500 hover:text-orange-500"
|
className="text-neutral-2 hover:text-neutral-2"
|
||||||
to="/$organizationSlug/$projectSlug/$targetSlug/insights/$operationName/$operationHash"
|
to="/$organizationSlug/$projectSlug/$targetSlug/insights/$operationName/$operationHash"
|
||||||
params={{
|
params={{
|
||||||
organizationSlug: props.organizationSlug,
|
organizationSlug: props.organizationSlug,
|
||||||
|
|
@ -381,7 +381,7 @@ function ChangeItem(
|
||||||
>
|
>
|
||||||
{target.slug}
|
{target.slug}
|
||||||
</Link>{' '}
|
</Link>{' '}
|
||||||
<span className="text-white">target</span>
|
<span className="text-neutral-12">target</span>
|
||||||
</p>
|
</p>
|
||||||
) : null,
|
) : null,
|
||||||
)}
|
)}
|
||||||
|
|
@ -421,8 +421,10 @@ function ChangeItem(
|
||||||
{'affectedAppDeployments' in change &&
|
{'affectedAppDeployments' in change &&
|
||||||
change.affectedAppDeployments?.edges?.length ? (
|
change.affectedAppDeployments?.edges?.length ? (
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<h4 className="mb-1 text-sm font-medium text-white">Affected App Deployments</h4>
|
<h4 className="text-neutral-12 mb-1 text-sm font-medium">
|
||||||
<p className="mb-2 text-sm text-gray-500">
|
Affected App Deployments
|
||||||
|
</h4>
|
||||||
|
<p className="text-neutral-10 mb-2 text-sm">
|
||||||
Top 5 active app deployments that have operations using this schema coordinate.
|
Top 5 active app deployments that have operations using this schema coordinate.
|
||||||
</p>
|
</p>
|
||||||
<Table>
|
<Table>
|
||||||
|
|
@ -447,7 +449,7 @@ function ChangeItem(
|
||||||
appVersion: deployment.version,
|
appVersion: deployment.version,
|
||||||
}}
|
}}
|
||||||
search={{ coordinates: change.path?.join('.') }}
|
search={{ coordinates: change.path?.join('.') }}
|
||||||
className="text-orange-500 hover:text-orange-500 hover:underline"
|
className="text-neutral-2 hover:text-neutral-2 hover:underline"
|
||||||
>
|
>
|
||||||
{deployment.name}
|
{deployment.name}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -456,7 +458,7 @@ function ChangeItem(
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button variant="link" className="h-auto p-0 text-orange-500">
|
<Button variant="link" className="h-auto p-0">
|
||||||
{deployment.totalAffectedOperations}{' '}
|
{deployment.totalAffectedOperations}{' '}
|
||||||
{deployment.totalAffectedOperations === 1
|
{deployment.totalAffectedOperations === 1
|
||||||
? 'operation'
|
? 'operation'
|
||||||
|
|
@ -465,10 +467,12 @@ function ChangeItem(
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent side="left" className="w-80">
|
<PopoverContent side="left" className="w-80">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h5 className="font-medium text-white">Affected Operations</h5>
|
<h5 className="text-neutral-12 font-medium">
|
||||||
|
Affected Operations
|
||||||
|
</h5>
|
||||||
<ul className="max-h-40 space-y-1 overflow-y-auto text-sm">
|
<ul className="max-h-40 space-y-1 overflow-y-auto text-sm">
|
||||||
{deployment.affectedOperations.edges.map(({ node: op }) => (
|
{deployment.affectedOperations.edges.map(({ node: op }) => (
|
||||||
<li key={op.hash} className="text-gray-300">
|
<li key={op.hash} className="text-neutral-11">
|
||||||
{op.name || `[anonymous] (${op.hash.substring(0, 8)}...)`}
|
{op.name || `[anonymous] (${op.hash.substring(0, 8)}...)`}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
@ -483,7 +487,7 @@ function ChangeItem(
|
||||||
appVersion: deployment.version,
|
appVersion: deployment.version,
|
||||||
}}
|
}}
|
||||||
search={{ coordinates: change.path?.join('.') }}
|
search={{ coordinates: change.path?.join('.') }}
|
||||||
className="block pt-2 text-sm text-orange-500 hover:underline"
|
className="text-neutral-2 block pt-2 text-sm hover:underline"
|
||||||
>
|
>
|
||||||
Show all ({deployment.totalAffectedOperations}) affected
|
Show all ({deployment.totalAffectedOperations}) affected
|
||||||
operations
|
operations
|
||||||
|
|
@ -507,7 +511,7 @@ function ChangeItem(
|
||||||
schemaCheckId: props.schemaCheckId,
|
schemaCheckId: props.schemaCheckId,
|
||||||
}}
|
}}
|
||||||
search={{ coordinate: change.path?.join('.') }}
|
search={{ coordinate: change.path?.join('.') }}
|
||||||
className="mt-2 block text-sm text-orange-500 hover:underline"
|
className="text-neutral-2 mt-2 block text-sm hover:underline"
|
||||||
>
|
>
|
||||||
View all ({change.affectedAppDeployments.totalCount}) affected app deployments
|
View all ({change.affectedAppDeployments.totalCount}) affected app deployments
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -517,8 +521,8 @@ function ChangeItem(
|
||||||
</div>
|
</div>
|
||||||
) : 'affectedAppDeployments' in change && change.affectedAppDeployments?.edges?.length ? (
|
) : 'affectedAppDeployments' in change && change.affectedAppDeployments?.edges?.length ? (
|
||||||
<div>
|
<div>
|
||||||
<h4 className="mb-1 text-sm font-medium text-white">Affected App Deployments</h4>
|
<h4 className="text-neutral-12 mb-1 text-sm font-medium">Affected App Deployments</h4>
|
||||||
<p className="mb-2 text-sm text-gray-500">
|
<p className="text-neutral-10 mb-2 text-sm">
|
||||||
Top 5 active app deployments that have operations using this schema coordinate.
|
Top 5 active app deployments that have operations using this schema coordinate.
|
||||||
</p>
|
</p>
|
||||||
<Table>
|
<Table>
|
||||||
|
|
@ -543,7 +547,7 @@ function ChangeItem(
|
||||||
appVersion: deployment.version,
|
appVersion: deployment.version,
|
||||||
}}
|
}}
|
||||||
search={{ coordinates: change.path?.join('.') }}
|
search={{ coordinates: change.path?.join('.') }}
|
||||||
className="text-orange-500 hover:text-orange-500 hover:underline"
|
className="text-neutral-2 hover:text-neutral-2 hover:underline"
|
||||||
>
|
>
|
||||||
{deployment.name}
|
{deployment.name}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -552,7 +556,7 @@ function ChangeItem(
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button variant="link" className="h-auto p-0 text-orange-500">
|
<Button variant="link" className="h-auto p-0">
|
||||||
{deployment.totalAffectedOperations}{' '}
|
{deployment.totalAffectedOperations}{' '}
|
||||||
{deployment.totalAffectedOperations === 1
|
{deployment.totalAffectedOperations === 1
|
||||||
? 'operation'
|
? 'operation'
|
||||||
|
|
@ -561,10 +565,10 @@ function ChangeItem(
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent side="left" className="w-80">
|
<PopoverContent side="left" className="w-80">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h5 className="font-medium text-white">Affected Operations</h5>
|
<h5 className="text-neutral-12 font-medium">Affected Operations</h5>
|
||||||
<ul className="max-h-40 space-y-1 overflow-y-auto text-sm">
|
<ul className="max-h-40 space-y-1 overflow-y-auto text-sm">
|
||||||
{deployment.affectedOperations.edges.map(({ node: op }) => (
|
{deployment.affectedOperations.edges.map(({ node: op }) => (
|
||||||
<li key={op.hash} className="text-gray-300">
|
<li key={op.hash} className="text-neutral-11">
|
||||||
{op.name || `[anonymous] (${op.hash.substring(0, 8)}...)`}
|
{op.name || `[anonymous] (${op.hash.substring(0, 8)}...)`}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
@ -579,7 +583,7 @@ function ChangeItem(
|
||||||
appVersion: deployment.version,
|
appVersion: deployment.version,
|
||||||
}}
|
}}
|
||||||
search={{ coordinates: change.path?.join('.') }}
|
search={{ coordinates: change.path?.join('.') }}
|
||||||
className="block pt-2 text-sm text-orange-500 hover:underline"
|
className="text-neutral-2 block pt-2 text-sm hover:underline"
|
||||||
>
|
>
|
||||||
Show all ({deployment.totalAffectedOperations}) affected operations
|
Show all ({deployment.totalAffectedOperations}) affected operations
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -602,7 +606,7 @@ function ChangeItem(
|
||||||
schemaCheckId: props.schemaCheckId,
|
schemaCheckId: props.schemaCheckId,
|
||||||
}}
|
}}
|
||||||
search={{ coordinate: change.path?.join('.') }}
|
search={{ coordinate: change.path?.join('.') }}
|
||||||
className="mt-2 block text-sm text-orange-500 hover:underline"
|
className="text-neutral-2 mt-2 block text-sm hover:underline"
|
||||||
>
|
>
|
||||||
View all ({change.affectedAppDeployments.totalCount}) affected app deployments
|
View all ({change.affectedAppDeployments.totalCount}) affected app deployments
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -659,7 +663,7 @@ function SchemaChangeApproval(props: {
|
||||||
approved by {approvalName} in this schema check on {approvalDate}.
|
approved by {approvalName} in this schema check on {approvalDate}.
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<a href={schemaCheckPath} className="text-orange-500 hover:underline">
|
<a href={schemaCheckPath} className="text-neutral-2 hover:underline">
|
||||||
approved by {approvalName} on {approvalDate}.
|
approved by {approvalName} on {approvalDate}.
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
|
@ -747,11 +751,9 @@ export function NoGraphChanges() {
|
||||||
<div className="cursor-default">
|
<div className="cursor-default">
|
||||||
<div className="mb-3 flex items-center gap-3">
|
<div className="mb-3 flex items-center gap-3">
|
||||||
<CheckCircledIcon className="h-4 w-auto text-emerald-500" />
|
<CheckCircledIcon className="h-4 w-auto text-emerald-500" />
|
||||||
<h2 className="text-base font-medium text-white">No Graph Changes</h2>
|
<h2 className="text-neutral-12 text-base font-medium">No Graph Changes</h2>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-muted-foreground text-xs">
|
<p className="text-neutral-10 text-xs">There are no changes in this graph for this graph.</p>
|
||||||
There are no changes in this graph for this graph.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,8 +171,8 @@ function OperationsFilter({
|
||||||
</div>
|
</div>
|
||||||
<div className="grow pl-1">
|
<div className="grow pl-1">
|
||||||
{clientFilteredOperations && (
|
{clientFilteredOperations && (
|
||||||
<div className="text-right text-xs text-gray-600">
|
<div className="text-neutral-8 text-right text-xs">
|
||||||
<span className="text-gray-500">selected</span> / all clients
|
<span className="text-neutral-10">selected</span> / all clients
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<AutoSizer>
|
<AutoSizer>
|
||||||
|
|
@ -338,13 +338,13 @@ function OperationRow({
|
||||||
const Totals = () => {
|
const Totals = () => {
|
||||||
if (hasClientOperation) {
|
if (hasClientOperation) {
|
||||||
return (
|
return (
|
||||||
<div className="flex shrink-0 text-right text-gray-500">
|
<div className="text-neutral-10 flex shrink-0 text-right">
|
||||||
<span>{clientsRequests === '-' ? 0 : clientsRequests}</span>
|
<span>{clientsRequests === '-' ? 0 : clientsRequests}</span>
|
||||||
<span className="ml-1 truncate text-gray-600">/ {requests}</span>
|
<span className="text-neutral-8 ml-1 truncate">/ {requests}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <div className="shrink-0 text-right text-gray-600">{requests}</div>;
|
return <div className="text-neutral-8 shrink-0 text-right">{requests}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -382,7 +382,7 @@ export function OperationsFilterTrigger({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button variant="outline" className="bg-accent" onClick={toggle}>
|
<Button variant="outline" className="bg-neutral-2" onClick={toggle}>
|
||||||
<span>Operations ({selected?.length || 'all'})</span>
|
<span>Operations ({selected?.length || 'all'})</span>
|
||||||
<FilterIcon className="ml-2 size-4" />
|
<FilterIcon className="ml-2 size-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -439,13 +439,13 @@ function ClientRow({
|
||||||
const Totals = () => {
|
const Totals = () => {
|
||||||
if (props.clientOperationStats !== false) {
|
if (props.clientOperationStats !== false) {
|
||||||
return (
|
return (
|
||||||
<div className="flex shrink-0 text-right text-gray-500">
|
<div className="text-neutral-10 flex shrink-0 text-right">
|
||||||
<span>{clientOperation?.count ?? 0}</span>
|
<span>{clientOperation?.count ?? 0}</span>
|
||||||
<span className="ml-1 truncate text-gray-600">/ {requests}</span>
|
<span className="text-neutral-8 ml-1 truncate">/ {requests}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <div className="shrink-0 text-right text-gray-600">{requests}</div>;
|
return <div className="text-neutral-8 shrink-0 text-right">{requests}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -611,8 +611,8 @@ function ClientsFilter({
|
||||||
</div>
|
</div>
|
||||||
<div className="grow pl-1">
|
<div className="grow pl-1">
|
||||||
{operationStatsConnection && (
|
{operationStatsConnection && (
|
||||||
<div className="text-right text-xs text-gray-600">
|
<div className="text-neutral-8 text-right text-xs">
|
||||||
<span className="text-gray-500">selected</span> / all operations
|
<span className="text-neutral-10">selected</span> / all operations
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<AutoSizer>
|
<AutoSizer>
|
||||||
|
|
@ -759,7 +759,7 @@ export function ClientsFilterTrigger({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button variant="outline" className="bg-accent" onClick={toggle}>
|
<Button variant="outline" className="bg-neutral-2" onClick={toggle}>
|
||||||
<span>Clients ({selected?.length || 'all'})</span>
|
<span>Clients ({selected?.length || 'all'})</span>
|
||||||
<FilterIcon className="ml-2 size-4" />
|
<FilterIcon className="ml-2 size-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,7 @@ function OperationsTable({
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'overflow-x-scroll rounded-md border border-gray-800 bg-gray-900/50 p-5',
|
'border-neutral-5 bg-neutral-2/50 overflow-x-scroll rounded-md border p-5',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -271,7 +271,7 @@ function OperationsTable({
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="size-4 text-gray-400" />
|
<InfoIcon className="text-neutral-10 size-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent className="max-w-[300px] text-left text-sm">
|
<TooltipContent className="max-w-[300px] text-left text-sm">
|
||||||
<p className="mb-4">
|
<p className="mb-4">
|
||||||
|
|
|
||||||
|
|
@ -76,14 +76,14 @@ function RequestsStats({
|
||||||
const value = useFormattedNumber(requests);
|
const value = useFormattedNumber(requests);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/50">
|
<Card className="bg-neutral-2/50">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">Requests</CardTitle>
|
<CardTitle className="text-sm font-medium">Requests</CardTitle>
|
||||||
<GlobeIcon className="text-muted-foreground size-4" />
|
<GlobeIcon className="text-neutral-10 size-4" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{value}</div>
|
<div className="text-2xl font-bold">{value}</div>
|
||||||
<p className="text-muted-foreground text-xs">Total requests served</p>
|
<p className="text-neutral-10 text-xs">Total requests served</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
@ -99,16 +99,14 @@ function UniqueOperationsStats({
|
||||||
const value = useFormattedNumber(operations);
|
const value = useFormattedNumber(operations);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/50">
|
<Card className="bg-neutral-2/50">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">Operations</CardTitle>
|
<CardTitle className="text-sm font-medium">Operations</CardTitle>
|
||||||
<BookIcon className="text-muted-foreground size-4" />
|
<BookIcon className="text-neutral-10 size-4" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{value}</div>
|
<div className="text-2xl font-bold">{value}</div>
|
||||||
<p className="text-muted-foreground text-xs">
|
<p className="text-neutral-10 text-xs">Distinct GraphQL operations in {dateRangeText}</p>
|
||||||
Distinct GraphQL operations in {dateRangeText}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
@ -127,14 +125,14 @@ function OperationRelativeFrequency({
|
||||||
: '-';
|
: '-';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/50">
|
<Card className="bg-neutral-2/50">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">Relative Request Frequency</CardTitle>
|
<CardTitle className="text-sm font-medium">Relative Request Frequency</CardTitle>
|
||||||
<PercentIcon className="text-muted-foreground size-4" />
|
<PercentIcon className="text-neutral-10 size-4" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{rate}</div>
|
<div className="text-2xl font-bold">{rate}</div>
|
||||||
<p className="text-muted-foreground text-xs">The impact on the overall API traffic</p>
|
<p className="text-neutral-10 text-xs">The impact on the overall API traffic</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
@ -152,14 +150,14 @@ function PercentileStats({
|
||||||
const formatted = useFormattedDuration(value);
|
const formatted = useFormattedDuration(value);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/50">
|
<Card className="bg-neutral-2/50">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">p{percentile}</CardTitle>
|
<CardTitle className="text-sm font-medium">p{percentile}</CardTitle>
|
||||||
<GaugeIcon className="text-muted-foreground size-4" />
|
<GaugeIcon className="text-neutral-10 size-4" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{formatted}</div>
|
<div className="text-2xl font-bold">{formatted}</div>
|
||||||
<p className="text-muted-foreground text-xs">
|
<p className="text-neutral-10 text-xs">
|
||||||
Latency p{percentile} in {dateRangeText}
|
Latency p{percentile} in {dateRangeText}
|
||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
@ -185,14 +183,14 @@ function RPM({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/50">
|
<Card className="bg-neutral-2/50">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium">Requests per minute</CardTitle>
|
<CardTitle className="text-sm font-medium">Requests per minute</CardTitle>
|
||||||
<ActivityIcon className="text-muted-foreground size-4" />
|
<ActivityIcon className="text-neutral-10 size-4" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{throughput}</div>
|
<div className="text-2xl font-bold">{throughput}</div>
|
||||||
<p className="text-muted-foreground text-xs">Throughput in {dateRangeText}</p>
|
<p className="text-neutral-10 text-xs">Throughput in {dateRangeText}</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
@ -213,14 +211,14 @@ function SuccessRateStats({
|
||||||
: '-';
|
: '-';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/50">
|
<Card className="bg-neutral-2/50">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium text-emerald-500">Success rate</CardTitle>
|
<CardTitle className="text-sm font-medium text-emerald-500">Success rate</CardTitle>
|
||||||
<SmileIcon className="text-muted-foreground size-4" />
|
<SmileIcon className="text-neutral-10 size-4" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{rate}</div>
|
<div className="text-2xl font-bold">{rate}</div>
|
||||||
<p className="text-muted-foreground text-xs">Successful requests in {dateRangeText}</p>
|
<p className="text-neutral-10 text-xs">Successful requests in {dateRangeText}</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
@ -238,14 +236,14 @@ function FailureRateStats({
|
||||||
const rate = requests || totalFailures ? `${toDecimal((totalFailures * 100) / requests)}%` : '-';
|
const rate = requests || totalFailures ? `${toDecimal((totalFailures * 100) / requests)}%` : '-';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-gray-900/50">
|
<Card className="bg-neutral-2/50">
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||||
<CardTitle className="text-sm font-medium text-red-500">Failure rate</CardTitle>
|
<CardTitle className="text-sm font-medium text-red-500">Failure rate</CardTitle>
|
||||||
<FrownIcon className="text-muted-foreground size-4" />
|
<FrownIcon className="text-neutral-10 size-4" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{rate}</div>
|
<div className="text-2xl font-bold">{rate}</div>
|
||||||
<p className="text-muted-foreground text-xs">Failed requests in {dateRangeText}</p>
|
<p className="text-neutral-10 text-xs">Failed requests in {dateRangeText}</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
@ -291,7 +289,7 @@ function OverTimeStats({
|
||||||
}, [failuresOverTime]);
|
}, [failuresOverTime]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
<div className="border-neutral-5 bg-neutral-2/50 rounded-md border p-5">
|
||||||
<Section.Title>Operations over time</Section.Title>
|
<Section.Title>Operations over time</Section.Title>
|
||||||
<Section.Subtitle>Timeline of GraphQL requests and failures</Section.Subtitle>
|
<Section.Subtitle>Timeline of GraphQL requests and failures</Section.Subtitle>
|
||||||
<AutoSizer disableHeight>
|
<AutoSizer disableHeight>
|
||||||
|
|
@ -589,7 +587,7 @@ function ClientsStats(props: {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
<div className="border-neutral-5 bg-neutral-2/50 w-full rounded-md border p-5">
|
||||||
<Section.Title>Clients</Section.Title>
|
<Section.Title>Clients</Section.Title>
|
||||||
<Section.Subtitle>Top 5 - GraphQL API consumers</Section.Subtitle>
|
<Section.Subtitle>Top 5 - GraphQL API consumers</Section.Subtitle>
|
||||||
<AutoSizer disableHeight className="mt-5 flex w-full flex-row gap-x-4">
|
<AutoSizer disableHeight className="mt-5 flex w-full flex-row gap-x-4">
|
||||||
|
|
@ -861,7 +859,7 @@ function LatencyOverTimeStats({
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
<div className="border-neutral-5 bg-neutral-2/50 rounded-md border p-5">
|
||||||
<Section.Title>Latency over time</Section.Title>
|
<Section.Title>Latency over time</Section.Title>
|
||||||
<Section.Subtitle>Timeline of latency of GraphQL requests</Section.Subtitle>
|
<Section.Subtitle>Timeline of latency of GraphQL requests</Section.Subtitle>
|
||||||
<AutoSizer disableHeight>
|
<AutoSizer disableHeight>
|
||||||
|
|
@ -962,7 +960,7 @@ function RpmOverTimeStats({
|
||||||
}, [requests, windowInM]);
|
}, [requests, windowInM]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
<div className="border-neutral-5 bg-neutral-2/50 rounded-md border p-5">
|
||||||
<Section.Title>RPM over time</Section.Title>
|
<Section.Title>RPM over time</Section.Title>
|
||||||
<Section.Subtitle>Requests per minute</Section.Subtitle>
|
<Section.Subtitle>Requests per minute</Section.Subtitle>
|
||||||
<AutoSizer disableHeight>
|
<AutoSizer disableHeight>
|
||||||
|
|
@ -1110,7 +1108,7 @@ export function OperationsStats({
|
||||||
: 'success';
|
: 'success';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="space-y-12 text-gray-400 transition-opacity duration-700 ease-in-out">
|
<section className="text-neutral-8 space-y-12 transition-opacity duration-700 ease-in-out">
|
||||||
<OperationsFallback state={state} refetch={refetch}>
|
<OperationsFallback state={state} refetch={refetch}>
|
||||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||||
<RequestsStats requests={operationsStats?.totalRequests} dateRangeText={dateRangeText} />
|
<RequestsStats requests={operationsStats?.totalRequests} dateRangeText={dateRangeText} />
|
||||||
|
|
|
||||||
|
|
@ -63,16 +63,16 @@ export const ConnectLabModalContent = (props: {
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
{props?.isCDNEnabled ? (
|
{props?.isCDNEnabled ? (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm text-white">High-availability CDN:</h3>
|
<h3 className="text-neutral-12 text-sm">High-availability CDN:</h3>
|
||||||
<Callout className="mt-2" type="info">
|
<Callout className="mt-2" type="info">
|
||||||
If you want to consume the GraphQL schema for a tool like GraphQL Code Generator, we
|
If you want to consume the GraphQL schema for a tool like GraphQL Code Generator, we
|
||||||
instead recommend using the high-availability CDN instead.
|
instead recommend using the high-availability CDN instead.
|
||||||
</Callout>
|
</Callout>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<span className="text-sm text-white">You can use the following endpoint:</span>
|
<span className="text-neutral-12 text-sm">You can use the following endpoint:</span>
|
||||||
<InputCopy value={props.endpoint} />
|
<InputCopy value={props.endpoint} />
|
||||||
<span className="text-sm text-white">
|
<span className="text-neutral-12 text-sm">
|
||||||
To authenticate, use the following HTTP headers, with a token that has `target:read`
|
To authenticate, use the following HTTP headers, with a token that has `target:read`
|
||||||
scope:
|
scope:
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -89,7 +89,7 @@ export const ConnectLabModalContent = (props: {
|
||||||
YOUR_TOKEN_HERE
|
YOUR_TOKEN_HERE
|
||||||
</Link>
|
</Link>
|
||||||
</Tag>
|
</Tag>
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-neutral-10 text-sm">
|
||||||
Read the{' '}
|
Read the{' '}
|
||||||
<Link as="a" variant="primary" target="_blank" rel="noreferrer" href={props.docsUrl}>
|
<Link as="a" variant="primary" target="_blank" rel="noreferrer" href={props.docsUrl}>
|
||||||
Managing Tokens
|
Managing Tokens
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ export function ReviewComments(props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mb-2 rounded-sm border border-gray-600 bg-black px-6 py-4 font-sans">
|
<div className="bg-neutral-1 border-neutral-8 mb-2 rounded-sm border px-6 py-4 font-sans">
|
||||||
{review.comments?.edges?.map(({ node: comment }, idx) => {
|
{review.comments?.edges?.map(({ node: comment }, idx) => {
|
||||||
return (
|
return (
|
||||||
<ReviewComment key={`comment-${comment.id}`} first={idx === 0} comment={comment} />
|
<ReviewComment key={`comment-${comment.id}`} first={idx === 0} comment={comment} />
|
||||||
|
|
@ -74,10 +74,10 @@ export function ReviewComment(props: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={cn(!props.first && 'pl-4', 'flex grow flex-row align-middle')}>
|
<div className={cn(!props.first && 'pl-4', 'flex grow flex-row align-middle')}>
|
||||||
<div className="flex grow font-bold text-gray-400">{comment.author ?? 'Unknown'}</div>
|
<div className="text-neutral-10 flex grow font-bold">{comment.author ?? 'Unknown'}</div>
|
||||||
<div className="flex text-xs">
|
<div className="flex text-xs">
|
||||||
{!!comment.updatedAt && 'updated '}
|
{!!comment.updatedAt && 'updated '}
|
||||||
<TimeAgo date={comment.updatedAt ?? comment.createdAt} className="text-gray-400" />
|
<TimeAgo date={comment.updatedAt ?? comment.createdAt} className="text-neutral-10" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 flex-row">{comment.body}</div>
|
<div className="mt-2 flex-row">{comment.body}</div>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export function ProposalChangeDetail(props: {
|
||||||
<Accordion type="single">
|
<Accordion type="single">
|
||||||
<AccordionItem value="item-1">
|
<AccordionItem value="item-1">
|
||||||
<AccordionHeader className="flex">
|
<AccordionHeader className="flex">
|
||||||
<AccordionTrigger className="py-3 text-white hover:no-underline">
|
<AccordionTrigger className="text-neutral-8 py-3 hover:no-underline">
|
||||||
<div className="flex w-full flex-row items-center text-left">
|
<div className="flex w-full flex-row items-center text-left">
|
||||||
<div>{labelize(props.change.message)}</div>
|
<div>{labelize(props.change.message)}</div>
|
||||||
<div className="min-w-fit grow pr-2 md:flex-none">{props.icon}</div>
|
<div className="min-w-fit grow pr-2 md:flex-none">{props.icon}</div>
|
||||||
|
|
@ -49,7 +49,7 @@ export function ChangeBlock(props: {
|
||||||
return (
|
return (
|
||||||
props.changes.length !== 0 && (
|
props.changes.length !== 0 && (
|
||||||
<>
|
<>
|
||||||
<h2 className="mb-2 mt-6 flex items-center font-bold text-white">
|
<h2 className="text-neutral-2 mb-2 mt-6 flex items-center font-bold">
|
||||||
{props.title}
|
{props.title}
|
||||||
{props.info && <ChangesBlockTooltip info={props.info} />}
|
{props.info && <ChangesBlockTooltip info={props.info} />}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
@ -65,7 +65,7 @@ export function ChangeBlock(props: {
|
||||||
);
|
);
|
||||||
} else if (mergeStatus === MergeStatus.IGNORED) {
|
} else if (mergeStatus === MergeStatus.IGNORED) {
|
||||||
icon = (
|
icon = (
|
||||||
<span className="flex items-center justify-end pl-4 text-gray-400">
|
<span className="text-neutral-10 flex items-center justify-end pl-4">
|
||||||
<ComponentNoneIcon className="mr-2" /> NO CHANGE
|
<ComponentNoneIcon className="mr-2" /> NO CHANGE
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
@ -90,7 +90,7 @@ function ChangesBlockTooltip(props: { info: string }) {
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip delayDuration={200}>
|
<Tooltip delayDuration={200}>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<Button variant="ghost" size="icon-sm" className="ml-1 text-gray-400">
|
<Button variant="ghost" size="icon-sm" className="text-neutral-10 ml-1">
|
||||||
<InfoCircledIcon className="size-4" />
|
<InfoCircledIcon className="size-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,7 @@ export function ProposalEditor(props: {
|
||||||
</TabsList>
|
</TabsList>
|
||||||
<div className="flex flex-row items-center justify-end">
|
<div className="flex flex-row items-center justify-end">
|
||||||
<Link
|
<Link
|
||||||
className="ml-2 cursor-pointer p-1 hover:text-orange-500"
|
className="hover:text-neutral-2 ml-2 cursor-pointer p-1"
|
||||||
title="Prettify schema"
|
title="Prettify schema"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -364,8 +364,8 @@ export function ProposalEditor(props: {
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
className={cn(
|
className={cn(
|
||||||
'ml-2 cursor-pointer p-1 hover:text-orange-500',
|
'hover:text-neutral-2 ml-2 cursor-pointer p-1',
|
||||||
showSettings && 'border-b-2 border-orange-500',
|
showSettings && 'border-neutral-2 border-b-2',
|
||||||
projectType?.project.type === ProjectType.Single && 'hidden',
|
projectType?.project.type === ProjectType.Single && 'hidden',
|
||||||
)}
|
)}
|
||||||
title="Edit schema settings"
|
title="Edit schema settings"
|
||||||
|
|
@ -402,7 +402,7 @@ export function ProposalEditor(props: {
|
||||||
onChange={setActiveTabSource}
|
onChange={setActiveTabSource}
|
||||||
/>
|
/>
|
||||||
{showSettings && service.__typename === 'CompositeSchema' && (
|
{showSettings && service.__typename === 'CompositeSchema' && (
|
||||||
<div className="absolute right-0 top-0 z-10 h-full w-[20vw] min-w-[200px] max-w-full border bg-black p-4 pt-6 text-sm">
|
<div className="bg-neutral-1 absolute right-0 top-0 z-10 h-full w-[20vw] min-w-[200px] max-w-full border p-4 pt-6 text-sm">
|
||||||
{!!service.service && (
|
{!!service.service && (
|
||||||
<SubPageLayoutHeader
|
<SubPageLayoutHeader
|
||||||
subPageTitle="Settings"
|
subPageTitle="Settings"
|
||||||
|
|
|
||||||
|
|
@ -489,7 +489,7 @@ export function Proposal(props: {
|
||||||
<Fragment key={cursor}>
|
<Fragment key={cursor}>
|
||||||
{/* @todo if node.resolvedBy/resolvedAt is set, then minimize this */}
|
{/* @todo if node.resolvedBy/resolvedAt is set, then minimize this */}
|
||||||
{withPreview === true && node.lineText && (
|
{withPreview === true && node.lineText && (
|
||||||
<code className="mb-3 block w-full bg-gray-900 p-3 pl-6 text-white">
|
<code className="text-neutral-12 bg-neutral-2 mb-3 block w-full p-3 pl-6">
|
||||||
{node.lineText}
|
{node.lineText}
|
||||||
</code>
|
</code>
|
||||||
)}
|
)}
|
||||||
|
|
@ -511,7 +511,7 @@ export function Proposal(props: {
|
||||||
coordinates={reviewssByCoordinate.keys().toArray()}
|
coordinates={reviewssByCoordinate.keys().toArray()}
|
||||||
annotate={(coordinate, withPreview) => (
|
annotate={(coordinate, withPreview) => (
|
||||||
<>
|
<>
|
||||||
<div className="p-2 text-sm text-gray-600">
|
<div className="text-neutral-8 p-2 text-sm">
|
||||||
This comment refers to a schema coordinate that no longer exists.
|
This comment refers to a schema coordinate that no longer exists.
|
||||||
</div>
|
</div>
|
||||||
{annotations(coordinate, withPreview)}
|
{annotations(coordinate, withPreview)}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ export function ChangeDocument(props: { children: ReactNode; className?: string
|
||||||
<table
|
<table
|
||||||
aria-label="change-document"
|
aria-label="change-document"
|
||||||
className={cn(
|
className={cn(
|
||||||
'min-w-full cursor-default whitespace-pre font-mono text-sm text-white',
|
'text-neutral-12 min-w-full cursor-default whitespace-pre font-mono text-sm',
|
||||||
props.className,
|
props.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -85,7 +85,7 @@ export function ChangeRow(props: {
|
||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-[42px] min-w-fit select-none bg-gray-900 pr-3 text-right text-gray-600',
|
'bg-neutral-3 text-neutral-7 w-[42px] min-w-fit select-none pr-3 text-right',
|
||||||
props.className,
|
props.className,
|
||||||
(props.type === 'removal' || removed) && 'bg-red-900/30',
|
(props.type === 'removal' || removed) && 'bg-red-900/30',
|
||||||
props.type === 'addition' && 'invisible',
|
props.type === 'addition' && 'invisible',
|
||||||
|
|
@ -95,7 +95,7 @@ export function ChangeRow(props: {
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-[42px] min-w-fit select-none bg-gray-900 pr-3 text-right text-gray-600',
|
'bg-neutral-3 text-neutral-7 w-[42px] min-w-fit select-none pr-3 text-right',
|
||||||
props.className,
|
props.className,
|
||||||
props.type === 'removal' && 'invisible',
|
props.type === 'removal' && 'invisible',
|
||||||
(props.type === 'addition' || added) && 'bg-green-900/30',
|
(props.type === 'addition' || added) && 'bg-green-900/30',
|
||||||
|
|
@ -105,7 +105,7 @@ export function ChangeRow(props: {
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-gray-900 px-2',
|
'bg-neutral-2 px-2',
|
||||||
props.className,
|
props.className,
|
||||||
props.type === 'removal' && 'bg-[#561c1d]',
|
props.type === 'removal' && 'bg-[#561c1d]',
|
||||||
props.type === 'addition' && 'bg-[#11362b]',
|
props.type === 'addition' && 'bg-[#11362b]',
|
||||||
|
|
@ -113,7 +113,7 @@ export function ChangeRow(props: {
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-gray-900',
|
'bg-neutral-2',
|
||||||
props.type === 'removal' && 'bg-[#561c1d] line-through decoration-[#998c8b]',
|
props.type === 'removal' && 'bg-[#561c1d] line-through decoration-[#998c8b]',
|
||||||
props.type === 'addition' && 'bg-[#11362b]',
|
props.type === 'addition' && 'bg-[#11362b]',
|
||||||
)}
|
)}
|
||||||
|
|
@ -178,7 +178,7 @@ function Addition(props: { children: ReactNode; className?: string }): ReactNode
|
||||||
}
|
}
|
||||||
}, [change.addition]);
|
}, [change.addition]);
|
||||||
return (
|
return (
|
||||||
<span className={cn('bg-[#11362b] hover:bg-green-900', props.className)}>{props.children}</span>
|
<span className={cn('bg-neutral-3 hover:bg-green-900', props.className)}>{props.children}</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export function LineGroup(props: { children?: ReactElement[]; collapsible?: bool
|
||||||
<tbody>
|
<tbody>
|
||||||
{props.children?.slice(0, 3)}
|
{props.children?.slice(0, 3)}
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={3} className="text-gray-500">
|
<td colSpan={3} className="text-neutral-8">
|
||||||
...
|
...
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -42,7 +42,7 @@ export function LineGroup(props: { children?: ReactElement[]; collapsible?: bool
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={3} className="text-gray-500">
|
<td colSpan={3} className="text-neutral-8">
|
||||||
...
|
...
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -68,7 +68,7 @@ export function Line(props: LineProps & { beforeLine: number; afterLine: number
|
||||||
{props.annotations?.map((node, i) => (
|
{props.annotations?.map((node, i) => (
|
||||||
<Fragment key={`annotations-${i}`}>
|
<Fragment key={`annotations-${i}`}>
|
||||||
{node.lineText && (
|
{node.lineText && (
|
||||||
<code className="mb-3 block w-full bg-gray-900 p-3 pl-6 text-white">
|
<code className="bg-neutral-3 text-neutral-12 mb-3 block w-full p-3 pl-6">
|
||||||
{node.lineText}
|
{node.lineText}
|
||||||
</code>
|
</code>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export function Word(props: WordProps) {
|
||||||
<Change type={props.change}>
|
<Change type={props.change}>
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
props.kind === 'description' && 'text-gray-500',
|
props.kind === 'description' && 'textneutral-8',
|
||||||
props.kind === 'field' && 'text-white',
|
props.kind === 'field' && 'text-white',
|
||||||
props.kind === 'keyword' && 'text-gray-400',
|
props.kind === 'keyword' && 'text-gray-400',
|
||||||
props.kind === 'literal' && 'text-white',
|
props.kind === 'literal' && 'text-white',
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ export function StageTransitionSelect(props: {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex flex-row truncate p-1 text-gray-400 hover:text-white',
|
'hover:text-neutral-12 text-neutral-10 flex flex-row truncate p-1',
|
||||||
s.value === props.stage && 'underline',
|
s.value === props.stage && 'underline',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ export function VersionSelect(props: {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex flex-row gap-x-6 p-1 text-gray-400 hover:text-white',
|
'hover:text-neutral-12 text-neutral-10 flex flex-row gap-x-6 p-1',
|
||||||
lastVersionCursor === selectedVersionCursor && 'underline',
|
lastVersionCursor === selectedVersionCursor && 'underline',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -375,7 +375,7 @@ export function CDNAccessTokens(props: {
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
<DocsLink
|
<DocsLink
|
||||||
href="/management/targets#cdn-access-tokens"
|
href="/management/targets#cdn-access-tokens"
|
||||||
className="text-gray-500 hover:text-gray-300"
|
className="text-neutral-10 hover:text-neutral-11"
|
||||||
>
|
>
|
||||||
Learn more about CDN Access Tokens
|
Learn more about CDN Access Tokens
|
||||||
</DocsLink>
|
</DocsLink>
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ export function SchemaContracts(props: {
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
<DocsLink
|
<DocsLink
|
||||||
href="/management/contracts"
|
href="/management/contracts"
|
||||||
className="text-gray-500 hover:text-gray-300"
|
className="text-neutral-10 hover:text-neutral-11"
|
||||||
>
|
>
|
||||||
Learn more about Schema Contracts
|
Learn more about Schema Contracts
|
||||||
</DocsLink>
|
</DocsLink>
|
||||||
|
|
@ -700,7 +700,7 @@ function CreateContractDialogContent(props: {
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor="removeUnreachableTypesFromPublicApiSchema"
|
htmlFor="removeUnreachableTypesFromPublicApiSchema"
|
||||||
className="ml-2 inline-block cursor-pointer text-sm text-gray-300"
|
className="text-neutral-11 ml-2 inline-block cursor-pointer text-sm"
|
||||||
>
|
>
|
||||||
Remove unreachable types from public API schema
|
Remove unreachable types from public API schema
|
||||||
</label>
|
</label>
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,6 @@ import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { useLocalStorage } from '@/lib/hooks';
|
import { useLocalStorage } from '@/lib/hooks';
|
||||||
|
|
||||||
const STORAGE_KEY = 'hive-theme';
|
const STORAGE_KEY = 'hive-theme';
|
||||||
const TEMP_THEME_SWITCHER_KEY = 'hive-temp-theme-switcher';
|
|
||||||
|
|
||||||
export function isThemeSwitcherEnabled(): boolean {
|
|
||||||
if (typeof window === 'undefined') return false;
|
|
||||||
return localStorage.getItem(TEMP_THEME_SWITCHER_KEY) === 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Theme = 'light' | 'dark' | 'system';
|
export type Theme = 'light' | 'dark' | 'system';
|
||||||
export type ResolvedTheme = 'light' | 'dark';
|
export type ResolvedTheme = 'light' | 'dark';
|
||||||
|
|
@ -34,15 +28,13 @@ function applyTheme(resolvedTheme: ResolvedTheme) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||||
const [storedTheme, setStoredTheme] = useLocalStorage(STORAGE_KEY, 'dark');
|
const [storedTheme, setStoredTheme] = useLocalStorage(STORAGE_KEY, 'system');
|
||||||
const [systemTheme, setSystemTheme] = useState<ResolvedTheme>(getSystemTheme);
|
const [systemTheme, setSystemTheme] = useState<ResolvedTheme>(getSystemTheme);
|
||||||
|
|
||||||
// When theme switcher is disabled, always use dark mode regardless of stored value
|
const theme: Theme =
|
||||||
const theme: Theme = isThemeSwitcherEnabled()
|
storedTheme === 'light' || storedTheme === 'dark' || storedTheme === 'system'
|
||||||
? ((storedTheme === 'light' || storedTheme === 'dark' || storedTheme === 'system'
|
? (storedTheme as Theme)
|
||||||
? storedTheme
|
: 'system';
|
||||||
: 'system') as Theme)
|
|
||||||
: 'dark';
|
|
||||||
|
|
||||||
const resolvedTheme: ResolvedTheme = theme === 'system' ? systemTheme : theme;
|
const resolvedTheme: ResolvedTheme = theme === 'system' ? systemTheme : theme;
|
||||||
|
|
||||||
|
|
@ -50,10 +42,8 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||||
setStoredTheme(newTheme);
|
setStoredTheme(newTheme);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen for system theme changes (only when theme switcher is enabled)
|
// Listen for system theme changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isThemeSwitcherEnabled()) return;
|
|
||||||
|
|
||||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
|
|
||||||
const handleChange = (e: MediaQueryListEvent) => {
|
const handleChange = (e: MediaQueryListEvent) => {
|
||||||
|
|
@ -66,9 +56,7 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
|
||||||
// Apply theme to document
|
// Apply theme to document
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// TODO: we're forcing dark mode here, remove when color palette work is complete
|
applyTheme(resolvedTheme);
|
||||||
// applyTheme(resolvedTheme);
|
|
||||||
applyTheme('dark');
|
|
||||||
}, [resolvedTheme]);
|
}, [resolvedTheme]);
|
||||||
|
|
||||||
const value = useMemo(() => ({ theme, setTheme, resolvedTheme }), [theme, resolvedTheme]);
|
const value = useMemo(() => ({ theme, setTheme, resolvedTheme }), [theme, resolvedTheme]);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ const AlertDialogOverlay = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<AlertDialogPrimitive.Overlay
|
<AlertDialogPrimitive.Overlay
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 backdrop-blur-sm',
|
'bg-neutral-1.01 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 backdrop-blur-sm',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -33,7 +33,7 @@ const AlertDialogContent = React.forwardRef<
|
||||||
<AlertDialogPrimitive.Content
|
<AlertDialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
|
'bg-neutral-3 border-neutral-5 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -73,7 +73,7 @@ const AlertDialogDescription = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<AlertDialogPrimitive.Description
|
<AlertDialogPrimitive.Description
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('text-muted-foreground text-sm', className)}
|
className={cn('text-neutral-10 text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@ import { cva, type VariantProps } from 'class-variance-authority';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
const alertVariants = cva(
|
const alertVariants = cva(
|
||||||
'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',
|
'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-neutral-11',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: 'bg-background text-foreground',
|
default: 'bg-neutral-3 text-neutral-11',
|
||||||
destructive: 'text-destructive border-destructive [&>svg]:text-destructive',
|
destructive: 'border-red-500 text-red-500 [&>svg]:text-red-500',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,13 @@ const badgeVariants = cva(
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
|
default: 'border-transparent bg-neutral-11 text-neutral-2 hover:bg-neutral-11/80',
|
||||||
secondary:
|
secondary: 'border-transparent bg-neutral-2 text-neutral-11 hover:bg-neutral-2/80',
|
||||||
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
destructive: 'border-transparent bg-red-500 text-neutral-12 hover:bg-red-800',
|
||||||
destructive:
|
outline: 'text-neutral-11',
|
||||||
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
|
||||||
outline: 'text-foreground',
|
|
||||||
success: 'bg-emerald-950 text-emerald-400 border-transparent',
|
success: 'bg-emerald-950 text-emerald-400 border-transparent',
|
||||||
warning: 'bg-yellow-700 border-transparent',
|
warning: 'bg-yellow-700 border-transparent',
|
||||||
failure: 'bg-red-900 text-white border-transparent',
|
failure: 'bg-red-900 text-neutral-12 border-transparent',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|
@ -33,15 +31,15 @@ function Badge({ className, variant, ...props }: BadgeProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const badgeRoundedVariants = cva(
|
const badgeRoundedVariants = cva(
|
||||||
'inline-block rounded-full mx-1 border-[3px] p-[3px] align-middle text-xs font-bold leading-none text-white',
|
'inline-block rounded-full mx-1 outline-offset-[-10px] border-[3px] p-[3px] align-middle text-xs font-bold leading-none text-neutral-12',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
color: {
|
color: {
|
||||||
red: 'border-red-900 bg-red-500',
|
red: 'border-red-900 bg-red-500',
|
||||||
yellow: 'border-yellow-900 bg-yellow-500',
|
yellow: 'border-yellow-900 bg-yellow-500',
|
||||||
green: 'border-green-900 bg-green-500',
|
green: 'border-green-900 bg-green-500',
|
||||||
gray: 'border-gray-900 bg-gray-500',
|
gray: 'border-neutral-7 bg-neutral-11',
|
||||||
orange: 'border-orange-900 bg-orange-500',
|
orange: 'border-orange-900 bg-orange-500',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,19 @@ import { cn } from '@/lib/utils';
|
||||||
import { Slot } from '@radix-ui/react-slot';
|
import { Slot } from '@radix-ui/react-slot';
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
|
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-neutral-2',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
default: 'bg-neutral-4 text-neutral-11 hover:text-neutral-12 hover:bg-neutral-5',
|
||||||
primary: 'bg-orange-600 text-white hover:brightness-110 active:bg-orange-700',
|
primary: 'bg-accent text-neutral-2 hover:brightness-110 active:bg-accent',
|
||||||
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
destructive: 'bg-red-500 text-neutral-1 dark:text-neutral-12 hover:bg-red-700',
|
||||||
outline: 'border border-input hover:bg-accent hover:text-accent-foreground',
|
outline:
|
||||||
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
'text-neutral-11 hover:text-neutral-12 border border-neutral-5 hover:border-neutral-6 bg-neutral-3 hover:bg-neutral-4',
|
||||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
secondary: 'bg-neutral-2 text-neutral-11 hover:bg-neutral-2/80',
|
||||||
link: 'underline-offset-4 hover:underline text-primary',
|
ghost: 'hover:bg-neutral-2 hover:text-neutral-12',
|
||||||
orangeLink: 'h-auto p-0 underline-offset-4 hover:underline text-orange-500',
|
link: 'underline-offset-4 hover:underline text-accent',
|
||||||
|
orangeLink: 'h-auto p-0 underline-offset-4 hover:underline text-accent',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: 'h-10 py-2 px-4',
|
default: 'h-10 py-2 px-4',
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C
|
||||||
nav_button_next: 'absolute right-1',
|
nav_button_next: 'absolute right-1',
|
||||||
table: 'w-full border-collapse space-y-1',
|
table: 'w-full border-collapse space-y-1',
|
||||||
head_row: 'flex',
|
head_row: 'flex',
|
||||||
head_cell: 'text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]',
|
head_cell: 'text-neutral-10 rounded-md w-8 font-normal text-[0.8rem]',
|
||||||
row: 'flex w-full mt-2',
|
row: 'flex w-full mt-2',
|
||||||
cell: cn(
|
cell: cn(
|
||||||
'relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md',
|
'relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-neutral-2 [&:has([aria-selected].day-outside)]:bg-neutral-2/50 [&:has([aria-selected].day-range-end)]:rounded-r-md',
|
||||||
props.mode === 'range'
|
props.mode === 'range'
|
||||||
? '[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md'
|
? '[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md'
|
||||||
: '[&:has([aria-selected])]:rounded-md',
|
: '[&:has([aria-selected])]:rounded-md',
|
||||||
|
|
@ -40,12 +40,12 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C
|
||||||
day_range_start: 'day-range-start',
|
day_range_start: 'day-range-start',
|
||||||
day_range_end: 'day-range-end',
|
day_range_end: 'day-range-end',
|
||||||
day_selected:
|
day_selected:
|
||||||
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
|
'bg-neutral-11 text-neutral-2 hover:bg-neutral-11 hover:text-neutral-2 focus:bg-neutral-11 focus:text-neutral-2',
|
||||||
day_today: 'bg-accent text-accent-foreground',
|
day_today: 'bg-neutral-2 text-neutral-12',
|
||||||
day_outside:
|
day_outside:
|
||||||
'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30',
|
'day-outside text-neutral-10 opacity-50 aria-selected:bg-neutral-2/50 aria-selected:text-neutral-10 aria-selected:opacity-30',
|
||||||
day_disabled: 'text-muted-foreground opacity-50',
|
day_disabled: 'text-neutral-10 opacity-50',
|
||||||
day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',
|
day_range_middle: 'aria-selected:bg-neutral-2 aria-selected:text-neutral-12',
|
||||||
day_hidden: 'invisible',
|
day_hidden: 'invisible',
|
||||||
...classNames,
|
...classNames,
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,10 @@ type CalloutType = keyof typeof TypeToEmoji;
|
||||||
const calloutVariants = cva('mt-6 flex items-center gap-4 rounded-lg border px-4 py-2', {
|
const calloutVariants = cva('mt-6 flex items-center gap-4 rounded-lg border px-4 py-2', {
|
||||||
variants: {
|
variants: {
|
||||||
type: {
|
type: {
|
||||||
default: ' border-orange-400/30 bg-orange-400/20 text-orange-300',
|
default: 'border-orange-300 bg-orange-200 text-orange-900',
|
||||||
error: ' border-red-200/30 bg-red-900/30 text-red-200',
|
error: 'border-red-300 bg-red-200 text-red-900',
|
||||||
info: ' border-blue-200/30 bg-blue-900/30 text-blue-200',
|
info: 'border-blue-300 bg-blue-200 text-blue-900',
|
||||||
warning: ' border-yellow-200/30 bg-yellow-700/30 text-yellow-200',
|
warning: 'border-yellow-300 bg-yellow-200 text-yellow-900',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElemen
|
||||||
({ className, ...props }, ref) => (
|
({ className, ...props }, ref) => (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('text-card-foreground rounded-lg border bg-gray-900/50 shadow-sm', className)}
|
className={cn(
|
||||||
|
'text-neutral-11 bg-neutral-3 border-neutral-4 rounded-lg border shadow-sm',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|
@ -28,7 +31,7 @@ const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HT
|
||||||
// eslint-disable-next-line jsx-a11y/heading-has-content
|
// eslint-disable-next-line jsx-a11y/heading-has-content
|
||||||
<h3
|
<h3
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('cursor-default text-lg font-semibold leading-none tracking-tight', className)}
|
className={cn('text-neutral-12 cursor-default text-lg font-medium leading-none', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|
@ -39,11 +42,7 @@ const CardDescription = React.forwardRef<
|
||||||
HTMLParagraphElement,
|
HTMLParagraphElement,
|
||||||
React.HTMLAttributes<HTMLParagraphElement>
|
React.HTMLAttributes<HTMLParagraphElement>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<p
|
<p ref={ref} className={cn('text-neutral-11 cursor-default text-sm', className)} {...props} />
|
||||||
ref={ref}
|
|
||||||
className={cn('text-muted-foreground cursor-default text-sm', className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
));
|
||||||
CardDescription.displayName = 'CardDescription';
|
CardDescription.displayName = 'CardDescription';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
||||||
Latest changes
|
Latest changes
|
||||||
{displayDot ? (
|
{displayDot ? (
|
||||||
<div className="absolute right-0 top-0 -mr-1 -mt-1 flex size-2">
|
<div className="absolute right-0 top-0 -mr-1 -mt-1 flex size-2">
|
||||||
<div className="absolute inline-flex size-full animate-pulse rounded-full bg-orange-500" />
|
<div className="bg-accent absolute inline-flex size-full animate-pulse rounded-full" />
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -71,8 +71,8 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
||||||
<PopoverArrow />
|
<PopoverArrow />
|
||||||
<div className="grid">
|
<div className="grid">
|
||||||
<div className="space-y-2 p-4">
|
<div className="space-y-2 p-4">
|
||||||
<h4 className="font-medium leading-none">What's new in GraphQL Hive</h4>
|
<h4 className="text-neutral-12 font-medium leading-none">What's new in GraphQL Hive</h4>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-neutral-11 text-sm">
|
||||||
Find out about the newest features, and enhancements
|
Find out about the newest features, and enhancements
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -81,17 +81,14 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
||||||
<li
|
<li
|
||||||
className={cn(
|
className={cn(
|
||||||
'border-l-2 pl-4',
|
'border-l-2 pl-4',
|
||||||
readChanges.includes(change.href) ? 'border-transparent' : 'border-orange-700',
|
readChanges.includes(change.href) ? 'border-transparent' : 'border-accent_80',
|
||||||
)}
|
)}
|
||||||
key={index}
|
key={index}
|
||||||
>
|
>
|
||||||
<time
|
<time className="text-neutral-10 mb-1 text-xs font-normal" dateTime={change.date}>
|
||||||
className="text-muted-foreground mb-1 text-sm font-normal"
|
|
||||||
dateTime={change.date}
|
|
||||||
>
|
|
||||||
{format(new Date(change.date), 'do MMMM yyyy')}
|
{format(new Date(change.date), 'do MMMM yyyy')}
|
||||||
</time>
|
</time>
|
||||||
<h3 className="text-pretty text-base font-semibold text-white hover:underline">
|
<h3 className="text-neutral-12 text-pretty text-base font-medium hover:underline">
|
||||||
<a
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
|
|
@ -101,7 +98,7 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
||||||
{change.title}
|
{change.title}
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
<div className="mb-4 mt-1 text-pretty text-sm font-normal text-white/80">
|
<div className="text-neutral-11 mb-4 text-pretty text-sm font-normal">
|
||||||
{change.description}
|
{change.description}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -109,7 +106,7 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center justify-center">
|
<div className="flex flex-row items-center justify-center">
|
||||||
<Button variant="link" asChild className="text-left text-sm">
|
<Button variant="link" asChild className="text-neutral-11 text-left text-sm">
|
||||||
<a
|
<a
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
href="https://the-guild.dev/graphql/hive/product-updates"
|
href="https://the-guild.dev/graphql/hive/product-updates"
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ const ChartContainer = React.forwardRef<
|
||||||
data-chart={chartId}
|
data-chart={chartId}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
|
"[&_.recharts-cartesian-axis-tick_text]:fill-neutral-10 [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-neutral-5/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-neutral-5 [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-neutral-5 [&_.recharts-radial-bar-neutral-2-sector]:fill-neutral-3 [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-neutral-3 [&_.recharts-reference-line_[stroke='#ccc']]:stroke-neutral-5 flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -160,7 +160,7 @@ const ChartTooltipContent = React.forwardRef<
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl',
|
'border-neutral-5/50 bg-neutral-3 grid min-w-32 items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -175,7 +175,7 @@ const ChartTooltipContent = React.forwardRef<
|
||||||
<div
|
<div
|
||||||
key={item.dataKey}
|
key={item.dataKey}
|
||||||
className={cn(
|
className={cn(
|
||||||
'[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:size-2.5',
|
'[&>svg]:text-neutral-10 flex w-full flex-wrap items-stretch gap-2 [&>svg]:size-2.5',
|
||||||
indicator === 'dot' && 'items-center',
|
indicator === 'dot' && 'items-center',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -188,16 +188,13 @@ const ChartTooltipContent = React.forwardRef<
|
||||||
) : (
|
) : (
|
||||||
!hideIndicator && (
|
!hideIndicator && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn('border-neutral-5 bg-neutral-2 shrink-0 rounded-[2px]', {
|
||||||
'border-(--color-border) bg-(--color-bg) shrink-0 rounded-[2px]',
|
'h-2.5 w-2.5': indicator === 'dot',
|
||||||
{
|
'w-1': indicator === 'line',
|
||||||
'h-2.5 w-2.5': indicator === 'dot',
|
'w-0 border-[1.5px] border-dashed bg-transparent':
|
||||||
'w-1': indicator === 'line',
|
indicator === 'dashed',
|
||||||
'w-0 border-[1.5px] border-dashed bg-transparent':
|
'my-0.5': nestLabel && indicator === 'dashed',
|
||||||
indicator === 'dashed',
|
})}
|
||||||
'my-0.5': nestLabel && indicator === 'dashed',
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
'--color-bg': indicatorColor,
|
'--color-bg': indicatorColor,
|
||||||
|
|
@ -215,12 +212,10 @@ const ChartTooltipContent = React.forwardRef<
|
||||||
>
|
>
|
||||||
<div className="grid gap-1.5">
|
<div className="grid gap-1.5">
|
||||||
{nestLabel ? tooltipLabel : null}
|
{nestLabel ? tooltipLabel : null}
|
||||||
<span className="text-muted-foreground">
|
<span className="text-neutral-10">{itemConfig?.label || item.name}</span>
|
||||||
{itemConfig?.label || item.name}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{item.value && (
|
{item.value && (
|
||||||
<span className="text-foreground font-mono font-medium tabular-nums">
|
<span className="text-neutral-11 font-mono font-medium tabular-nums">
|
||||||
{item.value.toLocaleString()}
|
{item.value.toLocaleString()}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
@ -269,7 +264,7 @@ const ChartLegendContent = React.forwardRef<
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={item.value}
|
key={item.value}
|
||||||
className={cn('[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:size-3')}
|
className={cn('[&>svg]:text-neutral-10 flex items-center gap-1.5 [&>svg]:size-3')}
|
||||||
>
|
>
|
||||||
{itemConfig?.icon && !hideIcon ? (
|
{itemConfig?.icon && !hideIcon ? (
|
||||||
<itemConfig.icon />
|
<itemConfig.icon />
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const Checkbox = React.forwardRef<
|
||||||
<CheckboxPrimitive.Root
|
<CheckboxPrimitive.Root
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'border-primary ring-offset-background focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer size-4 shrink-0 rounded-sm border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
'border-neutral-11 ring-offset-neutral-2 focus-visible:ring-ring data-[state=checked]:bg-neutral-11 data-[state=checked]:text-neutral-2 peer size-4 shrink-0 rounded-sm border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export const Code: FC<ComponentProps<'code'>> = ({ children, className, ...props
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className="relative flex cursor-text items-center gap-2 break-all rounded-md border border-gray-600 bg-black p-4 pr-14 font-mono text-sm"
|
className="bg-neutral-1 border-neutral-8 relative flex cursor-text items-center gap-2 break-all rounded-md border p-4 pr-14 font-mono text-sm"
|
||||||
// Make this element able to be focused by setting tabIndex.
|
// Make this element able to be focused by setting tabIndex.
|
||||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
|
@ -40,7 +40,7 @@ export const Code: FC<ComponentProps<'code'>> = ({ children, className, ...props
|
||||||
<button
|
<button
|
||||||
hidden={!navigatorClipboardSupport}
|
hidden={!navigatorClipboardSupport}
|
||||||
data-hovering={hovering || copied}
|
data-hovering={hovering || copied}
|
||||||
className="absolute right-3 top-2 cursor-pointer rounded-md border border-gray-600 p-2 opacity-0 hover:text-orange-600 data-[hovering=true]:opacity-100 data-[hovering=true]:transition-opacity"
|
className="border-neutral-8 absolute right-3 top-2 cursor-pointer rounded-md border p-2 opacity-0 hover:text-orange-500 data-[hovering=true]:opacity-100 data-[hovering=true]:transition-opacity"
|
||||||
onClick={async ev => {
|
onClick={async ev => {
|
||||||
const value = children?.valueOf().toString();
|
const value = children?.valueOf().toString();
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const Command = React.forwardRef<
|
||||||
<CommandPrimitive
|
<CommandPrimitive
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-popover text-popover-foreground flex size-full flex-col overflow-hidden rounded-md',
|
'bg-neutral-4 text-neutral-11 flex size-full flex-col overflow-hidden rounded-md',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -26,7 +26,7 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
||||||
return (
|
return (
|
||||||
<Dialog {...props}>
|
<Dialog {...props}>
|
||||||
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
||||||
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:size-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:size-5">
|
<Command className="**:[[cmdk-group-heading]]:text-neutral-10 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group]]:px-2 **:[[cmdk-input]]:h-12 **:[[cmdk-item]]:px-2 **:[[cmdk-item]]:py-3 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:size-5 [&_[cmdk-item]_svg]:size-5">
|
||||||
{children}
|
{children}
|
||||||
</Command>
|
</Command>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
@ -42,12 +42,12 @@ const CommandInput = React.forwardRef<
|
||||||
React.ElementRef<typeof CommandPrimitive.Input>,
|
React.ElementRef<typeof CommandPrimitive.Input>,
|
||||||
CommandInputProps
|
CommandInputProps
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
<div className="border-b-neutral-6 flex items-center border-b px-3" cmdk-input-wrapper="">
|
||||||
<Search className="mr-2 size-4 shrink-0 opacity-50" />
|
<Search className="mr-2 size-4 shrink-0 opacity-50" />
|
||||||
<CommandPrimitive.Input
|
<CommandPrimitive.Input
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'placeholder:text-muted-foreground flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
'placeholder:text-neutral-10 flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -86,7 +86,7 @@ const CommandGroup = React.forwardRef<
|
||||||
<CommandPrimitive.Group
|
<CommandPrimitive.Group
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium',
|
'text-neutral-11 **:[[cmdk-group-heading]]:text-neutral-10 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium overflow-hidden p-1',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -101,7 +101,7 @@ const CommandSeparator = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<CommandPrimitive.Separator
|
<CommandPrimitive.Separator
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('bg-border -mx-1 h-px', className)}
|
className={cn('bg-neutral-5 -mx-1 h-px', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
@ -114,7 +114,7 @@ const CommandItem = React.forwardRef<
|
||||||
<CommandPrimitive.Item
|
<CommandPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'aria-selected:bg-accent aria-selected:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
'aria-selected:bg-neutral-5 aria-selected:text-neutral-12 data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -125,10 +125,7 @@ CommandItem.displayName = CommandPrimitive.Item.displayName;
|
||||||
|
|
||||||
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||||
return (
|
return (
|
||||||
<span
|
<span className={cn('text-neutral-10 ml-auto text-xs tracking-widest', className)} {...props} />
|
||||||
className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
CommandShortcut.displayName = 'CommandShortcut';
|
CommandShortcut.displayName = 'CommandShortcut';
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,7 @@ export function DateRangePicker(props: DateRangePickerProps): JSX.Element {
|
||||||
<div className="mb-2 text-sm">Absolute date range</div>
|
<div className="mb-2 text-sm">Absolute date range</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="grid w-full max-w-sm items-center gap-1.5">
|
<div className="grid w-full max-w-sm items-center gap-1.5">
|
||||||
<Label htmlFor="from" className="text-xs text-gray-400">
|
<Label htmlFor="from" className="text-neutral-10 text-xs">
|
||||||
From
|
From
|
||||||
</Label>
|
</Label>
|
||||||
<div className="flex w-full max-w-sm items-center space-x-2">
|
<div className="flex w-full max-w-sm items-center space-x-2">
|
||||||
|
|
@ -399,7 +399,7 @@ export function DateRangePicker(props: DateRangePickerProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid w-full max-w-sm items-center gap-1.5">
|
<div className="grid w-full max-w-sm items-center gap-1.5">
|
||||||
<Label htmlFor="to" className="text-xs text-gray-400">
|
<Label htmlFor="to" className="text-neutral-10 text-xs">
|
||||||
To
|
To
|
||||||
</Label>
|
</Label>
|
||||||
<div className="flex w-full max-w-sm items-center space-x-2">
|
<div className="flex w-full max-w-sm items-center space-x-2">
|
||||||
|
|
@ -498,7 +498,7 @@ export function DateRangePicker(props: DateRangePickerProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
{showCalendar && (
|
{showCalendar && (
|
||||||
<div className="absolute left-0 top-[4px] -translate-x-full">
|
<div className="absolute left-0 top-[4px] -translate-x-full">
|
||||||
<div className="bg-popover mr-1 rounded-md border p-4">
|
<div className="bg-neutral-4 mr-1 rounded-md border p-4">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const DialogOverlay = React.forwardRef<
|
||||||
<DialogPrimitive.Overlay
|
<DialogPrimitive.Overlay
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 backdrop-blur-sm',
|
'bg-neutral-1.01 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 backdrop-blur-sm',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -37,15 +37,15 @@ const DialogContent = React.forwardRef<
|
||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
|
'bg-neutral-3 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] border-neutral-5 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
{hideCloseButton ? null : (
|
{hideCloseButton ? null : (
|
||||||
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
|
<DialogPrimitive.Close className="ring-offset-neutral-2 focus:ring-ring data-[state=open]:bg-neutral-2 data-[state=open]:text-neutral-10 absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
|
||||||
<X className="size-4" />
|
<X className="hover:text-neutral-12 text-neutral-11 size-4" />
|
||||||
<span className="sr-only">Close</span>
|
<span className="sr-only">Close</span>
|
||||||
</DialogPrimitive.Close>
|
</DialogPrimitive.Close>
|
||||||
)}
|
)}
|
||||||
|
|
@ -73,7 +73,7 @@ const DialogTitle = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<DialogPrimitive.Title
|
<DialogPrimitive.Title
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('text-lg font-semibold leading-none tracking-tight', className)}
|
className={cn('text-neutral-12 text-lg font-medium leading-none', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
@ -85,7 +85,7 @@ const DialogDescription = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<DialogPrimitive.Description
|
<DialogPrimitive.Description
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('text-muted-foreground text-sm', className)}
|
className={cn('text-neutral-11 text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -18,18 +18,18 @@ export const DocsNote = ({
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'my-2 flex border-l-2 px-4 py-2',
|
'my-2 flex border-l-2 px-4 py-2',
|
||||||
warn ? 'border-orange-500' : 'border-white',
|
warn ? 'border-neutral-2' : 'border-neutral-12',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{/* <div className="items-center align-middle pr-2 flex flex-row">
|
{/* <div className="items-center align-middle pr-2 flex flex-row">
|
||||||
{warn ? (
|
{warn ? (
|
||||||
<ExclamationTriangleIcon className="text-orange-500" />
|
<ExclamationTriangleIcon className="text-neutral-2" />
|
||||||
) : (
|
) : (
|
||||||
<InfoCircledIcon className="text-current" />
|
<InfoCircledIcon className="text-current" />
|
||||||
)}
|
)}
|
||||||
</div> */}
|
</div> */}
|
||||||
<div className="grow align-middle text-sm text-white">{children}</div>
|
<div className="text-neutral-12 grow align-middle text-sm">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -52,7 +52,7 @@ export const DocsLink = ({
|
||||||
asChild
|
asChild
|
||||||
variant="link"
|
variant="link"
|
||||||
className={cn(
|
className={cn(
|
||||||
'p-0 text-orange-500',
|
'p-0',
|
||||||
'whitespace-pre-wrap', // to not lose whitespace between tags due to `display: 'inline-flex'`
|
'whitespace-pre-wrap', // to not lose whitespace between tags due to `display: 'inline-flex'`
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ export function DottedBackground(props: { children: React.ReactNode; className?:
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'bg-dot-white/[0.2] relative flex size-full items-center justify-center bg-black',
|
'bg-dot-neutral-12/20 bg-neutral-1 relative flex size-full items-center justify-center',
|
||||||
props.className,
|
props.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="pointer-events-none absolute inset-0 flex items-center justify-center bg-black [mask-image:radial-gradient(ellipse_at_center,transparent_20%,black)]" />
|
<div className="bg-neutral-1 mask-[radial-gradient(ellipse_at_center,transparent_20%,black)] pointer-events-none absolute inset-0 flex items-center justify-center" />
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
||||||
<DropdownMenuPrimitive.SubTrigger
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'focus:bg-accent data-[state=open]:bg-accent flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
'focus:bg-neutral-5 data-[state=open]:bg-neutral-5 flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
||||||
inset && 'pl-8',
|
inset && 'pl-8',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
|
@ -39,7 +39,7 @@ const DropdownMenuSubContent = React.forwardRef<
|
||||||
<DropdownMenuPrimitive.SubContent
|
<DropdownMenuPrimitive.SubContent
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-popover text-popover-foreground animate-in data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md',
|
'bg-neutral-4 text-neutral-11 animate-in data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1 border-neutral-5 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -56,7 +56,7 @@ const DropdownMenuContent = React.forwardRef<
|
||||||
ref={ref}
|
ref={ref}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-popover text-popover-foreground animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-2 shadow-md',
|
'bg-neutral-4 text-neutral-11 animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-neutral-5 z-50 min-w-[8rem] overflow-hidden rounded-md border p-2 shadow-md',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -75,9 +75,9 @@ const DropdownMenuItem = React.forwardRef<
|
||||||
<DropdownMenuPrimitive.Item
|
<DropdownMenuPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-pointer select-none items-center rounded-sm p-2 text-sm outline-none transition-colors',
|
'focus:bg-neutral-5 focus:text-neutral-12 data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-pointer select-none items-center rounded-sm p-2 text-sm outline-none transition-colors',
|
||||||
inset && 'pl-8',
|
inset && 'pl-8',
|
||||||
active && 'bg-accent text-orange-500',
|
active && 'bg-neutral-5 text-neutral-12',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -92,7 +92,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
||||||
<DropdownMenuPrimitive.CheckboxItem
|
<DropdownMenuPrimitive.CheckboxItem
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors',
|
'focus:bg-neutral-5 focus:text-neutral-12 data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
checked={checked}
|
checked={checked}
|
||||||
|
|
@ -115,7 +115,7 @@ const DropdownMenuRadioItem = React.forwardRef<
|
||||||
<DropdownMenuPrimitive.RadioItem
|
<DropdownMenuPrimitive.RadioItem
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors',
|
'focus:bg-neutral-5 focus:text-neutral-12 data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -150,7 +150,7 @@ const DropdownMenuSeparator = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<DropdownMenuPrimitive.Separator
|
<DropdownMenuPrimitive.Separator
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('bg-muted -mx-1 my-1 h-px', className)}
|
className={cn('bg-neutral-6 -mx-1 my-1 h-px', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export const EmptyList = ({
|
||||||
className="drag-none"
|
className="drag-none"
|
||||||
/>
|
/>
|
||||||
<Heading className="text-center">{title}</Heading>
|
<Heading className="text-center">{title}</Heading>
|
||||||
<span className="text-center text-sm font-medium text-gray-500">{description}</span>
|
<span className="text-neutral-10 text-center text-sm font-medium">{description}</span>
|
||||||
{children}
|
{children}
|
||||||
{docsUrl && <DocsLink href={docsUrl}>Read about it in the documentation</DocsLink>}
|
{docsUrl && <DocsLink href={docsUrl}>Read about it in the documentation</DocsLink>}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -66,7 +66,7 @@ export const NoSchemaVersion = ({
|
||||||
if (recommendedAction === 'check') {
|
if (recommendedAction === 'check') {
|
||||||
children = (
|
children = (
|
||||||
<>
|
<>
|
||||||
<div className="flex w-full justify-center py-2 text-xs text-gray-500">
|
<div className="text-neutral-10 flex w-full justify-center py-2 text-xs">
|
||||||
It's recommended to check that the schema is valid and compatible with the state of the
|
It's recommended to check that the schema is valid and compatible with the state of the
|
||||||
registry before publishing.
|
registry before publishing.
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -81,7 +81,7 @@ export const NoSchemaVersion = ({
|
||||||
children = (
|
children = (
|
||||||
<>
|
<>
|
||||||
{isDistributed && (
|
{isDistributed && (
|
||||||
<div className="flex w-full justify-center py-2 text-xs text-gray-500">
|
<div className="text-neutral-10 flex w-full justify-center py-2 text-xs">
|
||||||
For distributed systems, it's recommended to publish the schema after the service is
|
For distributed systems, it's recommended to publish the schema after the service is
|
||||||
deployed.
|
deployed.
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,14 @@ const FormLabel = React.forwardRef<
|
||||||
>(({ className, ...props }, ref) => {
|
>(({ className, ...props }, ref) => {
|
||||||
const { formItemId } = useFormField();
|
const { formItemId } = useFormField();
|
||||||
|
|
||||||
return <Label ref={ref} className={className} htmlFor={formItemId} {...props} />;
|
return (
|
||||||
|
<Label
|
||||||
|
ref={ref}
|
||||||
|
className={cn('text-neutral-11 mb-2 inline-block', className)}
|
||||||
|
htmlFor={formItemId}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
FormLabel.displayName = 'FormLabel';
|
FormLabel.displayName = 'FormLabel';
|
||||||
|
|
||||||
|
|
@ -100,7 +107,7 @@ const FormControl = React.forwardRef<
|
||||||
id={formItemId}
|
id={formItemId}
|
||||||
aria-describedby={error ? `${formDescriptionId} ${formMessageId}` : formDescriptionId}
|
aria-describedby={error ? `${formDescriptionId} ${formMessageId}` : formDescriptionId}
|
||||||
aria-invalid={!!error}
|
aria-invalid={!!error}
|
||||||
className={cn(error && 'border-destructive')}
|
className={cn(error && 'border-red-500')}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
@ -117,7 +124,7 @@ const FormDescription = React.forwardRef<
|
||||||
<p
|
<p
|
||||||
ref={ref}
|
ref={ref}
|
||||||
id={formDescriptionId}
|
id={formDescriptionId}
|
||||||
className={cn('text-muted-foreground text-sm', className)}
|
className={cn('text-neutral-10 text-sm', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
@ -135,7 +142,7 @@ const FormMessage = React.forwardRef<
|
||||||
<p
|
<p
|
||||||
ref={ref}
|
ref={ref}
|
||||||
id={formMessageId}
|
id={formMessageId}
|
||||||
className={cn('text-destructive min-h-[1.25rem] text-sm font-medium', className)}
|
className={cn('min-h-[1.25rem] text-sm font-medium text-red-500', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{body}
|
{body}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export const Heading = ({
|
||||||
return (
|
return (
|
||||||
<HeadingLevel
|
<HeadingLevel
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'cursor-default text-white',
|
'text-neutral-12 cursor-default',
|
||||||
{
|
{
|
||||||
lg: 'text-lg font-bold',
|
lg: 'text-lg font-bold',
|
||||||
xl: 'text-xl font-bold',
|
xl: 'text-xl font-bold',
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ const HoverCardContent = React.forwardRef<
|
||||||
align={align}
|
align={align}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 rounded-md border p-4 shadow-md outline-none',
|
'bg-neutral-4 text-neutral-11 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 rounded-md border p-4 shadow-md outline-none',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
||||||
|
|
@ -397,7 +397,7 @@ export const HiveLogo = ({
|
||||||
viewBox="0 0 112 112"
|
viewBox="0 0 112 112"
|
||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
className={clsx('inline fill-none', className)}
|
className={clsx('fill-neutral-12 inline', className)}
|
||||||
{...(animated
|
{...(animated
|
||||||
? {
|
? {
|
||||||
whileHover: { scale: 1.1 },
|
whileHover: { scale: 1.1 },
|
||||||
|
|
@ -411,10 +411,12 @@ export const HiveLogo = ({
|
||||||
clipRule="evenodd"
|
clipRule="evenodd"
|
||||||
d="M33.59 0H78.41L112 33.59V78.41L78.41 112H33.59L0 78.41V33.59L33.59 0ZM62.11 104.85L104.85 62.11C108.22 58.74 108.22 53.27 104.85 49.89L62.11 7.15C58.73 3.78 53.26 3.78 49.89 7.15L7.15 49.89C3.78 53.27 3.78 58.74 7.15 62.11L49.89 104.85C53.26 108.22 58.73 108.22 62.11 104.85ZM44.27 56L56 44.27L67.72 56L56 67.72L44.27 56Z"
|
d="M33.59 0H78.41L112 33.59V78.41L78.41 112H33.59L0 78.41V33.59L33.59 0ZM62.11 104.85L104.85 62.11C108.22 58.74 108.22 53.27 104.85 49.89L62.11 7.15C58.73 3.78 53.26 3.78 49.89 7.15L7.15 49.89C3.78 53.27 3.78 58.74 7.15 62.11L49.89 104.85C53.26 108.22 58.73 108.22 62.11 104.85ZM44.27 56L56 44.27L67.72 56L56 67.72L44.27 56Z"
|
||||||
fill="white"
|
fill="white"
|
||||||
|
className="fill-neutral-12"
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
d="M78.41 0L78.76 -0.35L78.61 -0.5H78.41V0ZM33.59 0V-0.5H33.39L33.24 -0.35L33.59 0ZM112 33.59H112.5V33.39L112.35 33.24L112 33.59ZM112 78.41L112.35 78.76L112.5 78.61V78.41H112ZM78.41 112V112.5H78.61L78.76 112.35L78.41 112ZM33.59 112L33.24 112.35L33.39 112.5H33.59V112ZM0 78.41H-0.5V78.61L-0.35 78.76L0 78.41ZM0 33.59L-0.35 33.24L-0.5 33.39V33.59H0ZM104.85 62.11L105.2 62.46L104.85 62.11ZM62.11 104.85L61.75 104.5L62.11 104.85ZM104.85 49.89L104.49 50.25L104.85 49.89ZM62.11 7.15L62.46 6.8L62.11 7.15ZM49.89 7.15L49.54 6.8L49.54 6.8L49.89 7.15ZM7.15 49.89L7.51 50.25L7.51 50.25L7.15 49.89ZM7.15 62.11L7.51 61.76L7.51 61.76L7.15 62.11ZM49.89 104.85L49.54 105.2L49.54 105.2L49.89 104.85ZM56 44.27L56.35 43.92L56 43.57L55.64 43.92L56 44.27ZM44.27 56L43.92 55.64L43.57 56L43.92 56.35L44.27 56ZM67.72 56L68.08 56.35L68.43 56L68.08 55.64L67.72 56ZM56 67.72L55.64 68.08L56 68.43L56.35 68.08L56 67.72ZM78.41 -0.5H33.59V0.5H78.41V-0.5ZM112.35 33.24L78.76 -0.35L78.05 0.35L111.65 33.95L112.35 33.24ZM112.5 78.41V33.59H111.5V78.41H112.5ZM78.76 112.35L112.35 78.76L111.65 78.05L78.05 111.65L78.76 112.35ZM33.59 112.5H78.41V111.5H33.59V112.5ZM-0.35 78.76L33.24 112.35L33.95 111.65L0.35 78.05L-0.35 78.76ZM-0.5 33.59V78.41H0.5V33.59H-0.5ZM33.24 -0.35L-0.35 33.24L0.35 33.95L33.95 0.35L33.24 -0.35ZM104.49 61.76L61.75 104.5L62.46 105.2L105.2 62.46L104.49 61.76ZM104.49 50.25C107.67 53.43 107.67 58.58 104.49 61.76L105.2 62.46C108.77 58.89 108.77 53.11 105.2 49.54L104.49 50.25ZM61.75 7.51L104.49 50.25L105.2 49.54L62.46 6.8L61.75 7.51ZM50.24 7.51C53.42 4.33 58.57 4.33 61.75 7.51L62.46 6.8C58.89 3.23 53.11 3.23 49.54 6.8L50.24 7.51ZM7.51 50.25L50.24 7.51L49.54 6.8L6.8 49.54L7.51 50.25ZM7.51 61.76C4.33 58.58 4.33 53.43 7.51 50.25L6.8 49.54C3.23 53.11 3.23 58.89 6.8 62.46L7.51 61.76ZM50.24 104.5L7.51 61.76L6.8 62.46L49.54 105.2L50.24 104.5ZM61.75 104.5C58.57 107.68 53.42 107.68 50.24 104.5L49.54 105.2C53.11 108.77 58.89 108.77 62.46 105.2L61.75 104.5ZM55.64 43.92L43.92 55.64L44.63 56.35L56.35 44.63L55.64 43.92ZM68.08 55.64L56.35 43.92L55.64 44.63L67.37 56.35L68.08 55.64ZM56.35 68.08L68.08 56.35L67.37 55.64L55.64 67.37L56.35 68.08ZM43.92 56.35L55.64 68.08L56.35 67.37L44.63 55.64L43.92 56.35Z"
|
d="M78.41 0L78.76 -0.35L78.61 -0.5H78.41V0ZM33.59 0V-0.5H33.39L33.24 -0.35L33.59 0ZM112 33.59H112.5V33.39L112.35 33.24L112 33.59ZM112 78.41L112.35 78.76L112.5 78.61V78.41H112ZM78.41 112V112.5H78.61L78.76 112.35L78.41 112ZM33.59 112L33.24 112.35L33.39 112.5H33.59V112ZM0 78.41H-0.5V78.61L-0.35 78.76L0 78.41ZM0 33.59L-0.35 33.24L-0.5 33.39V33.59H0ZM104.85 62.11L105.2 62.46L104.85 62.11ZM62.11 104.85L61.75 104.5L62.11 104.85ZM104.85 49.89L104.49 50.25L104.85 49.89ZM62.11 7.15L62.46 6.8L62.11 7.15ZM49.89 7.15L49.54 6.8L49.54 6.8L49.89 7.15ZM7.15 49.89L7.51 50.25L7.51 50.25L7.15 49.89ZM7.15 62.11L7.51 61.76L7.51 61.76L7.15 62.11ZM49.89 104.85L49.54 105.2L49.54 105.2L49.89 104.85ZM56 44.27L56.35 43.92L56 43.57L55.64 43.92L56 44.27ZM44.27 56L43.92 55.64L43.57 56L43.92 56.35L44.27 56ZM67.72 56L68.08 56.35L68.43 56L68.08 55.64L67.72 56ZM56 67.72L55.64 68.08L56 68.43L56.35 68.08L56 67.72ZM78.41 -0.5H33.59V0.5H78.41V-0.5ZM112.35 33.24L78.76 -0.35L78.05 0.35L111.65 33.95L112.35 33.24ZM112.5 78.41V33.59H111.5V78.41H112.5ZM78.76 112.35L112.35 78.76L111.65 78.05L78.05 111.65L78.76 112.35ZM33.59 112.5H78.41V111.5H33.59V112.5ZM-0.35 78.76L33.24 112.35L33.95 111.65L0.35 78.05L-0.35 78.76ZM-0.5 33.59V78.41H0.5V33.59H-0.5ZM33.24 -0.35L-0.35 33.24L0.35 33.95L33.95 0.35L33.24 -0.35ZM104.49 61.76L61.75 104.5L62.46 105.2L105.2 62.46L104.49 61.76ZM104.49 50.25C107.67 53.43 107.67 58.58 104.49 61.76L105.2 62.46C108.77 58.89 108.77 53.11 105.2 49.54L104.49 50.25ZM61.75 7.51L104.49 50.25L105.2 49.54L62.46 6.8L61.75 7.51ZM50.24 7.51C53.42 4.33 58.57 4.33 61.75 7.51L62.46 6.8C58.89 3.23 53.11 3.23 49.54 6.8L50.24 7.51ZM7.51 50.25L50.24 7.51L49.54 6.8L6.8 49.54L7.51 50.25ZM7.51 61.76C4.33 58.58 4.33 53.43 7.51 50.25L6.8 49.54C3.23 53.11 3.23 58.89 6.8 62.46L7.51 61.76ZM50.24 104.5L7.51 61.76L6.8 62.46L49.54 105.2L50.24 104.5ZM61.75 104.5C58.57 107.68 53.42 107.68 50.24 104.5L49.54 105.2C53.11 108.77 58.89 108.77 62.46 105.2L61.75 104.5ZM55.64 43.92L43.92 55.64L44.63 56.35L56.35 44.63L55.64 43.92ZM68.08 55.64L56.35 43.92L55.64 44.63L67.37 56.35L68.08 55.64ZM56.35 68.08L68.08 56.35L67.37 55.64L55.64 67.37L56.35 68.08ZM43.92 56.35L55.64 68.08L56.35 67.37L44.63 55.64L43.92 56.35Z"
|
||||||
fill="white"
|
fill="white"
|
||||||
|
className="fill-neutral-12"
|
||||||
/>
|
/>
|
||||||
</motion.svg>
|
</motion.svg>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export function InputCopy(props: { value: string; className?: string; multiline?
|
||||||
readOnly
|
readOnly
|
||||||
autoSize
|
autoSize
|
||||||
onFocus={ev => ev.target.select()}
|
onFocus={ev => ev.target.select()}
|
||||||
className={`bg-secondary w-full resize-none font-mono text-xs text-white ${props.className}`}
|
className={`bg-neutral-2 text-neutral-12 w-full resize-none font-mono text-xs ${props.className}`}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="relative grow">
|
<div className="relative grow">
|
||||||
|
|
@ -41,7 +41,7 @@ export function InputCopy(props: { value: string; className?: string; multiline?
|
||||||
type="text"
|
type="text"
|
||||||
value={props.value}
|
value={props.value}
|
||||||
readOnly
|
readOnly
|
||||||
className={`bg-secondary truncate text-white ${props.className}`}
|
className={`bg-neutral-2 text-neutral-12 truncate ${props.className}`}
|
||||||
onFocus={ev => ev.target.select()}
|
onFocus={ev => ev.target.select()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -51,7 +51,7 @@ export function InputCopy(props: { value: string; className?: string; multiline?
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="bg-secondary size-10 shrink-0 self-baseline"
|
className="bg-neutral-2 size-10 shrink-0 self-baseline"
|
||||||
>
|
>
|
||||||
{isCopied ? (
|
{isCopied ? (
|
||||||
<CheckIcon className="size-4 text-emerald-500" />
|
<CheckIcon className="size-4 text-emerald-500" />
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||||
<input
|
<input
|
||||||
type={type}
|
type={type}
|
||||||
className={cn(
|
className={cn(
|
||||||
'border-input bg-background placeholder:text-muted-foreground flex h-10 w-full rounded-md border px-3 py-2 text-sm ring-offset-orange-900 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-transparent focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
'border-neutral-5 text-neutral-12 placeholder:text-neutral-9 flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-transparent focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { cn } from '@/lib/utils';
|
||||||
import * as LabelPrimitive from '@radix-ui/react-label';
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
||||||
|
|
||||||
const labelVariants = cva(
|
const labelVariants = cva(
|
||||||
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
'text-neutral-10 text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||||
);
|
);
|
||||||
|
|
||||||
const Label = React.forwardRef<
|
const Label = React.forwardRef<
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import { LinkOptions, RegisteredRouter, Link as RouterLink } from '@tanstack/rea
|
||||||
const linkVariants = cva('font-medium transition-colors', {
|
const linkVariants = cva('font-medium transition-colors', {
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
primary: 'text-orange-500 hover:underline',
|
primary: 'text-accent hover:underline',
|
||||||
secondary: 'text-gray-500 hover:text-gray-300',
|
secondary: 'text-neutral-10 hover:text-neutral-11',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue