# Line Chart Labeled

A single line with a dot and a printed value at every point, and no grid.

Line Chart Labeled is an open-source chart from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.

Source: https://ui.suiss.app/docs/charts/line-chart-labeled

**React**

**Example**

```tsx title="components/charts/line-chart-labeled.tsx"
"use client"

import { LabelList, Line, LineChart, XAxis } from "recharts"

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", desktop: 186, mobile: 80 },
  { month: "February", desktop: 305, mobile: 200 },
  { month: "March", desktop: 237, mobile: 120 },
  { month: "April", desktop: 173, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "June", desktop: 264, mobile: 140 },
]

const chartConfig = {
  desktop: { label: "Desktop", color: "var(--chart-1)" },
} satisfies ChartConfig

export function LineChartLabeled() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Labeled</CardTitle>
        <CardDescription>Every point shows its value</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          className="aspect-auto h-48 w-full"
        >
          <LineChart
            accessibilityLayer
            data={chartData}
            margin={{ top: 24, right: 16, left: 16, bottom: 0 }}
          >
            <XAxis
              dataKey="month"
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              interval={0}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ChartTooltip content={<ChartTooltipContent hideLabel />} />
            <Line
              dataKey="desktop"
              type="natural"
              stroke="var(--color-desktop)"
              strokeWidth={2.5}
              dot={{ r: 4, fill: "var(--color-desktop)", strokeWidth: 0 }}
            >
              <LabelList
                position="top"
                offset={10}
                className="fill-foreground font-semibold"
                fontSize={12}
              />
            </Line>
          </LineChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

A single smooth line with a dot and a printed value at every point and no grid. Choose it for short series where readers want the exact numbers without hovering.

## Installation

### CLI

```bash title="Terminal"
npx shadcn@latest add @esuiss/line-chart-labeled
```

Works in any project with a `components.json`. See [Installation](https://ui.suiss.app/docs/installation#add-components) for the one-line registry setup. Or use the suiss/ui CLI:

```bash title="Terminal"
npx @esuiss/ui@latest add charts line-chart-labeled
```

### Manual

1. Install the dependencies:

```bash title="Terminal"
npm install recharts
```

2. Add the pieces it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

3. Copy the source into `components/charts/line-chart-labeled.tsx`:

```tsx title="components/charts/line-chart-labeled.tsx"
"use client"

import { LabelList, Line, LineChart, XAxis } from "recharts"

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", desktop: 186, mobile: 80 },
  { month: "February", desktop: 305, mobile: 200 },
  { month: "March", desktop: 237, mobile: 120 },
  { month: "April", desktop: 173, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "June", desktop: 264, mobile: 140 },
]

const chartConfig = {
  desktop: { label: "Desktop", color: "var(--chart-1)" },
} satisfies ChartConfig

export function LineChartLabeled() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Labeled</CardTitle>
        <CardDescription>Every point shows its value</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          className="aspect-auto h-48 w-full"
        >
          <LineChart
            accessibilityLayer
            data={chartData}
            margin={{ top: 24, right: 16, left: 16, bottom: 0 }}
          >
            <XAxis
              dataKey="month"
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              interval={0}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ChartTooltip content={<ChartTooltipContent hideLabel />} />
            <Line
              dataKey="desktop"
              type="natural"
              stroke="var(--color-desktop)"
              strokeWidth={2.5}
              dot={{ r: 4, fill: "var(--color-desktop)", strokeWidth: 0 }}
            >
              <LabelList
                position="top"
                offset={10}
                className="fill-foreground font-semibold"
                fontSize={12}
              />
            </Line>
          </LineChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

4. Update the import paths to match your project.

## Usage

```tsx
import { LineChartLabeled } from "@/components/charts/line-chart-labeled"
```

```tsx
<LineChartLabeled />
```

Replace `chartData`, point each `dataKey` at your fields and set the label and color in `chartConfig`. Move the value labels with the `position` prop on `LabelList`, and raise the chart's top margin if labels get clipped.

## Notes

Labels overlap quickly on long or dense series; keep this variant to a dozen points or fewer.

**React Native, SwiftUI, Jetpack Compose**

