feat: widget update for de-duplication (#4771)
### Description Update widgets with new components from the hyperlane explorer and warp UI. These will be used to replace the current components from both mentioned repo ### Drive-by changes None ### Backward compatibility Not exactly, Spinner and WideChevron were renamed to SpinnerIcon and WideChevronIcon, these must be updated accordingly ### Testing Manual and Visual Testing with storybookpull/4781/head
parent
8ff194dc47
commit
f438d442a5
@ -0,0 +1,11 @@ |
||||
--- |
||||
'@hyperlane-xyz/widgets': minor |
||||
--- |
||||
|
||||
Update widgets with components from explorer and warp ui |
||||
|
||||
- Add icons: Discord, Docs, Github, History, LinkedIn, Medium, Twitter, Wallet and Web |
||||
- Add animation component: Fade component |
||||
- Add components: DatetimeField and SelectField |
||||
- New stories: IconList and Fade |
||||
- Add "Icon" suffix for icons that did not have it |
@ -0,0 +1,28 @@ |
||||
import React, { PropsWithChildren, useEffect, useState } from 'react'; |
||||
|
||||
export function Fade(props: PropsWithChildren<{ show: boolean }>) { |
||||
const { show, children } = props; |
||||
const [render, setRender] = useState(show); |
||||
|
||||
useEffect(() => { |
||||
if (show) setRender(true); |
||||
}, [show]); |
||||
|
||||
const onAnimationEnd = () => { |
||||
if (!show) setRender(false); |
||||
}; |
||||
|
||||
return render ? ( |
||||
<div |
||||
style={{ |
||||
animationName: show ? 'fadeIn' : 'fadeOut', |
||||
animationDuration: '1s', |
||||
//https://github.com/radix-ui/primitives/issues/1074#issuecomment-1089555751
|
||||
animationFillMode: 'forwards', |
||||
}} |
||||
onAnimationEnd={onAnimationEnd} |
||||
> |
||||
{children} |
||||
</div> |
||||
) : null; |
||||
} |
@ -0,0 +1,36 @@ |
||||
import React, { ChangeEvent } from 'react'; |
||||
|
||||
interface Props { |
||||
className?: string; |
||||
timestamp: number | null; |
||||
onChange: (t: number | null) => void; |
||||
name?: string; |
||||
} |
||||
|
||||
export function DatetimeField({ className, timestamp, onChange, name }: Props) { |
||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) => { |
||||
if (!e.target['validity'].valid) { |
||||
onChange(null); |
||||
} else { |
||||
const datetime = e.target['value'] + ':00Z'; |
||||
const newTimestamp = new Date(datetime).getTime(); |
||||
onChange(newTimestamp); |
||||
} |
||||
}; |
||||
|
||||
return ( |
||||
<input |
||||
type="datetime-local" |
||||
value={toShortIsoString(timestamp)} |
||||
onChange={handleChange} |
||||
name={name} |
||||
className={className} |
||||
/> |
||||
); |
||||
} |
||||
|
||||
function toShortIsoString(timestamp: number | null) { |
||||
if (!timestamp) return ''; |
||||
// Trim milliseconds and timezone to match input field format
|
||||
return new Date(timestamp).toISOString().split('.')[0]; |
||||
} |
@ -0,0 +1,45 @@ |
||||
import React, { ChangeEvent } from 'react'; |
||||
|
||||
export type SelectOption = { |
||||
display: string; |
||||
value: string; |
||||
}; |
||||
|
||||
type Props = React.DetailedHTMLProps< |
||||
React.SelectHTMLAttributes<HTMLSelectElement>, |
||||
HTMLSelectElement |
||||
> & { |
||||
options: Array<SelectOption>; |
||||
value: string; |
||||
onValueSelect: (value: string) => void; |
||||
classes?: string; |
||||
}; |
||||
|
||||
export function SelectField({ |
||||
options, |
||||
value, |
||||
onValueSelect, |
||||
classes, |
||||
...passThruProps |
||||
}: Props) { |
||||
const onChangeSelect = (event: ChangeEvent<HTMLSelectElement>) => { |
||||
onValueSelect(event?.target?.value || ''); |
||||
}; |
||||
|
||||
return ( |
||||
<select |
||||
className={`htw-rounded htw-border htw-border-gray-400 htw-bg-transparent htw-px-2 htw-py-1 htw-text-sm htw-font-light invalid:htw-text-gray-400 ${ |
||||
classes || '' |
||||
}`}
|
||||
{...passThruProps} |
||||
value={value} |
||||
onChange={onChangeSelect} |
||||
> |
||||
{options.map((o, i) => ( |
||||
<option key={`option-${i}`} value={o.value}> |
||||
{o.display} |
||||
</option> |
||||
))} |
||||
</select> |
||||
); |
||||
} |
@ -0,0 +1,25 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { ColorPalette } from '../color.js'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _Discord({ color, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 71 55" {...rest}> |
||||
<g clipPath="url(#a)"> |
||||
<path |
||||
d="M60.1 4.9A58.5 58.5 0 0 0 45.4.5l-1.8 3.7a54 54 0 0 0-16.2 0 37.4 37.4 0 0 0-2-3.8A58.4 58.4 0 0 0 10.7 5 60 60 0 0 0 .4 45.6a58.9 58.9 0 0 0 18 8.8 42 42 0 0 0 3.6-5.9l-.1-.3c-2-.7-3.8-1.6-5.6-2.6a.2.2 0 0 1 0-.4 30.3 30.3 0 0 0 1.3-.9 42 42 0 0 0 36 0l1 1c.2 0 .2.2 0 .3-1.7 1-3.6 1.9-5.5 2.6a47.2 47.2 0 0 0 3.8 6.3 58.7 58.7 0 0 0 17.8-9.1A59.5 59.5 0 0 0 60 4.9ZM23.7 37.3c-3.5 0-6.4-3.2-6.4-7.1 0-4 2.9-7.2 6.4-7.2 3.6 0 6.5 3.3 6.4 7.2 0 4-2.8 7.1-6.4 7.1Zm23.6 0c-3.5 0-6.4-3.2-6.4-7.1 0-4 2.9-7.2 6.4-7.2 3.6 0 6.5 3.3 6.4 7.2 0 4-2.8 7.1-6.4 7.1Z" |
||||
fill={color || ColorPalette.Black} |
||||
/> |
||||
</g> |
||||
<defs> |
||||
<clipPath id="a"> |
||||
<path fill={color || ColorPalette.Black} d="M0 0h71v55H0z" /> |
||||
</clipPath> |
||||
</defs> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const DiscordIcon = memo(_Discord); |
@ -0,0 +1,18 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { ColorPalette } from '../color.js'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _DocsIcon({ color, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" {...rest}> |
||||
<path |
||||
fill={color || ColorPalette.Black} |
||||
d="M320-440h320v-80H320v80Zm0 120h320v-80H320v80Zm0 120h200v-80H320v80ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z" |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const DocsIcon = memo(_DocsIcon); |
@ -0,0 +1,18 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { ColorPalette } from '../color.js'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _Github({ color, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" {...rest}> |
||||
<path |
||||
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z" |
||||
fill={color || ColorPalette.Black} |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const GithubIcon = memo(_Github); |
@ -0,0 +1,18 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { ColorPalette } from '../color.js'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _HistoryIcon({ color, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" {...rest}> |
||||
<path |
||||
fill={color || ColorPalette.Black} |
||||
d="M480-120q-138 0-240.5-91.5T122-440h82q14 104 92.5 172T480-200q117 0 198.5-81.5T760-480q0-117-81.5-198.5T480-760q-69 0-129 32t-101 88h110v80H120v-240h80v94q51-64 124.5-99T480-840q75 0 140.5 28.5t114 77q48.5 48.5 77 114T840-480q0 75-28.5 140.5t-77 114q-48.5 48.5-114 77T480-120Zm112-192L440-464v-216h80v184l128 128-56 56Z" |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const HistoryIcon = memo(_HistoryIcon); |
@ -0,0 +1,16 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _Linkedin({ color, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" {...rest}> |
||||
<path |
||||
d="M9 25H4V10h5v15zM6.5 8a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zM27 25h-4.8v-7.3c0-1.74-.04-3.98-2.5-3.98-2.5 0-2.9 1.9-2.9 3.85V25H12V9.99h4.61v2.05h.07a5.08 5.08 0 0 1 4.55-2.42c4.87 0 5.77 3.1 5.77 7.15V25z" |
||||
fill={color} |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const LinkedInIcon = memo(_Linkedin); |
@ -0,0 +1,24 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { ColorPalette } from '../color.js'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _Medium({ color, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
viewBox="0 -55 256 256" |
||||
preserveAspectRatio="xMidYMid" |
||||
fill="none" |
||||
{...rest} |
||||
> |
||||
<path |
||||
fill={color || ColorPalette.Black} |
||||
d="M72.2 0c39.88 0 72.2 32.55 72.2 72.7 0 40.14-32.33 72.69-72.2 72.69-39.87 0-72.2-32.55-72.2-72.7C0 32.56 32.33 0 72.2 0Zm115.3 4.26c19.94 0 36.1 30.64 36.1 68.44 0 37.79-16.16 68.43-36.1 68.43-19.93 0-36.1-30.64-36.1-68.43 0-37.8 16.16-68.44 36.1-68.44Zm55.8 7.13c7.01 0 12.7 27.45 12.7 61.3 0 33.86-5.68 61.32-12.7 61.32-7.01 0-12.7-27.46-12.7-61.31 0-33.86 5.7-61.31 12.7-61.31Z" |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const MediumIcon = memo(_Medium); |
@ -0,0 +1,18 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { ColorPalette } from '../color.js'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _Twitter({ color, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" {...rest}> |
||||
<path |
||||
d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z" |
||||
fill={color || ColorPalette.Black} |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const TwitterIcon = memo(_Twitter); |
@ -0,0 +1,18 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { ColorPalette } from '../color.js'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _WalletIcon({ color, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg viewBox="0 0 17 14" xmlns="http://www.w3.org/2000/svg" {...rest}> |
||||
<path |
||||
d="M3.33333 13.4737C2.41667 13.4737 1.63194 13.1439 0.979167 12.4842C0.326389 11.8246 0 11.0316 0 10.1053V3.36842C0 2.44211 0.326389 1.64912 0.979167 0.989474C1.63194 0.329825 2.41667 0 3.33333 0H13.3333C14.25 0 15.0347 0.329825 15.6875 0.989474C16.3403 1.64912 16.6667 2.44211 16.6667 3.36842V10.1053C16.6667 11.0316 16.3403 11.8246 15.6875 12.4842C15.0347 13.1439 14.25 13.4737 13.3333 13.4737H3.33333ZM3.33333 3.57895H13.3333C13.7361 3.57895 14.1146 3.64211 14.4687 3.76842C14.8229 3.89474 15.1389 4.07719 15.4167 4.31579V3.36842C15.4167 2.77895 15.2153 2.2807 14.8125 1.87368C14.4097 1.46667 13.9167 1.26316 13.3333 1.26316H3.33333C2.75 1.26316 2.25694 1.46667 1.85417 1.87368C1.45139 2.2807 1.25 2.77895 1.25 3.36842V4.31579C1.52778 4.07719 1.84375 3.89474 2.19792 3.76842C2.55208 3.64211 2.93056 3.57895 3.33333 3.57895ZM1.3125 6.4421L11.25 8.86316C11.3472 8.89123 11.4479 8.89474 11.5521 8.87368C11.6562 8.85263 11.7431 8.80702 11.8125 8.73684L15.1458 5.91579C14.9653 5.59298 14.7153 5.33333 14.3958 5.13684C14.0764 4.94035 13.7222 4.84211 13.3333 4.84211H3.33333C2.84722 4.84211 2.41667 4.99298 2.04167 5.29474C1.66667 5.59649 1.42361 5.97895 1.3125 6.4421Z" |
||||
fill={color || ColorPalette.Black} |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const WalletIcon = memo(_WalletIcon); |
@ -0,0 +1,68 @@ |
||||
import React, { memo } from 'react'; |
||||
|
||||
import { ColorPalette } from '../color.js'; |
||||
|
||||
import { DefaultIconProps } from './types.js'; |
||||
|
||||
function _Web({ color = ColorPalette.Black, ...rest }: DefaultIconProps) { |
||||
return ( |
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29 29" {...rest}> |
||||
<path |
||||
fill={color} |
||||
d="m11 18.6-.39.17a13.45 13.45 0 0 0 1.12 2.9 5.25 5.25 0 0 0 2.08 2.24c.36.18.7.26 1.03.26.95 0 2.1-.71 3.1-2.5.46-.82.85-1.8 1.13-2.9a10.3 10.3 0 0 0-8.06-.17Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M20.34 19.46a11.88 11.88 0 0 1-1.88 3.99 9.63 9.63 0 0 0 3.63-2.6 10.3 10.3 0 0 0-1.75-1.4Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M24.41 15.27a9.55 9.55 0 0 1-1.48 4.45l-.53-.49c-.54-.45-1.12-.86-1.74-1.22.08-.45.15-.9.2-1.38l.05-.61c.02-.25.04-.5.04-.75h3.46Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M22.96 9.45a9.55 9.55 0 0 1 1.45 4.42h-3.46a19 19 0 0 0-.28-2.7c.83-.47 1.6-1.06 2.3-1.72Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="m22.05 8.24.07.08c-.54.54-1.14 1.01-1.78 1.42a11.84 11.84 0 0 0-1.91-4.08 9.63 9.63 0 0 1 3.62 2.58Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M16.35 5.53a2.55 2.55 0 0 0-1.51-.57c-.96 0-2.11.72-3.11 2.5-.15.28-.3.57-.43.88l-.24.58c-.17.47-.33.97-.46 1.5a10.24 10.24 0 0 0 8.47 0 12.18 12.18 0 0 0-1.12-2.95 6.02 6.02 0 0 0-1.6-1.94Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M7.54 8.3a9.68 9.68 0 0 1 3.7-2.63 11.9 11.9 0 0 0-1.9 4.07 10.4 10.4 0 0 1-1.8-1.44Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M5.26 13.87A9.53 9.53 0 0 1 6.7 9.45c.69.67 1.46 1.25 2.3 1.73a19 19 0 0 0-.29 2.69H5.26Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M6.73 19.72a9.53 9.53 0 0 1-1.47-4.45h3.46c.03.95.14 1.87.3 2.74a11.33 11.33 0 0 0-2.29 1.7Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M11.24 23.47a9.62 9.62 0 0 1-3.66-2.61c.53-.54 1.12-1.01 1.76-1.41.45 1.6 1.1 2.98 1.9 4.02Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M19.55 15.27a14 14 0 0 1-.2 2.1 11.66 11.66 0 0 0-9.03 0c-.1-.67-.17-1.38-.2-2.1h9.43Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
d="M19.55 13.87h-9.43c.03-.71.1-1.4.2-2.05a11.78 11.78 0 0 0 9.04 0 18.37 18.37 0 0 1 .2 2.05Z" |
||||
/> |
||||
<path |
||||
fill={color} |
||||
fill-rule="evenodd" |
||||
d="M28.84 14.57a14 14 0 1 0-14 14 14 14 0 0 0 14-14Zm-3 0a11 11 0 1 0-22 0 11 11 0 0 0 22 0Z" |
||||
clip-rule="evenodd" |
||||
/> |
||||
</svg> |
||||
); |
||||
} |
||||
|
||||
export const WebIcon = memo(_Web); |
@ -0,0 +1,21 @@ |
||||
import { Meta, StoryObj } from '@storybook/react'; |
||||
import React from 'react'; |
||||
|
||||
import { Fade } from '../animations/Fade'; |
||||
|
||||
function MyFadeAnimation({ show }: { show: boolean }) { |
||||
return ( |
||||
<Fade show={show}> |
||||
<div>Hello Fade</div> |
||||
</Fade> |
||||
); |
||||
} |
||||
|
||||
const meta = { |
||||
title: 'Fade', |
||||
component: MyFadeAnimation, |
||||
} satisfies Meta<typeof MyFadeAnimation>; |
||||
export default meta; |
||||
type Story = StoryObj<typeof meta>; |
||||
|
||||
export const BaseFadeAnimation = { args: { show: false } } satisfies Story; |
@ -0,0 +1,102 @@ |
||||
import { Meta, StoryObj } from '@storybook/react'; |
||||
import React from 'react'; |
||||
|
||||
import * as Hyperlane from '../index'; |
||||
|
||||
interface StoryIconProps { |
||||
width?: number; |
||||
height?: number; |
||||
color?: string; |
||||
direction?: 'n' | 'e' | 's' | 'w'; |
||||
rounded?: boolean; |
||||
} |
||||
|
||||
const iconList = Object.entries(Hyperlane) |
||||
.filter(([name]) => name.includes('Icon') && !name.includes('IconButton')) |
||||
.map(([_, Component]) => Component as React.ComponentType<StoryIconProps>); |
||||
|
||||
function IconList({ |
||||
width, |
||||
height, |
||||
color, |
||||
direction, |
||||
bgColorSeed, |
||||
roundedWideChevron, |
||||
}: { |
||||
width: number; |
||||
height: number; |
||||
color: string; |
||||
direction: 'n' | 'e' | 's' | 'w'; |
||||
bgColorSeed: number | undefined; |
||||
roundedWideChevron: boolean; |
||||
}) { |
||||
return ( |
||||
<> |
||||
<div |
||||
style={{ |
||||
display: 'flex', |
||||
gap: '1rem', |
||||
textAlign: 'center', |
||||
flexWrap: 'wrap', |
||||
}} |
||||
> |
||||
{iconList.map((Icon) => ( |
||||
<IconContainer> |
||||
<span>{Icon.displayName}</span> |
||||
<Icon |
||||
width={width} |
||||
height={height} |
||||
color={color} |
||||
direction={direction} |
||||
rounded={roundedWideChevron} |
||||
/> |
||||
</IconContainer> |
||||
))} |
||||
<IconContainer> |
||||
<span>Circle</span> |
||||
<Hyperlane.Circle size={width} bgColorSeed={bgColorSeed} /> |
||||
</IconContainer> |
||||
</div> |
||||
</> |
||||
); |
||||
} |
||||
|
||||
function IconContainer({ children }: { children: React.ReactNode }) { |
||||
return ( |
||||
<div |
||||
style={{ |
||||
display: 'flex', |
||||
flexDirection: 'column', |
||||
gap: '0.5rem', |
||||
alignItems: 'center', |
||||
width: '120px', |
||||
}} |
||||
> |
||||
{children} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
const meta = { |
||||
title: 'Icon List', |
||||
component: IconList, |
||||
argTypes: { |
||||
direction: { |
||||
options: ['n', 'e', 's', 'w'], |
||||
control: { type: 'select' }, |
||||
}, |
||||
}, |
||||
} satisfies Meta<typeof IconList>; |
||||
export default meta; |
||||
type Story = StoryObj<typeof meta>; |
||||
|
||||
export const DefaultIconList = { |
||||
args: { |
||||
width: 24, |
||||
height: 24, |
||||
color: Hyperlane.ColorPalette.Black, |
||||
direction: 's', |
||||
bgColorSeed: 0, |
||||
roundedWideChevron: false, |
||||
}, |
||||
} satisfies Story; |
Loading…
Reference in new issue