ProgressGroup New

プログレスバーが複数のセグメントに分割され、合計になります。

使用法

ProgressGroupコンポーネントを使用して、複数の値を1つのプログレスバーのセグメントとして表示します。

  • System19%
  • Apps6%
  • Documents9%
  • Multimedia33%
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'System',
    value: 24,
    color: 'neutral',
    icon: 'i-lucide-cog'
  },
  {
    label: 'Apps',
    value: 8,
    color: 'error',
    icon: 'i-lucide-app-window'
  },
  {
    label: 'Documents',
    value: 12,
    color: 'warning',
    icon: 'i-lucide-file'
  },
  {
    label: 'Multimedia',
    value: 42,
    color: 'success',
    icon: 'i-lucide-film'
  }
])
</script>

<template>
  <UProgressGroup :max="128" :items="items" class="w-96" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'System',
    value: 24,
    color: 'neutral',
    icon: 'i-lucide-cog'
  },
  {
    label: 'Apps',
    value: 8,
    color: 'error',
    icon: 'i-lucide-app-window'
  },
  {
    label: 'Documents',
    value: 12,
    color: 'warning',
    icon: 'i-lucide-file'
  },
  {
    label: 'Multimedia',
    value: 42,
    color: 'success',
    icon: 'i-lucide-film'
  }
])
</script>

<template>
  <UProgressGroup :max="128" :items="items" class="w-96" />
</template>

アイテム

itemsプロパティを次のプロパティを持つオブジェクトの配列として使用します。

  • Compute42%
  • Storage18%
  • Bandwidth9%
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Compute',
    value: 42,
    color: 'primary'
  },
  {
    label: 'Storage',
    value: 18,
    color: 'info'
  },
  {
    label: 'Bandwidth',
    value: 9,
    color: 'warning'
  }
])
</script>

<template>
  <UProgressGroup :items="items" class="w-96" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Compute',
    value: 42,
    color: 'primary'
  },
  {
    label: 'Storage',
    value: 18,
    color: 'info'
  },
  {
    label: 'Bandwidth',
    value: 9,
    color: 'warning'
  }
])
</script>

<template>
  <UProgressGroup :items="items" class="w-96" />
</template>
iconがないアイテムは、代わりにリストに色付きドットが表示されます。

Max

maxプロパティを使用して、すべてのアイテムが加算される値を設定します。デフォルトは100です。

  • Used25%
  • Reserved13%
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Used',
    value: 128,
    color: 'primary'
  },
  {
    label: 'Reserved',
    value: 64,
    color: 'neutral'
  }
])
</script>

<template>
  <UProgressGroup :max="512" :items="items" class="w-96" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Used',
    value: 128,
    color: 'primary'
  },
  {
    label: 'Reserved',
    value: 64,
    color: 'neutral'
  }
])
</script>

<template>
  <UProgressGroup :max="512" :items="items" class="w-96" />
</template>
値は0とmaxの間でクランプされ、maxを超えるセグメントは比例してトラックを共有します。

Status

statusプロパティを使用して、バーの上に合計値を表示します。

58%
  • System19%
  • Apps6%
  • Multimedia33%
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'System',
    value: 24,
    color: 'neutral'
  },
  {
    label: 'Apps',
    value: 8,
    color: 'error'
  },
  {
    label: 'Multimedia',
    value: 42,
    color: 'success'
  }
])
</script>

<template>
  <UProgressGroup status :max="128" :items="items" class="w-96" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'System',
    value: 24,
    color: 'neutral'
  },
  {
    label: 'Apps',
    value: 8,
    color: 'error'
  },
  {
    label: 'Multimedia',
    value: 42,
    color: 'success'
  }
])
</script>

<template>
  <UProgressGroup status :max="128" :items="items" class="w-96" />
</template>
ステータスはバーの終わりを追跡します。:ui="{ status: 'w-full' }"を使用して、代わりに幅いっぱいにします。

Color

colorプロパティを使用して、独自の色を設定していないすべてのセグメントの色を変更します。

  • Read42%
  • Write18%
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Read',
    value: 42
  },
  {
    label: 'Write',
    value: 18
  }
])
</script>

