base
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { Badge } from "./badge";
|
||||
|
||||
const meta = {
|
||||
title: "Components/Badge",
|
||||
component: Badge,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
args: {
|
||||
children: "Badge",
|
||||
},
|
||||
} satisfies Meta<typeof Badge>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Neutral: Story = {
|
||||
args: {
|
||||
variant: "neutral",
|
||||
children: "Neutral Badge",
|
||||
},
|
||||
};
|
||||
|
||||
export const Brand: Story = {
|
||||
args: {
|
||||
variant: "brand",
|
||||
children: "Brand Badge",
|
||||
},
|
||||
};
|
||||
|
||||
export const Warning: Story = {
|
||||
args: {
|
||||
variant: "warning",
|
||||
children: "Warning Badge",
|
||||
},
|
||||
};
|
||||
|
||||
export const Success: Story = {
|
||||
args: {
|
||||
variant: "success",
|
||||
children: "Success Badge",
|
||||
},
|
||||
};
|
||||
|
||||
export const Danger: Story = {
|
||||
args: {
|
||||
variant: "danger",
|
||||
children: "Danger Badge",
|
||||
},
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
args: {
|
||||
size: "sm",
|
||||
children: "Small Badge",
|
||||
},
|
||||
};
|
||||
|
||||
export const Base: Story = {
|
||||
args: {
|
||||
size: "base",
|
||||
children: "Base Badge",
|
||||
},
|
||||
};
|
||||
|
||||
export const Large: Story = {
|
||||
args: {
|
||||
size: "lg",
|
||||
children: "Large Badge",
|
||||
},
|
||||
};
|
||||
|
||||
export const WithPrependIcon: Story = {
|
||||
args: {
|
||||
prependIcon: (
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M12 5v14m-7-7h14" />
|
||||
</svg>
|
||||
),
|
||||
children: "With Prepend Icon",
|
||||
},
|
||||
};
|
||||
|
||||
export const WithAppendIcon: Story = {
|
||||
args: {
|
||||
appendIcon: (
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
),
|
||||
children: "With Append Icon",
|
||||
},
|
||||
};
|
||||
|
||||
export const AllVariants: Story = {
|
||||
render() {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-16 font-semibold">Primary Variants</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Badge variant="neutral">Neutral</Badge>
|
||||
<Badge variant="brand">Brand</Badge>
|
||||
<Badge variant="warning">Warning</Badge>
|
||||
<Badge variant="success">Success</Badge>
|
||||
<Badge variant="danger">Danger</Badge>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const AllSizes: Story = {
|
||||
render() {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge size="sm">Small</Badge>
|
||||
<Badge size="base">Base</Badge>
|
||||
<Badge size="lg">Large</Badge>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import * as React from "react";
|
||||
import { cn } from "../utils";
|
||||
import type { BadgeProps } from "./helper";
|
||||
import { getBadgeIconStyling, badgeVariants } from "./helper";
|
||||
|
||||
const Badge = React.forwardRef(function Badge(props: BadgeProps, ref: React.ForwardedRef<HTMLSpanElement>) {
|
||||
const { variant = "neutral", size = "base", prependIcon = null, appendIcon = null, children, ...rest } = props;
|
||||
|
||||
const badgeIconStyle = getBadgeIconStyling(size ?? "base");
|
||||
|
||||
return (
|
||||
<span ref={ref} className={cn(badgeVariants({ variant, size }))} {...rest}>
|
||||
{prependIcon && React.cloneElement(prependIcon, { className: cn("shrink-0", badgeIconStyle), strokeWidth: 2 })}
|
||||
{children}
|
||||
{appendIcon && React.cloneElement(appendIcon, { className: cn("shrink-0", badgeIconStyle), strokeWidth: 2 })}
|
||||
</span>
|
||||
);
|
||||
});
|
||||
|
||||
Badge.displayName = "plane-ui-badge";
|
||||
|
||||
export { Badge };
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import type { VariantProps } from "class-variance-authority";
|
||||
import { cva } from "class-variance-authority";
|
||||
|
||||
export const badgeVariants = cva("inline-flex items-center justify-center gap-1 whitespace-nowrap transition-colors", {
|
||||
variants: {
|
||||
variant: {
|
||||
neutral: "bg-layer-3 text-tertiary",
|
||||
brand: "bg-accent-subtle-hover text-accent-primary",
|
||||
warning: "bg-warning-subtle text-warning-primary",
|
||||
success: "bg-success-subtle-1 text-success-primary",
|
||||
danger: "bg-danger-subtle text-danger-primary",
|
||||
},
|
||||
size: {
|
||||
sm: "h-4 rounded-sm px-1 text-caption-sm-medium",
|
||||
base: "h-5 rounded-md px-1.5 text-caption-sm-medium",
|
||||
lg: "h-6 rounded-md px-2 text-caption-md-medium",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "neutral",
|
||||
size: "base",
|
||||
},
|
||||
});
|
||||
|
||||
export type BadgeProps = Omit<React.HTMLAttributes<HTMLSpanElement>, "className"> &
|
||||
VariantProps<typeof badgeVariants> & {
|
||||
appendIcon?: React.ReactElement;
|
||||
prependIcon?: React.ReactElement;
|
||||
};
|
||||
|
||||
export type TBadgeVariant = NonNullable<BadgeProps["variant"]>;
|
||||
export type TBadgeSize = NonNullable<BadgeProps["size"]>;
|
||||
|
||||
const badgeIconStyling: Record<TBadgeSize, string> = {
|
||||
sm: "size-3.5",
|
||||
base: "size-3.5",
|
||||
lg: "size-4",
|
||||
};
|
||||
|
||||
export function getBadgeIconStyling(size: TBadgeSize): string {
|
||||
return badgeIconStyling[size];
|
||||
}
|
||||
|
||||
export function getBadgeStyling(variant: TBadgeVariant, size: TBadgeSize): string {
|
||||
return badgeVariants({ variant, size });
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
export { Badge } from "./badge";
|
||||
export { getBadgeStyling } from "./helper";
|
||||
export type { BadgeProps, TBadgeVariant, TBadgeSize } from "./helper";
|
||||
Reference in New Issue
Block a user