-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(chore/ui): Add Badge, Feedback, Image Card
- Loading branch information
Showing
25 changed files
with
765 additions
and
72 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import React from 'react'; | ||
import { ReactNode } from 'react'; | ||
|
||
/** | ||
* Enum representing the available variants for the Badge component. | ||
* The variants control the badge's appearance and color. | ||
*/ | ||
export enum BadgeVariant { | ||
default = "default", | ||
error = "error", | ||
success = "success", | ||
warning = "warning", | ||
reference = "reference", | ||
} | ||
|
||
/** | ||
* Props interface for the Badge component. | ||
* Defines the expected properties that can be passed into the component. | ||
*/ | ||
interface BadgeProps { | ||
|
||
/** | ||
* The content to be displayed inside the badge. | ||
* It can be text, icons, or other React components. | ||
*/ | ||
children: ReactNode; | ||
|
||
/** | ||
* Defines the style variant for the badge. | ||
* Controls the background and text color (default: 'default'). | ||
*/ | ||
variant?: BadgeVariant; | ||
|
||
/** | ||
* Custom background color for the badge. | ||
* Can be a Tailwind CSS color class or custom class. | ||
*/ | ||
background?: string; | ||
|
||
/** | ||
* Custom text color for the badge. | ||
* Can be a Tailwind CSS color class or custom class. | ||
*/ | ||
textColor?: string; | ||
|
||
/** | ||
* Additional custom CSS classes to apply to the badge element. | ||
* This is useful for applying further customization beyond the predefined styles. | ||
*/ | ||
className?: string; | ||
} | ||
|
||
/** | ||
* Badge component that renders a styled badge with text or other content. | ||
* The badge's appearance is controlled via variants, background, and text color. | ||
* | ||
* @param {BadgeProps} props - The props for the Badge component. | ||
* @returns {JSX.Element} The rendered Badge component. | ||
*/ | ||
const Badge: React.FC<BadgeProps> = ({ | ||
children, | ||
variant = BadgeVariant.default, | ||
background = 'bg-gray-200', | ||
textColor = 'text-gray-800', | ||
className = '', | ||
}) => { | ||
|
||
/** | ||
* A mapping of badge variants to their corresponding background and text color styles. | ||
* This is used to determine the appearance of the badge based on the `variant` prop. | ||
*/ | ||
const variantStyles: Record< | ||
BadgeVariant, | ||
{ background: string; textColor: string } | ||
> = { | ||
[BadgeVariant.default]: { background: 'bg-shark-800', textColor: 'text-shark-400' }, | ||
[BadgeVariant.error]: { background: 'bg-tamarind-800', textColor: 'text-tamarind-400' }, | ||
[BadgeVariant.success]: { background: 'bg-bush-800', textColor: 'text-bush-400' }, | ||
[BadgeVariant.warning]: { background: 'bg-clinker-800', textColor: 'text-clinker-400' }, | ||
[BadgeVariant.reference]: { background: 'bg-deep-teal-800', textColor: 'text-deep-teal-400' }, | ||
}; | ||
|
||
/** | ||
* Determine the resolved background color for the badge. | ||
* If a custom background is provided, it overrides the default variant background. | ||
*/ | ||
const resolvedBackground = background !== 'bg-gray-200' ? background : variantStyles[variant].background; | ||
|
||
/** | ||
* Determine the resolved text color for the badge. | ||
* If a custom text color is provided, it overrides the default variant text color. | ||
*/ | ||
const resolvedTextColor = textColor !== 'text-gray-800' ? textColor : variantStyles[variant].textColor; | ||
|
||
/** | ||
* Renders the badge as a span element with dynamic classes for styling. | ||
* The classes include padding, rounded corners, font size, and the background and text colors determined above. | ||
*/ | ||
return( | ||
<span className={`inline-block px-3 py-1 rounded-full text-sm font-semibold ${resolvedBackground} ${resolvedTextColor} ${className}`}> | ||
{children} | ||
</span> | ||
); | ||
}; | ||
|
||
export { Badge }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,19 @@ | ||
import { BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid } from 'recharts'; | ||
|
||
export default function BarchartExampleOne() { | ||
const data = [ | ||
{ name: 'Page A', uv: 400, pv: 2400, amt: 2400 }, | ||
{ name: 'Page B', uv: 300, pv: 1398, amt: 2210 }, | ||
{ name: 'Page C', uv: 200, pv: 9800, amt: 2290 }, | ||
]; | ||
const data = [ | ||
{ name: 'Page A', uv: 400, pv: 2400, amt: 2400 }, | ||
{ name: 'Page B', uv: 300, pv: 1398, amt: 2210 }, | ||
{ name: 'Page C', uv: 200, pv: 9800, amt: 2290 }, | ||
]; | ||
|
||
return( | ||
<BarChart width={500} height={300} data={data}> | ||
<CartesianGrid strokeDasharray="3 3" /> | ||
<XAxis dataKey="name" /> | ||
<YAxis /> | ||
<Tooltip /> | ||
<Bar dataKey="uv" fill="#8884d8" /> | ||
</BarChart> | ||
); | ||
} | ||
return ( | ||
<BarChart width={500} height={300} data={data}> | ||
<CartesianGrid strokeDasharray="3 3" /> | ||
<XAxis dataKey="name" /> | ||
<YAxis /> | ||
<Tooltip /> | ||
<Bar dataKey="uv" fill="#8884d8" /> | ||
</BarChart> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import * as React from 'react'; | ||
import { Slot } from '@radix-ui/react-slot'; | ||
import { cva, type VariantProps } from 'class-variance-authority'; | ||
|
||
import { cn } from '@/lib/utils'; | ||
|
||
const buttonVariants = cva( | ||
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', | ||
{ | ||
variants: { | ||
variant: { | ||
default: 'bg-primary text-primary-foreground hover:bg-primary/90', | ||
destructive: | ||
'bg-destructive text-destructive-foreground hover:bg-destructive/90', | ||
outline: | ||
'border border-input bg-background 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: 'text-primary underline-offset-4 hover:underline', | ||
}, | ||
size: { | ||
default: 'h-10 px-4 py-2', | ||
sm: 'h-9 rounded-md px-3', | ||
lg: 'h-11 rounded-md px-8', | ||
icon: 'h-10 w-10', | ||
}, | ||
}, | ||
defaultVariants: { | ||
variant: 'default', | ||
size: 'default', | ||
}, | ||
} | ||
); | ||
|
||
export interface ButtonProps | ||
extends React.ButtonHTMLAttributes<HTMLButtonElement>, | ||
VariantProps<typeof buttonVariants> { | ||
asChild?: boolean; | ||
} | ||
|
||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( | ||
({ className, variant, size, asChild = false, ...props }, ref) => { | ||
const Comp = asChild ? Slot : 'button'; | ||
return ( | ||
<Comp | ||
className={cn(buttonVariants({ variant, size, className }))} | ||
ref={ref} | ||
{...props} | ||
/> | ||
); | ||
} | ||
); | ||
Button.displayName = 'Button'; | ||
|
||
export { Button, buttonVariants }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
'use client'; | ||
|
||
import React, { useState } from 'react'; | ||
import { Textarea } from '@/components/ui/textarea'; | ||
import { Button } from '@/components/ui/button'; | ||
|
||
type FeedbackOption = { | ||
id: number; | ||
emoji: string; | ||
label: string; | ||
}; | ||
|
||
const feedbackOptions: FeedbackOption[] = [ | ||
{ id: 1, emoji: '🤩', label: 'Very helpful' }, | ||
{ id: 2, emoji: '🙂', label: 'Helpful' }, | ||
{ id: 3, emoji: '🙁', label: 'Not helpful' }, | ||
{ id: 4, emoji: '😭', label: 'Very unhelpful' }, | ||
]; | ||
|
||
const Feedback: React.FC = () => { | ||
const [selected, setSelected] = useState<number | null>(null); | ||
const [feedback, setFeedback] = useState<string>(''); | ||
|
||
const handleSelect = (id: number) => { | ||
setSelected((prevSelected) => (prevSelected === id ? null : id)); | ||
}; | ||
|
||
const handleSubmit = () => { | ||
setSelected(null); | ||
setFeedback(''); | ||
}; | ||
|
||
return ( | ||
<div className="flex items-center justify-center"> | ||
<div className="flex flex-col gap-4 px-4 py-2 border border-neutral-200 dark:border-neutral-800 rounded-3xl text-neutral-500 dark:text-neutral-400"> | ||
{/* Feedback Selection */} | ||
<div className="flex items-center gap-4"> | ||
<span className="text-sm flex items-center">Was this helpful?</span> | ||
{feedbackOptions.map((option) => ( | ||
<button | ||
key={option.id} | ||
onClick={() => handleSelect(option.id)} | ||
style={{ | ||
border: 'none', | ||
background: 'none', | ||
cursor: 'pointer', | ||
fontSize: '20px', | ||
opacity: selected === option.id ? 1 : 0.6, | ||
transition: 'opacity 0.2s', | ||
}} | ||
aria-label={option.label} | ||
> | ||
{option.emoji} | ||
</button> | ||
))} | ||
</div> | ||
|
||
{selected && ( | ||
<div | ||
className={`transition-all duration-300 overflow-hidden ${selected ? 'opacity-100 visible' : 'opacity-0 invisible'}`} | ||
> | ||
{/* Extended Feedback Form */} | ||
{selected && ( | ||
<div className="flex flex-col gap-2 py-2"> | ||
<Textarea | ||
placeholder="Type your feedback here." | ||
value={feedback} | ||
onChange={(e) => setFeedback(e.target.value)} | ||
/> | ||
|
||
<div className="border-t w-full border-neutral-200 dark:border-neutral-800 my-2"></div> | ||
|
||
<Button | ||
className="font-semibold hover:bg-orange-500 hover:text-white transition" | ||
onClick={handleSubmit} | ||
> | ||
Send | ||
</Button> | ||
</div> | ||
)} | ||
</div> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Feedback; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.