<template>
  <UProgressGroup color="neutral" :items="items" class="w-96" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Read',
    value: 42
  },
  {
    label: 'Write',
    value: 18
  }
])
</script>

<template>
  <UProgressGroup color="neutral" :items="items" class="w-96" />
</template>
このプロパティと各アイテムのcolorはどちらもCSSの色値を受け付けます。これはテーマ外のパレットに便利です。

サイズ

sizeプロパティを使用してProgressGroupのサイズを変更します。

  • Read42%
  • Write18%
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Read',
    value: 42,
    color: 'primary'
  },
  {
    label: 'Write',
    value: 18,
    color: 'info'
  }
])
</script>

<template>
  <UProgressGroup size="xl" :items="items" class="w-96" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Read',
    value: 42,
    color: 'primary'
  },
  {
    label: 'Write',
    value: 18,
    color: 'info'
  }
])
</script>

<template>
  <UProgressGroup size="xl" :items="items" class="w-96" />
</template>

Orientation

orientationプロパティを使用してProgressGroupの向きを変更します。デフォルトはhorizontalです。

  • Read42%
  • Write18%
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Read',
    value: 42,
    color: 'primary'
  },
  {
    label: 'Write',
    value: 18,
    color: 'info'
  }
])
</script>

<template>
  <UProgressGroup orientation="vertical" :items="items" class="h-48" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ProgressGroupItem } from '@nuxt/ui'

const items = ref<ProgressGroupItem[]>([
  {
    label: 'Read',
    value: 42,
    color: 'primary'
  },
  {
    label: 'Write',
    value: 18,
    color: 'info'
  }
])
</script>

<template>
  <UProgressGroup orientation="vertical" :items="items" class="h-48" />
</template>

Example

ステータススロット付き

#statusスロットを使用して、合計パーセンテージを独自のコンテンツに置き換えます。

86GB used

42GB remaining

  • System19%
  • Apps6%
  • Documents9%
  • Multimedia33%
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const max = 128

const items: ProgressGroupItem[] = [
  { label: 'System', value: 24, color: 'neutral', icon: 'i-lucide-cog' },
  { label: 'Apps', value: 8, color: 'error', icon: 'i-lucide-app-window' },
  { label: 'Documents', value: 12, color: 'warning', icon: 'i-lucide-file' },
  { label: 'Multimedia', value: 42, color: 'success', icon: 'i-lucide-film' }
]

const used = items.reduce((total, item) => total + (item.value ?? 0), 0)
</script>

<template>
  <UProgressGroup :items="items" :max="max" status class="w-96" :ui="{ status: 'w-full justify-between' }">
    <template #status>
      <p>{{ used }}GB used</p>
      <p class="text-muted">
        {{ max - used }}GB remaining
      </p>
    </template>
  </UProgressGroup>
</template>

アイテムスロット付き

#item-labelと#item-trailingスロットを使用して、各エントリの表示内容を変更します。どちらもitem、index、percentを受け取ります。

  • System24GB
  • Apps8GB
  • Documents12GB
  • Multimedia42GB
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const items: ProgressGroupItem[] = [
  { label: 'System', value: 24, color: 'neutral' },
  { label: 'Apps', value: 8, color: 'error' },
  { label: 'Documents', value: 12, color: 'warning' },
  { label: 'Multimedia', value: 42, color: 'success' }
]
</script>

<template>
  <UProgressGroup :items="items" :max="128" class="w-96">
    <template #item-label="{ item }">
      <span class="font-medium">{{ item.label }}</span>
    </template>

    <template #item-trailing="{ item }">
      {{ item.value }}GB
    </template>
  </UProgressGroup>
</template>

カスタムカラー

各項目にCSS色を付けて、テーマパレットの外で内訳を作成します。

70% Full

~89.7K / 128K Tokens

  • System prompt4.2K
  • Tool definitions18.4K
  • Rules12.8K
  • Skills7.1K
  • MCP & dynamic tools17.1K
  • Subagent definitions5.5K
  • Conversation24.6K