![Preview](https://ui.suiss.app/previews/charts-line--labeled.light.webp)

```tsx title="uniwind/components/charts/line-chart-labeled.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  LabelList,
  Line,
  LineChart,
  XAxis,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", desktop: 186, mobile: 80 },
  { month: "February", desktop: 305, mobile: 200 },
  { month: "March", desktop: 237, mobile: 120 },
  { month: "April", desktop: 173, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "June", desktop: 264, mobile: 140 },
]

const chartConfig = {
  desktop: { label: "Desktop", color: "chart-1" },
} satisfies ChartConfig

export function LineChartLabeled() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Labeled</CardTitle>
        <CardDescription>Every point shows its value</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Labeled"
          className="h-48 w-full"
        >
          <LineChart
            data={chartData}
            margin={{ top: 24, right: 16, left: 16, bottom: 0 }}
          >
            <XAxis
              dataKey="month"
              tickMargin={8}
              interval={0}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ChartTooltip content={<ChartTooltipContent hideLabel />} />
            <Line
              dataKey="desktop"
              type="natural"
              strokeWidth={2.5}
              dot={{ r: 4 }}
            >
              <LabelList position="top" offset={10} />
            </Line>
          </LineChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

```swift title="swift/Charts/LineChartLabeled.swift"
import Charts
import SwiftUI

private let chartData: [(month: String, desktop: Double, mobile: Double)] = [
  ("January", 186, 80),
  ("February", 305, 200),
  ("March", 237, 120),
  ("April", 173, 190),
  ("May", 209, 130),
  ("June", 264, 140),
]

private let chartConfig: ChartConfig = [
  "desktop": .init("Desktop", color: EsuissColor.chart1),
]

public struct LineChartLabeled: View {
  @State private var selection: Int?

  public init() {}

  public var body: some View {
    Card(.filled, size: .sm) {
      CardHeader("Labeled", description: "Every point shows its value")
      CardContent {
        ChartContainer(config: chartConfig) {
          ChartAnimator { progress in
            Chart {
              ForEach(chartData.indices, id: \.self) { index in
                LineMark(x: .value("Month", index), y: .value("Desktop", chartData[index].desktop))
                  .interpolationMethod(.catmullRom)
                  .lineStyle(StrokeStyle(lineWidth: 2.5, lineCap: .round, lineJoin: .round))
                  .foregroundStyle(chartConfig.color("desktop"))
                PointMark(x: .value("Month", index), y: .value("Desktop", chartData[index].desktop))
                  .symbolSize(selection == index ? 100 : 64)
                  .foregroundStyle(chartConfig.color("desktop"))
                  .annotation(position: .top, spacing: 6) {
                    Text(chartData[index].desktop, format: .number)
                      .scaledFont(TextStyle.xs, weight: .semibold)
                      .foregroundStyle(EsuissColor.foreground)
                      .opacity(progress < 1 ? 0 : 1)
                  }
              }
              .chartReveal(progress, x: 0...(chartData.count - 1))
            }
            .chartXScale(domain: 0...(chartData.count - 1), range: .plotDimension(padding: 16))
            .chartYScale(range: .plotDimension(endPadding: 24))
            .chartXAxis { ChartAxis.x(values: Array(chartData.indices)) { String(chartData[$0].month.prefix(3)) } }
            .chartYAxis(.hidden)
            .chartTooltip(
              x: Array(chartData.indices),
              labels: chartData.map(\.month),
              selection: $selection,
              accessibilityLabel: "Labeled",
              items: { [ChartTooltipItem("desktop", value: chartData[$0].desktop)] }
            ) { payload in
              ChartTooltipContent(payload, hideLabel: true)
            }
          }
        }
        .frame(height: 192)
      }
    }
  }
}
```

```kt title="kotlin/charts/LineChartLabeled.kt"
package com.esuiss.ui.charts

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.esuiss.ui.components.Card
import com.esuiss.ui.components.CardContent
import com.esuiss.ui.components.CardHeader
import com.esuiss.ui.components.CardSize
import com.esuiss.ui.components.CardVariant
import com.esuiss.ui.components.ChartConfig
import com.esuiss.ui.components.ChartConfigItem
import com.esuiss.ui.components.ChartContainer
import com.esuiss.ui.components.ChartCurve
import com.esuiss.ui.components.ChartDot
import com.esuiss.ui.components.ChartLabelList
import com.esuiss.ui.components.ChartMargin
import com.esuiss.ui.components.ChartTooltipContent
import com.esuiss.ui.components.LineChart
import com.esuiss.ui.theme.EsuissTheme

private class LineLabeledRow(val month: String, val desktop: Double, val mobile: Double)

private val chartData = listOf(
    LineLabeledRow("January", 186.0, 80.0),
    LineLabeledRow("February", 305.0, 200.0),
    LineLabeledRow("March", 237.0, 120.0),
    LineLabeledRow("April", 173.0, 190.0),
    LineLabeledRow("May", 209.0, 130.0),
    LineLabeledRow("June", 264.0, 140.0),
)

private val chartConfig = ChartConfig(
    "desktop" to ChartConfigItem("Desktop") { chart1 },
)

@Composable
fun LineChartLabeled(modifier: Modifier = Modifier) {
    val colors = EsuissTheme.colors
    Card(modifier, variant = CardVariant.Filled, size = CardSize.Sm) {
        CardHeader("Labeled", description = "Every point shows its value")
        CardContent {
            ChartContainer(
                chartConfig,
                Modifier
                    .fillMaxWidth()
                    .height(192.dp),
            ) {
                LineChart(
                    chartData,
                    margin = ChartMargin(top = 24.dp, right = 16.dp, bottom = 0.dp, left = 16.dp),
                    accessibilityLabel = "Labeled",
                ) {
                    XAxis(label = { it.month }, tickMargin = 8.dp, interval = 0, tickFormatter = { it.take(3) })
                    ChartTooltip { ChartTooltipContent(hideLabel = true) }
                    Line(
                        "desktop",
                        value = { it.desktop },
                        curve = ChartCurve.Natural,
                        strokeWidth = 2.5.dp,
                        dot = ChartDot(4.dp),
                        labelList = ChartLabelList(offset = 10.dp, color = colors.foreground),
                    )
                }
            }
        }
    }
}
```

One natural curve with dots on each month and a `LabelList` above every point, so values are readable without touching the chart. There is no grid; a month axis and a tooltip remain.

## Installation

**React Native**

```bash title="Terminal"
npx shadcn@latest add @esuiss-rn/line-chart-labeled
```

See [Installation](https://ui.suiss.app/docs/installation) for the `components.json` setup. Or use the suiss/ui CLI:

```bash title="Terminal"
npx @esuiss/ui@latest add line-chart-labeled
```

**SwiftUI**

```bash title="Terminal"
npx @esuiss/ui@latest add line-chart-labeled --platform swift
```

**Jetpack Compose**

```bash title="Terminal"
npx @esuiss/ui@latest add line-chart-labeled --platform kotlin
```

The CLI also adds what it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

### Manual

**React Native**

**Uniwind**

1. Add the pieces it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

2. Copy the source into `components/charts/line-chart-labeled.tsx`:

- `uniwind/components/charts/line-chart-labeled.tsx`: shown above

3. Update the import paths to match your project.

**NativeWind**

1. Add the pieces it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

2. Copy the source into `components/charts/line-chart-labeled.tsx`:

```tsx title="nativewind/components/charts/line-chart-labeled.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  LabelList,
  Line,
  LineChart,
  XAxis,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", desktop: 186, mobile: 80 },
  { month: "February", desktop: 305, mobile: 200 },
  { month: "March", desktop: 237, mobile: 120 },
  { month: "April", desktop: 173, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "June", desktop: 264, mobile: 140 },
]

