mirror of https://github.com/buster-so/buster.git
code card update
Update toaster naming Update BusterNotifications.tsx Update BusterChart.tsx remove theme detector
This commit is contained in:
parent
4b4ba2e21e
commit
61916ce7ce
|
@ -30,9 +30,9 @@ const roundingVariants = {
|
|||
};
|
||||
|
||||
const sizeVariants = {
|
||||
default: 'h-7',
|
||||
tall: 'h-8',
|
||||
small: 'h-6'
|
||||
default: 'h-6',
|
||||
tall: 'h-7',
|
||||
small: 'h-5'
|
||||
};
|
||||
|
||||
export const buttonVariants = cva(
|
||||
|
|
|
@ -5,6 +5,7 @@ import { cn } from '@/lib/utils';
|
|||
const sizeVariants = cva('', {
|
||||
variants: {
|
||||
size: {
|
||||
xsmall: 'h-[32px] min-h-[32px] px-2.5',
|
||||
small: 'p-2.5',
|
||||
default: 'p-4'
|
||||
}
|
||||
|
@ -19,7 +20,7 @@ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElemen
|
|||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'bg-background text-foreground overflow-hidden rounded border shadow',
|
||||
'bg-background text-foreground flex flex-col overflow-hidden rounded border shadow',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { CodeCard } from './CodeCard';
|
||||
|
||||
const meta: Meta<typeof CodeCard> = {
|
||||
title: 'Base/Cards/CodeCard',
|
||||
component: CodeCard,
|
||||
parameters: {
|
||||
layout: 'centered'
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div className="w-full min-w-[500px]">
|
||||
<Story />
|
||||
</div>
|
||||
)
|
||||
]
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof CodeCard>;
|
||||
|
||||
const sampleCode = `function helloWorld() {
|
||||
console.log('Hello, World!');
|
||||
}`;
|
||||
|
||||
const longCode = `import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
|
||||
export const MyComponent = () => {
|
||||
const handleClick = () => {
|
||||
console.log('Button clicked!');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<h1>Hello World</h1>
|
||||
<Button onClick={handleClick}>
|
||||
Click me
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};`;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
code: sampleCode,
|
||||
language: 'javascript',
|
||||
fileName: 'example.js',
|
||||
className: 'w-[500px] h-[300px]'
|
||||
}
|
||||
};
|
||||
|
||||
export const ReadOnly: Story = {
|
||||
args: {
|
||||
code: sampleCode,
|
||||
language: 'javascript',
|
||||
fileName: 'readonly.js',
|
||||
readOnly: true,
|
||||
className: 'w-[500px] h-[300px]'
|
||||
}
|
||||
};
|
||||
|
||||
export const LargerEditor: Story = {
|
||||
args: {
|
||||
code: longCode,
|
||||
language: 'typescript',
|
||||
fileName: 'MyComponent.tsx',
|
||||
className: 'w-[600px] h-[400px]'
|
||||
}
|
||||
};
|
||||
|
||||
export const NoButtons: Story = {
|
||||
args: {
|
||||
code: sampleCode,
|
||||
language: 'javascript',
|
||||
fileName: 'no-buttons.js',
|
||||
buttons: false,
|
||||
className: 'w-[500px] h-[300px]'
|
||||
}
|
||||
};
|
||||
|
||||
export const CustomButtons: Story = {
|
||||
args: {
|
||||
code: sampleCode,
|
||||
language: 'javascript',
|
||||
fileName: 'custom-buttons.js',
|
||||
buttons: <div className="px-2">Custom Buttons</div>,
|
||||
className: 'w-[500px] h-[300px]'
|
||||
}
|
||||
};
|
|
@ -1,11 +1,11 @@
|
|||
import { createStyles } from 'antd-style';
|
||||
import React from 'react';
|
||||
import { Text } from '@/components/ui';
|
||||
import { AppCodeEditor } from '../inputs/AppCodeEditor';
|
||||
import { Button } from 'antd';
|
||||
import { AppMaterialIcons } from '../icons';
|
||||
import { AppCodeEditor } from '../inputs/AppCodeEditor/AppCodeEditor';
|
||||
import { Download, Copy } from '../icons';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
import { Button } from '../buttons/Button';
|
||||
import { Card, CardHeader, CardContent, CardDescription, CardFooter, CardTitle } from './CardBase';
|
||||
|
||||
export const CodeCard: React.FC<{
|
||||
code: string;
|
||||
|
@ -28,22 +28,17 @@ export const CodeCard: React.FC<{
|
|||
onChange,
|
||||
readOnly = false
|
||||
}) => {
|
||||
const { styles, cx } = useStyles();
|
||||
|
||||
const ShownButtons = buttons === true ? <CardButtons fileName={fileName} code={code} /> : buttons;
|
||||
|
||||
return (
|
||||
<div className={cx(styles.container, className)}>
|
||||
<div
|
||||
className={cx(
|
||||
styles.containerHeader,
|
||||
'flex items-center justify-between space-x-1 px-2.5'
|
||||
)}>
|
||||
<Text className="truncate">{fileName}</Text>
|
||||
|
||||
{ShownButtons}
|
||||
</div>
|
||||
<div className={cx(styles.containerBody, bodyClassName)}>
|
||||
<Card className={cn('h-full', className)}>
|
||||
<CardHeader variant={'gray'} size={'xsmall'} className="justify-center">
|
||||
<div className="flex items-center justify-between gap-x-1">
|
||||
<span className="truncate text-base">{fileName}</span>
|
||||
{ShownButtons}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className={cn('bg-background overflow-hidden p-0', bodyClassName)}>
|
||||
<AppCodeEditor
|
||||
language={language}
|
||||
value={code}
|
||||
|
@ -52,8 +47,8 @@ export const CodeCard: React.FC<{
|
|||
height="100%"
|
||||
onMetaEnter={onMetaEnter}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -90,15 +85,10 @@ const CardButtons: React.FC<{
|
|||
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
<Button variant="ghost" prefix={<Copy />} onClick={handleCopyCode} title="Copy code" />
|
||||
<Button
|
||||
type="text"
|
||||
icon={<AppMaterialIcons icon="content_copy" />}
|
||||
onClick={handleCopyCode}
|
||||
title="Copy code"
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<AppMaterialIcons icon="download" />}
|
||||
variant="ghost"
|
||||
prefix={<Download />}
|
||||
onClick={handleDownload}
|
||||
title="Download file"
|
||||
/>
|
||||
|
@ -106,18 +96,3 @@ const CardButtons: React.FC<{
|
|||
);
|
||||
});
|
||||
CardButtons.displayName = 'CardButtons';
|
||||
|
||||
const useStyles = createStyles(({ token, css }) => ({
|
||||
container: css`
|
||||
border-radius: ${token.borderRadius}px;
|
||||
border: 0.5px solid ${token.colorBorder};
|
||||
`,
|
||||
containerHeader: css`
|
||||
background: ${token.controlItemBgActive};
|
||||
border-bottom: 0.5px solid ${token.colorBorder};
|
||||
height: 32px;
|
||||
`,
|
||||
containerBody: css`
|
||||
background: ${token.colorBgBase};
|
||||
`
|
||||
}));
|
||||
|
|
|
@ -153,7 +153,7 @@ export const BusterChart: React.FC<BusterChartProps> = React.memo(
|
|||
|
||||
return (
|
||||
<BusterChartErrorWrapper>
|
||||
<BusterChartWrapper id={id} className={className} bordered={bordered} loading={loading}>
|
||||
<BusterChartWrapper id={id} className={className} loading={loading}>
|
||||
{SwitchComponent()}
|
||||
</BusterChartWrapper>
|
||||
</BusterChartErrorWrapper>
|
||||
|
|
|
@ -36,5 +36,3 @@ export const CircleSpinnerLoader: React.FC<{
|
|||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CircleSpinnerLoader;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import CircleSpinnerLoader from './CircleSpinnerLoader';
|
||||
import { Text } from '@/components/ui';
|
||||
import { CircleSpinnerLoader } from './CircleSpinnerLoader';
|
||||
|
||||
export const CircleSpinnerLoaderContainer: React.FC<{
|
||||
text?: string;
|
||||
|
@ -9,7 +8,7 @@ export const CircleSpinnerLoaderContainer: React.FC<{
|
|||
return (
|
||||
<div className={`flex h-full w-full flex-col items-center justify-center ${className}`}>
|
||||
<CircleSpinnerLoader />
|
||||
{text && <Text className="mt-3">{text}</Text>}
|
||||
{text && <span className="mt-3 text-base">{text}</span>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { BusterNotificationsProvider } from '@/context/BusterNotifications';
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||
|
||||
|
@ -84,11 +83,7 @@ const meta: Meta<typeof TestComponent> = {
|
|||
},
|
||||
decorators: [
|
||||
(Story) => {
|
||||
return (
|
||||
<BusterNotificationsProvider>
|
||||
<Story />
|
||||
</BusterNotificationsProvider>
|
||||
);
|
||||
return <Story />;
|
||||
}
|
||||
]
|
||||
};
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
import React from 'react';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { Toaster } from 'sonner';
|
||||
import { CircleCheck } from '@/components/ui/icons';
|
||||
import { Toaster as SonnerToaster } from 'sonner';
|
||||
import { CircleCheck, CircleXmark, CircleWarning } from '@/components/ui/icons';
|
||||
|
||||
type ToasterProps = React.ComponentProps<typeof Toaster>;
|
||||
type ToasterProps = React.ComponentProps<typeof SonnerToaster>;
|
||||
|
||||
const AppToaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = 'system' } = useTheme();
|
||||
export const Toaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = 'light' } = useTheme();
|
||||
|
||||
return (
|
||||
<Toaster
|
||||
|
@ -16,7 +16,9 @@ const AppToaster = ({ ...props }: ToasterProps) => {
|
|||
expand={true}
|
||||
visibleToasts={5}
|
||||
icons={{
|
||||
success: <CircleCheck />
|
||||
success: <CircleCheck />,
|
||||
error: <CircleXmark />,
|
||||
warning: <CircleWarning />
|
||||
}}
|
||||
swipeDirections={['right']}
|
||||
theme={theme as ToasterProps['theme']}
|
||||
|
@ -24,8 +26,8 @@ const AppToaster = ({ ...props }: ToasterProps) => {
|
|||
toastOptions={{
|
||||
classNames: {
|
||||
toast:
|
||||
'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg',
|
||||
description: 'group-[.toast]:text-muted-foreground',
|
||||
'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-hard',
|
||||
description: 'group-[.toast]:text-foreground',
|
||||
actionButton: 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground',
|
||||
cancelButton: 'group-[.toast]:bg-border group-[.toast]:text-foreground'
|
||||
}
|
||||
|
@ -34,5 +36,3 @@ const AppToaster = ({ ...props }: ToasterProps) => {
|
|||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { AppToaster };
|
|
@ -1 +1 @@
|
|||
export * from './AppToaster';
|
||||
export * from './Toaster';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
// import { App, ModalFuncProps } from 'antd';
|
||||
import { toast, type ExternalToast } from 'sonner';
|
||||
// import { createStyles } from 'antd-style';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import {
|
||||
useContextSelector,
|
||||
|
@ -22,35 +22,7 @@ export interface NotificationProps {
|
|||
};
|
||||
}
|
||||
|
||||
// const useStyles = createStyles(({ token, css }) => ({
|
||||
// modal: css`
|
||||
// .busterv2-modal-body {
|
||||
// padding: 0px !important;
|
||||
// }
|
||||
|
||||
// .busterv2-modal-confirm-body {
|
||||
// padding: 24px 32px 16px 32px !important;
|
||||
// }
|
||||
|
||||
// .busterv2-modal-confirm-btns {
|
||||
// margin-top: 0px !important;
|
||||
// padding: 12px 32px !important;
|
||||
// border-top: 0.5px solid ${token.colorBorder};
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// justify-content: flex-end;
|
||||
// }
|
||||
|
||||
// .busterv2-modal-confirm-content {
|
||||
// color: ${token.colorTextSecondary} !important;
|
||||
// }
|
||||
// `
|
||||
// }));
|
||||
|
||||
export const useBusterNotificationsInternal = () => {
|
||||
// const { message, notification, modal } = App.useApp();
|
||||
// const { cx, styles } = useStyles();
|
||||
|
||||
const openNotification = useMemoizedFn((props: NotificationProps) => {
|
||||
const { title, message, type } = props;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
export * from './useThemeDetector';
|
||||
export * from './usePreventBackwardsNavigation';
|
||||
export * from './useIsShowingEllipsis';
|
||||
export * from './useBeforeUnload';
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import { ENABLE_DARK_MODE } from '@/context/BusterStyles/BusterStyles';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { useEffect, useLayoutEffect, useState } from 'react';
|
||||
import { isServer } from '@tanstack/react-query';
|
||||
|
||||
const DARK_MODE_MEDIA = '(prefers-color-scheme: dark)';
|
||||
|
||||
export const useThemeDetector = ({ addDarkClass }: { addDarkClass?: boolean }) => {
|
||||
const [isDarkTheme, setIsDarkTheme] = useState(() => getSystemTheme());
|
||||
|
||||
const getSystemTheme = (e?: MediaQueryList | MediaQueryListEvent) => {
|
||||
if (!ENABLE_DARK_MODE) return false;
|
||||
if (isServer) return false;
|
||||
if (!e) e = window.matchMedia(DARK_MODE_MEDIA);
|
||||
const isDark = e.matches;
|
||||
return isDark;
|
||||
};
|
||||
|
||||
const getCurrentTheme = useMemoizedFn(() => {
|
||||
if (!isServer) {
|
||||
document.documentElement.style.display = 'none';
|
||||
|
||||
const isDarkMode = getSystemTheme();
|
||||
|
||||
if (addDarkClass) {
|
||||
const d = document.documentElement;
|
||||
d.classList.toggle('dark', isDarkMode);
|
||||
d.classList.toggle('bg-black', isDarkMode);
|
||||
d.setAttribute('data-color-scheme', !isDarkMode ? 'light' : 'dark');
|
||||
}
|
||||
|
||||
// trigger reflow so that overflow style is applied
|
||||
document.documentElement.style.display = '';
|
||||
|
||||
return isDarkMode;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const mqListener = useMemoizedFn(() => {
|
||||
setIsDarkTheme(getCurrentTheme());
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const darkThemeMq = window.matchMedia(DARK_MODE_MEDIA);
|
||||
darkThemeMq.addEventListener('change', mqListener);
|
||||
return () => darkThemeMq.removeEventListener('change', mqListener);
|
||||
}, []);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setIsDarkTheme(getCurrentTheme());
|
||||
}, []);
|
||||
|
||||
return isDarkTheme;
|
||||
};
|
Loading…
Reference in New Issue