<script setup lang="ts">
import type { ProgressGroupItem } from '@nuxt/ui'

const max = 128

const items: ProgressGroupItem[] = [
  { label: 'System prompt', value: 4.2, color: 'var(--color-neutral-400)' },
  { label: 'Tool definitions', value: 18.4, color: 'var(--color-violet-400)' },
  { label: 'Rules', value: 12.8, color: 'var(--color-green-400)' },
  { label: 'Skills', value: 7.1, color: 'var(--color-amber-400)' },
  { label: 'MCP & dynamic tools', value: 17.1, color: 'var(--color-rose-400)' },
  { label: 'Subagent definitions', value: 5.5, color: 'var(--color-sky-400)' },
  { label: 'Conversation', value: 24.6, color: 'var(--color-orange-400)' }
]

const used = items.reduce((total, item) => total + (item.value ?? 0), 0)
</script>

<template>
  <UProgressGroup :items="items" :max="max" status class="w-96" :ui="{ status: 'w-full justify-between' }">
    <template #status="{ percent }">
      <p>{{ percent }}% Full</p>
      <p class="text-muted">
        ~{{ used.toFixed(1) }}K / {{ max }}K Tokens
      </p>
    </template>

    <template #item-trailing="{ item }">
      {{ item.value }}K
    </template>
  </UProgressGroup>
</template>

API

Props

Prop Default Type
as
'div'
any

The element or component this component should render as.

items
T[]
max
100
number

The value all items add up to, used to compute each segment's share of the track.

status
boolean

Display the summed progress value.

size
'md'
"2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
color
'primary'
"primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" | string

Any theme color, or any CSS color value for palettes outside the theme.

orientation
'horizontal'
"horizontal" | "vertical"

The orientation of the progress bar.

ui
{ root?: SlotClass; base?: SlotClass; segment?: SlotClass; indicator?: SlotClass; status?: SlotClass; list?: SlotClass; item?: SlotClass; itemLeadingIcon?: SlotClass; itemLeadingDot?: SlotClass; itemLabel?: SlotClass; itemTrailing?: SlotClass; }

スロット