const chartConfig = {
  desktop: { label: "Desktop", color: "chart-1" },
} satisfies ChartConfig

export function LineChartLabeled() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Labeled</CardTitle>
        <CardDescription>Every point shows its value</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Labeled"
          className="h-48 w-full"
        >
          <LineChart
            data={chartData}
            margin={{ top: 24, right: 16, left: 16, bottom: 0 }}
          >
            <XAxis
              dataKey="month"
              tickMargin={8}
              interval={0}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ChartTooltip content={<ChartTooltipContent hideLabel />} />
            <Line
              dataKey="desktop"
              type="natural"
              strokeWidth={2.5}
              dot={{ r: 4 }}
            >
              <LabelList position="top" offset={10} />
            </Line>
          </LineChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

3. Update the import paths to match your project.

**StyleSheet**

1. Add the pieces it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

2. Copy the source into `components/charts/line-chart-labeled.tsx`:

```tsx title="stylesheet/components/charts/line-chart-labeled.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  LabelList,
  Line,
  LineChart,
  XAxis,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", desktop: 186, mobile: 80 },
  { month: "February", desktop: 305, mobile: 200 },
  { month: "March", desktop: 237, mobile: 120 },
  { month: "April", desktop: 173, mobile: 190 },
  { month: "May", desktop: 209, mobile: 130 },
  { month: "June", desktop: 264, mobile: 140 },
]

const chartConfig = {
  desktop: { label: "Desktop", color: "chart-1" },
} satisfies ChartConfig

export function LineChartLabeled() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Labeled</CardTitle>
        <CardDescription>Every point shows its value</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Labeled"
          style={{ height: 192 }}
        >
          <LineChart
            data={chartData}
            margin={{ top: 24, right: 16, left: 16, bottom: 0 }}
          >
            <XAxis
              dataKey="month"
              tickMargin={8}
              interval={0}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ChartTooltip content={<ChartTooltipContent hideLabel />} />
            <Line
              dataKey="desktop"
              type="natural"
              strokeWidth={2.5}
              dot={{ r: 4 }}
            >
              <LabelList position="top" offset={10} />
            </Line>
          </LineChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

3. Update the import paths to match your project.

**SwiftUI**

1. Target iOS 17 or later.

2. Copy the theme files every view uses:

- `swift/Theme/Theme.swift`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/swiftui/Sources/EsuissUI/Theme/Theme.swift)

- `swift/Theme/Tokens.swift`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/swiftui/Sources/EsuissUI/Theme/Tokens.swift)

3. Copy the source and every file it uses:

- `swift/Charts/LineChartLabeled.swift`: shown above

- `swift/Components/Card.swift`: see [Card](https://ui.suiss.app/docs/components/card.md)

- `swift/Components/Chart.swift`: see [Chart](https://ui.suiss.app/docs/components/chart.md)

- `swift/Components/Haptics.swift`: see [Haptics](https://ui.suiss.app/docs/components/haptics.md)

- `swift/Components/Item.swift`: see [Item](https://ui.suiss.app/docs/components/item.md)

- `swift/Components/Separator.swift`: see [Separator](https://ui.suiss.app/docs/components/separator.md)

- `swift/Components/TextVariant.swift`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/swiftui/Sources/EsuissUI/Components/TextVariant.swift)

4. Add the files to your app target.

**Jetpack Compose**

1. Set `minSdk` to 24 or higher and add the dependencies:

```kotlin title="build.gradle.kts"
implementation(platform("androidx.compose:compose-bom:2026.09.00"))
implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.ui:ui")
```

2. Copy the theme files every view uses:

- `kotlin/theme/Theme.kt`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/kotlin/ui/src/main/kotlin/com/esuiss/ui/theme/Theme.kt)

- `kotlin/theme/Tokens.kt`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/kotlin/ui/src/main/kotlin/com/esuiss/ui/theme/Tokens.kt)

3. Copy the source and every file it uses:

- `kotlin/charts/LineChartLabeled.kt`: shown above

- `kotlin/components/Card.kt`: see [Card](https://ui.suiss.app/docs/components/card.md)

- `kotlin/components/Chart.kt`: see [Chart](https://ui.suiss.app/docs/components/chart.md)

- `kotlin/components/Content.kt`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/kotlin/ui/src/main/kotlin/com/esuiss/ui/components/Content.kt)

- `kotlin/components/FormSupport.kt`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/kotlin/ui/src/main/kotlin/com/esuiss/ui/components/FormSupport.kt)

- `kotlin/components/Haptics.kt`: see [Haptics](https://ui.suiss.app/docs/components/haptics.md)

- `kotlin/components/Icon.kt`: see [Icon](https://ui.suiss.app/docs/components/icon.md)

4. Update the `com.esuiss.ui` package names to match your project.

## Usage

```tsx
import { LineChartLabeled } from "@/components/charts/line-chart-labeled"
```

```tsx
<LineChartLabeled />
```

Replace `chartData` with your records and change each `dataKey` to match your fields. Change `position` and `offset` on the `LabelList` to move the labels. The component takes no props.

