Skip to content
Draft
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
20 changes: 20 additions & 0 deletions apps/mobile-app/scripts/utils/routes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export const routes = [
getComponent: () =>
require('@coinbase/cds-mobile/overlays/__stories__/AlertVerticalActions.stories').default,
},
{
key: 'AlphaContentCard',
getComponent: () =>
require('@coinbase/cds-mobile/alpha/content-card/__stories__/AlphaContentCard.stories')
.default,
},
{
key: 'AlphaSelect',
getComponent: () =>
Expand Down Expand Up @@ -195,6 +201,11 @@ export const routes = [
getComponent: () =>
require('@coinbase/cds-mobile/controls/__stories__/ControlGroup.stories').default,
},
{
key: 'DataCard',
getComponent: () =>
require('@coinbase/cds-mobile/alpha/data-card/__stories__/DataCard.stories').default,
},
{
key: 'DateInput',
getComponent: () => require('@coinbase/cds-mobile/dates/__stories__/DateInput.stories').default,
Expand Down Expand Up @@ -341,10 +352,19 @@ export const routes = [
getComponent: () =>
require('@coinbase/cds-mobile/animation/__stories__/LottieStatusAnimation.stories').default,
},
{
key: 'MediaCard',
getComponent: () => require('@coinbase/cds-mobile/cards/__stories__/MediaCard.stories').default,
},
{
key: 'MediaChip',
getComponent: () => require('@coinbase/cds-mobile/chips/__stories__/MediaChip.stories').default,
},
{
key: 'MessagingCard',
getComponent: () =>
require('@coinbase/cds-mobile/cards/__stories__/MessagingCard.stories').default,
},
{
key: 'ModalBackButton',
getComponent: () =>
Expand Down
20 changes: 20 additions & 0 deletions apps/mobile-app/src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export const routes = [
getComponent: () =>
require('@coinbase/cds-mobile/overlays/__stories__/AlertVerticalActions.stories').default,
},
{
key: 'AlphaContentCard',
getComponent: () =>
require('@coinbase/cds-mobile/alpha/content-card/__stories__/AlphaContentCard.stories')
.default,
},
{
key: 'AlphaSelect',
getComponent: () =>
Expand Down Expand Up @@ -200,6 +206,11 @@ export const routes = [
getComponent: () =>
require('@coinbase/cds-mobile/controls/__stories__/ControlGroup.stories').default,
},
{
key: 'DataCard',
getComponent: () =>
require('@coinbase/cds-mobile/alpha/data-card/__stories__/DataCard.stories').default,
},
{
key: 'DateInput',
getComponent: () => require('@coinbase/cds-mobile/dates/__stories__/DateInput.stories').default,
Expand Down Expand Up @@ -346,10 +357,19 @@ export const routes = [
getComponent: () =>
require('@coinbase/cds-mobile/animation/__stories__/LottieStatusAnimation.stories').default,
},
{
key: 'MediaCard',
getComponent: () => require('@coinbase/cds-mobile/cards/__stories__/MediaCard.stories').default,
},
{
key: 'MediaChip',
getComponent: () => require('@coinbase/cds-mobile/chips/__stories__/MediaChip.stories').default,
},
{
key: 'MessagingCard',
getComponent: () =>
require('@coinbase/cds-mobile/cards/__stories__/MessagingCard.stories').default,
},
{
key: 'ModalBackButton',
getComponent: () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ import {
withTiming,
} from 'react-native-reanimated';
import type { ThemeVars } from '@coinbase/cds-common/core/theme';
import { assets } from '@coinbase/cds-common/internal/data/assets';
import { assets, ethBackground } from '@coinbase/cds-common/internal/data/assets';
import { candles as btcCandles } from '@coinbase/cds-common/internal/data/candles';
import { prices } from '@coinbase/cds-common/internal/data/prices';
import { sparklineInteractiveData } from '@coinbase/cds-common/internal/visualizations/SparklineInteractiveData';
import { useTabsContext } from '@coinbase/cds-common/tabs/TabsContext';
import type { TabValue } from '@coinbase/cds-common/tabs/useTabs';
import { NoopFn } from '@coinbase/cds-common/utils/mockUtils';
import { useTheme } from '@coinbase/cds-mobile';
import { DataCard } from '@coinbase/cds-mobile/alpha/data-card/DataCard';
import { Button, IconButton } from '@coinbase/cds-mobile/buttons';
import { ListCell } from '@coinbase/cds-mobile/cells';
import { Example, ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
import { ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
import { Box, type BoxBaseProps, HStack, VStack } from '@coinbase/cds-mobile/layout';
import { Avatar, RemoteImage } from '@coinbase/cds-mobile/media';
import { NavigationTitleSelect } from '@coinbase/cds-mobile/navigation';
import { SectionHeader } from '@coinbase/cds-mobile/section-header/SectionHeader';
import { Pressable } from '@coinbase/cds-mobile/system';
import { type TabComponent, type TabsActiveIndicatorProps } from '@coinbase/cds-mobile/tabs';
Expand All @@ -38,7 +41,7 @@ import {

import { Area, DottedArea, type DottedAreaProps } from '../../area';
import { DefaultAxisTickLabel, XAxis, YAxis } from '../../axis';
import { BarChart, type BarComponentProps, BarPlot } from '../../bar';
import { type BarComponentProps, BarPlot } from '../../bar';
import { CartesianChart } from '../../CartesianChart';
import { useCartesianChartContext } from '../../ChartProvider';
import { PeriodSelector, PeriodSelectorActiveIndicator } from '../../PeriodSelector';
Expand Down Expand Up @@ -2281,6 +2284,106 @@ function TwoLineScrubberLabel() {
</VStack>
);
}
function DataCardWithLineChart() {
const exampleThumbnail = (
<RemoteImage accessibilityLabel="Ethereum" source={ethBackground} testID="thumbnail" />
);

const getLineChartSeries = () => [
{
id: 'price',
data: prices.slice(0, 30).map((price: string) => parseFloat(price)),
color: 'accentBoldBlue',
},
];

const lineChartSeries = useMemo(() => getLineChartSeries(), []);
const lineChartSeries2 = useMemo(() => getLineChartSeries(), []);
const ref = useRef<View>(null);

return (
<VStack gap={2}>
<DataCard
layout="vertical"
subtitle="Price trend"
thumbnail={exampleThumbnail}
title="Line Chart Card"
>
<LineChart
showArea
accessibilityLabel="Ethereum price chart"
areaType="dotted"
height={120}
inset={0}
series={lineChartSeries}
/>
</DataCard>
<DataCard
layout="vertical"
subtitle="Price trend"
tag="Trending"
thumbnail={exampleThumbnail}
title="Line Chart with Tag"
>
<LineChart
showArea
accessibilityLabel="Ethereum price chart"
areaType="dotted"
height={100}
inset={0}
series={lineChartSeries}
/>
</DataCard>
<DataCard
ref={ref}
renderAsPressable
layout="vertical"
onPress={NoopFn}
subtitle="Clickable line chart card"
tag="Interactive"
thumbnail={exampleThumbnail}
title="Actionable Line Chart"
>
<LineChart
showArea
accessibilityLabel="Ethereum price chart"
areaType="dotted"
height={120}
inset={0}
series={lineChartSeries}
showXAxis={false}
showYAxis={false}
/>
</DataCard>
<DataCard
layout="vertical"
subtitle="Price trend"
tag="Trending"
thumbnail={
<RemoteImage
accessibilityLabel="Bitcoin"
shape="circle"
size="l"
source={assets.btc.imageUrl}
testID="thumbnail"
/>
}
title="Card with Line Chart"
>
<LineChart
showArea
accessibilityLabel="Price chart"
areaType="dotted"
height={100}
inset={0}
series={lineChartSeries2}
showXAxis={false}
showYAxis={false}
/>
</DataCard>
</VStack>
);
}

type ExampleItem = {
title: string;
Expand Down Expand Up @@ -2542,20 +2645,22 @@ function ExampleNavigator() {
title: 'Two-Line Scrubber Label',
component: <TwoLineScrubberLabel />,
},
{
title: 'In DataCard',
component: <DataCardWithLineChart />,
},
],
[theme.color.fg, theme.color.fgPositive, theme.spectrum.gray50],
);

const currentExample = examples[currentIndex];
const isFirstExample = currentIndex === 0;
const isLastExample = currentIndex === examples.length - 1;

const handlePrevious = useCallback(() => {
setCurrentIndex((prev) => Math.max(0, prev - 1));
}, []);
setCurrentIndex((prev) => (prev - 1 + examples.length) % examples.length);
}, [examples.length]);

const handleNext = useCallback(() => {
setCurrentIndex((prev) => Math.min(examples.length - 1, prev + 1));
setCurrentIndex((prev) => (prev + 1 + examples.length) % examples.length);
}, [examples.length]);

return (
Expand All @@ -2565,12 +2670,11 @@ function ExampleNavigator() {
<IconButton
accessibilityHint="Navigate to previous example"
accessibilityLabel="Previous"
disabled={isFirstExample}
name="arrowLeft"
onPress={handlePrevious}
variant="secondary"
/>
<VStack alignItems="center" gap={1}>
<VStack alignItems="center">
<Text font="title3">{currentExample.title}</Text>
<Text color="fgMuted" font="label1">
{currentIndex + 1} / {examples.length}
Expand All @@ -2579,7 +2683,6 @@ function ExampleNavigator() {
<IconButton
accessibilityHint="Navigate to next example"
accessibilityLabel="Next"
disabled={isLastExample}
name="arrowRight"
onPress={handleNext}
variant="secondary"
Expand Down
25 changes: 25 additions & 0 deletions packages/mobile/src/alpha/content-card/ContentCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { forwardRef, memo } from 'react';
import type { View } from 'react-native';

import { VStack } from '../../layout';
import { Pressable, type PressableProps } from '../../system';

export type ContentCardBaseProps = {
children: React.ReactNode;
renderAsPressable?: boolean;
};

export type ContentCardProps = ContentCardBaseProps & PressableProps;

export const ContentCard = memo(
forwardRef<View, ContentCardProps>(({ children, renderAsPressable, ...props }, ref) => {
const Component = renderAsPressable ? Pressable : VStack;
return (
<Component ref={ref} borderRadius={500} {...props}>
{children}
</Component>
);
}),
);

ContentCard.displayName = 'ContentCard';
Loading