mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 06:37:15 +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: {
|
||||
// conflicts with official prettier-plugin-tailwindcss and tailwind v3
|
||||
'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
|
||||
// enable wrapping in text editors to make classes human readable
|
||||
'better-tailwindcss/enforce-consistent-line-wrapping': 'off',
|
||||
|
|
@ -214,10 +214,6 @@ module.exports = {
|
|||
{
|
||||
ignore: [
|
||||
'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)
|
||||
'animate-in',
|
||||
'animate-out',
|
||||
|
|
|
|||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -36,6 +36,9 @@
|
|||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"git.mergeEditor": false,
|
||||
"tailwindCSS.experimental.configFile": {
|
||||
"packages/web/app/src/index.css": "packages/web/app/**"
|
||||
},
|
||||
"tailwindCSS.classFunctions": ["cva", "cx", "cn", "clsx"],
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@
|
|||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="preconnect" href="https://rsms.me/" />
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<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
|
||||
rel="icon"
|
||||
type="image/svg+xml"
|
||||
|
|
@ -22,7 +26,7 @@
|
|||
<script src="/__env.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="font-sans text-white" id="root"></div>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ export function AdminStats({
|
|||
<DataWrapper query={query} organizationSlug={null}>
|
||||
{({ data }) => (
|
||||
<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="Organizations" value={overall.organizations} />
|
||||
<OverallStat label="Projects" value={overall.projects} />
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ export function AuthCardStack(props: { children: React.ReactNode }) {
|
|||
export function AuthOrSeparator() {
|
||||
return (
|
||||
<div className="flex flex-row items-center justify-between gap-x-4">
|
||||
<div className="h-[1px] w-full bg-gray-700" />
|
||||
<div className="text-center text-gray-400">or</div>
|
||||
<div className="h-[1px] w-full bg-gray-700" />
|
||||
<div className="bg-neutral-4 h-px w-full" />
|
||||
<div className="text-neutral-9 text-center">or</div>
|
||||
<div className="bg-neutral-4 h-px w-full" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export function Label({ className, children, ...props }: ComponentProps<'span'>)
|
|||
return (
|
||||
<span
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -36,15 +36,15 @@ export const Page = ({
|
|||
<div className={cn('relative flex h-full flex-col', className)}>
|
||||
<div className="flex shrink-0 flex-row items-center justify-between p-4">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-white">{title}</h2>
|
||||
<span className="mt-2 text-sm text-gray-300">{subtitle}</span>
|
||||
<h2 className="text-neutral-1 text-xl font-bold">{title}title</h2>
|
||||
<span className="text-neutral-8 mt-2 text-sm">{subtitle}</span>
|
||||
</div>
|
||||
<div className="flex flex-row items-center space-x-2">{actions}</div>
|
||||
</div>
|
||||
{noPadding ? (
|
||||
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}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -54,17 +54,17 @@ export const Page = ({
|
|||
|
||||
export const Section = {
|
||||
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}
|
||||
</h3>
|
||||
),
|
||||
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}
|
||||
</h2>
|
||||
),
|
||||
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}
|
||||
</div>
|
||||
),
|
||||
|
|
@ -86,7 +86,7 @@ export function Scale({
|
|||
{new Array(size).fill(null).map((_, i) => (
|
||||
<div
|
||||
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>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export function ErrorComponent(props: { error: any; message?: string }) {
|
|||
<p>{commonErrorStrings.reported}</p>
|
||||
<p>
|
||||
{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>
|
||||
</Button>
|
||||
.
|
||||
|
|
|
|||
|
|
@ -45,14 +45,14 @@ export function GetStartedProgress(props: {
|
|||
props.className,
|
||||
)}
|
||||
>
|
||||
<div className="text-sm font-medium">Get Started</div>
|
||||
<div className="text-xs text-gray-500">
|
||||
<div className="text-neutral-11 text-sm font-medium">Get Started</div>
|
||||
<div className="text-neutral-10 text-xs">
|
||||
{remaining} remaining task{remaining > 1 ? 's' : ''}
|
||||
</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
|
||||
className="h-full bg-orange-500"
|
||||
className="bg-accent_80 h-full"
|
||||
style={{ width: `${(completed / total) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -100,19 +100,19 @@ function Task({
|
|||
target="_blank"
|
||||
rel="noreferrer"
|
||||
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,
|
||||
)}
|
||||
>
|
||||
<div className="flex items-start space-x-3">
|
||||
{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">
|
||||
<p className="font-medium leading-5 text-white">{title}</p>
|
||||
<p className="text-muted-foreground mt-1 text-sm">{description}</p>
|
||||
<p className="text-neutral-12 font-medium leading-5">{title}</p>
|
||||
<p className="text-neutral-10 mt-1 text-sm">{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { PrimaryNavigationLink } from '@/components/navigation/primary-navigation-link';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { Link, useRouter } from '@tanstack/react-router';
|
||||
import { useRouter } from '@tanstack/react-router';
|
||||
|
||||
const OrganizationSelector_OrganizationConnectionFragment = graphql(`
|
||||
fragment OrganizationSelector_OrganizationConnectionFragment on OrganizationConnection {
|
||||
|
|
@ -27,18 +28,18 @@ export function OrganizationSelector(props: {
|
|||
);
|
||||
|
||||
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) {
|
||||
return (
|
||||
<Link
|
||||
to="/$organizationSlug"
|
||||
params={{ organizationSlug: props.currentOrganizationSlug }}
|
||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
||||
>
|
||||
{props.currentOrganizationSlug}
|
||||
</Link>
|
||||
<PrimaryNavigationLink
|
||||
linkProps={{
|
||||
to: '/$organizationSlug',
|
||||
params: { organizationSlug: props.currentOrganizationSlug },
|
||||
}}
|
||||
linkText={props.currentOrganizationSlug}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import { useForm, UseFormReturn } from 'react-hook-form';
|
|||
import { useMutation, useQuery } from 'urql';
|
||||
import { z } from 'zod';
|
||||
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 {
|
||||
Dialog,
|
||||
|
|
@ -123,26 +125,22 @@ export function OrganizationLayout({
|
|||
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
<div className="h-(--header-height) container flex items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="size-8" />
|
||||
<OrganizationSelector
|
||||
isOIDCUser={query.data?.me.provider === AuthProviderType.Oidc}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<UserMenu
|
||||
me={query.data?.me ?? null}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
<Header>
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="size-8" />
|
||||
<OrganizationSelector
|
||||
isOIDCUser={query.data?.me.provider === AuthProviderType.Oidc}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div className="h-(--tabs-navbar-height) relative border-b border-gray-800">
|
||||
<UserMenu
|
||||
me={query.data?.me ?? null}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</Header>
|
||||
<SecondaryNavigation>
|
||||
<div className="container flex items-center justify-between">
|
||||
{currentOrganization ? (
|
||||
<Tabs value={page} className="min-w-[600px]">
|
||||
|
|
@ -198,19 +196,14 @@ export function OrganizationLayout({
|
|||
</Tabs>
|
||||
) : (
|
||||
<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="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<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="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||
</div>
|
||||
)}
|
||||
{currentOrganization?.viewerCanCreateProject ? (
|
||||
<>
|
||||
<Button
|
||||
onClick={toggleModalOpen}
|
||||
variant="link"
|
||||
className="text-orange-500"
|
||||
data-cy="new-project-button"
|
||||
>
|
||||
<Button onClick={toggleModalOpen} variant="link" data-cy="new-project-button">
|
||||
<PlusIcon size={16} className="mr-2" />
|
||||
New project
|
||||
</Button>
|
||||
|
|
@ -224,8 +217,8 @@ export function OrganizationLayout({
|
|||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="container min-h-[var(--content-height)] pb-7">
|
||||
</SecondaryNavigation>
|
||||
<div className="min-h-(--content-height) container pb-7">
|
||||
{currentOrganization ? (
|
||||
<>
|
||||
<ProPlanBilling organization={currentOrganization} />
|
||||
|
|
@ -297,15 +290,15 @@ function ProjectTypeCard(props: {
|
|||
}) {
|
||||
return (
|
||||
<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>
|
||||
<RadioGroupItem value={props.type} className="sr-only" />
|
||||
</FormControl>
|
||||
<div className="border-muted hover:border-accent hover:bg-accent flex items-center gap-4 rounded-md border-2 p-4">
|
||||
<Slot className="size-8 text-gray-400">{props.icon}</Slot>
|
||||
<div className="border-neutral-5 hover:border-neutral-2 flex items-center gap-4 rounded-md border p-4">
|
||||
<Slot className="text-neutral-12 size-8">{props.icon}</Slot>
|
||||
<div>
|
||||
<span className="text-sm font-medium">{props.title}</span>
|
||||
<p className="text-sm text-gray-400">{props.description}</p>
|
||||
<span className="text-neutral-12 text-sm font-medium">{props.title}</span>
|
||||
<p className="text-neutral-11 text-sm">{props.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</FormLabel>
|
||||
|
|
@ -427,7 +420,9 @@ export function CreateProjectModalContent(props: {
|
|||
description="Single GraphQL schema developed as a monolith"
|
||||
icon={
|
||||
<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"
|
||||
icon={
|
||||
<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"
|
||||
icon={
|
||||
<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 { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { Link, useRouter } from '@tanstack/react-router';
|
||||
import { useRouter } from '@tanstack/react-router';
|
||||
|
||||
const ProjectSelector_OrganizationConnectionFragment = graphql(`
|
||||
fragment ProjectSelector_OrganizationConnectionFragment on OrganizationConnection {
|
||||
|
|
@ -43,19 +44,19 @@ export function ProjectSelector(props: {
|
|||
return (
|
||||
<>
|
||||
{currentOrganization ? (
|
||||
<Link
|
||||
to="/$organizationSlug"
|
||||
params={{ organizationSlug: props.currentOrganizationSlug }}
|
||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
||||
>
|
||||
{currentOrganization.slug}
|
||||
</Link>
|
||||
<PrimaryNavigationLink
|
||||
linkProps={{
|
||||
to: '/$organizationSlug',
|
||||
params: { organizationSlug: props.currentOrganizationSlug },
|
||||
}}
|
||||
linkText={currentOrganization.slug}
|
||||
/>
|
||||
) : (
|
||||
<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 ? (
|
||||
<>
|
||||
<div className="italic text-gray-500">/</div>
|
||||
<div className="text-neutral-10 italic">/</div>
|
||||
<Select
|
||||
value={props.currentProjectSlug}
|
||||
onValueChange={id => {
|
||||
|
|
@ -87,7 +88,7 @@ export function ProjectSelector(props: {
|
|||
</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 { useMutation, useQuery } from 'urql';
|
||||
import { z } from 'zod';
|
||||
import { Header } from '@/components/navigation/header';
|
||||
import { SecondaryNavigation } from '@/components/navigation/secondary-navigation';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
|
|
@ -86,32 +88,30 @@ export function ProjectLayout({
|
|||
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
<div className="h-(--header-height) container flex items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="size-8" />
|
||||
<ProjectSelector
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
currentProjectSlug={props.projectSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<UserMenu
|
||||
me={me ?? null}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
<Header>
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="size-8" />
|
||||
<ProjectSelector
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
currentProjectSlug={props.projectSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div>
|
||||
<UserMenu
|
||||
me={me ?? null}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
</Header>
|
||||
{query.fetching === false &&
|
||||
query.stale === false &&
|
||||
(currentProject === null || currentOrganization === null) ? (
|
||||
<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">
|
||||
{currentOrganization && currentProject ? (
|
||||
<Tabs value={page}>
|
||||
|
|
@ -155,13 +155,13 @@ export function ProjectLayout({
|
|||
</Tabs>
|
||||
) : (
|
||||
<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="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<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="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||
</div>
|
||||
)}
|
||||
{currentProject?.viewerCanCreateTarget ? (
|
||||
<Button onClick={toggleModalOpen} variant="link" className="text-orange-500">
|
||||
<Button onClick={toggleModalOpen} variant="link">
|
||||
<PlusIcon size={16} className="mr-2" />
|
||||
New target
|
||||
</Button>
|
||||
|
|
@ -173,8 +173,8 @@ export function ProjectLayout({
|
|||
toggleModalOpen={toggleModalOpen}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="container min-h-[var(--content-height)] pb-7">
|
||||
</SecondaryNavigation>
|
||||
<div className="min-h-(--content-height) container pb-7">
|
||||
<div className={className}>{children}</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { PrimaryNavigationLink } from '@/components/navigation/primary-navigation-link';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { Link, useRouter } from '@tanstack/react-router';
|
||||
import { useRouter } from '@tanstack/react-router';
|
||||
|
||||
const TargetSelector_OrganizationConnectionFragment = graphql(`
|
||||
fragment TargetSelector_OrganizationConnectionFragment on OrganizationConnection {
|
||||
|
|
@ -53,34 +54,32 @@ export function TargetSelector(props: {
|
|||
return (
|
||||
<>
|
||||
{currentOrganization ? (
|
||||
<Link
|
||||
to="/$organizationSlug"
|
||||
params={{
|
||||
organizationSlug: currentOrganization.slug,
|
||||
<PrimaryNavigationLink
|
||||
linkProps={{
|
||||
to: '/$organizationSlug',
|
||||
params: { organizationSlug: currentOrganization.slug },
|
||||
}}
|
||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
||||
>
|
||||
{currentOrganization.slug}
|
||||
</Link>
|
||||
linkText={currentOrganization.slug}
|
||||
/>
|
||||
) : (
|
||||
<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 ? (
|
||||
<Link
|
||||
to="/$organizationSlug/$projectSlug"
|
||||
params={{
|
||||
organizationSlug: props.currentOrganizationSlug,
|
||||
projectSlug: props.currentProjectSlug,
|
||||
<PrimaryNavigationLink
|
||||
linkProps={{
|
||||
to: '/$organizationSlug/$projectSlug',
|
||||
params: {
|
||||
organizationSlug: props.currentOrganizationSlug,
|
||||
projectSlug: props.currentProjectSlug,
|
||||
},
|
||||
}}
|
||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
||||
>
|
||||
{currentProject.slug}
|
||||
</Link>
|
||||
linkText={currentProject.slug}
|
||||
/>
|
||||
) : (
|
||||
<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 ? (
|
||||
<>
|
||||
<Select
|
||||
|
|
@ -112,7 +111,7 @@ export function TargetSelector(props: {
|
|||
</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 { LinkIcon } from 'lucide-react';
|
||||
import { useQuery } from 'urql';
|
||||
import { Header } from '@/components/navigation/header';
|
||||
import { SecondaryNavigation } from '@/components/navigation/secondary-navigation';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
|
|
@ -156,26 +158,24 @@ export const TargetLayout = ({
|
|||
projectSlug={props.projectSlug}
|
||||
targetSlug={props.targetSlug}
|
||||
>
|
||||
<header>
|
||||
<div className="h-(--header-height) container flex items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="size-8" />
|
||||
<TargetSelector
|
||||
organizations={query.data?.organizations ?? null}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
currentProjectSlug={props.projectSlug}
|
||||
currentTargetSlug={props.targetSlug}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<UserMenu
|
||||
me={me ?? null}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
<Header>
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="size-8" />
|
||||
<TargetSelector
|
||||
organizations={query.data?.organizations ?? null}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
currentProjectSlug={props.projectSlug}
|
||||
currentTargetSlug={props.targetSlug}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div>
|
||||
<UserMenu
|
||||
me={me ?? null}
|
||||
currentOrganizationSlug={props.organizationSlug}
|
||||
organizations={query.data?.organizations ?? null}
|
||||
/>
|
||||
</div>
|
||||
</Header>
|
||||
|
||||
{query.fetching === false &&
|
||||
query.stale === false &&
|
||||
|
|
@ -183,7 +183,7 @@ export const TargetLayout = ({
|
|||
<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">
|
||||
{currentOrganization && currentProject && currentTarget ? (
|
||||
<Tabs className="flex h-full grow flex-col" value={page}>
|
||||
|
|
@ -323,9 +323,9 @@ export const TargetLayout = ({
|
|||
</Tabs>
|
||||
) : (
|
||||
<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="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<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="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||
<div className="bg-neutral-5 h-5 w-12 animate-pulse rounded-full" />
|
||||
</div>
|
||||
)}
|
||||
{currentTarget && isCDNEnabled && (
|
||||
|
|
@ -333,7 +333,7 @@ export const TargetLayout = ({
|
|||
<Button
|
||||
onClick={toggleModalOpen}
|
||||
variant="link"
|
||||
className="hidden whitespace-nowrap text-orange-500 md:flex"
|
||||
className="hidden whitespace-nowrap md:flex"
|
||||
>
|
||||
<LinkIcon size={16} className="mr-2" />
|
||||
Connect to CDN
|
||||
|
|
@ -348,10 +348,8 @@ export const TargetLayout = ({
|
|||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={cn('container min-h-[var(--content-height)] pb-7', className)}>
|
||||
{children}
|
||||
</div>
|
||||
</SecondaryNavigation>
|
||||
<div className={cn('min-h-(--content-height) container pb-7', className)}>{children}</div>
|
||||
</>
|
||||
)}
|
||||
</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}
|
||||
>
|
||||
<div>
|
||||
<div className="font-semibold text-white">{props.scope.name}</div>
|
||||
<div className="text-xs text-gray-400">{props.scope.description}</div>
|
||||
<div className="text-neutral-12 font-semibold">{props.scope.name}</div>
|
||||
<div className="text-neutral-10 text-xs">{props.scope.description}</div>
|
||||
</div>
|
||||
<Select
|
||||
disabled={!props.canManageScope || props.disabled}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const planCollection: {
|
|||
href="https://the-guild.dev"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="font-medium text-orange-500 transition-colors hover:underline"
|
||||
className="text-neutral-2 font-medium transition-colors hover:underline"
|
||||
>
|
||||
The Guild
|
||||
</a>
|
||||
|
|
@ -84,16 +84,16 @@ function Plan(plan: {
|
|||
) : (
|
||||
<>
|
||||
${plan.price}
|
||||
<span className="text-sm text-gray-500">/mo</span>
|
||||
<span className="text-neutral-10 text-sm">/mo</span>
|
||||
</>
|
||||
)}
|
||||
</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">
|
||||
{plan.features.map((feature, i) => (
|
||||
<div key={i}>
|
||||
<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}
|
||||
</Section.Subtitle>
|
||||
</div>
|
||||
|
|
@ -102,8 +102,8 @@ function Plan(plan: {
|
|||
</div>
|
||||
{plan.footer && (
|
||||
<div>
|
||||
<div className="mx-auto my-4 w-9/12 border-b border-gray-800" />
|
||||
<div className="text-xs text-gray-300">{plan.footer}</div>
|
||||
<div className="border-neutral-5 mx-auto my-4 w-9/12 border-b" />
|
||||
<div className="text-neutral-11 text-xs">{plan.footer}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ function PriceEstimationTable(props: {
|
|||
<TBody>
|
||||
<Tr>
|
||||
<Td>
|
||||
Base price <span className="text-gray-500">(unlimited seats)</span>
|
||||
Base price <span className="text-neutral-10">(unlimited seats)</span>
|
||||
</Td>
|
||||
<Td align="right" />
|
||||
<Td align="right">{CurrencyFormatter.format(plan.basePrice ?? 0)}</Td>
|
||||
|
|
@ -46,7 +46,7 @@ function PriceEstimationTable(props: {
|
|||
{includedOperationsInMillions > 0 && (
|
||||
<Tr>
|
||||
<Td>
|
||||
Included Operations <span className="text-gray-500">(free)</span>
|
||||
Included Operations <span className="text-neutral-10">(free)</span>
|
||||
</Td>
|
||||
<Td align="right">{includedOperationsInMillions}M</Td>
|
||||
<Td align="right">{CurrencyFormatter.format(0)}</Td>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export function RoleSelector<T>(props: {
|
|||
>
|
||||
{props.defaultRole?.name ?? 'Select role'}
|
||||
</span>
|
||||
<ChevronDownIcon className="text-muted-foreground ml-2 size-4" />
|
||||
<ChevronDownIcon className="text-neutral-10 ml-2 size-4" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[400px] p-0" align="end">
|
||||
|
|
@ -81,7 +81,7 @@ export function RoleSelector<T>(props: {
|
|||
}}
|
||||
>
|
||||
<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>
|
||||
) : null}
|
||||
{props.roles.map(role => {
|
||||
|
|
@ -118,7 +118,7 @@ export function RoleSelector<T>(props: {
|
|||
disabled={!isActive}
|
||||
>
|
||||
<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>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{reason}</TooltipContent>
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ function MemberInvitationForm(props: {
|
|||
return (
|
||||
<>
|
||||
<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 (
|
||||
<>
|
||||
<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}>
|
||||
{invitation.role.name}
|
||||
</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))}
|
||||
</td>
|
||||
<td className="py-3 text-right text-sm">
|
||||
<DropdownMenu>
|
||||
<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" />
|
||||
<span className="sr-only">Open menu</span>
|
||||
</Button>
|
||||
|
|
@ -494,7 +494,7 @@ export function OrganizationInvitations(props: {
|
|||
/>
|
||||
</SubPageLayoutHeader>
|
||||
{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>
|
||||
<tr>
|
||||
<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" />
|
||||
</tr>
|
||||
</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 => (
|
||||
<Invitation
|
||||
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="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>
|
||||
<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.
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ const OrganizationMemberRow = memo(function OrganizationMemberRow(props: {
|
|||
</td>
|
||||
<td className="grow overflow-hidden py-3 text-sm font-medium">
|
||||
<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 className="relative py-3 text-center text-sm">
|
||||
{member.isOwner ? (
|
||||
|
|
@ -199,7 +199,7 @@ const OrganizationMemberRow = memo(function OrganizationMemberRow(props: {
|
|||
{member.viewerCanRemove && (
|
||||
<DropdownMenu>
|
||||
<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" />
|
||||
<span className="sr-only">Open menu</span>
|
||||
</Button>
|
||||
|
|
@ -264,7 +264,7 @@ function MemberRole(props: {
|
|||
{organization.viewerCanAssignUserRoles && (
|
||||
<Sheet.Sheet open={isOpen} onOpenChange={isOpen => setIsOpen(isOpen)}>
|
||||
<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
|
||||
</button>
|
||||
</Sheet.SheetTrigger>
|
||||
|
|
@ -377,7 +377,7 @@ export function OrganizationMembers(props: {
|
|||
)}
|
||||
</div>
|
||||
</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>
|
||||
<tr>
|
||||
<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" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y-[1px] divide-gray-500/20">
|
||||
<tbody className="divide-neutral-10/20 divide-y-[1px]">
|
||||
{members.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan={4} className="py-16">
|
||||
<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.`}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -415,7 +415,7 @@ export function OrganizationMembers(props: {
|
|||
</table>
|
||||
{/* Pagination Controls */}
|
||||
<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}
|
||||
{searchValue && members.length > 0 && ` - showing results for "${searchValue}"`}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ export function MemberRolePicker(props: {
|
|||
selectedRoleId={selectedRoleId}
|
||||
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.
|
||||
</p>
|
||||
{selectedRole && (
|
||||
|
|
@ -136,7 +136,7 @@ export function MemberRolePicker(props: {
|
|||
<Heading size="lg" className="mb-1 text-sm">
|
||||
Assigned Resources
|
||||
</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.
|
||||
</p>
|
||||
<ResourceSelector
|
||||
|
|
|
|||
|
|
@ -145,8 +145,8 @@ export function PermissionSelector(props: PermissionSelectorProps) {
|
|||
(needsDependency || !permission.isAssignableByViewer) && 'opacity-30',
|
||||
)}
|
||||
>
|
||||
<div className="font-semibold text-white">{permission.title}</div>
|
||||
<div className="text-xs text-gray-400">{permission.description}</div>
|
||||
<div className="text-neutral-12 font-semibold">{permission.title}</div>
|
||||
<div className="text-neutral-11 text-xs">{permission.description}</div>
|
||||
</div>
|
||||
{permission.isAssignableByViewer === false ? (
|
||||
<div className="flex grow justify-end">
|
||||
|
|
|
|||
|
|
@ -811,7 +811,7 @@ export function ResourceSelector(props: {
|
|||
{/** Projects Content */}
|
||||
{showProjectsTab && (
|
||||
<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
|
||||
</div>
|
||||
{projectState.selected.length ? (
|
||||
|
|
@ -838,7 +838,7 @@ export function ResourceSelector(props: {
|
|||
) : (
|
||||
<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
|
||||
</div>
|
||||
{projectState.notSelected.length ? (
|
||||
|
|
@ -864,18 +864,18 @@ export function ResourceSelector(props: {
|
|||
)}
|
||||
>
|
||||
{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.
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{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.
|
||||
</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
|
||||
</div>
|
||||
{targetState.selection.selected.length ? (
|
||||
|
|
@ -910,7 +910,7 @@ export function ResourceSelector(props: {
|
|||
) : (
|
||||
<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
|
||||
</div>
|
||||
{targetState.selection.notSelected.length ? (
|
||||
|
|
@ -939,26 +939,26 @@ export function ResourceSelector(props: {
|
|||
<div className="py-2">
|
||||
{projectState.activeProject?.projectSelection.targets.mode ===
|
||||
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.
|
||||
</div>
|
||||
) : 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.
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{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.
|
||||
</div>
|
||||
) : 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.
|
||||
</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
|
||||
</div>
|
||||
{serviceState.selection.selected.length ? (
|
||||
|
|
@ -973,7 +973,7 @@ export function ResourceSelector(props: {
|
|||
) : (
|
||||
<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
|
||||
</div>
|
||||
{serviceState.selection.notSelected.map(serviceName => (
|
||||
|
|
@ -1066,22 +1066,22 @@ export function ResourceSelector(props: {
|
|||
<div className="py-2">
|
||||
{projectState.activeProject?.projectSelection.targets.mode ===
|
||||
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.
|
||||
</div>
|
||||
) : 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.
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{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.
|
||||
</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
|
||||
</div>
|
||||
{appsState.selection.selected.length ? (
|
||||
|
|
@ -1096,7 +1096,7 @@ export function ResourceSelector(props: {
|
|||
) : (
|
||||
<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
|
||||
</div>
|
||||
{appsState.selection.notSelected.map(serviceName => (
|
||||
|
|
@ -1170,7 +1170,7 @@ function RowItem(props: {
|
|||
}) {
|
||||
return (
|
||||
<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}
|
||||
>
|
||||
<span className="grow text-sm" onClick={props.onClick}>
|
||||
|
|
@ -1189,7 +1189,7 @@ function RowItem(props: {
|
|||
<XIcon
|
||||
size={12}
|
||||
data-active={props.isActive}
|
||||
className="text-muted-foreground data-[active=true]:text-secondary"
|
||||
className="text-neutral-10 data-[active=true]:text-neutral-2"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
|
|
|
|||
|
|
@ -633,7 +633,7 @@ function OrganizationMemberRoleRow(props: {
|
|||
<TooltipContent side="right">
|
||||
<div className="flex flex-col items-start gap-y-2 p-2">
|
||||
<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.
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -652,7 +652,7 @@ function OrganizationMemberRoleRow(props: {
|
|||
<TooltipContent side="right">
|
||||
<div className="flex flex-col items-start gap-y-2 p-2">
|
||||
<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>
|
||||
{props.canChangeOIDCDefaultRole ? (
|
||||
<p>
|
||||
|
|
@ -681,7 +681,7 @@ function OrganizationMemberRoleRow(props: {
|
|||
) : null}
|
||||
</div>
|
||||
</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}
|
||||
</td>
|
||||
<td className="py-3 text-center text-sm">
|
||||
|
|
@ -690,7 +690,7 @@ function OrganizationMemberRoleRow(props: {
|
|||
<td className="py-3 text-right text-sm">
|
||||
<DropdownMenu>
|
||||
<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" />
|
||||
<span className="sr-only">Open menu</span>
|
||||
</Button>
|
||||
|
|
@ -929,7 +929,7 @@ export function OrganizationMemberRoles(props: {
|
|||
>
|
||||
<OrganizationMemberRoleCreateButton organization={organization} />
|
||||
</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>
|
||||
<tr>
|
||||
<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" />
|
||||
</tr>
|
||||
</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 }) => (
|
||||
<OrganizationMemberRoleRow
|
||||
organizationSlug={organization.slug}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export function AccessTokensSubPage(props: AccessTokensSubPageProps): React.Reac
|
|||
<CardDescription>
|
||||
<DocsLink
|
||||
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
|
||||
</DocsLink>
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ export function CreateAccessTokenSheetContent(
|
|||
'step-4-confirmation': () => (
|
||||
<>
|
||||
<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
|
||||
align with your intended access needs.
|
||||
</p>
|
||||
|
|
@ -320,7 +320,7 @@ export function CreateAccessTokenSheetContent(
|
|||
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-gray-400">
|
||||
<p className="text-neutral-10">
|
||||
Granted on {permissionLevelToResourceName(group.level)}:
|
||||
</p>
|
||||
<ul className="flex list-none flex-wrap gap-1">
|
||||
|
|
@ -337,7 +337,7 @@ export function CreateAccessTokenSheetContent(
|
|||
{resolvedResources[group.level].map(id => (
|
||||
<li key={id}>
|
||||
<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"
|
||||
>
|
||||
{id}
|
||||
|
|
|
|||
|
|
@ -89,19 +89,19 @@ export function PermissionDetailView(props: {
|
|||
))}
|
||||
<div className="w-full space-y-1">
|
||||
{group.resolvedResourceIds == null ? (
|
||||
<p className="text-gray-400">
|
||||
<p className="text-neutral-10">
|
||||
Granted on all {permissionLevelToResourceName(group.level)}
|
||||
</p>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-gray-400">
|
||||
<p className="text-neutral-10">
|
||||
Granted on {permissionLevelToResourceName(group.level)}:
|
||||
</p>
|
||||
<ul className="flex list-none flex-wrap gap-1">
|
||||
{group.resolvedResourceIds.map(id => (
|
||||
<li key={id}>
|
||||
<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"
|
||||
>
|
||||
{id}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ const classes = {
|
|||
};
|
||||
|
||||
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(`
|
||||
|
|
@ -488,7 +488,7 @@ function CreateOIDCIntegrationForm(props: {
|
|||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<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
|
||||
onEndpointChange={endpoints => {
|
||||
void formik.setFieldValue('tokenEndpoint', endpoints.token);
|
||||
|
|
@ -1008,13 +1008,13 @@ function UpdateOIDCIntegrationForm(props: {
|
|||
<Dialog open={props.isOpen} onOpenChange={props.close}>
|
||||
<DialogContent className="flex max-h-[100vh] w-[960px] max-w-[100%] overflow-y-auto">
|
||||
<div className={classes.container}>
|
||||
<div className="bg-border 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-5 grid grid-cols-1 gap-[1px] md:grid-cols-2">
|
||||
<div className="bg-neutral-3 py-4 pr-4 md:pt-0">
|
||||
<div className="flex flex-col gap-y-5">
|
||||
<div className={cn(classes.container, 'flex flex-col gap-y-4')}>
|
||||
<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
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1048,7 +1048,7 @@ function UpdateOIDCIntegrationForm(props: {
|
|||
<div className="flex items-center justify-between space-x-4">
|
||||
<div className="flex flex-col space-y-1 text-sm font-medium leading-none">
|
||||
<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.
|
||||
<br />
|
||||
<span className="font-medium">
|
||||
|
|
@ -1071,7 +1071,7 @@ function UpdateOIDCIntegrationForm(props: {
|
|||
<p>Default Member Role</p>
|
||||
<div className="flex items-start justify-between space-x-4">
|
||||
<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.{' '}
|
||||
<span className="font-medium">
|
||||
Only members with the Admin role can modify it.
|
||||
|
|
@ -1098,12 +1098,12 @@ function UpdateOIDCIntegrationForm(props: {
|
|||
onSubmit={formik.handleSubmit}
|
||||
className={cn(
|
||||
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 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
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1223,7 +1223,7 @@ function UpdateOIDCIntegrationForm(props: {
|
|||
</div>
|
||||
<div className="space-y-1 text-sm font-medium leading-none">
|
||||
<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.{' '}
|
||||
<span className="font-medium">Only members with the Admin role can modify it.</span>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ export function CreatePersonalAccessTokenSheetContent(
|
|||
'step-4-confirmation': () => (
|
||||
<>
|
||||
<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
|
||||
align with your intended access needs.
|
||||
</p>
|
||||
|
|
@ -313,7 +313,7 @@ export function CreatePersonalAccessTokenSheetContent(
|
|||
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-gray-400">
|
||||
<p className="text-neutral-10">
|
||||
Granted on {permissionLevelToResourceName(group.level)}:
|
||||
</p>
|
||||
<ul className="flex list-none flex-wrap gap-1">
|
||||
|
|
@ -330,7 +330,7 @@ export function CreatePersonalAccessTokenSheetContent(
|
|||
{resolvedResources[group.level].map(id => (
|
||||
<li key={id}>
|
||||
<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"
|
||||
>
|
||||
{id}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export function PersonalAccessTokensSubPage(
|
|||
<CardDescription>
|
||||
<DocsLink
|
||||
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
|
||||
</DocsLink>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ const statusVariants = cva('inline-flex items-center text-sm font-semibold', {
|
|||
variants: {
|
||||
variant: {
|
||||
[SupportTicketStatus.Open]: 'text-yellow-400',
|
||||
[SupportTicketStatus.Solved]: 'text-gray-500',
|
||||
[SupportTicketStatus.Solved]: 'text-neutral-10',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
@ -38,12 +38,9 @@ const priorityVariants = cva(
|
|||
{
|
||||
variants: {
|
||||
variant: {
|
||||
[SupportTicketPriority.Normal]:
|
||||
'border-transparent bg-destructive/40 text-destructive-foreground',
|
||||
[SupportTicketPriority.High]:
|
||||
'border-transparent bg-destructive/60 text-destructive-foreground',
|
||||
[SupportTicketPriority.Urgent]:
|
||||
'border-transparent bg-destructive/80 text-destructive-foreground',
|
||||
[SupportTicketPriority.Normal]: 'border-transparent bg-red-400 text-neutral-12',
|
||||
[SupportTicketPriority.High]: 'border-transparent bg-red-600 text-neutral-12',
|
||||
[SupportTicketPriority.Urgent]: 'border-transparent bg-red-800 text-neutral-12',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export function PolicyConfigBox(props: 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>
|
||||
</>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -89,7 +89,7 @@ export function PolicyListItem(props: {
|
|||
<div>
|
||||
<SeverityLevelToggle canTurnOff={props.overridingParentRule} rule={ruleInfo.id} />
|
||||
</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 && (
|
||||
<PolicyRuleConfig
|
||||
rule={ruleInfo.id}
|
||||
|
|
@ -101,8 +101,8 @@ export function PolicyListItem(props: {
|
|||
</div>
|
||||
) : null}
|
||||
{props.overridingParentRule && enabled ? (
|
||||
<div className="mt-4 text-xs font-medium text-gray-400">
|
||||
<p className="mr-2 inline-block text-sm font-medium text-orange-500">!</p>
|
||||
<div className="text-neutral-10 mt-4 text-xs font-medium">
|
||||
<p className="text-neutral-2 mr-2 inline-block text-sm font-medium">!</p>
|
||||
You are {severity === RuleInstanceSeverityLevel.Off ? 'disabling' : 'overriding'} a
|
||||
rule configured at the organization level
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ function PolicySettingsListForm({
|
|||
<>
|
||||
{children ? children(props) : null}
|
||||
<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
|
||||
disabled={!props.dirty || saving || !props.isValid || !onSave}
|
||||
|
|
@ -127,7 +127,7 @@ function PolicySettingsListForm({
|
|||
{error}
|
||||
</Callout>
|
||||
) : 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 => (
|
||||
<PolicyListItem
|
||||
disabled={!onSave}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const PolicyBooleanToggle = (props: {
|
|||
|
||||
const 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}`}
|
||||
>
|
||||
{props.title}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export const PolicyEnumSelect = (props: {
|
|||
<div>{props.title}</div>
|
||||
{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>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
@ -47,7 +47,7 @@ export const PolicyEnumSelect = (props: {
|
|||
}}
|
||||
value={currentValue}
|
||||
type="single"
|
||||
className="bg-gray-900/50 text-gray-500"
|
||||
className="text-neutral-10 bg-neutral-2/50"
|
||||
>
|
||||
{props.options.map(option => (
|
||||
<ToggleGroupItem
|
||||
|
|
@ -55,8 +55,8 @@ export const PolicyEnumSelect = (props: {
|
|||
value={option.value}
|
||||
title={option.label}
|
||||
className={clsx(
|
||||
'text-xs hover:text-white',
|
||||
currentValue === option.value && 'bg-gray-800 text-white',
|
||||
'hover:text-neutral-12 text-xs',
|
||||
currentValue === option.value && 'bg-neutral-5 text-neutral-12',
|
||||
)}
|
||||
>
|
||||
{option.label}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export const PolicyMultiSelect = (props: {
|
|||
<div>{props.title}</div>
|
||||
{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>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { ReactElement, useEffect } from 'react';
|
||||
import type { JSONSchema } from 'json-schema-typed';
|
||||
import { useTheme } from '@/components/theme/theme-provider';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { cn } from '@/lib/utils';
|
||||
import MonacoEditor, { type Monaco } from '@monaco-editor/react';
|
||||
|
|
@ -29,6 +30,7 @@ const DEFAULT_VALUE = {
|
|||
export function NamingConventionConfigEditor(props: {
|
||||
configJsonSchema: JSONSchema | null;
|
||||
}): ReactElement {
|
||||
const { resolvedTheme } = useTheme();
|
||||
const { config, setConfig, getConfigValue, setConfigAsInvalid, getValidationStatus } =
|
||||
useConfigurationHelper().ruleConfig('naming-convention');
|
||||
const currentValue = getConfigValue<string | undefined>('');
|
||||
|
|
@ -63,7 +65,8 @@ export function NamingConventionConfigEditor(props: {
|
|||
return (
|
||||
<div className="col-span-4">
|
||||
<MonacoEditor
|
||||
theme="vs-dark"
|
||||
// this outputs either "vs-light" or "vs-dark"
|
||||
theme={`vs-${resolvedTheme}`}
|
||||
loading={<Spinner />}
|
||||
height="40vh"
|
||||
beforeMount={handleEditorWillMount}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export const SeverityLevelToggle = (props: { rule: string; canTurnOff: boolean }
|
|||
label: 'Warning',
|
||||
icon: (active: boolean) => (
|
||||
<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',
|
||||
icon: (active: boolean) => (
|
||||
<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',
|
||||
icon: (active: boolean) => (
|
||||
<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"
|
||||
className="bg-gray-900/50 text-gray-500"
|
||||
className="text-neutral-10 bg-neutral-2/50"
|
||||
>
|
||||
{options.map(
|
||||
level =>
|
||||
|
|
@ -61,8 +61,8 @@ export const SeverityLevelToggle = (props: { rule: string; canTurnOff: boolean }
|
|||
value={level.value}
|
||||
title={level.label}
|
||||
className={clsx(
|
||||
'hover:text-white',
|
||||
config.severity === level.value && 'bg-gray-800 text-white',
|
||||
'hover:text-neutral-12',
|
||||
config.severity === level.value && 'bg-neutral-5 text-neutral-12',
|
||||
)}
|
||||
>
|
||||
<Tooltip content={level.label}>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const PolicyStringInputConfig = (props: {
|
|||
<div>{props.title}</div>
|
||||
{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>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export function ChannelsTable(props: {
|
|||
/>
|
||||
</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)}
|
||||
</Td>
|
||||
<Td className="flex max-w-24 content-end">
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ export const CreateChannelModal = ({
|
|||
{mutation.data.addAlertChannel.error.inputErrors.name}
|
||||
</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.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -164,7 +164,7 @@ export const CreateChannelModal = ({
|
|||
</div>
|
||||
)}
|
||||
{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">
|
||||
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}
|
||||
</div>
|
||||
)}
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-neutral-10 text-sm">
|
||||
Use <Tag>#channel</Tag> or <Tag>@username</Tag> form.
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ export function CreateProjectAccessTokenSheetContent(
|
|||
'step-4-confirmation': () => (
|
||||
<>
|
||||
<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
|
||||
align with your intended access needs.
|
||||
</p>
|
||||
|
|
@ -335,7 +335,7 @@ export function CreateProjectAccessTokenSheetContent(
|
|||
<>Granted on all {permissionLevelToResourceName(group.level)}</>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-gray-400">
|
||||
<p className="text-neutral-10">
|
||||
Granted on {permissionLevelToResourceName(group.level)}:
|
||||
</p>
|
||||
<ul className="flex list-none flex-wrap gap-1">
|
||||
|
|
@ -352,7 +352,7 @@ export function CreateProjectAccessTokenSheetContent(
|
|||
{resolvedResources[group.level].map(id => (
|
||||
<li key={id}>
|
||||
<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"
|
||||
>
|
||||
{id}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export function ProjectAccessTokensSubPage(
|
|||
<CardDescription>
|
||||
<DocsLink
|
||||
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
|
||||
</DocsLink>
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ const ExternalCompositionStatus = ({
|
|||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<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()}
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
|
|
@ -295,7 +295,7 @@ export const ExternalCompositionSettings = (props: {
|
|||
return (
|
||||
<div className="flex flex-col items-start gap-y-6">
|
||||
<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
|
||||
can be used to implement custom composition logic.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ export function LegacyCompositionSettings(props: {
|
|||
return (
|
||||
<div className="flex flex-col items-start gap-y-6">
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
<p className="text-neutral-10 text-sm">
|
||||
Not recommended. Migrate towards using Native Federation v2.
|
||||
</p>
|
||||
<ProductUpdatesLink href="2023-10-10-native-federation-2">
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const IncrementalNativeCompositionSwitch = (props: {
|
|||
return (
|
||||
<div
|
||||
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',
|
||||
)}
|
||||
>
|
||||
|
|
@ -207,7 +207,7 @@ export function NativeCompositionSettings(props: {
|
|||
return (
|
||||
<div className="flex flex-col items-start gap-y-6">
|
||||
<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.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -220,7 +220,7 @@ export function NativeCompositionSettings(props: {
|
|||
<div className="font-semibold">Incremental migration</div>
|
||||
<Badge variant="outline">experimental</Badge>
|
||||
</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 />
|
||||
Migrate targets one by one to the native schema composition.
|
||||
</div>
|
||||
|
|
@ -266,7 +266,7 @@ export function NativeCompositionSettings(props: {
|
|||
) : null}
|
||||
{projectQuery.data.project.nativeFederationCompatibility.status ===
|
||||
NativeFederationCompatibilityStatusType.Unknown ? (
|
||||
<FlaskConicalIcon className="size-10 text-orange-500" />
|
||||
<FlaskConicalIcon className="text-neutral-2 size-10" />
|
||||
) : null}
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -284,13 +284,13 @@ export function NativeCompositionSettings(props: {
|
|||
? 'Unclear whether your project is compatible'
|
||||
: null}
|
||||
</div>
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<div className="text-neutral-10 text-sm">
|
||||
{projectQuery.data.project.nativeFederationCompatibility.status ===
|
||||
NativeFederationCompatibilityStatusType.Compatible ? (
|
||||
<>
|
||||
Subgraphs of this project are composed and validated correctly by our{' '}
|
||||
<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"
|
||||
>
|
||||
Open Source composition library
|
||||
|
|
@ -303,7 +303,7 @@ export function NativeCompositionSettings(props: {
|
|||
<>
|
||||
Our{' '}
|
||||
<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"
|
||||
>
|
||||
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
|
||||
us to assess compatibility with our{' '}
|
||||
<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"
|
||||
>
|
||||
Open Source composition library
|
||||
|
|
@ -355,7 +355,7 @@ export function NativeCompositionSettings(props: {
|
|||
)}
|
||||
</Button>
|
||||
<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">
|
||||
Learn more about risks and compatibility with other composition libraries
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export function Description(props: { description: string }) {
|
|||
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>
|
||||
);
|
||||
}
|
||||
|
|
@ -62,10 +62,10 @@ export function SchemaExplorerUsageStats(props: {
|
|||
</div>
|
||||
<div
|
||||
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 }}
|
||||
>
|
||||
<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>
|
||||
<Tooltip>
|
||||
|
|
@ -101,7 +101,7 @@ export function SchemaExplorerUsageStats(props: {
|
|||
<tr key={op.hash}>
|
||||
<td className="px-2 pl-0 text-left">
|
||||
<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"
|
||||
params={{
|
||||
organizationSlug: props.organizationSlug,
|
||||
|
|
@ -146,7 +146,7 @@ export function SchemaExplorerUsageStats(props: {
|
|||
{usage.usedByClients.map(clientName => (
|
||||
<li key={clientName} className="font-bold">
|
||||
<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"
|
||||
params={{
|
||||
organizationSlug: props.organizationSlug,
|
||||
|
|
@ -219,7 +219,7 @@ export function DeprecationNote(props: {
|
|||
</TooltipTrigger>
|
||||
<TooltipContent className="min-w-6 max-w-screen-md" side="right" sideOffset={5}>
|
||||
<div className="mb-2">Deprecation reason</div>
|
||||
<Markdown className="text-gray-400" content={props.deprecationReason} />
|
||||
<Markdown className="text-neutral-10" content={props.deprecationReason} />
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
|
@ -245,11 +245,11 @@ export function GraphQLTypeCard(props: {
|
|||
);
|
||||
|
||||
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>
|
||||
<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">
|
||||
<GraphQLTypeAsLink
|
||||
organizationSlug={props.organizationSlug}
|
||||
|
|
@ -262,7 +262,7 @@ export function GraphQLTypeCard(props: {
|
|||
{props.description && <Description description={props.description} />}
|
||||
</div>
|
||||
{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="flex flex-row gap-2">
|
||||
{props.implements.map(t => (
|
||||
|
|
@ -312,7 +312,7 @@ export function GraphQLTypeCardListItem(props: {
|
|||
onClick={props.onClick}
|
||||
className={clsx(
|
||||
'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,
|
||||
)}
|
||||
>
|
||||
|
|
@ -343,14 +343,14 @@ export function GraphQLInputFields(props: {
|
|||
<GraphQLTypeCardListItem key={field.name} index={i}>
|
||||
<div>
|
||||
<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}>
|
||||
<LinkToCoordinatePage
|
||||
organizationSlug={props.organizationSlug}
|
||||
projectSlug={props.projectSlug}
|
||||
targetSlug={props.targetSlug}
|
||||
coordinate={coordinate}
|
||||
className="font-semibold text-white"
|
||||
className="text-neutral-12 font-semibold"
|
||||
>
|
||||
{field.name}
|
||||
</LinkToCoordinatePage>
|
||||
|
|
@ -414,7 +414,7 @@ export function GraphQLTypeAsLink(props: {
|
|||
>
|
||||
Visit in <span className="font-bold">Explorer</span>
|
||||
</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>
|
||||
<NextLink
|
||||
|
|
@ -430,7 +430,7 @@ export function GraphQLTypeAsLink(props: {
|
|||
>
|
||||
Visit in <span className="font-bold">Insights</span>
|
||||
</NextLink>
|
||||
<span className="text-xs text-gray-500"> - usage insights</span>
|
||||
<span className="text-neutral-10 text-xs"> - usage insights</span>
|
||||
</p>
|
||||
</div>
|
||||
<PopoverArrow />
|
||||
|
|
@ -488,11 +488,11 @@ export const GraphQLFieldsSkeleton = (props: { count?: number }) => {
|
|||
{widths.map((width, index) => (
|
||||
<GraphQLTypeCardListItem key={index} index={index} className="w-full">
|
||||
<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">
|
||||
<Skeleton className="bg-muted my-1 size-4" />
|
||||
<Skeleton className="bg-muted my-1 size-4" />
|
||||
<Skeleton className="bg-muted my-1 size-4" />
|
||||
<Skeleton className="bg-neutral-3 my-1 size-4" />
|
||||
<Skeleton className="bg-neutral-3 my-1 size-4" />
|
||||
<Skeleton className="bg-neutral-3 my-1 size-4" />
|
||||
</div>
|
||||
</div>
|
||||
</GraphQLTypeCardListItem>
|
||||
|
|
@ -503,10 +503,10 @@ export const GraphQLFieldsSkeleton = (props: { count?: number }) => {
|
|||
|
||||
export const GraphQLTypeCardSkeleton = (props: { children: ReactNode }) => {
|
||||
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 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>{props.children}</div>
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ export function DescriptionsVisibilityFilter() {
|
|||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<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>
|
||||
<Label htmlFor="filter-toggle-descriptions" className="text-sm font-normal">
|
||||
Show descriptions
|
||||
|
|
@ -338,7 +338,7 @@ export function MetadataFilter(props: { options: Array<{ name: string; values: s
|
|||
return (
|
||||
<DropdownMenu>
|
||||
<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" />
|
||||
Metadata
|
||||
<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}>
|
||||
{i > 0 && <DropdownMenuSeparator />}
|
||||
<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={() => {
|
||||
const isChecked = !values.every(value => hasMetadataFilter(name, value));
|
||||
if (isChecked) {
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ export function GraphQLArguments(props: {
|
|||
const { isDescriptionsVisible } = useDescriptionsVisibleToggle();
|
||||
|
||||
return (
|
||||
<span className="ml-1 text-gray-400">
|
||||
<span className="text-neutral-10 ml-1">
|
||||
<span>(</span>
|
||||
<div className="pl-4 text-gray-300">
|
||||
<div className="text-neutral-11 pl-4">
|
||||
{args.map(arg => {
|
||||
const coordinate = `${props.parentCoordinate}.${arg.name}`;
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export function GraphQLFields(props: {
|
|||
This field is used but the presented arguments are not.
|
||||
</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<span className="mr-1 text-sm text-orange-500">*</span>
|
||||
<span className="text-neutral-2 mr-1 text-sm">*</span>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
|
@ -83,7 +83,7 @@ export function GraphQLFields(props: {
|
|||
This field is not deprecated but the presented arguments are.
|
||||
</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<span className="mr-1 text-sm text-orange-500">*</span>
|
||||
<span className="text-neutral-2 mr-1 text-sm">*</span>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
|
@ -112,7 +112,7 @@ export function GraphQLFields(props: {
|
|||
organizationSlug={props.organizationSlug}
|
||||
projectSlug={props.projectSlug}
|
||||
targetSlug={props.targetSlug}
|
||||
className="font-semibold text-gray-300"
|
||||
className="text-neutral-11 font-semibold"
|
||||
type={field.type}
|
||||
/>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
|
@ -216,7 +216,7 @@ export function SupergraphMetadataList(props: {
|
|||
}
|
||||
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
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -155,8 +155,8 @@ export function ChangesBlock(
|
|||
): ReactElement | null {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="mb-3 font-bold text-white">{props.title}</h2>
|
||||
<div className="list-inside list-disc space-y-2 text-sm leading-relaxed">
|
||||
<h2 className="text-neutral-2 mb-3 font-bold">{props.title}</h2>
|
||||
<div className="list-inside list-disc space-y-2 text-sm/relaxed">
|
||||
{props.changesWithUsage?.map((change, key) => (
|
||||
<ChangeItem
|
||||
organizationSlug={props.organizationSlug}
|
||||
|
|
@ -228,12 +228,12 @@ function ChangeItem(
|
|||
<div
|
||||
className={clsx(
|
||||
'text-left',
|
||||
(change.approval && 'text-orange-500') ||
|
||||
(change.approval && 'text-neutral-2') ||
|
||||
(severityLevelMapping[change.severityLevel] ?? 'text-red-400'),
|
||||
)}
|
||||
>
|
||||
<div>
|
||||
<span className="text-white">{labelize(change.message)}</span>
|
||||
<span className="text-neutral-10">{labelize(change.message)}</span>
|
||||
{change.isSafeBasedOnUsage && (
|
||||
<span className="cursor-pointer text-yellow-500">
|
||||
{' '}
|
||||
|
|
@ -243,7 +243,7 @@ function ChangeItem(
|
|||
{'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]" />
|
||||
<span className="text-xs">
|
||||
{change.usageStatistics.topAffectedOperations.length}
|
||||
|
|
@ -263,7 +263,7 @@ function ChangeItem(
|
|||
{'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]" />
|
||||
<span className="text-xs">
|
||||
{change.affectedAppDeployments.totalCount}{' '}
|
||||
|
|
@ -297,15 +297,15 @@ function ChangeItem(
|
|||
)}
|
||||
{'usageStatistics' in change && change.usageStatistics && metadata ? (
|
||||
<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)
|
||||
</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>
|
||||
Top 10 operations and clients affected by this change based on usage data.
|
||||
</span>
|
||||
{metadata && (
|
||||
<span className="text-xs text-gray-100">
|
||||
<span className="text-neutral-11 text-xs">
|
||||
See{' '}
|
||||
{metadata.settings.targets.map((target, index, arr) => (
|
||||
<>
|
||||
|
|
@ -319,7 +319,7 @@ function ChangeItem(
|
|||
) : (
|
||||
<Link
|
||||
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"
|
||||
params={{
|
||||
organizationSlug: props.organizationSlug,
|
||||
|
|
@ -358,7 +358,7 @@ function ChangeItem(
|
|||
<TableRow key={hash}>
|
||||
<TableCell className="font-medium">
|
||||
<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}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent side="right">
|
||||
|
|
@ -368,7 +368,7 @@ function ChangeItem(
|
|||
target.target ? (
|
||||
<p key={i}>
|
||||
<Link
|
||||
className="text-orange-500 hover:text-orange-500"
|
||||
className="text-neutral-2 hover:text-neutral-2"
|
||||
to="/$organizationSlug/$projectSlug/$targetSlug/insights/$operationName/$operationHash"
|
||||
params={{
|
||||
organizationSlug: props.organizationSlug,
|
||||
|
|
@ -381,7 +381,7 @@ function ChangeItem(
|
|||
>
|
||||
{target.slug}
|
||||
</Link>{' '}
|
||||
<span className="text-white">target</span>
|
||||
<span className="text-neutral-12">target</span>
|
||||
</p>
|
||||
) : null,
|
||||
)}
|
||||
|
|
@ -421,8 +421,10 @@ function ChangeItem(
|
|||
{'affectedAppDeployments' in change &&
|
||||
change.affectedAppDeployments?.edges?.length ? (
|
||||
<div className="mt-6">
|
||||
<h4 className="mb-1 text-sm font-medium text-white">Affected App Deployments</h4>
|
||||
<p className="mb-2 text-sm text-gray-500">
|
||||
<h4 className="text-neutral-12 mb-1 text-sm font-medium">
|
||||
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.
|
||||
</p>
|
||||
<Table>
|
||||
|
|
@ -447,7 +449,7 @@ function ChangeItem(
|
|||
appVersion: deployment.version,
|
||||
}}
|
||||
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}
|
||||
</Link>
|
||||
|
|
@ -456,7 +458,7 @@ function ChangeItem(
|
|||
<TableCell className="text-right">
|
||||
<Popover>
|
||||
<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 === 1
|
||||
? 'operation'
|
||||
|
|
@ -465,10 +467,12 @@ function ChangeItem(
|
|||
</PopoverTrigger>
|
||||
<PopoverContent side="left" className="w-80">
|
||||
<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">
|
||||
{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)}...)`}
|
||||
</li>
|
||||
))}
|
||||
|
|
@ -483,7 +487,7 @@ function ChangeItem(
|
|||
appVersion: deployment.version,
|
||||
}}
|
||||
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
|
||||
|
|
@ -507,7 +511,7 @@ function ChangeItem(
|
|||
schemaCheckId: props.schemaCheckId,
|
||||
}}
|
||||
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
|
||||
</Link>
|
||||
|
|
@ -517,8 +521,8 @@ function ChangeItem(
|
|||
</div>
|
||||
) : 'affectedAppDeployments' in change && change.affectedAppDeployments?.edges?.length ? (
|
||||
<div>
|
||||
<h4 className="mb-1 text-sm font-medium text-white">Affected App Deployments</h4>
|
||||
<p className="mb-2 text-sm text-gray-500">
|
||||
<h4 className="text-neutral-12 mb-1 text-sm font-medium">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.
|
||||
</p>
|
||||
<Table>
|
||||
|
|
@ -543,7 +547,7 @@ function ChangeItem(
|
|||
appVersion: deployment.version,
|
||||
}}
|
||||
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}
|
||||
</Link>
|
||||
|
|
@ -552,7 +556,7 @@ function ChangeItem(
|
|||
<TableCell className="text-right">
|
||||
<Popover>
|
||||
<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 === 1
|
||||
? 'operation'
|
||||
|
|
@ -561,10 +565,10 @@ function ChangeItem(
|
|||
</PopoverTrigger>
|
||||
<PopoverContent side="left" className="w-80">
|
||||
<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">
|
||||
{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)}...)`}
|
||||
</li>
|
||||
))}
|
||||
|
|
@ -579,7 +583,7 @@ function ChangeItem(
|
|||
appVersion: deployment.version,
|
||||
}}
|
||||
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
|
||||
</Link>
|
||||
|
|
@ -602,7 +606,7 @@ function ChangeItem(
|
|||
schemaCheckId: props.schemaCheckId,
|
||||
}}
|
||||
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
|
||||
</Link>
|
||||
|
|
@ -659,7 +663,7 @@ function SchemaChangeApproval(props: {
|
|||
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}.
|
||||
</a>
|
||||
)}
|
||||
|
|
@ -747,11 +751,9 @@ export function NoGraphChanges() {
|
|||
<div className="cursor-default">
|
||||
<div className="mb-3 flex items-center gap-3">
|
||||
<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>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
There are no changes in this graph for this graph.
|
||||
</p>
|
||||
<p className="text-neutral-10 text-xs">There are no changes in this graph for this graph.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,8 +171,8 @@ function OperationsFilter({
|
|||
</div>
|
||||
<div className="grow pl-1">
|
||||
{clientFilteredOperations && (
|
||||
<div className="text-right text-xs text-gray-600">
|
||||
<span className="text-gray-500">selected</span> / all clients
|
||||
<div className="text-neutral-8 text-right text-xs">
|
||||
<span className="text-neutral-10">selected</span> / all clients
|
||||
</div>
|
||||
)}
|
||||
<AutoSizer>
|
||||
|
|
@ -338,13 +338,13 @@ function OperationRow({
|
|||
const Totals = () => {
|
||||
if (hasClientOperation) {
|
||||
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 className="ml-1 truncate text-gray-600">/ {requests}</span>
|
||||
<span className="text-neutral-8 ml-1 truncate">/ {requests}</span>
|
||||
</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 (
|
||||
|
|
@ -382,7 +382,7 @@ export function OperationsFilterTrigger({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Button variant="outline" className="bg-accent" onClick={toggle}>
|
||||
<Button variant="outline" className="bg-neutral-2" onClick={toggle}>
|
||||
<span>Operations ({selected?.length || 'all'})</span>
|
||||
<FilterIcon className="ml-2 size-4" />
|
||||
</Button>
|
||||
|
|
@ -439,13 +439,13 @@ function ClientRow({
|
|||
const Totals = () => {
|
||||
if (props.clientOperationStats !== false) {
|
||||
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 className="ml-1 truncate text-gray-600">/ {requests}</span>
|
||||
<span className="text-neutral-8 ml-1 truncate">/ {requests}</span>
|
||||
</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 (
|
||||
|
|
@ -611,8 +611,8 @@ function ClientsFilter({
|
|||
</div>
|
||||
<div className="grow pl-1">
|
||||
{operationStatsConnection && (
|
||||
<div className="text-right text-xs text-gray-600">
|
||||
<span className="text-gray-500">selected</span> / all operations
|
||||
<div className="text-neutral-8 text-right text-xs">
|
||||
<span className="text-neutral-10">selected</span> / all operations
|
||||
</div>
|
||||
)}
|
||||
<AutoSizer>
|
||||
|
|
@ -759,7 +759,7 @@ export function ClientsFilterTrigger({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Button variant="outline" className="bg-accent" onClick={toggle}>
|
||||
<Button variant="outline" className="bg-neutral-2" onClick={toggle}>
|
||||
<span>Clients ({selected?.length || 'all'})</span>
|
||||
<FilterIcon className="ml-2 size-4" />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ function OperationsTable({
|
|||
return (
|
||||
<div
|
||||
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,
|
||||
)}
|
||||
>
|
||||
|
|
@ -271,7 +271,7 @@ function OperationsTable({
|
|||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<InfoIcon className="size-4 text-gray-400" />
|
||||
<InfoIcon className="text-neutral-10 size-4" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-[300px] text-left text-sm">
|
||||
<p className="mb-4">
|
||||
|
|
|
|||
|
|
@ -76,14 +76,14 @@ function RequestsStats({
|
|||
const value = useFormattedNumber(requests);
|
||||
|
||||
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">
|
||||
<CardTitle className="text-sm font-medium">Requests</CardTitle>
|
||||
<GlobeIcon className="text-muted-foreground size-4" />
|
||||
<GlobeIcon className="text-neutral-10 size-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<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>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -99,16 +99,14 @@ function UniqueOperationsStats({
|
|||
const value = useFormattedNumber(operations);
|
||||
|
||||
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">
|
||||
<CardTitle className="text-sm font-medium">Operations</CardTitle>
|
||||
<BookIcon className="text-muted-foreground size-4" />
|
||||
<BookIcon className="text-neutral-10 size-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{value}</div>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Distinct GraphQL operations in {dateRangeText}
|
||||
</p>
|
||||
<p className="text-neutral-10 text-xs">Distinct GraphQL operations in {dateRangeText}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -127,14 +125,14 @@ function OperationRelativeFrequency({
|
|||
: '-';
|
||||
|
||||
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">
|
||||
<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>
|
||||
<CardContent>
|
||||
<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>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -152,14 +150,14 @@ function PercentileStats({
|
|||
const formatted = useFormattedDuration(value);
|
||||
|
||||
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">
|
||||
<CardTitle className="text-sm font-medium">p{percentile}</CardTitle>
|
||||
<GaugeIcon className="text-muted-foreground size-4" />
|
||||
<GaugeIcon className="text-neutral-10 size-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<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}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -185,14 +183,14 @@ function RPM({
|
|||
});
|
||||
|
||||
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">
|
||||
<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>
|
||||
<CardContent>
|
||||
<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>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -213,14 +211,14 @@ function SuccessRateStats({
|
|||
: '-';
|
||||
|
||||
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">
|
||||
<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>
|
||||
<CardContent>
|
||||
<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>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -238,14 +236,14 @@ function FailureRateStats({
|
|||
const rate = requests || totalFailures ? `${toDecimal((totalFailures * 100) / requests)}%` : '-';
|
||||
|
||||
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">
|
||||
<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>
|
||||
<CardContent>
|
||||
<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>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -291,7 +289,7 @@ function OverTimeStats({
|
|||
}, [failuresOverTime]);
|
||||
|
||||
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.Subtitle>Timeline of GraphQL requests and failures</Section.Subtitle>
|
||||
<AutoSizer disableHeight>
|
||||
|
|
@ -589,7 +587,7 @@ function ClientsStats(props: {
|
|||
);
|
||||
|
||||
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.Subtitle>Top 5 - GraphQL API consumers</Section.Subtitle>
|
||||
<AutoSizer disableHeight className="mt-5 flex w-full flex-row gap-x-4">
|
||||
|
|
@ -861,7 +859,7 @@ function LatencyOverTimeStats({
|
|||
];
|
||||
|
||||
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.Subtitle>Timeline of latency of GraphQL requests</Section.Subtitle>
|
||||
<AutoSizer disableHeight>
|
||||
|
|
@ -962,7 +960,7 @@ function RpmOverTimeStats({
|
|||
}, [requests, windowInM]);
|
||||
|
||||
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.Subtitle>Requests per minute</Section.Subtitle>
|
||||
<AutoSizer disableHeight>
|
||||
|
|
@ -1110,7 +1108,7 @@ export function OperationsStats({
|
|||
: 'success';
|
||||
|
||||
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}>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<RequestsStats requests={operationsStats?.totalRequests} dateRangeText={dateRangeText} />
|
||||
|
|
|
|||
|
|
@ -63,16 +63,16 @@ export const ConnectLabModalContent = (props: {
|
|||
</DialogHeader>
|
||||
{props?.isCDNEnabled ? (
|
||||
<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">
|
||||
If you want to consume the GraphQL schema for a tool like GraphQL Code Generator, we
|
||||
instead recommend using the high-availability CDN instead.
|
||||
</Callout>
|
||||
</div>
|
||||
) : 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} />
|
||||
<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`
|
||||
scope:
|
||||
</span>
|
||||
|
|
@ -89,7 +89,7 @@ export const ConnectLabModalContent = (props: {
|
|||
YOUR_TOKEN_HERE
|
||||
</Link>
|
||||
</Tag>
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-neutral-10 text-sm">
|
||||
Read the{' '}
|
||||
<Link as="a" variant="primary" target="_blank" rel="noreferrer" href={props.docsUrl}>
|
||||
Managing Tokens
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export function ReviewComments(props: {
|
|||
|
||||
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) => {
|
||||
return (
|
||||
<ReviewComment key={`comment-${comment.id}`} first={idx === 0} comment={comment} />
|
||||
|
|
@ -74,10 +74,10 @@ export function ReviewComment(props: {
|
|||
return (
|
||||
<>
|
||||
<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">
|
||||
{!!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 className="mt-2 flex-row">{comment.body}</div>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export function ProposalChangeDetail(props: {
|
|||
<Accordion type="single">
|
||||
<AccordionItem value="item-1">
|
||||
<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>{labelize(props.change.message)}</div>
|
||||
<div className="min-w-fit grow pr-2 md:flex-none">{props.icon}</div>
|
||||
|
|
@ -49,7 +49,7 @@ export function ChangeBlock(props: {
|
|||
return (
|
||||
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.info && <ChangesBlockTooltip info={props.info} />}
|
||||
</h2>
|
||||
|
|
@ -65,7 +65,7 @@ export function ChangeBlock(props: {
|
|||
);
|
||||
} else if (mergeStatus === MergeStatus.IGNORED) {
|
||||
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
|
||||
</span>
|
||||
);
|
||||
|
|
@ -90,7 +90,7 @@ function ChangesBlockTooltip(props: { info: string }) {
|
|||
<TooltipProvider>
|
||||
<Tooltip delayDuration={200}>
|
||||
<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" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ export function ProposalEditor(props: {
|
|||
</TabsList>
|
||||
<div className="flex flex-row items-center justify-end">
|
||||
<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"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
|
|
@ -364,8 +364,8 @@ export function ProposalEditor(props: {
|
|||
</Link>
|
||||
<Link
|
||||
className={cn(
|
||||
'ml-2 cursor-pointer p-1 hover:text-orange-500',
|
||||
showSettings && 'border-b-2 border-orange-500',
|
||||
'hover:text-neutral-2 ml-2 cursor-pointer p-1',
|
||||
showSettings && 'border-neutral-2 border-b-2',
|
||||
projectType?.project.type === ProjectType.Single && 'hidden',
|
||||
)}
|
||||
title="Edit schema settings"
|
||||
|
|
@ -402,7 +402,7 @@ export function ProposalEditor(props: {
|
|||
onChange={setActiveTabSource}
|
||||
/>
|
||||
{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 && (
|
||||
<SubPageLayoutHeader
|
||||
subPageTitle="Settings"
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ export function Proposal(props: {
|
|||
<Fragment key={cursor}>
|
||||
{/* @todo if node.resolvedBy/resolvedAt is set, then minimize this */}
|
||||
{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}
|
||||
</code>
|
||||
)}
|
||||
|
|
@ -511,7 +511,7 @@ export function Proposal(props: {
|
|||
coordinates={reviewssByCoordinate.keys().toArray()}
|
||||
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.
|
||||
</div>
|
||||
{annotations(coordinate, withPreview)}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export function ChangeDocument(props: { children: ReactNode; className?: string
|
|||
<table
|
||||
aria-label="change-document"
|
||||
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,
|
||||
)}
|
||||
>
|
||||
|
|
@ -85,7 +85,7 @@ export function ChangeRow(props: {
|
|||
<tr>
|
||||
<td
|
||||
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.type === 'removal' || removed) && 'bg-red-900/30',
|
||||
props.type === 'addition' && 'invisible',
|
||||
|
|
@ -95,7 +95,7 @@ export function ChangeRow(props: {
|
|||
</td>
|
||||
<td
|
||||
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.type === 'removal' && 'invisible',
|
||||
(props.type === 'addition' || added) && 'bg-green-900/30',
|
||||
|
|
@ -105,7 +105,7 @@ export function ChangeRow(props: {
|
|||
</td>
|
||||
<td
|
||||
className={cn(
|
||||
'bg-gray-900 px-2',
|
||||
'bg-neutral-2 px-2',
|
||||
props.className,
|
||||
props.type === 'removal' && 'bg-[#561c1d]',
|
||||
props.type === 'addition' && 'bg-[#11362b]',
|
||||
|
|
@ -113,7 +113,7 @@ export function ChangeRow(props: {
|
|||
>
|
||||
<span
|
||||
className={cn(
|
||||
'bg-gray-900',
|
||||
'bg-neutral-2',
|
||||
props.type === 'removal' && 'bg-[#561c1d] line-through decoration-[#998c8b]',
|
||||
props.type === 'addition' && 'bg-[#11362b]',
|
||||
)}
|
||||
|
|
@ -178,7 +178,7 @@ function Addition(props: { children: ReactNode; className?: string }): ReactNode
|
|||
}
|
||||
}, [change.addition]);
|
||||
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>
|
||||
{props.children?.slice(0, 3)}
|
||||
<tr>
|
||||
<td colSpan={3} className="text-gray-500">
|
||||
<td colSpan={3} className="text-neutral-8">
|
||||
...
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -42,7 +42,7 @@ export function LineGroup(props: { children?: ReactElement[]; collapsible?: bool
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={3} className="text-gray-500">
|
||||
<td colSpan={3} className="text-neutral-8">
|
||||
...
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -68,7 +68,7 @@ export function Line(props: LineProps & { beforeLine: number; afterLine: number
|
|||
{props.annotations?.map((node, i) => (
|
||||
<Fragment key={`annotations-${i}`}>
|
||||
{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}
|
||||
</code>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export function Word(props: WordProps) {
|
|||
<Change type={props.change}>
|
||||
<span
|
||||
className={cn(
|
||||
props.kind === 'description' && 'text-gray-500',
|
||||
props.kind === 'description' && 'textneutral-8',
|
||||
props.kind === 'field' && 'text-white',
|
||||
props.kind === 'keyword' && 'text-gray-400',
|
||||
props.kind === 'literal' && 'text-white',
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ export function StageTransitionSelect(props: {
|
|||
>
|
||||
<div
|
||||
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',
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export function VersionSelect(props: {
|
|||
>
|
||||
<div
|
||||
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',
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ export function CDNAccessTokens(props: {
|
|||
<CardDescription>
|
||||
<DocsLink
|
||||
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
|
||||
</DocsLink>
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ export function SchemaContracts(props: {
|
|||
<CardDescription>
|
||||
<DocsLink
|
||||
href="/management/contracts"
|
||||
className="text-gray-500 hover:text-gray-300"
|
||||
className="text-neutral-10 hover:text-neutral-11"
|
||||
>
|
||||
Learn more about Schema Contracts
|
||||
</DocsLink>
|
||||
|
|
@ -700,7 +700,7 @@ function CreateContractDialogContent(props: {
|
|||
/>
|
||||
<label
|
||||
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
|
||||
</label>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,6 @@ import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
|||
import { useLocalStorage } from '@/lib/hooks';
|
||||
|
||||
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 ResolvedTheme = 'light' | 'dark';
|
||||
|
|
@ -34,15 +28,13 @@ function applyTheme(resolvedTheme: ResolvedTheme) {
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
// When theme switcher is disabled, always use dark mode regardless of stored value
|
||||
const theme: Theme = isThemeSwitcherEnabled()
|
||||
? ((storedTheme === 'light' || storedTheme === 'dark' || storedTheme === 'system'
|
||||
? storedTheme
|
||||
: 'system') as Theme)
|
||||
: 'dark';
|
||||
const theme: Theme =
|
||||
storedTheme === 'light' || storedTheme === 'dark' || storedTheme === 'system'
|
||||
? (storedTheme as Theme)
|
||||
: 'system';
|
||||
|
||||
const resolvedTheme: ResolvedTheme = theme === 'system' ? systemTheme : theme;
|
||||
|
||||
|
|
@ -50,10 +42,8 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|||
setStoredTheme(newTheme);
|
||||
};
|
||||
|
||||
// Listen for system theme changes (only when theme switcher is enabled)
|
||||
// Listen for system theme changes
|
||||
useEffect(() => {
|
||||
if (!isThemeSwitcherEnabled()) return;
|
||||
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
const handleChange = (e: MediaQueryListEvent) => {
|
||||
|
|
@ -66,9 +56,7 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|||
|
||||
// Apply theme to document
|
||||
useEffect(() => {
|
||||
// TODO: we're forcing dark mode here, remove when color palette work is complete
|
||||
// applyTheme(resolvedTheme);
|
||||
applyTheme('dark');
|
||||
applyTheme(resolvedTheme);
|
||||
}, [resolvedTheme]);
|
||||
|
||||
const value = useMemo(() => ({ theme, setTheme, resolvedTheme }), [theme, resolvedTheme]);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const AlertDialogOverlay = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Overlay
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -33,7 +33,7 @@ const AlertDialogContent = React.forwardRef<
|
|||
<AlertDialogPrimitive.Content
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -73,7 +73,7 @@ const AlertDialogDescription = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
className={cn('text-neutral-10 text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import { cva, type VariantProps } from 'class-variance-authority';
|
|||
import { cn } from '@/lib/utils';
|
||||
|
||||
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: {
|
||||
variant: {
|
||||
default: 'bg-background text-foreground',
|
||||
destructive: 'text-destructive border-destructive [&>svg]:text-destructive',
|
||||
default: 'bg-neutral-3 text-neutral-11',
|
||||
destructive: 'border-red-500 text-red-500 [&>svg]:text-red-500',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
|
|||
|
|
@ -7,15 +7,13 @@ const badgeVariants = cva(
|
|||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
|
||||
secondary:
|
||||
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
destructive:
|
||||
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
||||
outline: 'text-foreground',
|
||||
default: 'border-transparent bg-neutral-11 text-neutral-2 hover:bg-neutral-11/80',
|
||||
secondary: 'border-transparent bg-neutral-2 text-neutral-11 hover:bg-neutral-2/80',
|
||||
destructive: 'border-transparent bg-red-500 text-neutral-12 hover:bg-red-800',
|
||||
outline: 'text-neutral-11',
|
||||
success: 'bg-emerald-950 text-emerald-400 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: {
|
||||
|
|
@ -33,15 +31,15 @@ function Badge({ className, variant, ...props }: BadgeProps) {
|
|||
}
|
||||
|
||||
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: {
|
||||
color: {
|
||||
red: 'border-red-900 bg-red-500',
|
||||
yellow: 'border-yellow-900 bg-yellow-500',
|
||||
green: 'border-green-900 bg-green-500',
|
||||
gray: 'border-gray-900 bg-gray-500',
|
||||
orange: 'border-orange-900 bg-orange-500',
|
||||
gray: 'border-neutral-7 bg-neutral-11',
|
||||
orange: 'border-orange-900 bg-orange-500',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
|
|||
|
|
@ -4,18 +4,19 @@ import { cn } from '@/lib/utils';
|
|||
import { Slot } from '@radix-ui/react-slot';
|
||||
|
||||
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: {
|
||||
variant: {
|
||||
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
||||
primary: 'bg-orange-600 text-white hover:brightness-110 active:bg-orange-700',
|
||||
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
||||
outline: 'border border-input hover:bg-accent hover:text-accent-foreground',
|
||||
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||
link: 'underline-offset-4 hover:underline text-primary',
|
||||
orangeLink: 'h-auto p-0 underline-offset-4 hover:underline text-orange-500',
|
||||
default: 'bg-neutral-4 text-neutral-11 hover:text-neutral-12 hover:bg-neutral-5',
|
||||
primary: 'bg-accent text-neutral-2 hover:brightness-110 active:bg-accent',
|
||||
destructive: 'bg-red-500 text-neutral-1 dark:text-neutral-12 hover:bg-red-700',
|
||||
outline:
|
||||
'text-neutral-11 hover:text-neutral-12 border border-neutral-5 hover:border-neutral-6 bg-neutral-3 hover:bg-neutral-4',
|
||||
secondary: 'bg-neutral-2 text-neutral-11 hover:bg-neutral-2/80',
|
||||
ghost: 'hover:bg-neutral-2 hover:text-neutral-12',
|
||||
link: 'underline-offset-4 hover:underline text-accent',
|
||||
orangeLink: 'h-auto p-0 underline-offset-4 hover:underline text-accent',
|
||||
},
|
||||
size: {
|
||||
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',
|
||||
table: 'w-full border-collapse space-y-1',
|
||||
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',
|
||||
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'
|
||||
? '[&: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',
|
||||
|
|
@ -40,12 +40,12 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C
|
|||
day_range_start: 'day-range-start',
|
||||
day_range_end: 'day-range-end',
|
||||
day_selected:
|
||||
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
|
||||
day_today: 'bg-accent text-accent-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-neutral-2 text-neutral-12',
|
||||
day_outside:
|
||||
'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30',
|
||||
day_disabled: 'text-muted-foreground opacity-50',
|
||||
day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',
|
||||
'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-neutral-10 opacity-50',
|
||||
day_range_middle: 'aria-selected:bg-neutral-2 aria-selected:text-neutral-12',
|
||||
day_hidden: 'invisible',
|
||||
...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', {
|
||||
variants: {
|
||||
type: {
|
||||
default: ' border-orange-400/30 bg-orange-400/20 text-orange-300',
|
||||
error: ' border-red-200/30 bg-red-900/30 text-red-200',
|
||||
info: ' border-blue-200/30 bg-blue-900/30 text-blue-200',
|
||||
warning: ' border-yellow-200/30 bg-yellow-700/30 text-yellow-200',
|
||||
default: 'border-orange-300 bg-orange-200 text-orange-900',
|
||||
error: 'border-red-300 bg-red-200 text-red-900',
|
||||
info: 'border-blue-300 bg-blue-200 text-blue-900',
|
||||
warning: 'border-yellow-300 bg-yellow-200 text-yellow-900',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElemen
|
|||
({ className, ...props }, ref) => (
|
||||
<div
|
||||
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}
|
||||
/>
|
||||
),
|
||||
|
|
@ -28,7 +31,7 @@ const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HT
|
|||
// eslint-disable-next-line jsx-a11y/heading-has-content
|
||||
<h3
|
||||
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}
|
||||
/>
|
||||
),
|
||||
|
|
@ -39,11 +42,7 @@ const CardDescription = React.forwardRef<
|
|||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
ref={ref}
|
||||
className={cn('text-muted-foreground cursor-default text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
<p ref={ref} className={cn('text-neutral-11 cursor-default text-sm', className)} {...props} />
|
||||
));
|
||||
CardDescription.displayName = 'CardDescription';
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
|||
Latest changes
|
||||
{displayDot ? (
|
||||
<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>
|
||||
) : null}
|
||||
</Button>
|
||||
|
|
@ -71,8 +71,8 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
|||
<PopoverArrow />
|
||||
<div className="grid">
|
||||
<div className="space-y-2 p-4">
|
||||
<h4 className="font-medium leading-none">What's new in GraphQL Hive</h4>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
<h4 className="text-neutral-12 font-medium leading-none">What's new in GraphQL Hive</h4>
|
||||
<p className="text-neutral-11 text-sm">
|
||||
Find out about the newest features, and enhancements
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -81,17 +81,14 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
|||
<li
|
||||
className={cn(
|
||||
'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}
|
||||
>
|
||||
<time
|
||||
className="text-muted-foreground mb-1 text-sm font-normal"
|
||||
dateTime={change.date}
|
||||
>
|
||||
<time className="text-neutral-10 mb-1 text-xs font-normal" dateTime={change.date}>
|
||||
{format(new Date(change.date), 'do MMMM yyyy')}
|
||||
</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
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
|
|
@ -101,7 +98,7 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
|||
{change.title}
|
||||
</a>
|
||||
</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}
|
||||
</div>
|
||||
</li>
|
||||
|
|
@ -109,7 +106,7 @@ function ChangelogPopover(props: { changes: Changelog[] }) {
|
|||
</ol>
|
||||
</div>
|
||||
<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
|
||||
rel="noopener noreferrer"
|
||||
href="https://the-guild.dev/graphql/hive/product-updates"
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ const ChartContainer = React.forwardRef<
|
|||
data-chart={chartId}
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -160,7 +160,7 @@ const ChartTooltipContent = React.forwardRef<
|
|||
<div
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
>
|
||||
|
|
@ -175,7 +175,7 @@ const ChartTooltipContent = React.forwardRef<
|
|||
<div
|
||||
key={item.dataKey}
|
||||
className={cn(
|
||||
'[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:size-2.5',
|
||||
'[&>svg]:text-neutral-10 flex w-full flex-wrap items-stretch gap-2 [&>svg]:size-2.5',
|
||||
indicator === 'dot' && 'items-center',
|
||||
)}
|
||||
>
|
||||
|
|
@ -188,16 +188,13 @@ const ChartTooltipContent = React.forwardRef<
|
|||
) : (
|
||||
!hideIndicator && (
|
||||
<div
|
||||
className={cn(
|
||||
'border-(--color-border) bg-(--color-bg) shrink-0 rounded-[2px]',
|
||||
{
|
||||
'h-2.5 w-2.5': indicator === 'dot',
|
||||
'w-1': indicator === 'line',
|
||||
'w-0 border-[1.5px] border-dashed bg-transparent':
|
||||
indicator === 'dashed',
|
||||
'my-0.5': nestLabel && indicator === 'dashed',
|
||||
},
|
||||
)}
|
||||
className={cn('border-neutral-5 bg-neutral-2 shrink-0 rounded-[2px]', {
|
||||
'h-2.5 w-2.5': indicator === 'dot',
|
||||
'w-1': indicator === 'line',
|
||||
'w-0 border-[1.5px] border-dashed bg-transparent':
|
||||
indicator === 'dashed',
|
||||
'my-0.5': nestLabel && indicator === 'dashed',
|
||||
})}
|
||||
style={
|
||||
{
|
||||
'--color-bg': indicatorColor,
|
||||
|
|
@ -215,12 +212,10 @@ const ChartTooltipContent = React.forwardRef<
|
|||
>
|
||||
<div className="grid gap-1.5">
|
||||
{nestLabel ? tooltipLabel : null}
|
||||
<span className="text-muted-foreground">
|
||||
{itemConfig?.label || item.name}
|
||||
</span>
|
||||
<span className="text-neutral-10">{itemConfig?.label || item.name}</span>
|
||||
</div>
|
||||
{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()}
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -269,7 +264,7 @@ const ChartLegendContent = React.forwardRef<
|
|||
return (
|
||||
<div
|
||||
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 />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const Checkbox = React.forwardRef<
|
|||
<CheckboxPrimitive.Root
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export const Code: FC<ComponentProps<'code'>> = ({ children, className, ...props
|
|||
return (
|
||||
<span
|
||||
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.
|
||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
||||
tabIndex={0}
|
||||
|
|
@ -40,7 +40,7 @@ export const Code: FC<ComponentProps<'code'>> = ({ children, className, ...props
|
|||
<button
|
||||
hidden={!navigatorClipboardSupport}
|
||||
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 => {
|
||||
const value = children?.valueOf().toString();
|
||||
if (value) {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const Command = React.forwardRef<
|
|||
<CommandPrimitive
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -26,7 +26,7 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
|||
return (
|
||||
<Dialog {...props}>
|
||||
<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}
|
||||
</Command>
|
||||
</DialogContent>
|
||||
|
|
@ -42,12 +42,12 @@ const CommandInput = React.forwardRef<
|
|||
React.ElementRef<typeof CommandPrimitive.Input>,
|
||||
CommandInputProps
|
||||
>(({ 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" />
|
||||
<CommandPrimitive.Input
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -86,7 +86,7 @@ const CommandGroup = React.forwardRef<
|
|||
<CommandPrimitive.Group
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -101,7 +101,7 @@ const CommandSeparator = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<CommandPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn('bg-border -mx-1 h-px', className)}
|
||||
className={cn('bg-neutral-5 -mx-1 h-px', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
|
@ -114,7 +114,7 @@ const CommandItem = React.forwardRef<
|
|||
<CommandPrimitive.Item
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -125,10 +125,7 @@ CommandItem.displayName = CommandPrimitive.Item.displayName;
|
|||
|
||||
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
|
||||
{...props}
|
||||
/>
|
||||
<span className={cn('text-neutral-10 ml-auto text-xs tracking-widest', className)} {...props} />
|
||||
);
|
||||
};
|
||||
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="space-y-2">
|
||||
<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
|
||||
</Label>
|
||||
<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 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
|
||||
</Label>
|
||||
<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>
|
||||
{showCalendar && (
|
||||
<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
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const DialogOverlay = React.forwardRef<
|
|||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -37,15 +37,15 @@ const DialogContent = React.forwardRef<
|
|||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
{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">
|
||||
<X className="size-4" />
|
||||
<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="hover:text-neutral-12 text-neutral-11 size-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
)}
|
||||
|
|
@ -73,7 +73,7 @@ const DialogTitle = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title
|
||||
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}
|
||||
/>
|
||||
));
|
||||
|
|
@ -85,7 +85,7 @@ const DialogDescription = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
className={cn('text-neutral-11 text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -18,18 +18,18 @@ export const DocsNote = ({
|
|||
<div
|
||||
className={cn(
|
||||
'my-2 flex border-l-2 px-4 py-2',
|
||||
warn ? 'border-orange-500' : 'border-white',
|
||||
warn ? 'border-neutral-2' : 'border-neutral-12',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{/* <div className="items-center align-middle pr-2 flex flex-row">
|
||||
{warn ? (
|
||||
<ExclamationTriangleIcon className="text-orange-500" />
|
||||
<ExclamationTriangleIcon className="text-neutral-2" />
|
||||
) : (
|
||||
<InfoCircledIcon className="text-current" />
|
||||
)}
|
||||
</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>
|
||||
);
|
||||
};
|
||||
|
|
@ -52,7 +52,7 @@ export const DocsLink = ({
|
|||
asChild
|
||||
variant="link"
|
||||
className={cn(
|
||||
'p-0 text-orange-500',
|
||||
'p-0',
|
||||
'whitespace-pre-wrap', // to not lose whitespace between tags due to `display: 'inline-flex'`
|
||||
className,
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ export function DottedBackground(props: { children: React.ReactNode; className?:
|
|||
return (
|
||||
<div
|
||||
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,
|
||||
)}
|
||||
>
|
||||
<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}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
|||
<DropdownMenuPrimitive.SubTrigger
|
||||
ref={ref}
|
||||
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',
|
||||
className,
|
||||
)}
|
||||
|
|
@ -39,7 +39,7 @@ const DropdownMenuSubContent = React.forwardRef<
|
|||
<DropdownMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -56,7 +56,7 @@ const DropdownMenuContent = React.forwardRef<
|
|||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -75,9 +75,9 @@ const DropdownMenuItem = React.forwardRef<
|
|||
<DropdownMenuPrimitive.Item
|
||||
ref={ref}
|
||||
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',
|
||||
active && 'bg-accent text-orange-500',
|
||||
active && 'bg-neutral-5 text-neutral-12',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -92,7 +92,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
|||
<DropdownMenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
checked={checked}
|
||||
|
|
@ -115,7 +115,7 @@ const DropdownMenuRadioItem = React.forwardRef<
|
|||
<DropdownMenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -150,7 +150,7 @@ const DropdownMenuSeparator = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Separator
|
||||
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}
|
||||
/>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export const EmptyList = ({
|
|||
className="drag-none"
|
||||
/>
|
||||
<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}
|
||||
{docsUrl && <DocsLink href={docsUrl}>Read about it in the documentation</DocsLink>}
|
||||
</Card>
|
||||
|
|
@ -66,7 +66,7 @@ export const NoSchemaVersion = ({
|
|||
if (recommendedAction === 'check') {
|
||||
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
|
||||
registry before publishing.
|
||||
</div>
|
||||
|
|
@ -81,7 +81,7 @@ export const NoSchemaVersion = ({
|
|||
children = (
|
||||
<>
|
||||
{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
|
||||
deployed.
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -84,7 +84,14 @@ const FormLabel = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => {
|
||||
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';
|
||||
|
||||
|
|
@ -100,7 +107,7 @@ const FormControl = React.forwardRef<
|
|||
id={formItemId}
|
||||
aria-describedby={error ? `${formDescriptionId} ${formMessageId}` : formDescriptionId}
|
||||
aria-invalid={!!error}
|
||||
className={cn(error && 'border-destructive')}
|
||||
className={cn(error && 'border-red-500')}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
@ -117,7 +124,7 @@ const FormDescription = React.forwardRef<
|
|||
<p
|
||||
ref={ref}
|
||||
id={formDescriptionId}
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
className={cn('text-neutral-10 text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
@ -135,7 +142,7 @@ const FormMessage = React.forwardRef<
|
|||
<p
|
||||
ref={ref}
|
||||
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}
|
||||
>
|
||||
{body}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const Heading = ({
|
|||
return (
|
||||
<HeadingLevel
|
||||
className={clsx(
|
||||
'cursor-default text-white',
|
||||
'text-neutral-12 cursor-default',
|
||||
{
|
||||
lg: 'text-lg font-bold',
|
||||
xl: 'text-xl font-bold',
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const HoverCardContent = React.forwardRef<
|
|||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
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,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ export const HiveLogo = ({
|
|||
viewBox="0 0 112 112"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={clsx('inline fill-none', className)}
|
||||
className={clsx('fill-neutral-12 inline', className)}
|
||||
{...(animated
|
||||
? {
|
||||
whileHover: { scale: 1.1 },
|
||||
|
|
@ -411,10 +411,12 @@ export const HiveLogo = ({
|
|||
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"
|
||||
fill="white"
|
||||
className="fill-neutral-12"
|
||||
/>
|
||||
<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"
|
||||
fill="white"
|
||||
className="fill-neutral-12"
|
||||
/>
|
||||
</motion.svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export function InputCopy(props: { value: string; className?: string; multiline?
|
|||
readOnly
|
||||
autoSize
|
||||
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">
|
||||
|
|
@ -41,7 +41,7 @@ export function InputCopy(props: { value: string; className?: string; multiline?
|
|||
type="text"
|
||||
value={props.value}
|
||||
readOnly
|
||||
className={`bg-secondary truncate text-white ${props.className}`}
|
||||
className={`bg-neutral-2 text-neutral-12 truncate ${props.className}`}
|
||||
onFocus={ev => ev.target.select()}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -51,7 +51,7 @@ export function InputCopy(props: { value: string; className?: string; multiline?
|
|||
onClick={handleClick}
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="bg-secondary size-10 shrink-0 self-baseline"
|
||||
className="bg-neutral-2 size-10 shrink-0 self-baseline"
|
||||
>
|
||||
{isCopied ? (
|
||||
<CheckIcon className="size-4 text-emerald-500" />
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||
<input
|
||||
type={type}
|
||||
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,
|
||||
)}
|
||||
ref={ref}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { cn } from '@/lib/utils';
|
|||
import * as LabelPrimitive from '@radix-ui/react-label';
|
||||
|
||||
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<
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import { LinkOptions, RegisteredRouter, Link as RouterLink } from '@tanstack/rea
|
|||
const linkVariants = cva('font-medium transition-colors', {
|
||||
variants: {
|
||||
variant: {
|
||||
primary: 'text-orange-500 hover:underline',
|
||||
secondary: 'text-gray-500 hover:text-gray-300',
|
||||
primary: 'text-accent hover:underline',
|
||||
secondary: 'text-neutral-10 hover:text-neutral-11',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue