Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions apps/docs/docs/components/graphs/XAxis/_mobileExamples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,42 @@ function CustomGridLineExample() {
}
```

On band scales, you can also use `bandGridLinePlacement` to control where grid lines appear relative to each band.

Using edges will place a grid line at the start of each band, plus a grid line at the end of the last band.

```jsx
function BandGridPlacement() {
const [selectedBandGridPlacement, setSelectedBandGridPlacement] = useState('edges');

return (
<CartesianChart
height={250}
series={[
{
id: 'prices',
data: [10, 22, 29, 45, 98, 45, 22],
},
]}
xAxis={{
scaleType: 'band',
data: ['April 1', 'April 2', 'April 3', 'April 4', 'April 5', 'April 6', 'April 7'],
}}
yAxis={{ domain: { min: 0 } }}
>
<XAxis
bandGridLinePlacement={selectedBandGridPlacement}
GridLineComponent={SolidLine}
showGrid
showLine
showTickMarks
/>
<BarPlot />
</CartesianChart>
);
}
```

### Line

You can show the axis line using the `showLine` prop.
Expand Down Expand Up @@ -536,6 +572,41 @@ function XAxisTickMarksExample() {
}
```

On band scales, you can also use `bandTickMarkPlacement` to control where tick marks appear relative to each band.

Using edges will place a tick mark at the start of each band, plus a tick mark at the end of the last band.

```jsx
function BandTickMarkPlacement() {
const [selectedBandTickMarkPlacement, setSelectedBandTickMarkPlacement] = useState('middle');

return (
<CartesianChart
height={250}
series={[
{
id: 'prices',
data: [10, 22, 29, 45, 98, 45, 22],
},
]}
xAxis={{
scaleType: 'band',
data: ['April 1', 'April 2', 'April 3', 'April 4', 'April 5', 'April 6', 'April 7'],
}}
yAxis={{ domain: { min: 0 } }}
>
<XAxis
bandTickMarkPlacement={selectedBandTickMarkPlacement}
showLine
showTickMarks
tickMarkSize={8}
/>
<BarPlot />
</CartesianChart>
);
}
```

### Tick Labels

You can customize the tick labels using the `tickLabelFormatter` prop. It will receive the x data value of the tick. Meaning, if data is provided for the axis, it will receive the string label for the tick.
Expand Down
111 changes: 111 additions & 0 deletions apps/docs/docs/components/graphs/XAxis/_webExamples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,62 @@ function CustomGridLineExample() {
}
```

On band scales, you can also use `bandGridLinePlacement` to control where grid lines appear relative to each band.

Using edges will place a grid line at the start of each band, plus a grid line at the end of the last band.

```jsx live
function BandGridPlacement() {
const bandGridLinePlacements = [
{ id: 'edges', label: 'Edges' },
{ id: 'start', label: 'Start' },
{ id: 'middle', label: 'Middle' },
{ id: 'end', label: 'End' },
];
const [selectedBandGridPlacement, setSelectedBandGridPlacement] = useState(
bandGridLinePlacements[0],
);

return (
<VStack gap={2}>
<HStack justifyContent="flex-end" gap={2} alignItems="center">
<Text as="h3" font="headline">
Band Grid Placement
</Text>
<SegmentedTabs
activeTab={selectedBandGridPlacement}
onChange={setSelectedBandGridPlacement}
tabs={bandGridLinePlacements}
/>
</HStack>
<CartesianChart
height={250}
series={[
{
id: 'prices',
data: [10, 22, 29, 45, 98, 45, 22],
},
]}
xAxis={{
scaleType: 'band',
data: ['April 1', 'April 2', 'April 3', 'April 4', 'April 5', 'April 6', 'April 7'],
}}
yAxis={{ domain: { min: 0 } }}
>
<XAxis
bandGridLinePlacement={selectedBandGridPlacement.id}
GridLineComponent={SolidLine}
showGrid
showLine
showTickMarks
/>
<BarPlot />
</CartesianChart>
</VStack>
);
}
```

### Line

You can show the axis line using the `showLine` prop.
Expand Down Expand Up @@ -534,6 +590,61 @@ function XAxisTickMarksExample() {
}
```

On band scales, you can also use `bandTickMarkPlacement` to control where tick marks appear relative to each band.

Using edges will place a tick mark at the start of each band, plus a tick mark at the end of the last band.

