Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
typedCartesianChart,
Heading,
Section,
} from "@mittwald/flow-react-components";

export default () => {
const data = [
{
Monat: "Juli",
Datenbanken: 10,
Webspace: 15.4,
Email: 5.1,
},
{
Monat: "August",
Datenbanken: 32.9,
Webspace: 25.6,
Email: 10,
},
{
Monat: "September",
Datenbanken: 40,
Webspace: 20.2,
Email: 8,
},
];

const CartesianChart = typedCartesianChart<{
Monat: string;
Datenbanken: number;
Webspace: number;
Email: number;
}>();

return (
<Section>
<Heading>Speicherplatz</Heading>
<CartesianChart.Chart data={data} height="300px">
<CartesianChart.Bar
dataKey="Datenbanken"
unit="GB"
/>
<CartesianChart.Bar
dataKey="Webspace"
color="palatinate-blue"
unit="GB"
/>
<CartesianChart.Bar
dataKey="Email"
color="tangerine"
unit="GB"
/>
<CartesianChart.XAxis dataKey="Monat" />
<CartesianChart.YAxis unit=" GB" />
<CartesianChart.Grid />
<CartesianChart.Legend />
<CartesianChart.Tooltip />
</CartesianChart.Chart>
</Section>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
typedCartesianChart,
Heading,
Section,
} from "@mittwald/flow-react-components";

export default () => {
const data = [
{ Projekt: "Projekt A", Speicherplatz: 68 },
{ Projekt: "Projekt B", Speicherplatz: 42 },
{ Projekt: "Projekt C", Speicherplatz: 21 },
];

const CartesianChart = typedCartesianChart<{
Projekt: string;
Speicherplatz: number;
}>();

return (
<Section>
<Heading>Speicherplatz pro Projekt</Heading>
<CartesianChart.Chart
data={data}
height="300px"
layout="vertical"
>
<CartesianChart.Bar
dataKey="Speicherplatz"
unit="GB"
/>
<CartesianChart.XAxis unit=" GB" />
<CartesianChart.YAxis dataKey="Projekt" />
<CartesianChart.Grid vertical horizontal={false} />
<CartesianChart.Tooltip />
</CartesianChart.Chart>
</Section>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
typedCartesianChart,
Heading,
Section,
} from "@mittwald/flow-react-components";

export default () => {
const data = [
{
Monat: "Juli",
Datenbanken: 10,
Webspace: 15.4,
Email: 5.1,
},
{
Monat: "August",
Datenbanken: 32.9,
Webspace: 25.6,
Email: 10,
},
{
Monat: "September",
Datenbanken: 40,
Webspace: 20.2,
Email: 8,
},
];

const CartesianChart = typedCartesianChart<{
Monat: string;
Datenbanken: number;
Webspace: number;
Email: number;
}>();

return (
<Section>
<Heading>Speicherplatz</Heading>
<CartesianChart.Chart data={data} height="300px">
<CartesianChart.Bar
dataKey="Datenbanken"
stackId="speicher"
unit="GB"
/>
<CartesianChart.Bar
dataKey="Webspace"
color="palatinate-blue"
stackId="speicher"
unit="GB"
/>
<CartesianChart.Bar
dataKey="Email"
color="tangerine"
stackId="speicher"
unit="GB"
/>
<CartesianChart.XAxis dataKey="Monat" />
<CartesianChart.YAxis unit=" GB" />
<CartesianChart.Grid />
<CartesianChart.Legend />
<CartesianChart.Tooltip />
</CartesianChart.Chart>
</Section>
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
component: CartesianChart
description:
Das CartesianChart stellt Metriken über Zeit als Liniendiagramm oder
Flächendiagramm dar.
Das CartesianChart stellt Metriken als Linien-, Flächen- oder Balkendiagramm
dar.
---

<LiveCodeEditor editorCollapsed />
Expand All @@ -16,13 +16,16 @@ description:
[Categorical Colors](/foundations/design/colors#categorical-color) dar.
- Sortiere die Areas bei der Area-Darstellung nach Größe, die größte unten.
- Halte die Zahl der Dimensionen übersichtlich. Das sichert die Lesbarkeit.
- Bei der Bar-Darstellung darf die x-Achse auch kategorisch sein. Balken
vergleichen Kategorien, nicht nur Zeitpunkte.
- Stapele Balken nur dort, wo die Summe eine Bedeutung hat.

---

# Darstellungstypen

Im CartesianChart können unterschiedliche Darstellungstypen wie `<Area />`,
`<Line />` oder eine Kombination aus beiden verwendet werden.
`<Line />`, `<Bar />` oder eine Kombination daraus verwendet werden.

## Line

Expand All @@ -38,6 +41,32 @@ Anteil einzelner Objekte daran.

<LiveCodeEditor example="area" editorCollapsed />

## Bar

Vergleicht Werte einzelner Kategorien miteinander. Ohne `stackId` stehen die
Balken einer Kategorie nebeneinander.

<LiveCodeEditor example="bar" editorCollapsed />

Mehrere `<Bar />` mit derselben `stackId` werden gestapelt. Das zeigt den Anteil
einzelner Objekte am Gesamtwert einer Kategorie.

<LiveCodeEditor example="barStacked" editorCollapsed />

### Ausrichtung

Die Property `layout` bestimmt, wo die Kategorie-Achse liegt. Mit dem Default
`horizontal` liegt sie auf der x-Achse, die Balken wachsen nach oben. Mit
`vertical` liegt sie auf der y-Achse und die Balken wachsen zur Seite. Der
`dataKey` wandert dabei auf die `<YAxis />`, die Achsentypen ergeben sich von
selbst.

Nutze die vertikale Ausrichtung für lange Kategorie-Namen oder für viele
Kategorien. Nur Balken lassen sich sinnvoll drehen. `<Line />` und `<Area />`
zeigen einen Verlauf und bleiben horizontal.

<LiveCodeEditor example="barHorizontal" editorCollapsed />

---

# Color
Expand Down
22 changes: 22 additions & 0 deletions apps/remote-dom-demo/src/app/remote/chart/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import {
Area,
Bar,
CartesianChart,
CartesianGrid,
ChartTooltip,
Expand Down Expand Up @@ -69,11 +70,32 @@ export default function Page() {
);
};

const BarChart: FC<{ layout: "horizontal" | "vertical" }> = ({ layout }) => {
const vertical = layout === "vertical";

return (
<CartesianChart data={data} height="300px" layout={layout}>
<CartesianGrid vertical={vertical} horizontal={!vertical} />
<Bar dataKey="Shields" />
<Bar dataKey="Hull" color="palatinate-blue" />
{vertical ? <XAxis unit="%" /> : <XAxis dataKey="time" />}
{vertical ? (
<YAxis dataKey="time" />
) : (
<YAxis domain={[0, 100]} unit="%" />
)}
<ChartTooltip />
</CartesianChart>
);
};

return (
<>
<ExampleChart data={data} />
<ExampleChart data={data} />
<ExampleChart data={[]} />
<BarChart layout="horizontal" />

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Die Charts zeigen nichts an

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ich guck mir das grad mal an, das scheint nicht an den Bars zu liegen, tritt auch mit anderen Charts auf

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ich mach für das Problem ein eigenes Issue auf, du kannst das hier aber so bauen, dann funktioniert es trotzdem:

const createBarData = () => [
  { project: "Alpha", Shields: 68, Hull: 24 },
  { project: "Beta", Shields: 42, Hull: 13 },
  { project: "Gamma", Shields: 21, Hull: 39 },
];

const barData = {
  horizontal: createBarData(),
  vertical: createBarData(),
};

<CartesianChart data={barData[layout]} height="300px" layout={layout}>

<BarChart layout="vertical" />
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import { useChartClipRect } from "@/components/CartesianChart/hooks/useChartClip
import DivView from "@/views/DivView";
import Wrap from "@/components/Wrap";
import type {
CartesianChartLayout,
ChartDataValue,
DataKeyProp,
} from "@/components/CartesianChart/types";
import { CartesianChartContextProvider } from "@/components/CartesianChart/context";
import { TypedArea } from "@/components/CartesianChart/components/Area";
import { TypedBar } from "@/components/CartesianChart/components/Bar";
import { TypedXAxis } from "@/components/CartesianChart/components/XAxis";
import { TypedYAxis } from "@/components/CartesianChart/components/YAxis";
import { TypedChartGrid } from "@/components/CartesianChart/components/ChartGrid";
Expand All @@ -44,6 +47,17 @@ export interface CartesianChartProps<TData = ChartDataValue>
/** The height of the chart. */
height?: string;

/**
* The orientation of the axes and graphical items. `"horizontal"` puts the
* category axis on the x-axis — bars grow upwards. `"vertical"` puts it on
* the y-axis — bars grow to the side. `XAxis` and `YAxis` follow the layout
* on their own; only the `dataKey` moves to whichever axis is the categorical
* one.
*
* @default "horizontal"
*/
layout?: CartesianChartLayout;

/** View that is provided when data is empty/undefined */
emptyView?: ReactNode;

Expand All @@ -56,8 +70,16 @@ export interface CartesianChartProps<TData = ChartDataValue>

/** @flr-generate all */
export const CartesianChart: FC<CartesianChartProps> = (props) => {
const { children, data, className, height, flexGrow, emptyView, ...rest } =
props;
const {
children,
data,
className,
height,
flexGrow,
emptyView,
layout = "horizontal",
...rest
} = props;
const warnDeprecation = useWarnDeprecation();

const { viewDimensions, ref: containerRef } = useChartClipRect();
Expand Down Expand Up @@ -88,32 +110,41 @@ export const CartesianChart: FC<CartesianChartProps> = (props) => {
return null;
}, [emptyView]);

const contextValue = useMemo(() => ({ layout }), [layout]);

return (
<Wrap if={height}>
<div style={{ height, flex: flexGrow ? 1 : undefined }}>
<ResponsiveContainer
initialDimension={{
// fix warning on initial render
width: 1,
height: 1,
}}
width={height ? undefined : "100%"}
aspect={height ? undefined : 3}
ref={containerRef}
>
<ComposedChart data={data} className={rootClassName} {...rest}>
{children}
{showEmptyView && viewDimensions && (
<foreignObject {...viewDimensions}>
<DivView className={styles.emptyViewContainer}>
{emptyElement}
</DivView>
</foreignObject>
)}
</ComposedChart>
</ResponsiveContainer>
</div>
</Wrap>
<CartesianChartContextProvider value={contextValue}>
<Wrap if={height}>
<div style={{ height, flex: flexGrow ? 1 : undefined }}>
<ResponsiveContainer
initialDimension={{
// fix warning on initial render
width: 1,
height: 1,
}}
width={height ? undefined : "100%"}
aspect={height ? undefined : 3}
ref={containerRef}
>
<ComposedChart
data={data}
className={rootClassName}
layout={layout}
{...rest}
>
{children}
{showEmptyView && viewDimensions && (
<foreignObject {...viewDimensions}>
<DivView className={styles.emptyViewContainer}>
{emptyElement}
</DivView>
</foreignObject>
)}
</ComposedChart>
</ResponsiveContainer>
</div>
</Wrap>
</CartesianChartContextProvider>
);
};

Expand All @@ -124,6 +155,7 @@ export const typedCartesianChart = <
>() => ({
Chart: CartesianChart as ComponentType<CartesianChartProps<TData>>,
Area: TypedArea<TData>(),
Bar: TypedBar<TData>(),
XAxis: TypedXAxis<TData, XAxisDataKey>(),
YAxis: TypedYAxis<TData>(),
Grid: TypedChartGrid(),
Expand Down
Loading
Loading