Skip to content

Commit 8f3fa83

Browse files
committed
feat(programs): add ProgramSwitch component for selecting Pyth programs
1 parent 1c85fc6 commit 8f3fa83

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { ProgramType } from '@pythnetwork/xc-admin-common'
2+
import { useProgramContext } from '../contexts/ProgramContext'
3+
import { Menu, Transition } from '@headlessui/react'
4+
import { Fragment } from 'react'
5+
6+
const Arrow = ({ className }: { className?: string }) => (
7+
<svg
8+
className={className}
9+
width="10"
10+
height="6"
11+
viewBox="0 0 10 6"
12+
fill="none"
13+
xmlns="http://www.w3.org/2000/svg"
14+
>
15+
<path
16+
d="M1 1L5 5L9 1"
17+
stroke="currentColor"
18+
strokeWidth="1.5"
19+
strokeLinecap="round"
20+
strokeLinejoin="round"
21+
/>
22+
</svg>
23+
)
24+
25+
/**
26+
* Component that allows users to switch between different Pyth programs
27+
* (Core, Lazer, etc.)
28+
*/
29+
const ProgramSwitch = ({ light = false }: { light?: boolean }) => {
30+
const { programType, setProgramType } = useProgramContext()
31+
32+
// Convert enum to array of options
33+
const programOptions = Object.values(ProgramType).map((value) => ({
34+
value,
35+
// Format display name (e.g., "PYTH_CORE" -> "Pyth Core")
36+
label: value
37+
.split('_')
38+
.map((word) => word.charAt(0) + word.slice(1).toLowerCase())
39+
.join(' '),
40+
}))
41+
42+
return (
43+
<Menu as="div" className="relative z-[3] block w-[180px] text-left">
44+
{({ open }) => (
45+
<>
46+
<Menu.Button
47+
className={`inline-flex w-full items-center justify-between py-3 px-6 text-sm outline-0 ${
48+
light ? 'bg-beige2' : 'bg-darkGray2'
49+
}`}
50+
>
51+
<span className="mr-3">
52+
{programOptions.find((option) => option.value === programType)
53+
?.label || programType}
54+
</span>
55+
<Arrow className={`${open ? 'rotate-180' : ''}`} />
56+
</Menu.Button>
57+
<Transition
58+
as={Fragment}
59+
enter="transition ease-out duration-100"
60+
enterFrom="transform opacity-0 scale-95"
61+
enterTo="transform opacity-100 scale-100"
62+
leave="transition ease-in duration-75"
63+
leaveFrom="transform opacity-100 scale-100"
64+
leaveTo="transform opacity-0 scale-95"
65+
>
66+
<Menu.Items className="absolute right-0 mt-2 w-full origin-top-right">
67+
{programOptions.map((option) => (
68+
<Menu.Item key={option.value}>
69+
{({ active }) => (
70+
<button
71+
className={`block w-full py-3 px-6 text-left text-sm ${
72+
light
73+
? active
74+
? 'bg-beige3'
75+
: 'bg-beige2'
76+
: active
77+
? 'bg-darkGray2'
78+
: 'bg-darkGray'
79+
}`}
80+
onClick={() =>
81+
setProgramType(option.value as ProgramType)
82+
}
83+
>
84+
{option.label}
85+
</button>
86+
)}
87+
</Menu.Item>
88+
))}
89+
</Menu.Items>
90+
</Transition>
91+
</>
92+
)}
93+
</Menu>
94+
)
95+
}
96+
97+
export default ProgramSwitch

governance/xc_admin/packages/xc_admin_frontend/components/tabs/General.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { useMultisigContext } from '../../contexts/MultisigContext'
2929
import { usePythContext } from '../../contexts/PythContext'
3030
import { capitalizeFirstLetter } from '../../utils/capitalizeFirstLetter'
3131
import ClusterSwitch from '../ClusterSwitch'
32+
import ProgramSwitch from '../ProgramSwitch'
3233
import Modal from '../common/Modal'
3334
import Spinner from '../common/Spinner'
3435
import Loadbar from '../loaders/Loadbar'
@@ -960,7 +961,10 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
960961
<div className="container min-h-[50vh]">
961962
<div className="flex justify-between">
962963
<div className="mb-4 md:mb-0">
963-
<ClusterSwitch />
964+
<div className="flex space-x-4 items-center">
965+
<ProgramSwitch />
966+
<ClusterSwitch />
967+
</div>
964968
</div>
965969
</div>
966970
<div className="relative mt-6 flex space-x-4">

governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/Proposals.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ClusterContext } from '../../../contexts/ClusterContext'
55
import { useMultisigContext } from '../../../contexts/MultisigContext'
66
import { PROPOSAL_STATUSES } from './utils'
77
import ClusterSwitch from '../../ClusterSwitch'
8+
import ProgramSwitch from '../../ProgramSwitch'
89
import Loadbar from '../../loaders/Loadbar'
910
import { Select } from '../../Select'
1011
import { useQueryState, parseAsStringLiteral } from 'nuqs'
@@ -195,7 +196,10 @@ const Proposals = () => {
195196
<>
196197
<div className="flex flex-col justify-between md:flex-row">
197198
<div className="mb-4 flex items-center md:mb-0">
198-
<ClusterSwitch />
199+
<div className="flex space-x-4 items-center">
200+
<ProgramSwitch />
201+
<ClusterSwitch />
202+
</div>
199203
</div>
200204
<div className="flex space-x-2">
201205
{refreshData && (

0 commit comments

Comments
 (0)