```jsx live
function BandTickMarkPlacement() {
const bandTickMarkPlacements = [
{ id: 'middle', label: 'Middle' },
{ id: 'edges', label: 'Edges' },
{ id: 'start', label: 'Start' },
{ id: 'end', label: 'End' },
];
const [selectedBandTickMarkPlacement, setSelectedBandTickMarkPlacement] = useState(
bandTickMarkPlacements[0],
);

return (
<VStack gap={2}>
<HStack justifyContent="flex-end" gap={2} alignItems="center">
<Text as="h3" font="headline">
Band Tick Mark Placement
</Text>
<SegmentedTabs
activeTab={selectedBandTickMarkPlacement}
onChange={setSelectedBandTickMarkPlacement}
tabs={bandTickMarkPlacements}
/>
</HStack>
<CartesianChart
height={250}
series={[
{
id: 'prices',
data: [10, 22, 29, 45, 98, 45, 22],
},
]}
xAxis={{
scaleType: 'band',
data: ['April 1', 'April 2', 'April 3', 'April 4', 'April 5', 'April 6', 'April 7'],
}}
yAxis={{ domain: { min: 0 } }}
>
<XAxis
bandTickMarkPlacement={selectedBandTickMarkPlacement.id}
showLine
showTickMarks
tickMarkSize={8}
/>
<BarPlot />
</CartesianChart>
</VStack>
);
}
```

### Tick Labels

You can customize the tick labels using the `tickLabelFormatter` prop. It will receive the x data value of the tick. Meaning, if data is provided for the axis, it will receive the string label for the tick.
Expand Down
6 changes: 6 additions & 0 deletions packages/mobile-visualization/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ All notable changes to this project will be documented in this file.

<!-- template-start -->

## 3.4.0-beta.11 (1/7/2026 PST)

#### 🐞 Fixes

- Allow customization of axis tick mark and grid line alignment in band scale. [[#291](https://github.com/coinbase/cds/pull/291)]

## 3.4.0-beta.10 (1/6/2026 PST)

#### 🐞 Fixes
Expand Down
2 changes: 1 addition & 1 deletion packages/mobile-visualization/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@coinbase/cds-mobile-visualization",
"version": "3.4.0-beta.10",
"version": "3.4.0-beta.11",
"description": "Coinbase Design System - Mobile Visualization Native",
"repository": {
"type": "git",
Expand Down
61 changes: 19 additions & 42 deletions packages/mobile-visualization/src/chart/axis/Axis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,14 @@ import type React from 'react';

import { type LineComponent } from '../line';
import type { ChartTextChildren, ChartTextProps } from '../text/ChartText';
import { accessoryFadeTransitionDuration, type AxisBandPlacement } from '../utils';

/**
* Animation variants for grouped axis tick labels - initial mount
* Note: Mobile currently doesn't use these variants. Axes render immediately without animation.
* Web uses similar variants with delay to match path enter animation timing.
* Animation transition for axis elements (grid lines, tick marks, tick labels).
* Matches web's axisUpdateAnimationTransition timing.
*/
export const axisTickLabelsInitialAnimationVariants = {
initial: {
opacity: 0,
},
animate: {
opacity: 1,
transition: {
duration: 0,
delay: 0,
},
},
exit: {
opacity: 0,
transition: {
duration: 0.15,
},
},
};

/**
* Animation variants for axis elements - updates (used for both grid lines and tick labels)
*/
export const axisUpdateAnimationVariants = {
initial: {
opacity: 0,
},
animate: {
opacity: 1,
transition: {
duration: 0.15,
delay: 0.15, // For updates: fade out 150ms, then fade in 150ms
},
},
exit: {
opacity: 0,
transition: {
duration: 0.15,
},
},
export const axisUpdateAnimationTransition = {
duration: accessoryFadeTransitionDuration,
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We weren't correctly doing this animation on mobile so I removed it. The initial goal for this functionality was to nicely fade in and out grid lines coinciding with text as that previously wouldn't show immediately.

This is still the case on web but with our new mobile library we can immediately show text, since we are able to synchronously measure the bounding box of it with Skia.


export type AxisTickLabelComponentProps = Pick<
Expand All @@ -70,6 +33,20 @@ export type AxisTickLabelComponentProps = Pick<
export type AxisTickLabelComponent = React.FC<AxisTickLabelComponentProps>;

export type AxisBaseProps = {
/**
* Placement of grid lines relative to each band.
* Options: 'start', 'middle', 'end', 'edges'
* @note This property only applies to band scales.
* @default 'edges'
*/
bandGridLinePlacement?: AxisBandPlacement;
/**
* Placement of tick marks relative to each band.
* Options: 'start', 'middle', 'end', 'edges'
* @note This property only applies to band scales.
* @default 'middle'
*/
bandTickMarkPlacement?: AxisBandPlacement;
Copy link
Contributor Author

@hcopp hcopp Jan 7, 2026

Choose a reason for hiding this comment

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

These props determine the location of the tick mark and grid lines.

/**
* Label text to display for the axis.
*/
Expand Down
Loading