mirror of https://github.com/buster-so/buster.git
make avatar
This commit is contained in:
parent
bf377b5c80
commit
715132a7bc
|
@ -17,6 +17,7 @@
|
|||
"@manufac/echarts-simple-transform": "^2.0.11",
|
||||
"@million/lint": "^1.0.14",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@radix-ui/react-avatar": "^1.1.3",
|
||||
"@radix-ui/react-checkbox": "^1.1.4",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||
"@radix-ui/react-popover": "^1.1.6",
|
||||
|
@ -5626,6 +5627,32 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-avatar": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.3.tgz",
|
||||
"integrity": "sha512-Paen00T4P8L8gd9bNsRMw7Cbaz85oxiv+hzomsRZgFm2byltPFDtfcoqlWJ8GyZlIBWgLssJlzLCnKU0G0302g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-context": "1.1.1",
|
||||
"@radix-ui/react-primitive": "2.0.2",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-checkbox": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.4.tgz",
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"@manufac/echarts-simple-transform": "^2.0.11",
|
||||
"@million/lint": "^1.0.14",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@radix-ui/react-avatar": "^1.1.3",
|
||||
"@radix-ui/react-checkbox": "^1.1.4",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||
"@radix-ui/react-popover": "^1.1.6",
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Avatar } from './Avatar';
|
||||
|
||||
const meta = {
|
||||
title: 'Base/Avatar',
|
||||
component: Avatar,
|
||||
parameters: {
|
||||
layout: 'centered'
|
||||
},
|
||||
tags: ['autodocs']
|
||||
} satisfies Meta<typeof Avatar>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Avatar>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
name: 'John Doe'
|
||||
}
|
||||
};
|
||||
|
||||
export const WithImage: Story = {
|
||||
args: {
|
||||
name: 'John Doe',
|
||||
image: 'https://github.com/shadcn.png'
|
||||
}
|
||||
};
|
||||
|
||||
export const WithTooltip: Story = {
|
||||
args: {
|
||||
name: 'John Doe',
|
||||
useToolTip: true
|
||||
}
|
||||
};
|
||||
|
||||
export const CustomClassName: Story = {
|
||||
args: {
|
||||
name: 'John Doe',
|
||||
className: 'h-12 w-12'
|
||||
}
|
||||
};
|
||||
|
||||
export const SingleLetter: Story = {
|
||||
args: {
|
||||
name: 'John'
|
||||
}
|
||||
};
|
||||
|
||||
export const NoName: Story = {
|
||||
args: {}
|
||||
};
|
|
@ -0,0 +1,54 @@
|
|||
import React from 'react';
|
||||
import { Avatar as AvatarBase, AvatarFallback, AvatarImage } from './AvatarBase';
|
||||
import { getFirstTwoCapitalizedLetters } from '@/lib/text';
|
||||
import { Tooltip } from '../tooltip/Tooltip';
|
||||
import { BusterLogo } from '@/assets/svg/BusterLogo';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export interface BusterUserAvatarProps {
|
||||
image?: string;
|
||||
name?: string | null;
|
||||
className?: string;
|
||||
useToolTip?: boolean;
|
||||
}
|
||||
|
||||
export const Avatar: React.FC<BusterUserAvatarProps> = React.memo(
|
||||
({ image, name, className, useToolTip }) => {
|
||||
const hasName = !!name;
|
||||
const nameLetters = hasName ? createNameLetters(name, image) : '';
|
||||
|
||||
return (
|
||||
<Tooltip title={useToolTip ? nameLetters : ''}>
|
||||
<AvatarBase className={className}>
|
||||
{image && <AvatarImage src={image} />}
|
||||
<AvatarFallback className={cn(!hasName && 'border bg-white')}>
|
||||
{nameLetters || <BusterAvatarFallback />}
|
||||
</AvatarFallback>
|
||||
</AvatarBase>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
);
|
||||
Avatar.displayName = 'Avatar';
|
||||
|
||||
const BusterAvatarFallback: React.FC = () => {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center text-black dark:text-white">
|
||||
<BusterLogo className="h-full w-full" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const createNameLetters = (name?: string | null, image?: string | null | React.ReactNode) => {
|
||||
if (name && !image) {
|
||||
const firstTwoLetters = getFirstTwoCapitalizedLetters(name);
|
||||
if (firstTwoLetters.length == 2) return firstTwoLetters;
|
||||
|
||||
//Get First Name Initial
|
||||
const _name = name.split(' ') as [string, string];
|
||||
const returnName = `${_name[0][0]}`.toUpperCase().replace('@', '');
|
||||
|
||||
return returnName;
|
||||
}
|
||||
return '';
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const Avatar = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn('relative flex h-7 w-7 shrink-0 overflow-hidden rounded-full', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
||||
|
||||
const AvatarImage = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Image>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Image
|
||||
ref={ref}
|
||||
className={cn('aspect-square h-full w-full', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
||||
|
||||
const AvatarFallback = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Fallback
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'bg-gray-light/70 text-background flex h-full w-full items-center justify-center rounded-full text-base',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
||||
|
||||
export { Avatar, AvatarImage, AvatarFallback };
|
|
@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
|||
import { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } from './CardBase';
|
||||
|
||||
const meta = {
|
||||
title: 'Base/Card',
|
||||
title: 'Base/Cards/Card',
|
||||
component: Card,
|
||||
parameters: {
|
||||
layout: 'centered'
|
||||
|
|
|
@ -4,7 +4,7 @@ import { BellOutlined } from '@ant-design/icons';
|
|||
import { faker } from '@faker-js/faker';
|
||||
|
||||
const meta: Meta<typeof InfoCard> = {
|
||||
title: 'Base/InfoCard',
|
||||
title: 'Base/Cards/InfoCard',
|
||||
component: InfoCard,
|
||||
tags: ['autodocs'],
|
||||
args: {
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
import { createStyles } from 'antd-style';
|
||||
import React from 'react';
|
||||
|
||||
const useStyles = createStyles(({ token, css }) => ({
|
||||
container: css`
|
||||
border-radius: ${token.borderRadius}px;
|
||||
border: 0.5px solid ${token.colorBorder};
|
||||
`,
|
||||
header: css`
|
||||
color: ${token.colorText};
|
||||
background: ${token.controlItemBgActive};
|
||||
border-bottom: 0.5px solid ${token.colorBorder};
|
||||
height: 36px;
|
||||
`,
|
||||
body: css`
|
||||
background: ${token.colorBgBase};
|
||||
`
|
||||
}));
|
||||
|
||||
export const ItemContainer: React.FC<{
|
||||
children: React.ReactNode;
|
||||
title: string | React.ReactNode;
|
||||
bodyClass?: string;
|
||||
className?: string;
|
||||
}> = ({ className = '', bodyClass = '', children, title }) => {
|
||||
const { styles, cx } = useStyles();
|
||||
|
||||
return (
|
||||
<div className={cx(styles.container, className)}>
|
||||
<div className={cx(styles.header, 'flex items-center py-1 pr-3 pl-4')}>{title}</div>
|
||||
<div className={cx(styles.body, bodyClass || 'px-4 py-5')}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -19,6 +19,8 @@ export interface TooltipProps
|
|||
|
||||
export const Tooltip = React.memo<TooltipProps>(
|
||||
({ children, title, shortcut, delayDuration, skipDelayDuration, align, side, open }) => {
|
||||
if (!title && !shortcut?.length) return children;
|
||||
|
||||
return (
|
||||
<TooltipProvider delayDuration={delayDuration} skipDelayDuration={skipDelayDuration}>
|
||||
<TooltipBase open={open}>
|
||||
|
|
|
@ -11,10 +11,17 @@ import { useAntToken } from '@/styles/useAntToken';
|
|||
import { AppCodeEditor } from '@/components/ui/inputs/AppCodeEditor';
|
||||
import clamp from 'lodash/clamp';
|
||||
import { MenuProps } from 'antd/lib';
|
||||
import { ItemContainer } from '@/components/ui/card/ItemContainer';
|
||||
import { Text } from '@/components/ui';
|
||||
import { BusterRoutes } from '@/routes';
|
||||
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
CardContent
|
||||
} from '@/components/ui/card/CardBase';
|
||||
|
||||
export const TermIndividualContent: React.FC<{
|
||||
termId: string;
|
||||
|
@ -209,3 +216,16 @@ const MoreDropdown: React.FC<{ termId: string; setEditingTermName: (value: boole
|
|||
</Dropdown>
|
||||
);
|
||||
};
|
||||
|
||||
const ItemContainer: React.FC<{
|
||||
title: string | React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}> = ({ title, children, className }) => {
|
||||
return (
|
||||
<Card className={className}>
|
||||
<CardHeader variant={'gray'}>{title}</CardHeader>
|
||||
<CardContent>{children}</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue