Skip to content

Commit

Permalink
mib
Browse files Browse the repository at this point in the history
  • Loading branch information
irsyadadl committed Aug 20, 2024
1 parent df1087e commit 1efcc6c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 60 deletions.
65 changes: 34 additions & 31 deletions components/ui/meter.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,54 @@
"use client"

import * as React from "react"

import { motion } from "framer-motion"
import { IconTriangleInfoFill } from "justd-icons"
import type { MeterProps as AriaMeterProps } from "react-aria-components"
import { IconCircleInfo, IconTriangleInfo } from "justd-icons"
import type { MeterProps as MeterPrimitiveProps } from "react-aria-components"
import { Meter as MeterPrimitive } from "react-aria-components"

import { Label } from "./field"
import { ctr } from "./primitive"
import { cn, ctr } from "./primitive"

export interface MeterProps extends AriaMeterProps {
export interface MeterProps extends MeterPrimitiveProps {
label?: string
}

const Meter = ({ label, ...props }: MeterProps) => {
export function Meter({
label,
positive,
informative,
...props
}: MeterProps &
(
| {
positive?: true
informative?: never
}
| { positive?: never; informative?: true }
)) {
return (
<MeterPrimitive {...props} className={ctr(props.className, "flex flex-col gap-1")}>
{({ percentage, valueText }) => (
<>
<div className="flex w-full justify-between gap-2">
<div className="flex justify-between gap-2">
<Label>{label}</Label>
<span className={`text-sm ${percentage >= 80 ? "text-danger" : "text-muted-fg"}`}>
{percentage >= 80 && (
<IconTriangleInfoFill
<span className="text-sm text-muted-fg">
{percentage >= 90 ? (
<IconTriangleInfo
aria-label="Alert"
className="inline-block size-4 animate-in slide-in-from-left align-text-bottom fill-danger/20 mr-1 text-danger"
/>
) : percentage >= 80 ? (
<IconCircleInfo
aria-label="Alert"
className="inline-block size-4 align-text-bottom"
className="inline-block size-4 animate-in slide-in-from-left align-text-bottom fill-warning/20 mr-1 text-warning"
/>
)}
{" " + valueText}
) : null}
<span className="w-10 bg-red-500 inline-block">{valueText}</span>
</span>
</div>
<div className="relative h-2 min-w-64 rounded-full bg-muted outline outline-1 -outline-offset-1 outline-transparent">
<motion.div
className="absolute left-0 top-0 h-full rounded-full forced-colors:bg-[Highlight]"
initial={{ width: "0%", backgroundColor: getColor(0) }}
animate={{
width: `${percentage}%`,
backgroundColor: getColor(percentage)
}}
transition={{ duration: 0.5 }}
<div className="relative h-2 w-64 overflow-hidden rounded-full bg-secondary outline outline-1 -outline-offset-1 outline-transparent">
<div
className={cn("absolute left-0 top-0 mr-1 h-full rounded-full", getColor(percentage))}
style={{ width: percentage + "%" }}
/>
</div>
</>
Expand All @@ -49,12 +58,8 @@ const Meter = ({ label, ...props }: MeterProps) => {
}

const getColor = (percentage: number) => {
if (percentage < 30) {
return "#0d6efd" // Blue
}

if (percentage < 50) {
return "#198754" // Green
return "#0d6efd" // Green
}

if (percentage < 70) {
Expand All @@ -67,5 +72,3 @@ const getColor = (percentage: number) => {

return "#e11d48" // Red
}

export { Meter, getColor }
41 changes: 13 additions & 28 deletions components/ui/progress-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
"use client"

import * as React from "react"

import { motion } from "framer-motion"
import {
ProgressBar as ProgressBarPrimitive,
type ProgressBarProps as ProgressBarPrimitiveProps
} from "react-aria-components"
import type { ProgressBarProps as ProgressBarPrimitiveProps } from "react-aria-components"
import { ProgressBar as ProgressBarPrimitive } from "react-aria-components"

import { Label } from "./field"
import { ctr } from "./primitive"
import { cn, ctr } from "./primitive"

interface ProgressBarProps extends ProgressBarPrimitiveProps {
export interface ProgressBarProps extends ProgressBarPrimitiveProps {
label?: string
}

Expand All @@ -25,25 +20,15 @@ const ProgressBar = ({ label, ...props }: ProgressBarProps) => {
<span className="text-sm text-muted-fg">{valueText}</span>
</div>
<div className="relative h-2 min-w-64 overflow-hidden rounded-full bg-secondary outline outline-1 -outline-offset-1 outline-transparent">
{!isIndeterminate ? (
<motion.div
className="absolute left-0 top-0 h-full rounded-full bg-primary forced-colors:bg-[Highlight]"
initial={{ width: "0%" }}
animate={{ width: `${percentage}%` }}
transition={{ duration: 0.5, ease: "easeInOut" }}
/>
) : (
<motion.div
className="absolute top-0 h-full rounded-full bg-primary forced-colors:bg-[Highlight]"
initial={{ left: "0%", width: "40%" }}
animate={{ left: ["0%", "100%", "0%"] }}
transition={{
repeat: Infinity,
duration: 2,
ease: "easeInOut"
}}
/>
)}
<div
className={cn(
"absolute top-0 h-full rounded-full bg-accent forced-colors:bg-[Highlight]",
isIndeterminate
? "left-full duration-1000 ease-out animate-in slide-out-to-right-full repeat-infinite [--tw-enter-translate-x:calc(-16rem-100%)]"
: "left-0 duration-300"
)}
style={{ width: (isIndeterminate ? 30 : percentage) + "%" }}
/>
</div>
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ Progress bars show how much an operation is done, either exactly or roughly, ove
## Indeterminate Progress Bar

An indeterminate progress bar is a type of progress indicator that does not show a specific amount of progress or percentage complete.
<How isCenter={false} className='px-32' toUse="statuses/indeterminate-progress-bar-demo" />
<How toUse="statuses/indeterminate-progress-bar-demo" />

0 comments on commit 1efcc6c

Please sign in to comment.