mirror of
https://github.com/graphql-hive/console
synced 2026-05-24 01:28:32 +00:00
(6) Drop V2: Callout component (#5319)
This commit is contained in:
parent
c153264c45
commit
f85d177767
8 changed files with 118 additions and 84 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { ReactElement } from 'react';
|
||||
import { Callout } from '@/components/v2';
|
||||
import { Callout } from '@/components/ui/callout';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
|
||||
const ProPlanBilling_OrganizationFragment = graphql(`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { ReactElement } from 'react';
|
||||
import { Callout } from '@/components/v2';
|
||||
import { Callout } from '@/components/ui/callout';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { BillingPlanType } from '@/gql/graphql';
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import {
|
|||
SchemaPolicyInput,
|
||||
} from '@/gql/graphql';
|
||||
import type { ResultOf } from '@graphql-typed-document-node/core';
|
||||
import { Callout, DataWrapper } from '../v2';
|
||||
import { Callout } from '../ui/callout';
|
||||
import { DataWrapper } from '../v2';
|
||||
import { PolicyListItem } from './policy-list-item';
|
||||
import { buildValidationSchema, PolicyFormValues } from './rules-configuration';
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { useForm, UseFormReturn } from 'react-hook-form';
|
|||
import { useMutation, useQuery } from 'urql';
|
||||
import { z } from 'zod';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Callout } from '@/components/ui/callout';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -20,7 +21,6 @@ import {
|
|||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Callout } from '@/components/v2';
|
||||
import { graphql } from '@/gql';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
|
||||
|
|
|
|||
65
packages/web/app/src/components/ui/callout.tsx
Normal file
65
packages/web/app/src/components/ui/callout.tsx
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import React from 'react';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
import { cn } from '@/lib/utils';
|
||||
import {
|
||||
CrossCircledIcon,
|
||||
ExclamationTriangleIcon,
|
||||
InfoCircledIcon,
|
||||
LightningBoltIcon,
|
||||
} from '@radix-ui/react-icons';
|
||||
|
||||
const TypeToEmoji = {
|
||||
default: <LightningBoltIcon className="h-6 w-auto" />,
|
||||
error: <CrossCircledIcon className="h-6 w-auto" />,
|
||||
info: <InfoCircledIcon className="h-6 w-auto" />,
|
||||
warning: <ExclamationTriangleIcon className="h-6 w-auto" />,
|
||||
};
|
||||
|
||||
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-100 bg-orange-50 text-orange-800 dark:border-orange-400/30 dark:bg-orange-400/20 dark:text-orange-300',
|
||||
error:
|
||||
'border-red-200 bg-red-100 text-red-900 dark:border-red-200/30 dark:bg-red-900/30 dark:text-red-200',
|
||||
info: 'border-blue-200 bg-blue-100 text-blue-900 dark:border-blue-200/30 dark:bg-blue-900/30 dark:text-blue-200',
|
||||
warning:
|
||||
'border-yellow-100 bg-yellow-50 text-yellow-900 dark:border-yellow-200/30 dark:bg-yellow-700/30 dark:text-yellow-200',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
type: 'default',
|
||||
},
|
||||
});
|
||||
|
||||
type CalloutProps = {
|
||||
type?: CalloutType;
|
||||
emoji?: string | React.ReactElement;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const Callout = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
CalloutProps & VariantProps<typeof calloutVariants>
|
||||
>(({ children, type = 'default', emoji = TypeToEmoji[type], className, ...props }, ref) => {
|
||||
return (
|
||||
<div ref={ref} className={cn(calloutVariants({ type }), className)} {...props}>
|
||||
<div
|
||||
className="select-none text-xl"
|
||||
style={{
|
||||
fontFamily: '"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
|
||||
}}
|
||||
>
|
||||
{emoji}
|
||||
</div>
|
||||
<div className="w-full min-w-0 leading-7">{children}</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Callout.displayName = 'Callout';
|
||||
|
||||
export { Callout };
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import type { ReactElement, ReactNode } from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { InfoCircledIcon } from '@radix-ui/react-icons';
|
||||
|
||||
const TypeToEmoji = {
|
||||
default: '💡',
|
||||
error: '🚫',
|
||||
info: <InfoCircledIcon className="h-6 w-auto" />,
|
||||
warning: '⚠️',
|
||||
};
|
||||
|
||||
type CalloutType = keyof typeof TypeToEmoji;
|
||||
|
||||
const classes: Record<CalloutType, string> = {
|
||||
default: cn(
|
||||
'border-orange-100 bg-orange-50 text-orange-800 dark:border-orange-400/30 dark:bg-orange-400/20 dark:text-orange-300',
|
||||
),
|
||||
error: cn(
|
||||
'border-red-200 bg-red-100 text-red-900 dark:border-red-200/30 dark:bg-red-900/30 dark:text-red-200',
|
||||
),
|
||||
info: cn(
|
||||
'border-blue-200 bg-blue-100 text-blue-900 dark:border-blue-200/30 dark:bg-blue-900/30 dark:text-blue-200',
|
||||
),
|
||||
warning: cn(
|
||||
'border-yellow-100 bg-yellow-50 text-yellow-900 dark:border-yellow-200/30 dark:bg-yellow-700/30 dark:text-yellow-200',
|
||||
),
|
||||
};
|
||||
|
||||
type CalloutProps = {
|
||||
type?: CalloutType;
|
||||
emoji?: string | ReactElement;
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export function Callout({
|
||||
children,
|
||||
type = 'default',
|
||||
emoji = TypeToEmoji[type],
|
||||
className,
|
||||
}: CalloutProps): ReactElement {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'mt-6 flex items-center gap-4 rounded-lg border px-4 py-2',
|
||||
classes[type],
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="select-none text-xl"
|
||||
style={{
|
||||
fontFamily: '"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
|
||||
}}
|
||||
>
|
||||
{emoji}
|
||||
</div>
|
||||
<div className="w-full min-w-0 leading-7">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
export { Accordion } from '@/components/v2/accordion';
|
||||
export { Autocomplete } from '@/components/v2/autocomplete';
|
||||
export { Avatar } from '@/components/v2/avatar';
|
||||
export { Callout } from '@/components/v2/callout';
|
||||
export { Card } from '@/components/v2/card';
|
||||
export { Checkbox } from '@/components/v2/checkbox';
|
||||
export { CopyValue } from '@/components/v2/copy-value';
|
||||
|
|
|
|||
|
|
@ -1,37 +1,67 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Callout } from '../components/v2/callout';
|
||||
import { Callout } from '@/components/ui/callout';
|
||||
import {
|
||||
CrossCircledIcon,
|
||||
ExclamationTriangleIcon,
|
||||
InfoCircledIcon,
|
||||
LightningBoltIcon,
|
||||
} from '@radix-ui/react-icons';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
const meta: Meta<typeof Callout> = {
|
||||
title: 'Callout',
|
||||
title: 'Components/Callout',
|
||||
component: Callout,
|
||||
argTypes: {
|
||||
type: {
|
||||
control: { type: 'inline-radio' },
|
||||
options: ['default', 'error', 'info', 'warning'],
|
||||
},
|
||||
emoji: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
children: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
className: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
},
|
||||
args: {
|
||||
type: 'default',
|
||||
children: 'This is a callout',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof Callout>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: () => <Callout>Hello</Callout>,
|
||||
args: {
|
||||
type: 'default',
|
||||
emoji: <LightningBoltIcon className="h-6 w-auto" />,
|
||||
},
|
||||
};
|
||||
|
||||
export const Error: Story = {
|
||||
render: () => <Callout type="error">Hello</Callout>,
|
||||
args: {
|
||||
type: 'error',
|
||||
emoji: <CrossCircledIcon className="h-6 w-auto" />,
|
||||
children: 'This is an error callout',
|
||||
},
|
||||
};
|
||||
|
||||
export const Info: Story = {
|
||||
render: () => <Callout type="info">Hello</Callout>,
|
||||
args: {
|
||||
type: 'info',
|
||||
emoji: <InfoCircledIcon className="h-6 w-auto" />,
|
||||
children: 'This is an info callout',
|
||||
},
|
||||
};
|
||||
|
||||
export const Warning: Story = {
|
||||
render: () => <Callout type="warning">Hello</Callout>,
|
||||
};
|
||||
|
||||
export const Long: Story = {
|
||||
render: () => (
|
||||
<Callout type="warning">
|
||||
<b>Your organization is being rate-limited for operations.</b>
|
||||
<br />
|
||||
Since you reached your organization rate-limit and data ingestion limitation, your
|
||||
organization <b>The Guild</b> is currently unable to ingest data.
|
||||
</Callout>
|
||||
),
|
||||
args: {
|
||||
type: 'warning',
|
||||
emoji: <ExclamationTriangleIcon className="h-6 w-auto" />,
|
||||
children: 'This is a warning callout',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue