1 звезда на GitHub = 1 новый компонент.

Поставить звезду
Графики и статистика chartsvgzero-dependencysegmentedpart-to-wholestoragebreakdown

Segmented Bar Chart

Одна сегментированная полоса «часть целого» с подписями и разбивкой — нагляднее круговой диаграммы.

Живое превью

Storage usage

512 GB plan

402 GB
45% 24% 16% 9%
  • Media 182 GB
  • Backups 96 GB
  • Databases 64 GB
  • Logs 38 GB
  • Other 22 GB
View data
SegmentValueShare
Media182 GB45.3%
Backups96 GB23.9%
Databases64 GB15.9%
Logs38 GB9.5%
Other22 GB5.5%

Использование

Скопируйте и вставьте этот код на вашу страницу Astro:

astro
---
import { SegmentedBarChart } from 'astro-component-kit/charts';
---

<SegmentedBarChart
  segments={[
    { label: 'Media', value: 182 },
    { label: 'Backups', value: 96 },
    { label: 'Other', value: 22 },
  ]}
  suffix=" GB"
/>
--- import { SegmentedBarChart } from 'astro-component-kit/charts'; --- <SegmentedBarChart segments={[ { label: 'Media', value: 182 }, { label: 'Backups', value: 96 }, { label: 'Other', value: 22 }, ]} suffix=" GB" />

Ручная установка

Если вы не используете пакет npm, создайте файл и вставьте следующий код: src/components/lib/SegmentedBarChart.astro:

astro
---
/**
 * SegmentedBarChart — A single tall part-to-whole bar with labelled segments
 * and a breakdown list. A clearer alternative to a pie for ≤ 6 parts.
 *
 * @param {Array<{label: string, value: number}>} segments - Parts of the whole.
 * @param {string} total - Optional formatted total for the header.
 * @param {string} prefix - Value prefix.
 * @param {string} suffix - Value suffix.
 * @param {string[]} colors - Optional per-segment colors.
 * @param {string} variant - Card style (glass|solid|ghost).
 * @param {string} size - Density (sm|md|lg).
 */
import ChartFrame from './ChartFrame.astro';
import { colorAt, formatValue, sum } from './chart-utils';

interface Props {
  title?: string;
  subtitle?: string;
  segments?: Array<{ label: string; value: number }>;
  total?: string;
  prefix?: string;
  suffix?: string;
  colors?: string[];
  variant?: 'glass' | 'solid' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  className?: string;
}

const {
  title = 'Storage usage',
  subtitle = '512 GB plan',
  segments = [
    { label: 'Media', value: 182 },
    { label: 'Backups', value: 96 },
    { label: 'Databases', value: 64 },
    { label: 'Logs', value: 38 },
    { label: 'Other', value: 22 },
  ],
  total,
  prefix = '',
  suffix = ' GB',
  colors,
  variant = 'glass',
  size = 'md',
  className = '',
} = Astro.props;

const tot = sum(segments.map((s) => s.value)) || 1;
const fmt = (v: number) => formatValue(v, prefix, suffix, false);
const segs = segments.slice(0, 8).map((s, i) => ({ ...s, pct: (s.value / tot) * 100, color: colorAt(i, colors) }));
---

<ChartFrame
  title={title}
  subtitle={subtitle}
  value={total ?? fmt(tot)}
  variant={variant}
  size={size}
  className={className}
  table={{ headers: ['Segment', 'Value', 'Share'], rows: segs.map((s) => [s.label, fmt(s.value), `${s.pct.toFixed(1)}%`]) }}
>
  <div class="sb__bar" role="list" aria-label={`${title} breakdown`}>
    {segs.map((s) => (
      <span class="sb__seg cf-mark" role="listitem" tabindex="0" style={`flex-grow:${s.value}; background:${s.color}`}
        aria-label={`${s.label}: ${fmt(s.value)} (${s.pct.toFixed(1)}%)`}
        data-tip-title={s.label} data-tip={`${s.color}::${fmt(s.value)} · ${s.pct.toFixed(1)}%`}>
        {s.pct >= 9 && <span class="sb__pct">{s.pct.toFixed(0)}%</span>}
      </span>
    ))}
  </div>
  <ul class="sb__list">
    {segs.map((s) => (
      <li>
        <span class="sb__dot" style={`background:${s.color}`} aria-hidden="true"></span>
        <span class="sb__name">{s.label}</span>
        <span class="sb__val">{fmt(s.value)}</span>
      </li>
    ))}
  </ul>
</ChartFrame>