Slot Type
status
{ percent: number; }
item
{ item: T; index: number; percent: number; }
item-leading
{ item: T; index: number; percent: number; }
item-label
{ item: T; index: number; percent: number; }
item-trailing
{ item: T; index: number; percent: number; }

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    progressGroup: {
      slots: {
        root: 'gap-2',
        base: 'flex overflow-hidden rounded-full bg-accented',
        segment: 'duration-200 ease-out motion-reduce:transition-none',
        indicator: 'size-full',
        status: 'flex text-dimmed duration-200 ease-out motion-reduce:transition-none',
        list: 'flex flex-col gap-1',
        item: 'flex items-center gap-1.5 min-w-0',
        itemLeadingIcon: 'shrink-0',
        itemLeadingDot: 'shrink-0 rounded-full',
        itemLabel: 'truncate',
        itemTrailing: 'ms-auto shrink-0 text-dimmed'
      },
      variants: {
        color: {
          primary: {
            indicator: 'bg-primary',
            itemLeadingIcon: 'text-primary',
            itemLeadingDot: 'bg-primary'
          },
          secondary: {
            indicator: 'bg-secondary',
            itemLeadingIcon: 'text-secondary',
            itemLeadingDot: 'bg-secondary'
          },
          success: {
            indicator: 'bg-success',
            itemLeadingIcon: 'text-success',
            itemLeadingDot: 'bg-success'
          },
          info: {
            indicator: 'bg-info',
            itemLeadingIcon: 'text-info',
            itemLeadingDot: 'bg-info'
          },
          warning: {
            indicator: 'bg-warning',
            itemLeadingIcon: 'text-warning',
            itemLeadingDot: 'bg-warning'
          },
          error: {
            indicator: 'bg-error',
            itemLeadingIcon: 'text-error',
            itemLeadingDot: 'bg-error'
          },
          neutral: {
            indicator: 'bg-inverted',
            itemLeadingIcon: 'text-highlighted',
            itemLeadingDot: 'bg-inverted'
          }
        },
        size: {
          '2xs': {
            status: 'text-xs',
            list: 'text-xs',
            itemLeadingIcon: 'size-3',
            itemLeadingDot: 'size-1.5'
          },
          xs: {
            status: 'text-xs',
            list: 'text-xs',
            itemLeadingIcon: 'size-3',
            itemLeadingDot: 'size-1.5'
          },
          sm: {
            status: 'text-sm',
            list: 'text-sm',
            itemLeadingIcon: 'size-4',
            itemLeadingDot: 'size-2'
          },
          md: {
            status: 'text-sm',
            list: 'text-sm',
            itemLeadingIcon: 'size-4',
            itemLeadingDot: 'size-2'
          },
          lg: {
            status: 'text-sm',
            list: 'text-sm',
            itemLeadingIcon: 'size-4',
            itemLeadingDot: 'size-2'
          },
          xl: {
            status: 'text-base',
            list: 'text-base',
            itemLeadingIcon: 'size-5',
            itemLeadingDot: 'size-2.5'
          },
          '2xl': {
            status: 'text-base',
            list: 'text-base',
            itemLeadingIcon: 'size-5',
            itemLeadingDot: 'size-2.5'
          }
        },
        orientation: {
          horizontal: {
            root: 'w-full flex flex-col',
            base: 'w-full flex-row',
            segment: 'h-full transition-[width]',
            status: 'flex-row items-center justify-end w-(--percent) min-w-fit transition-[width]'
          },
          vertical: {
            root: 'h-full flex flex-row',
            base: 'h-full flex-col',
            segment: 'w-full transition-[height]',
            status: 'flex-col justify-end h-(--percent) min-h-fit transition-[height]'
          }
        }
      },
      compoundVariants: [
        {
          orientation: 'horizontal',
          size: '2xs',
          class: 'h-px'
        },
        {
          orientation: 'horizontal',
          size: 'xs',
          class: 'h-0.5'
        },
        {
          orientation: 'horizontal',
          size: 'sm',
          class: 'h-1'
        },
        {
          orientation: 'horizontal',
          size: 'md',
          class: 'h-2'
        },
        {
          orientation: 'horizontal',
          size: 'lg',
          class: 'h-3'
        },
        {
          orientation: 'horizontal',
          size: 'xl',
          class: 'h-4'
        },
        {
          orientation: 'horizontal',
          size: '2xl',
          class: 'h-5'
        },
        {
          orientation: 'vertical',
          size: '2xs',
          class: 'w-px'
        },
        {
          orientation: 'vertical',
          size: 'xs',
          class: 'w-0.5'
        },
        {
          orientation: 'vertical',
          size: 'sm',
          class: 'w-1'
        },
        {
          orientation: 'vertical',
          size: 'md',
          class: 'w-2'
        },
        {
          orientation: 'vertical',
          size: 'lg',
          class: 'w-3'
        },
        {
          orientation: 'vertical',
          size: 'xl',
          class: 'w-4'
        },
        {
          orientation: 'vertical',
          size: '2xl',
          class: 'w-5'
        }
      ],
      defaultVariants: {
        color: 'primary',
        size: 'md'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        progressGroup: {
          slots: {
            root: 'gap-2',
            base: 'flex overflow-hidden rounded-full bg-accented',
            segment: 'duration-200 ease-out motion-reduce:transition-none',
            indicator: 'size-full',
            status: 'flex text-dimmed duration-200 ease-out motion-reduce:transition-none',
            list: 'flex flex-col gap-1',
            item: 'flex items-center gap-1.5 min-w-0',
            itemLeadingIcon: 'shrink-0',
            itemLeadingDot: 'shrink-0 rounded-full',
            itemLabel: 'truncate',
            itemTrailing: 'ms-auto shrink-0 text-dimmed'
          },
          variants: {
            color: {
              primary: {
                indicator: 'bg-primary',
                itemLeadingIcon: 'text-primary',
                itemLeadingDot: 'bg-primary'
              },
              secondary: {
                indicator: 'bg-secondary',
                itemLeadingIcon: 'text-secondary',
                itemLeadingDot: 'bg-secondary'
              },
              success: {
                indicator: 'bg-success',
                itemLeadingIcon: 'text-success',
                itemLeadingDot: 'bg-success'
              },
              info: {
                indicator: 'bg-info',
                itemLeadingIcon: 'text-info',
                itemLeadingDot: 'bg-info'
              },
              warning: {
                indicator: 'bg-warning',
                itemLeadingIcon: 'text-warning',
                itemLeadingDot: 'bg-warning'
              },
              error: {
                indicator: 'bg-error',
                itemLeadingIcon: 'text-error',
                itemLeadingDot: 'bg-error'
              },
              neutral: {
                indicator: 'bg-inverted',
                itemLeadingIcon: 'text-highlighted',
                itemLeadingDot: 'bg-inverted'
              }
            },
            size: {
              '2xs': {
                status: 'text-xs',
                list: 'text-xs',
                itemLeadingIcon: 'size-3',
                itemLeadingDot: 'size-1.5'
              },
              xs: {
                status: 'text-xs',
                list: 'text-xs',
                itemLeadingIcon: 'size-3',
                itemLeadingDot: 'size-1.5'
              },
              sm: {
                status: 'text-sm',
                list: 'text-sm',
                itemLeadingIcon: 'size-4',
                itemLeadingDot: 'size-2'
              },
              md: {
                status: 'text-sm',
                list: 'text-sm',
                itemLeadingIcon: 'size-4',
                itemLeadingDot: 'size-2'
              },
              lg: {
                status: 'text-sm',
                list: 'text-sm',
                itemLeadingIcon: 'size-4',
                itemLeadingDot: 'size-2'
              },
              xl: {
                status: 'text-base',
                list: 'text-base',
                itemLeadingIcon: 'size-5',
                itemLeadingDot: 'size-2.5'
              },
              '2xl': {
                status: 'text-base',
                list: 'text-base',
                itemLeadingIcon: 'size-5',
                itemLeadingDot: 'size-2.5'
              }
            },
            orientation: {
              horizontal: {
                root: 'w-full flex flex-col',
                base: 'w-full flex-row',
                segment: 'h-full transition-[width]',
                status: 'flex-row items-center justify-end w-(--percent) min-w-fit transition-[width]'
              },
              vertical: {
                root: 'h-full flex flex-row',
                base: 'h-full flex-col',
                segment: 'w-full transition-[height]',
                status: 'flex-col justify-end h-(--percent) min-h-fit transition-[height]'
              }
            }
          },
          compoundVariants: [
            {
              orientation: 'horizontal',
              size: '2xs',
              class: 'h-px'
            },
            {
              orientation: 'horizontal',
              size: 'xs',
              class: 'h-0.5'
            },
            {
              orientation: 'horizontal',
              size: 'sm',
              class: 'h-1'
            },
            {
              orientation: 'horizontal',
              size: 'md',
              class: 'h-2'
            },
            {
              orientation: 'horizontal',
              size: 'lg',
              class: 'h-3'
            },
            {
              orientation: 'horizontal',
              size: 'xl',
              class: 'h-4'
            },
            {
              orientation: 'horizontal',
              size: '2xl',
              class: 'h-5'
            },
            {
              orientation: 'vertical',
              size: '2xs',
              class: 'w-px'
            },
            {
              orientation: 'vertical',
              size: 'xs',
              class: 'w-0.5'
            },
            {
              orientation: 'vertical',
              size: 'sm',
              class: 'w-1'
            },
            {
              orientation: 'vertical',
              size: 'md',
              class: 'w-2'
            },
            {
              orientation: 'vertical',
              size: 'lg',
              class: 'w-3'
            },
            {
              orientation: 'vertical',
              size: 'xl',
              class: 'w-4'
            },
            {
              orientation: 'vertical',
              size: '2xl',
              class: 'w-5'
            }
          ],
          defaultVariants: {
            color: 'primary',
            size: 'md'
          }
        }
      }
    })
  ]
})

Changelog

No recent changes