Skip to content

Commit

Permalink
Merge pull request #2211 from pyth-network/cprussin/add-test-feed-toggle
Browse files Browse the repository at this point in the history
feat(insights): add a toggle to include test price components
  • Loading branch information
cprussin authored Dec 22, 2024
2 parents 68c1b81 + 882fb38 commit 26e9d9f
Show file tree
Hide file tree
Showing 16 changed files with 275 additions and 521 deletions.
32 changes: 30 additions & 2 deletions apps/insights/src/components/PriceFeed/price-components-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import { Card } from "@pythnetwork/component-library/Card";
import { Paginator } from "@pythnetwork/component-library/Paginator";
import { Switch } from "@pythnetwork/component-library/Switch";
import {
type RowConfig,
type SortDescriptor,
Table,
} from "@pythnetwork/component-library/Table";
import { type ReactNode, Suspense, useMemo } from "react";
import { type ReactNode, Suspense, useMemo, useState } from "react";
import { useFilter, useCollator } from "react-aria";

import { useQueryParamFilterPagination } from "../../use-query-param-filter-pagination";
Expand All @@ -33,6 +34,7 @@ type PriceComponent = {
deviationScore: number;
stalledPenalty: number;
stalledScore: number;
isTest: boolean;
};

export const PriceComponentsCard = ({
Expand All @@ -56,6 +58,16 @@ const ResolvedPriceComponentsCard = ({
}: Props) => {
const collator = useCollator();
const filter = useFilter({ sensitivity: "base", usage: "search" });
const [includeTestComponents, setIncludeTestComponents] = useState(false);

const filteredPriceComponents = useMemo(
() =>
includeTestComponents
? priceComponents
: priceComponents.filter((component) => !component.isTest),
[includeTestComponents, priceComponents],
);

const {
search,
sortDescriptor,
Expand All @@ -70,7 +82,7 @@ const ResolvedPriceComponentsCard = ({
numPages,
mkPageLink,
} = useQueryParamFilterPagination(
priceComponents,
filteredPriceComponents,
(priceComponent, search) =>
filter.contains(priceComponent.id, search) ||
(priceComponent.publisherNameAsString !== undefined &&
Expand Down Expand Up @@ -181,6 +193,8 @@ const ResolvedPriceComponentsCard = ({

return (
<PriceComponentsCardContents
includeTestComponents={includeTestComponents}
setIncludeTestComponents={setIncludeTestComponents}
numResults={numResults}
search={search}
sortDescriptor={sortDescriptor}
Expand All @@ -206,6 +220,8 @@ type PriceComponentsCardProps = Pick<
| { isLoading: true }
| {
isLoading?: false;
includeTestComponents: boolean;
setIncludeTestComponents: (newValue: boolean) => void;
numResults: number;
search: string;
sortDescriptor: SortDescriptor;
Expand Down Expand Up @@ -237,6 +253,18 @@ const PriceComponentsCardContents = ({
<Card
className={className}
title="Price components"
toolbar={
<Switch
{...(props.isLoading
? { isPending: true }
: {
isSelected: props.includeTestComponents,
onChange: props.setIncludeTestComponents,
})}
>
Show test components
</Switch>
}
{...(!props.isLoading && {
footer: (
<Paginator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const PriceComponents = async ({ children, params }: Props) => {
id: ranking.publisher,
publisherNameAsString: lookupPublisher(ranking.publisher)?.name,
score: ranking.final_score,
isTest: ranking.cluster === "pythtest-conformance",
name: (
<div className={styles.publisherName}>
<PublisherTag publisherKey={ranking.publisher} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
border-color 100ms linear,
outline-color 100ms linear,
color 100ms linear;
background-color: transparent;

&[data-hovered] {
border-color: theme.color("forms", "input", "hover", "border");
Expand Down
10 changes: 4 additions & 6 deletions apps/insights/src/components/PriceFeed/price-feed-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ import {
ListBoxItem,
} from "@pythnetwork/component-library/unstyled/ListBox";
import { Popover } from "@pythnetwork/component-library/unstyled/Popover";
import { SearchField } from "@pythnetwork/component-library/unstyled/SearchField";
import { Select } from "@pythnetwork/component-library/unstyled/Select";
import {
TextField,
Input,
} from "@pythnetwork/component-library/unstyled/TextField";
import { Input } from "@pythnetwork/component-library/unstyled/TextField";
import { type ReactNode, useMemo, useState } from "react";
import { useCollator, useFilter } from "react-aria";

Expand Down Expand Up @@ -66,7 +64,7 @@ export const PriceFeedSelect = ({ children, feeds }: Props) => {
</Button>
<Popover placement="bottom start" className={styles.popover ?? ""}>
<Dialog aria-label="Price Feeds" className={styles.dialog ?? ""}>
<TextField
<SearchField
value={search}
onChange={setSearch}
className={styles.searchField ?? ""}
Expand All @@ -78,7 +76,7 @@ export const PriceFeedSelect = ({ children, feeds }: Props) => {
className={styles.searchInput ?? ""}
placeholder="Symbol, asset class, or key"
/>
</TextField>
</SearchField>
<Virtualizer layout={new ListLayout()}>
<ListBox
items={filteredFeeds}
Expand Down
1 change: 1 addition & 0 deletions packages/component-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"postcss-loader": "catalog:",
"prettier": "catalog:",
"react": "catalog:",
"react-dom": "catalog:",
"sass": "catalog:",
"sass-loader": "catalog:",
"storybook": "catalog:",
Expand Down
5 changes: 5 additions & 0 deletions packages/component-library/src/Drawer/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ const meta = {
category: "Contents",
},
},
closeHref: {
table: {
disable: true,
},
},
},
} satisfies Meta<typeof DrawerComponent>;
export default meta;
Expand Down
5 changes: 5 additions & 0 deletions packages/component-library/src/MainNavTabs/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const meta = {
disable: true,
},
},
pathname: {
table: {
disable: true,
},
},
},
} satisfies Meta<typeof MainNavTabsComponent>;
export default meta;
Expand Down
3 changes: 2 additions & 1 deletion packages/component-library/src/SearchInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { MagnifyingGlass } from "@phosphor-icons/react/dist/ssr/MagnifyingGlass"
import { XCircle } from "@phosphor-icons/react/dist/ssr/XCircle";
import clsx from "clsx";
import { type CSSProperties, type ComponentProps } from "react";
import { Input, SearchField } from "react-aria-components";

import styles from "./index.module.scss";
import { Button } from "../unstyled/Button/index.js";
import { SearchField } from "../unstyled/SearchField/index.js";
import { Input } from "../unstyled/TextField/index.js";

export const SIZES = ["xs", "sm", "md", "lg"] as const;

Expand Down
83 changes: 83 additions & 0 deletions packages/component-library/src/Switch/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
@use "../theme";

.switch {
cursor: pointer;
line-height: theme.spacing(4);

.indicator {
flex: none;
width: theme.spacing(6);
height: theme.spacing(4);
background: theme.color("border");
border-radius: theme.border-radius("2xl");
display: inline-flex;
align-items: center;
padding: 0 theme.spacing(0.5);
margin-right: theme.spacing(2);
justify-content: flex-start;
transition-property: background-color, border-color, outline-color;
transition-duration: 100ms;
transition-timing-function: linear;
border: 1px solid transparent;
outline-offset: 0;
outline: theme.spacing(1) solid transparent;

.dot {
width: theme.spacing(2.5);
height: theme.spacing(2.5);
background-color: theme.color("background", "primary");
border-radius: theme.border-radius("full");
transition: background-color 100ms linear;
}
}

.label {
@include theme.text("sm", "normal");

display: inline-block;
}

&[data-hovered] {
.indicator {
background-color: theme.color("forms", "input", "hover", "border");
}
}

&[data-selected] {
.indicator {
justify-content: flex-end;
background-color: theme.color(
"button",
"primary",
"background",
"normal"
);
}
}

&[data-disabled],
&[data-pending] {
.indicator {
background-color: theme.color("button", "disabled", "background");

.dot {
background-color: theme.color("button", "disabled", "foreground");
}
}
}

&[data-disabled] {
cursor: not-allowed;
}

&[data-pending] {
cursor: wait;
}

&[data-focus-visible] {
.indicator {
border-color: theme.color("focus");
outline-color: theme.color("focus-dim");
}
}
}
41 changes: 41 additions & 0 deletions packages/component-library/src/Switch/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { Meta, StoryObj } from "@storybook/react";

import { Switch as SwitchComponent } from "./index.js";

const meta = {
component: SwitchComponent,
argTypes: {
isDisabled: {
control: "boolean",
table: {
category: "State",
},
},
isPending: {
control: "boolean",
table: {
category: "State",
},
},
onChange: {
table: {
category: "Behavior",
},
},
children: {
control: "text",
table: {
category: "Label",
},
},
},
} satisfies Meta<typeof SwitchComponent>;
export default meta;

export const Switch = {
args: {
children: "Click me!",
isDisabled: false,
isPending: false,
},
} satisfies StoryObj<typeof SwitchComponent>;
46 changes: 46 additions & 0 deletions packages/component-library/src/Switch/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import clsx from "clsx";
import { motion } from "motion/react";
import type { ComponentProps } from "react";

import styles from "./index.module.scss";
import { Switch as UnstyledSwitch } from "../unstyled/Switch/index.js";

type OwnProps = {
isPending?: boolean | undefined;
};
type Props = Omit<ComponentProps<typeof UnstyledSwitch>, keyof OwnProps> &
OwnProps;

export const Switch = ({
children,
className,
isPending,
isDisabled,
...props
}: Props) => (
<UnstyledSwitch
className={clsx(styles.switch, className)}
isDisabled={isDisabled === true || isPending === true}
data-pending={isPending ? "" : undefined}
{...props}
>
{(args) => (
<>
<div className={styles.indicator}>
<motion.div
layout
className={styles.dot}
transition={{
type: "spring",
stiffness: 500,
damping: 20,
}}
/>
</div>
<div className={styles.label}>
{typeof children === "function" ? children(args) : children}
</div>
</>
)}
</UnstyledSwitch>
);
8 changes: 7 additions & 1 deletion packages/component-library/src/TabList/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ const meta = {
disable: true,
},
},
pathname: {
table: {
disable: true,
},
},
},
} satisfies Meta<typeof TabListComponent>;
export default meta;

export const Tabs = {
export const TabList = {
decorators: [
(Story) => (
<UnstyledTabs>
Expand All @@ -24,6 +29,7 @@ export const Tabs = {
),
],
args: {
label: "Tab List",
items: [
{ id: "foo", children: "Foo" },
{ id: "bar", children: "Bar" },
Expand Down
3 changes: 2 additions & 1 deletion packages/component-library/src/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,8 @@ $color: (
"forms": (
"input": (
"hover": (
"border": pallette-color("stone", 400),
"border":
light-dark(pallette-color("stone", 400), pallette-color("steel", 500)),
),
),
),
Expand Down
3 changes: 3 additions & 0 deletions packages/component-library/src/unstyled/SearchField/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"use client";

export { SearchField } from "react-aria-components";
3 changes: 3 additions & 0 deletions packages/component-library/src/unstyled/Switch/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"use client";

export { Switch } from "react-aria-components";
Loading

0 comments on commit 26e9d9f

Please sign in to comment.