<style>
  .sb__bar {
    display: flex;
    gap: 2px;
    height: 44px;
    border-radius: 8px;
    overflow: hidden;
  }
  .sb__seg {
    flex-basis: 0;
    min-width: 4px;
    display: flex;
    align-items: center;
    padding-left: 0.6rem;
    transition: filter 0.2s ease;
  }
  .sb__seg:hover { filter: brightness(1.15); }
  .sb__seg:focus-visible { outline: 2px solid var(--c-text-1, #fff); outline-offset: -2px; }
  .sb__pct {
    font-size: 0.75rem;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
  }
  .sb__list {
    list-style: none;
    margin: 1rem 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 0.6rem 1.25rem;
  }
  .sb__list li { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8125rem; }
  .sb__dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
  .sb__name { color: var(--c-text-2, #a3a3a3); }
  .sb__val { margin-left: auto; color: var(--c-text-1, #fff); font-weight: 600; font-variant-numeric: tabular-nums; }
</style>
--- /** * SegmentedBarChart — A single tall part-to-whole bar with labelled segments * and a breakdown list. A clearer alternative to a pie for ≤ 6 parts. * * @param {Array<{label: string, value: number}>} segments - Parts of the whole. * @param {string} total - Optional formatted total for the header. * @param {string} prefix - Value prefix. * @param {string} suffix - Value suffix. * @param {string[]} colors - Optional per-segment colors. * @param {string} variant - Card style (glass|solid|ghost). * @param {string} size - Density (sm|md|lg). */ import ChartFrame from './ChartFrame.astro'; import { colorAt, formatValue, sum } from './chart-utils'; interface Props { title?: string; subtitle?: string; segments?: Array<{ label: string; value: number }>; total?: string; prefix?: string; suffix?: string; colors?: string[]; variant?: 'glass' | 'solid' | 'ghost'; size?: 'sm' | 'md' | 'lg'; className?: string; } const { title = 'Storage usage', subtitle = '512 GB plan', segments = [ { label: 'Media', value: 182 }, { label: 'Backups', value: 96 }, { label: 'Databases', value: 64 }, { label: 'Logs', value: 38 }, { label: 'Other', value: 22 }, ], total, prefix = '', suffix = ' GB', colors, variant = 'glass', size = 'md', className = '', } = Astro.props; const tot = sum(segments.map((s) => s.value)) || 1; const fmt = (v: number) => formatValue(v, prefix, suffix, false); const segs = segments.slice(0, 8).map((s, i) => ({ ...s, pct: (s.value / tot) * 100, color: colorAt(i, colors) })); --- <ChartFrame title={title} subtitle={subtitle} value={total ?? fmt(tot)} variant={variant} size={size} className={className} table={{ headers: ['Segment', 'Value', 'Share'], rows: segs.map((s) => [s.label, fmt(s.value), `${s.pct.toFixed(1)}%`]) }} > <div class="sb__bar" role="list" aria-label={`${title} breakdown`}> {segs.map((s) => ( <span class="sb__seg cf-mark" role="listitem" tabindex="0" style={`flex-grow:${s.value}; background:${s.color}`} aria-label={`${s.label}: ${fmt(s.value)} (${s.pct.toFixed(1)}%)`} data-tip-title={s.label} data-tip={`${s.color}::${fmt(s.value)} · ${s.pct.toFixed(1)}%`}> {s.pct >= 9 && <span class="sb__pct">{s.pct.toFixed(0)}%</span>} </span> ))} </div> <ul class="sb__list"> {segs.map((s) => ( <li> <span class="sb__dot" style={`background:${s.color}`} aria-hidden="true"></span> <span class="sb__name">{s.label}</span> <span class="sb__val">{fmt(s.value)}</span> </li> ))} </ul> </ChartFrame> <style> .sb__bar { display: flex; gap: 2px; height: 44px; border-radius: 8px; overflow: hidden; } .sb__seg { flex-basis: 0; min-width: 4px; display: flex; align-items: center; padding-left: 0.6rem; transition: filter 0.2s ease; } .sb__seg:hover { filter: brightness(1.15); } .sb__seg:focus-visible { outline: 2px solid var(--c-text-1, #fff); outline-offset: -2px; } .sb__pct { font-size: 0.75rem; font-weight: 700; color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45); } .sb__list { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.6rem 1.25rem; } .sb__list li { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8125rem; } .sb__dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; } .sb__name { color: var(--c-text-2, #a3a3a3); } .sb__val { margin-left: auto; color: var(--c-text-1, #fff); font-weight: 600; font-variant-numeric: tabular-nums; } </style>

Краткая информация

Категория
Графики и статистика
Имя файла
SegmentedBarChart.astro
Зависимости
apexcharts (peer)
Теги
chartsvgzero-dependencysegmentedpart-to-wholestoragebreakdown