Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
31a8d6be
Commit
31a8d6be
authored
Feb 03, 2025
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
styles for sort button
parent
3cfd4d1a
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
339 additions
and
321 deletions
+339
-321
eslint.config.mjs
eslint.config.mjs
+1
-0
icon-button.tsx
toolkit/chakra/icon-button.tsx
+1
-0
select.tsx
toolkit/chakra/select.tsx
+36
-14
semanticTokens.ts
toolkit/theme/foundations/semanticTokens.ts
+19
-8
badge.recipe.ts
toolkit/theme/recipes/badge.recipe.ts
+1
-0
select.recipe.ts
toolkit/theme/recipes/select.recipe.ts
+101
-131
transaction.ts
types/api/transaction.ts
+1
-1
Chakra.tsx
ui/pages/Chakra.tsx
+4
-23
Utilization.tsx
ui/shared/Utilization/Utilization.tsx
+3
-3
Select.tsx
ui/shared/select/Select.tsx
+1
-0
types.ts
ui/shared/select/types.ts
+1
-1
ButtonDesktop.tsx
ui/shared/sort/ButtonDesktop.tsx
+0
-57
ButtonMobile.tsx
ui/shared/sort/ButtonMobile.tsx
+0
-36
Sort.tsx
ui/shared/sort/Sort.tsx
+59
-26
getNextSortValue.ts
ui/shared/sort/getNextSortValue.ts
+2
-2
Select.tsx
ui/showcases/Select.tsx
+83
-0
TxsContent.tsx
ui/txs/TxsContent.tsx
+6
-6
TxsHeaderMobile.tsx
ui/txs/TxsHeaderMobile.tsx
+16
-9
useTxsSort.tsx
ui/txs/useTxsSort.tsx
+4
-4
No files found.
eslint.config.mjs
View file @
31a8d6be
...
...
@@ -28,6 +28,7 @@ const RESTRICTED_MODULES = {
{
name
:
'
ui/shared/chakra/Skeleton
'
,
message
:
'
Please use Skeleton component from toolkit/chakra instead
'
},
{
name
:
'
ui/shared/Tabs/RoutedTabs
'
,
message
:
'
Please use RoutedTabs component from toolkit/components/RoutedTabs instead
'
},
{
name
:
'
ui/shared/chakra/Tag
'
,
message
:
'
Please use Tag component from toolkit/chakra instead
'
},
{
name
:
'
ui/shared/select/Select
'
,
message
:
'
Please use Select component from toolkit/chakra instead
'
},
{
name
:
'
@chakra-ui/react
'
,
importNames
:
[
...
...
toolkit/chakra/icon-button.tsx
View file @
31a8d6be
...
...
@@ -16,6 +16,7 @@ export const IconButton = React.forwardRef<HTMLDivElement, IconButtonProps>(
<
Skeleton
loading=
{
loading
}
ref=
{
ref
}
asChild
>
<
Button
display=
"inline-flex"
justifyContent=
"center"
px=
"0"
py=
"0"
{
...
(
size
?
{
size
}
:
{
height
:
'
auto
',
minW
:
'
auto
'
})
}
...
...
toolkit/chakra/select.tsx
View file @
31a8d6be
...
...
@@ -4,25 +4,43 @@ import type { CollectionItem } from '@chakra-ui/react';
import
{
Select
as
ChakraSelect
,
Portal
}
from
'
@chakra-ui/react
'
;
import
*
as
React
from
'
react
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
CloseButton
}
from
'
./close-button
'
;
import
{
Skeleton
}
from
'
./skeleton
'
;
interface
SelectTrigger
Props
extends
ChakraSelect
.
ControlProps
{
export
interface
SelectControl
Props
extends
ChakraSelect
.
ControlProps
{
clearable
?:
boolean
;
noIndicator
?:
boolean
;
triggerProps
?:
ChakraSelect
.
TriggerProps
;
loading
?:
boolean
;
}
export
const
Select
Trigger
=
React
.
forwardRef
<
export
const
Select
Control
=
React
.
forwardRef
<
HTMLButtonElement
,
Select
Trigger
Props
>
(
function
Select
Trigger
(
props
,
ref
)
{
const
{
children
,
clearable
,
...
rest
}
=
props
;
Select
Control
Props
>
(
function
Select
Control
(
props
,
ref
)
{
const
{
children
,
clearable
,
noIndicator
,
triggerProps
,
loading
,
...
rest
}
=
props
;
return
(
<
ChakraSelect
.
Control
{
...
rest
}
>
<
ChakraSelect
.
Trigger
ref=
{
ref
}
>
{
children
}
</
ChakraSelect
.
Trigger
>
<
Skeleton
loading=
{
loading
}
asChild
>
<
ChakraSelect
.
Control
{
...
rest
}
className=
"group"
>
<
ChakraSelect
.
Trigger
ref=
{
ref
}
{
...
triggerProps
}
>
{
children
}
</
ChakraSelect
.
Trigger
>
{
(
!
noIndicator
||
clearable
)
&&
(
<
ChakraSelect
.
IndicatorGroup
>
{
clearable
&&
<
SelectClearTrigger
/>
}
<
ChakraSelect
.
Indicator
/>
{
!
noIndicator
&&
(
<
ChakraSelect
.
Indicator
transform=
"rotate(-90deg)"
_open=
{
{
transform
:
'
rotate(90deg)
'
}
}
flexShrink=
{
0
}
>
<
IconSvg
name=
"arrows/east-mini"
/>
</
ChakraSelect
.
Indicator
>
)
}
</
ChakraSelect
.
IndicatorGroup
>
)
}
</
ChakraSelect
.
Control
>
</
Skeleton
>
);
});
...
...
@@ -68,8 +86,10 @@ export const SelectItem = React.forwardRef<
const
{
item
,
children
,
...
rest
}
=
props
;
return
(
<
ChakraSelect
.
Item
key=
{
item
.
value
}
item=
{
item
}
{
...
rest
}
ref=
{
ref
}
>
<
ChakraSelect
.
ItemIndicator
asChild
>
<
IconSvg
name=
"check"
boxSize=
{
5
}
flexShrink=
{
0
}
/>
</
ChakraSelect
.
ItemIndicator
>
{
children
}
<
ChakraSelect
.
ItemIndicator
/>
</
ChakraSelect
.
Item
>
);
});
...
...
@@ -100,6 +120,8 @@ export const SelectValueText = React.forwardRef<
);
});
export
interface
SelectRootProps
extends
ChakraSelect
.
RootProps
{}
export
const
SelectRoot
=
React
.
forwardRef
<
HTMLDivElement
,
ChakraSelect
.
RootProps
...
...
@@ -108,7 +130,7 @@ export const SelectRoot = React.forwardRef<
<
ChakraSelect
.
Root
{
...
props
}
ref=
{
ref
}
positioning=
{
{
sameWidth
:
tru
e
,
...
props
.
positioning
}
}
positioning=
{
{
sameWidth
:
fals
e
,
...
props
.
positioning
}
}
>
{
props
.
asChild
?
(
props
.
children
...
...
toolkit/theme/foundations/semanticTokens.ts
View file @
31a8d6be
...
...
@@ -238,15 +238,26 @@ const semanticTokens: ThemingConfig['semanticTokens'] = {
},
},
select
:
{
trigger
:
{
outline
:
{
fg
:
{
value
:
{
_light
:
'
{colors.blackAlpha.800}
'
,
_dark
:
'
{colors.whiteAlpha.800}
'
}
},
border
:
{
value
:
{
_light
:
'
{colors.gray.200}
'
,
_dark
:
'
{colors.gray.600}
'
}
},
},
filter
:
{
fg
:
{
DEFAULT
:
{
value
:
{
_light
:
'
{colors.blackAlpha.800}
'
,
_dark
:
'
{colors.whiteAlpha.800}
'
}
},
hover
:
{
value
:
'
{colors.blue.400}
'
},
error
:
{
value
:
'
{colors.red.500}
'
},
selected
:
{
value
:
{
_light
:
'
{colors.blue.600}
'
,
_dark
:
'
{colors.gray.50}
'
}
},
},
border
:
{
DEFAULT
:
{
value
:
{
_light
:
'
{colors.gray.300}
'
,
_dark
:
'
{colors.gray.600}
'
}
},
hover
:
{
value
:
'
{colors.blue.400}
'
},
error
:
{
value
:
'
{colors.red.500}
'
},
DEFAULT
:
{
value
:
{
_light
:
'
{colors.gray.200}
'
,
_dark
:
'
{colors.gray.600}
'
}
},
selected
:
{
value
:
{
_light
:
'
{colors.blue.50}
'
,
_dark
:
'
{colors.gray.600}
'
}
},
},
},
},
item
:
{
bg
:
{
highlighted
:
{
value
:
{
_light
:
'
{colors.blue.50}
'
,
_dark
:
'
{colors.whiteAlpha.100}
'
}
},
},
},
},
spinner
:
{
...
...
toolkit/theme/recipes/badge.recipe.ts
View file @
31a8d6be
...
...
@@ -10,6 +10,7 @@ export const recipe = defineRecipe({
width
:
'
fit-content
'
,
maxWidth
:
'
100%
'
,
whiteSpace
:
'
nowrap
'
,
fontVariantNumeric
:
'
normal
'
,
userSelect
:
'
none
'
,
_loading
:
{
borderRadius
:
'
sm
'
,
...
...
toolkit/theme/recipes/select.recipe.ts
View file @
31a8d6be
...
...
@@ -13,24 +13,20 @@ export const recipe = defineSlotRecipe({
trigger
:
{
display
:
'
flex
'
,
alignItems
:
'
center
'
,
justifyContent
:
'
space-between
'
,
justifyContent
:
'
flex-start
'
,
width
:
'
full
'
,
minH
:
'
var(--select-trigger-height)
'
,
px
:
'
var(--select-trigger-padding-x)
'
,
pr
:
'
var(--select-trigger-padding-right)
'
,
pl
:
'
var(--select-trigger-padding-left)
'
,
borderRadius
:
'
base
'
,
userSelect
:
'
none
'
,
textAlign
:
'
start
'
,
fontWeight
:
'
500
'
,
fontWeight
:
'
semibold
'
,
cursor
:
'
pointer
'
,
focusVisibleRing
:
'
none
'
,
_placeholderShown
:
{
color
:
'
gray.500
'
,
},
_disabled
:
{
layerStyle
:
'
disabled
'
,
},
_invalid
:
{
borderColor
:
'
select.border.error
'
,
},
},
indicatorGroup
:
{
display
:
'
flex
'
,
...
...
@@ -40,7 +36,7 @@ export const recipe = defineSlotRecipe({
right
:
'
0
'
,
top
:
'
0
'
,
bottom
:
'
0
'
,
px
:
'
var(--select-trigger-padding-x)
'
,
px
:
'
0
'
,
pointerEvents
:
'
none
'
,
},
indicator
:
{
...
...
@@ -48,17 +44,27 @@ export const recipe = defineSlotRecipe({
alignItems
:
'
center
'
,
justifyContent
:
'
center
'
,
color
:
'
inherit
'
,
_groupHover
:
{
color
:
'
link.primary.hover
'
,
},
_open
:
{
color
:
'
link.primary.hover
'
,
},
},
content
:
{
background
:
'
popover.bg
'
,
display
:
'
flex
'
,
flexDirection
:
'
column
'
,
zIndex
:
'
dropdown
'
,
borderRadius
:
'
base
'
,
borderRadius
:
'
md
'
,
borderWidth
:
'
0
'
,
outline
:
0
,
boxShadow
:
'
popover
'
,
boxShadowColor
:
'
colors.popover.shadow
'
,
maxH
:
'
96
'
,
overflowY
:
'
auto
'
,
boxShadow
:
'
md
'
,
width
:
'
max-content
'
,
minWidth
:
'
150px
'
,
_open
:
{
animationStyle
:
'
slide-fade-in
'
,
animationDuration
:
'
fast
'
,
...
...
@@ -74,14 +80,11 @@ export const recipe = defineSlotRecipe({
display
:
'
flex
'
,
alignItems
:
'
center
'
,
gap
:
'
2
'
,
cursor
:
'
option
'
,
justifyContent
:
'
space-between
'
,
cursor
:
'
pointer
'
,
justifyContent
:
'
flex-start
'
,
flex
:
'
1
'
,
textAlign
:
'
start
'
,
borderRadius
:
'
base
'
,
_highlighted
:
{
bg
:
'
bg.emphasized/60
'
,
},
borderRadius
:
'
none
'
,
_disabled
:
{
pointerEvents
:
'
none
'
,
opacity
:
'
0.5
'
,
...
...
@@ -90,6 +93,9 @@ export const recipe = defineSlotRecipe({
width
:
'
4
'
,
height
:
'
4
'
,
},
_highlighted
:
{
bg
:
'
select.item.bg.highlighted
'
,
},
},
control
:
{
pos
:
'
relative
'
,
...
...
@@ -122,160 +128,124 @@ export const recipe = defineSlotRecipe({
variant
:
{
outline
:
{
trigger
:
{
bg
:
'
transparent
'
,
borderWidth
:
'
2px
'
,
borderColor
:
'
select.border
'
,
color
:
'
select.trigger.outline.fg
'
,
bgColor
:
'
transparent
'
,
borderColor
:
'
select.trigger.outline.border
'
,
_expanded
:
{
borderColor
:
'
select.border.hover
'
,
color
:
'
link.primary.hover
'
,
borderColor
:
'
link.primary.hover
'
,
},
_hover
:
{
borderColor
:
'
select.border.hover
'
,
color
:
'
link.primary.hover
'
,
borderColor
:
'
link.primary.hover
'
,
},
_focusVisible
:
{
borderColor
:
'
select.border
.hover
'
,
borderColor
:
'
link.primary
.hover
'
,
focusVisibleRing
:
'
none
'
,
},
_invalid
:
{
borderColor
:
'
border.error
'
,
},
},
},
size
:
{
xs
:
{
root
:
{
'
--select-trigger-height
'
:
'
sizes.8
'
,
'
--select-trigger-padding-x
'
:
'
spacing.2
'
,
},
content
:
{
p
:
'
1
'
,
gap
:
'
1
'
,
textStyle
:
'
xs
'
,
},
filter
:
{
trigger
:
{
textStyle
:
'
xs
'
,
gap
:
'
1
'
,
},
item
:
{
py
:
'
1
'
,
px
:
'
2
'
,
borderWidth
:
'
2px
'
,
color
:
'
select.trigger.filter.fg.selected
'
,
bgColor
:
'
select.trigger.filter.border.selected
'
,
borderColor
:
'
select.trigger.filter.border.selected
'
,
_expanded
:
{
color
:
'
link.primary.hover
'
,
borderColor
:
'
link.primary.hover
'
,
},
itemGroupLabel
:
{
py
:
'
1
'
,
px
:
'
2
'
,
_hover
:
{
color
:
'
select.trigger.filter.fg.selected
'
,
borderColor
:
'
select.trigger.filter.border.selected
'
,
},
indicator
:
{
_icon
:
{
width
:
'
3.5
'
,
height
:
'
3.5
'
,
_focusVisible
:
{
borderColor
:
'
link.primary.hover
'
,
focusVisibleRing
:
'
none
'
,
},
_placeholderShown
:
{
color
:
'
select.trigger.filter.fg
'
,
borderColor
:
'
select.trigger.filter.border
'
,
bgColor
:
'
transparent
'
,
_hover
:
{
color
:
'
link.primary.hover
'
,
borderColor
:
'
link.primary.hover
'
,
},
},
sm
:
{
root
:
{
'
--select-trigger-height
'
:
'
sizes.9
'
,
'
--select-trigger-padding-x
'
:
'
spacing.2.5
'
,
},
content
:
{
p
:
'
1
'
,
textStyle
:
'
sm
'
,
},
sort
:
{
trigger
:
{
textStyle
:
'
sm
'
,
gap
:
'
1
'
,
borderWidth
:
'
2px
'
,
borderColor
:
'
transparent
'
,
bgColor
:
'
transparent
'
,
_hover
:
{
color
:
'
link.primary.hover
'
,
borderColor
:
'
link.primary.hover
'
,
},
indicator
:
{
_icon
:
{
width
:
'
4
'
,
height
:
'
4
'
,
_open
:
{
bg
:
'
button.dropdown.border.selected
'
,
color
:
'
button.dropdown.fg.selected
'
,
borderColor
:
'
button.dropdown.border.selected
'
,
_hover
:
{
bg
:
'
button.dropdown.border.selected
'
,
color
:
'
button.dropdown.fg.selected
'
,
borderColor
:
'
button.dropdown.border.selected
'
,
},
},
item
:
{
py
:
'
1
'
,
px
:
'
1.5
'
,
},
itemGroup
:
{
mt
:
'
1
'
,
},
itemGroupLabel
:
{
py
:
'
1
'
,
px
:
'
1.5
'
,
},
},
md
:
{
size
:
{
sm
:
{
root
:
{
'
--select-trigger-height
'
:
'
sizes.10
'
,
'
--select-trigger-padding-x
'
:
'
spacing.3
'
,
'
--select-trigger-height
'
:
'
sizes.8
'
,
'
--select-trigger-padding-right
'
:
'
spacing.8
'
,
'
--select-trigger-padding-left
'
:
'
spacing.2
'
,
},
content
:
{
p
:
'
1
'
,
textStyle
:
'
sm
'
,
},
itemGroup
:
{
mt
:
'
1.5
'
,
},
item
:
{
py
:
'
1.5
'
,
px
:
'
2
'
,
},
itemIndicator
:
{
display
:
'
flex
'
,
alignItems
:
'
center
'
,
justifyContent
:
'
center
'
,
},
itemGroupLabel
:
{
py
:
'
1.5
'
,
px
:
'
2
'
,
px
:
'
0
'
,
py
:
'
2
'
,
textStyle
:
'
md
'
,
},
trigger
:
{
textStyle
:
'
sm
'
,
gap
:
'
2
'
,
gap
:
'
1
'
,
},
indicator
:
{
_icon
:
{
width
:
'
4
'
,
height
:
'
4
'
,
},
},
},
lg
:
{
root
:
{
'
--select-trigger-height
'
:
'
sizes.12
'
,
'
--select-trigger-padding-x
'
:
'
spacing.4
'
,
},
content
:
{
p
:
'
1.5
'
,
textStyle
:
'
md
'
,
width
:
'
5
'
,
height
:
'
5
'
,
},
itemGroup
:
{
mt
:
'
2
'
,
indicatorGroup
:
{
pr
:
'
2
'
,
pl
:
'
1
'
,
},
item
:
{
py
:
'
2
'
,
px
:
'
3
'
,
pr
:
'
4
'
,
pl
:
'
44px
'
,
_selected
:
{
px
:
'
4
'
,
},
itemGroupLabel
:
{
py
:
'
2
'
,
px
:
'
3
'
,
},
trigger
:
{
textStyle
:
'
md
'
,
py
:
'
3
'
,
gap
:
'
2
'
,
},
indicator
:
{
_icon
:
{
width
:
'
5
'
,
height
:
'
5
'
,
itemGroup
:
{
mt
:
'
1
'
,
},
itemGroupLabel
:
{
py
:
'
1
'
,
px
:
'
1.5
'
,
},
},
},
},
defaultVariants
:
{
size
:
'
md
'
,
size
:
'
sm
'
,
variant
:
'
outline
'
,
},
});
types/api/transaction.ts
View file @
31a8d6be
...
...
@@ -191,7 +191,7 @@ export interface TransactionsSorting {
export
type
TransactionsSortingField
=
TransactionsSorting
[
'
sort
'
];
export
type
TransactionsSortingValue
=
`
${
TransactionsSortingField
}
-
${
TransactionsSorting
[
'
order
'
]
}
`
;
export
type
TransactionsSortingValue
=
`
${
TransactionsSortingField
}
-
${
TransactionsSorting
[
'
order
'
]
}
`
|
'
default
'
;
export
type
ScrollTransactionData
=
{
l1_fee
:
string
;
...
...
ui/pages/Chakra.tsx
View file @
31a8d6be
/* eslint-disable max-len */
/* eslint-disable react/jsx-no-bind */
import
{
createListCollection
,
HStack
,
Spinner
,
VStack
}
from
'
@chakra-ui/react
'
;
import
{
HStack
,
Spinner
,
VStack
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
...
...
@@ -12,7 +12,6 @@ import { InputGroup } from 'toolkit/chakra/input-group';
import
{
NativeSelectField
,
NativeSelectRoot
}
from
'
toolkit/chakra/native-select
'
;
import
{
PinInput
}
from
'
toolkit/chakra/pin-input
'
;
import
{
ProgressCircleRing
,
ProgressCircleRoot
}
from
'
toolkit/chakra/progress-circle
'
;
import
{
SelectContent
,
SelectItem
,
SelectRoot
,
SelectTrigger
,
SelectValueText
}
from
'
toolkit/chakra/select
'
;
import
{
Skeleton
}
from
'
toolkit/chakra/skeleton
'
;
import
{
Switch
}
from
'
toolkit/chakra/switch
'
;
import
{
TabsContent
,
TabsList
,
TabsRoot
,
TabsTrigger
}
from
'
toolkit/chakra/tabs
'
;
...
...
@@ -27,6 +26,7 @@ import BadgesShowcase from 'ui/showcases/Badges';
import
ButtonShowcase
from
'
ui/showcases/Button
'
;
import
LinksShowcase
from
'
ui/showcases/Links
'
;
import
PaginationShowcase
from
'
ui/showcases/Pagination
'
;
import
SelectsShowcase
from
'
ui/showcases/Select
'
;
import
TabsShowcase
from
'
ui/showcases/Tabs
'
;
import
TagsShowcase
from
'
ui/showcases/Tags
'
;
import
TooltipsShowcase
from
'
ui/showcases/Tooltip
'
;
...
...
@@ -36,15 +36,6 @@ const TEXT = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do ei
const
ChakraShowcases
=
()
=>
{
const
colorMode
=
useColorMode
();
const
frameworks
=
createListCollection
({
items
:
[
{
label
:
'
React.js
'
,
value
:
'
react
'
},
{
label
:
'
Vue.js
'
,
value
:
'
vue
'
},
{
label
:
'
Angular
'
,
value
:
'
angular
'
},
{
label
:
'
Svelte
'
,
value
:
'
svelte
'
},
],
});
return
(
<>
<
PageTitle
title=
"Chakra UI Showcase"
/>
...
...
@@ -60,6 +51,7 @@ const ChakraShowcases = () => {
<
TabsTrigger
value=
"buttons"
>
Buttons
</
TabsTrigger
>
<
TabsTrigger
value=
"links"
>
Links
</
TabsTrigger
>
<
TabsTrigger
value=
"pagination"
>
Pagination
</
TabsTrigger
>
<
TabsTrigger
value=
"selects"
>
Selects
</
TabsTrigger
>
<
TabsTrigger
value=
"tabs"
>
Tabs
</
TabsTrigger
>
<
TabsTrigger
value=
"tags"
>
Tags
</
TabsTrigger
>
<
TabsTrigger
value=
"tooltips"
>
Tooltips
</
TabsTrigger
>
...
...
@@ -72,6 +64,7 @@ const ChakraShowcases = () => {
<
LinksShowcase
/>
<
TabsShowcase
/>
<
PaginationShowcase
/>
<
SelectsShowcase
/>
<
TooltipsShowcase
/>
<
TagsShowcase
/>
...
...
@@ -194,18 +187,6 @@ const ChakraShowcases = () => {
<
section
>
<
Heading
textStyle=
"heading.md"
mb=
{
2
}
>
Select
</
Heading
>
<
HStack
gap=
{
4
}
whiteSpace=
"nowrap"
flexWrap=
"wrap"
>
<
SelectRoot
collection=
{
frameworks
}
>
<
SelectTrigger
w=
"350px"
>
<
SelectValueText
placeholder=
"Select framework"
/>
</
SelectTrigger
>
<
SelectContent
>
{
frameworks
.
items
.
map
((
framework
)
=>
(
<
SelectItem
item=
{
framework
}
key=
{
framework
.
value
}
>
{
framework
.
label
}
</
SelectItem
>
))
}
</
SelectContent
>
</
SelectRoot
>
<
NativeSelectRoot
w=
"350px"
>
<
NativeSelectField
>
<
option
value=
"1"
>
Option 1
</
option
>
...
...
ui/shared/Utilization/Utilization.tsx
View file @
31a8d6be
...
...
@@ -13,13 +13,13 @@ interface Props extends Omit<HTMLChakraProps<'div'>, 'direction'> {
const
WIDTH
=
50
;
const
Utilization
=
({
value
,
colorScheme
=
'
green
'
,
isLoading
,
...
rest
}:
Props
)
=>
{
const
Utilization
=
({
value
,
colorScheme
=
'
green
'
,
isLoading
,
...
rest
}:
Props
,
ref
:
React
.
Ref
<
HTMLDivElement
>
)
=>
{
const
valueString
=
(
clamp
(
value
*
100
||
0
,
0
,
100
)).
toLocaleString
(
undefined
,
{
maximumFractionDigits
:
2
})
+
'
%
'
;
const
colorGrayScheme
=
{
_light
:
'
gray.500
'
,
_dark
:
'
gray.400
'
};
const
color
=
colorScheme
===
'
gray
'
?
colorGrayScheme
:
'
green.500
'
;
return
(
<
Flex
alignItems=
"center"
columnGap=
{
2
}
{
...
rest
}
>
<
Flex
alignItems=
"center"
columnGap=
{
2
}
{
...
rest
}
ref=
{
ref
}
>
<
Skeleton
loading=
{
isLoading
}
w=
{
`${ WIDTH }px`
}
h=
"4px"
borderRadius=
"full"
overflow=
"hidden"
>
<
Box
bg=
{
{
_light
:
'
blackAlpha.200
'
,
_dark
:
'
whiteAlpha.200
'
}
}
h=
"100%"
>
<
Box
bg=
{
color
}
w=
{
valueString
}
h=
"100%"
/>
...
...
@@ -34,4 +34,4 @@ const Utilization = ({ value, colorScheme = 'green', isLoading, ...rest }: Props
);
};
export
default
React
.
memo
(
Utilization
);
export
default
React
.
memo
(
React
.
forwardRef
(
Utilization
)
);
ui/shared/select/Select.tsx
View file @
31a8d6be
...
...
@@ -24,6 +24,7 @@ export interface Props<Value extends string> {
children
?:
(
props
:
InjectedProps
<
Value
>
)
=>
React
.
ReactNode
;
}
// TODO @tom2drum remove this component
const
Select
=
<
Value
extends
string
>
(
{
className
,
isLoading
,
options
,
name
,
defaultValue
,
onChange
,
children
}
: Props
<
Value
>
) =
>
{
const
{
isOpen
,
onToggle
,
onClose
}
=
useDisclosure
();
...
...
ui/shared/select/types.ts
View file @
31a8d6be
export
interface
SelectOption
<
Value
extends
string
=
string
>
{
value
:
Value
|
undefined
;
value
:
Value
;
label
:
string
;
}
ui/shared/sort/ButtonDesktop.tsx
deleted
100644 → 0
View file @
3cfd4d1a
import
{
Box
,
useColorModeValue
,
Button
,
chakra
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
type
ButtonProps
=
{
isActive
:
boolean
;
onClick
:
()
=>
void
;
isLoading
?:
boolean
;
children
:
React
.
ReactNode
;
className
?:
string
;
};
const
ButtonDesktop
=
({
children
,
isActive
,
onClick
,
isLoading
,
className
}:
ButtonProps
,
ref
:
React
.
ForwardedRef
<
HTMLButtonElement
>
)
=>
{
const
primaryColor
=
useColorModeValue
(
'
blackAlpha.800
'
,
'
whiteAlpha.800
'
);
const
secondaryColor
=
useColorModeValue
(
'
blackAlpha.600
'
,
'
whiteAlpha.600
'
);
return
(
<
Skeleton
isLoaded=
{
!
isLoading
}
>
<
Button
className=
{
className
}
ref=
{
ref
}
size=
"sm"
variant=
"outline"
onClick=
{
onClick
}
color=
{
primaryColor
}
fontWeight=
"600"
borderColor=
"transparent"
px=
{
2
}
selected=
{
isActive
}
>
<
Box
as=
{
isActive
?
'
div
'
:
'
span
'
}
color=
{
isActive
?
'
inherit
'
:
secondaryColor
}
fontWeight=
"400"
mr=
{
1
}
transition=
{
isActive
?
'
none
'
:
'
inherit
'
}
>
Sort by
</
Box
>
{
children
}
<
IconSvg
name=
"arrows/east-mini"
boxSize=
{
5
}
ml=
{
1
}
transform=
{
isActive
?
'
rotate(90deg)
'
:
'
rotate(-90deg)
'
}
/>
</
Button
>
</
Skeleton
>
);
};
export
default
chakra
(
React
.
forwardRef
(
ButtonDesktop
));
ui/shared/sort/ButtonMobile.tsx
deleted
100644 → 0
View file @
3cfd4d1a
import
{
IconButton
,
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
type
Props
=
{
onClick
:
()
=>
void
;
isActive
:
boolean
;
className
?:
string
;
isLoading
?:
boolean
;
};
const
ButtonMobile
=
({
onClick
,
isActive
,
className
,
isLoading
}:
Props
,
ref
:
React
.
ForwardedRef
<
HTMLButtonElement
>
)
=>
{
if
(
isLoading
)
{
return
<
Skeleton
className=
{
className
}
w=
"36px"
h=
"32px"
borderRadius=
"base"
/>;
}
return
(
<
IconButton
ref=
{
ref
}
icon=
{
<
IconSvg
name=
"arrows/up-down"
boxSize=
{
5
}
/>
}
aria
-
label=
"sort"
size=
"sm"
variant=
"outline"
colorScheme=
"gray"
minWidth=
"36px"
onClick=
{
onClick
}
isActive=
{
isActive
}
display=
"flex"
className=
{
className
}
/>
);
};
export
default
chakra
(
React
.
forwardRef
(
ButtonMobile
));
ui/shared/sort/Sort.tsx
View file @
31a8d6be
import
{
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
SelectOption
}
from
'
ui/shared/select/types
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
Select
,
{
type
Props
as
SelectProps
}
from
'
ui/shared/select/Select
'
;
import
SortButtonDesktop
from
'
./ButtonDesktop
'
;
import
SortButtonMobile
from
'
./ButtonMobile
'
;
import
{
IconButton
}
from
'
toolkit/chakra/icon-button
'
;
import
type
{
SelectRootProps
,
SelectControlProps
}
from
'
toolkit/chakra/select
'
;
import
{
SelectContent
,
SelectItem
,
SelectRoot
,
SelectControl
,
SelectValueText
}
from
'
toolkit/chakra/select
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
type
Props
<
Value
extends
string
>
=
Omit
<
SelectProps
<
Value
>
,
'
children
'
>
;
export
interface
Props
extends
SelectRootProps
{
controlProps
?:
SelectControlProps
;
isLoading
?:
boolean
;
}
const
Sort
=
<
Sort
extends
string
>
(
{
name
,
options
,
isLoading
,
onChange
,
defaultValue
}
: Props
<
Sort
>
) =
>
{
const
Sort
=
(
props
:
Props
)
=>
{
const
{
collection
,
controlProps
,
isLoading
,
...
rest
}
=
props
;
const
isMobile
=
useIsMobile
(
false
);
const
trigger
=
(()
=>
{
if
(
isMobile
)
{
return
(
<
Select
options=
{
options
}
name=
{
name
}
defaultValue=
{
defaultValue
}
onChange=
{
onChange
}
<
SelectControl
{
...
controlProps
}
triggerProps=
{
{
asChild
:
true
}
}
noIndicator
>
<
IconButton
loading=
{
isLoading
}
aria
-
label=
"sort"
size=
"sm"
variant=
"outline"
colorScheme=
"gray"
width=
"36px"
>
{
({
isOpen
,
onToggle
,
value
})
=>
{
<
IconSvg
name=
"arrows/up-down"
boxSize=
{
5
}
/>
</
IconButton
>
</
SelectControl
>
);
}
return
(
isMobile
?
(
<
SortButtonMobile
isActive=
{
isOpen
||
Boolean
(
value
)
}
onClick=
{
onToggle
}
isLoading=
{
isLoading
}
/>
)
:
(
<
SortButtonDesktop
isActive=
{
isOpen
}
isLoading=
{
isLoading
}
onClick=
{
onToggle
}
>
{
options
.
find
((
option
:
SelectOption
<
Sort
>
)
=>
option
.
value
===
value
||
(
!
option
.
value
&&
!
value
))?.
label
}
</
SortButtonDesktop
>
)
<
SelectControl
{
...
controlProps
}
loading=
{
isLoading
}
>
<
chakra
.
span
flexShrink=
{
0
}
fontWeight=
"normal"
color=
{
{
_light
:
'
blackAlpha.600
'
,
_dark
:
'
whiteAlpha.600
'
}
}
_groupHover=
{
{
color
:
'
inherit
'
}
}
>
Sort by
</
chakra
.
span
>
<
SelectValueText
color=
{
{
_light
:
'
blackAlpha.800
'
,
_dark
:
'
whiteAlpha.800
'
}
}
_groupHover=
{
{
color
:
'
inherit
'
}
}
/>
</
SelectControl
>
);
}
}
</
Select
>
})();
return
(
<
SelectRoot
variant=
{
{
lgDown
:
'
outline
'
,
lg
:
'
sort
'
}
}
collection=
{
collection
}
{
...
rest
}
>
{
trigger
}
<
SelectContent
>
{
collection
.
items
.
map
((
item
)
=>
(
<
SelectItem
item=
{
item
}
key=
{
item
.
value
}
>
{
item
.
label
}
</
SelectItem
>
))
}
</
SelectContent
>
</
SelectRoot
>
);
};
...
...
ui/shared/sort/getNextSortValue.ts
View file @
31a8d6be
export
default
function
getNextSortValue
<
SortField
extends
string
,
Sort
extends
string
>
(
sortSequence
:
Record
<
SortField
,
Array
<
Sort
|
undefined
>>
,
field
:
SortField
,
sortSequence
:
Record
<
SortField
,
Array
<
Sort
>>
,
field
:
SortField
,
)
{
return
(
prevValue
:
Sort
|
undefined
)
=>
{
return
(
prevValue
:
Sort
)
=>
{
const
sequence
=
sortSequence
[
field
];
return
getNextValueFromSequence
(
sequence
,
prevValue
);
};
...
...
ui/showcases/Select.tsx
0 → 100644
View file @
31a8d6be
import
{
createListCollection
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
SelectContent
,
SelectItem
,
SelectRoot
,
SelectControl
,
SelectValueText
}
from
'
toolkit/chakra/select
'
;
import
Sort
from
'
ui/shared/sort/Sort
'
;
import
{
SORT_OPTIONS
}
from
'
ui/txs/useTxsSort
'
;
import
{
Section
,
Container
,
SectionHeader
,
SamplesStack
,
Sample
,
SectionSubHeader
}
from
'
./parts
'
;
const
frameworks
=
createListCollection
({
items
:
[
{
label
:
'
React.js
'
,
value
:
'
react
'
},
{
label
:
'
Vue.js
'
,
value
:
'
vue
'
},
{
label
:
'
Angular
'
,
value
:
'
angular
'
},
{
label
:
'
Svelte
'
,
value
:
'
svelte
'
},
],
});
const
txSortingOptions
=
createListCollection
({
items
:
SORT_OPTIONS
,
});
const
SelectsShowcase
=
()
=>
{
return
(
<
Container
value=
"selects"
>
<
Section
>
<
SectionHeader
>
Variant
</
SectionHeader
>
<
SamplesStack
>
<
Sample
label=
"variant: outline"
>
<
SelectRoot
collection=
{
frameworks
}
variant=
"outline"
defaultValue=
{
[
frameworks
.
items
[
0
].
value
]
}
>
<
SelectControl
w=
"200px"
>
<
SelectValueText
placeholder=
"Select framework"
/>
</
SelectControl
>
<
SelectContent
>
{
frameworks
.
items
.
map
((
framework
)
=>
(
<
SelectItem
item=
{
framework
}
key=
{
framework
.
value
}
>
{
framework
.
label
}
</
SelectItem
>
))
}
</
SelectContent
>
</
SelectRoot
>
</
Sample
>
<
Sample
label=
"variant: filter"
>
<
SelectRoot
collection=
{
frameworks
}
variant=
"filter"
multiple
>
<
SelectControl
w=
"200px"
>
<
SelectValueText
placeholder=
"Select framework"
/>
</
SelectControl
>
<
SelectContent
>
{
frameworks
.
items
.
map
((
framework
)
=>
(
<
SelectItem
item=
{
framework
}
key=
{
framework
.
value
}
>
{
framework
.
label
}
</
SelectItem
>
))
}
</
SelectContent
>
</
SelectRoot
>
</
Sample
>
</
SamplesStack
>
</
Section
>
<
Section
>
<
SectionHeader
>
Examples
</
SectionHeader
>
<
SectionSubHeader
>
Sort
</
SectionSubHeader
>
<
SamplesStack
>
<
Sample
>
<
Sort
name=
"transactions_sorting"
defaultValue=
{
[
txSortingOptions
.
items
[
0
].
value
]
}
collection=
{
txSortingOptions
}
/>
<
Sort
name=
"transactions_sorting"
defaultValue=
{
[
txSortingOptions
.
items
[
0
].
value
]
}
collection=
{
txSortingOptions
}
isLoading
/>
</
Sample
>
</
SamplesStack
>
</
Section
>
</
Container
>
);
};
export
default
React
.
memo
(
SelectsShowcase
);
ui/txs/TxsContent.tsx
View file @
31a8d6be
...
...
@@ -16,10 +16,10 @@ import TxsHeaderMobile from './TxsHeaderMobile';
import
TxsList
from
'
./TxsList
'
;
import
TxsTable
from
'
./TxsTable
'
;
const
SORT_SEQUENCE
:
Record
<
TransactionsSortingField
,
Array
<
TransactionsSortingValue
|
undefined
>>
=
{
value
:
[
'
value-desc
'
,
'
value-asc
'
,
undefined
],
fee
:
[
'
fee-desc
'
,
'
fee-asc
'
,
undefined
],
block_number
:
[
'
block_number-asc
'
,
undefined
],
const
SORT_SEQUENCE
:
Record
<
TransactionsSortingField
,
Array
<
TransactionsSortingValue
>>
=
{
value
:
[
'
value-desc
'
,
'
value-asc
'
,
'
default
'
],
fee
:
[
'
fee-desc
'
,
'
fee-asc
'
,
'
default
'
],
block_number
:
[
'
block_number-asc
'
,
'
default
'
],
};
type
Props
=
{
...
...
@@ -37,8 +37,8 @@ type Props = {
items
?:
Array
<
Transaction
>
;
isPlaceholderData
:
boolean
;
isError
:
boolean
;
setSorting
:
(
value
:
TransactionsSortingValue
|
undefined
)
=>
void
;
sort
:
TransactionsSortingValue
|
undefined
;
setSorting
:
(
value
:
TransactionsSortingValue
)
=>
void
;
sort
:
TransactionsSortingValue
;
};
const
TxsContent
=
({
...
...
ui/txs/TxsHeaderMobile.tsx
View file @
31a8d6be
import
{
HStack
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
HStack
,
chakra
,
createListCollection
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
TransactionsSortingValue
}
from
'
types/api/transaction
'
;
...
...
@@ -15,8 +15,8 @@ import { SORT_OPTIONS } from './useTxsSort';
// import TxsFilters from './TxsFilters';
type
Props
=
{
sorting
:
TransactionsSortingValue
|
undefined
;
setSorting
:
(
val
:
TransactionsSortingValue
|
undefined
)
=>
void
;
sorting
:
TransactionsSortingValue
;
setSorting
:
(
val
:
TransactionsSortingValue
)
=>
void
;
paginationProps
:
PaginationParams
;
className
?:
string
;
showPagination
?:
boolean
;
...
...
@@ -24,19 +24,26 @@ type Props = {
linkSlot
?:
React
.
ReactNode
;
};
const
collection
=
createListCollection
({
items
:
SORT_OPTIONS
,
});
const
TxsHeaderMobile
=
({
filterComponent
,
sorting
,
setSorting
,
paginationProps
,
className
,
showPagination
=
true
,
linkSlot
}:
Props
)
=>
{
const
handleSortValueChange
=
React
.
useCallback
(({
value
}:
{
value
:
Array
<
string
>
})
=>
{
setSorting
(
value
[
0
]
as
TransactionsSortingValue
);
},
[
setSorting
]);
return
(
<
ActionBar
className=
{
className
}
>
<
HStack
>
{
filterComponent
}
{
/* TODO @tom2drum fix sort select */
}
{
/* <Sort
<
Sort
name=
"transactions_sorting"
defaultValue={
sorting
}
options={ SORT_OPTIONS
}
on
Change={ setSorting
}
defaultValue=
{
[
sorting
]
}
collection=
{
collection
}
on
ValueChange=
{
handleSortValueChange
}
isLoading=
{
paginationProps
.
isLoading
}
/>
*/
}
/>
{
/* api is not implemented */
}
{
/* <FilterInput
// eslint-disable-next-line react/jsx-no-bind
...
...
ui/txs/useTxsSort.tsx
View file @
31a8d6be
...
...
@@ -10,7 +10,7 @@ import * as cookies from 'lib/cookies';
import
sortTxs
from
'
./sortTxs
'
;
export
const
SORT_OPTIONS
:
Array
<
SelectOption
<
TransactionsSortingValue
>>
=
[
{
label
:
'
Default
'
,
value
:
undefined
},
{
label
:
'
Default
'
,
value
:
'
default
'
},
{
label
:
'
Value ascending
'
,
value
:
'
value-asc
'
},
{
label
:
'
Value descending
'
,
value
:
'
value-desc
'
},
{
label
:
'
Fee ascending
'
,
value
:
'
fee-asc
'
},
...
...
@@ -18,7 +18,7 @@ export const SORT_OPTIONS: Array<SelectOption<TransactionsSortingValue>> = [
{
label
:
'
Block number ascending
'
,
value
:
'
block_number-asc
'
},
];
type
SortingValue
=
TransactionsSortingValue
|
undefined
;
type
SortingValue
=
TransactionsSortingValue
;
type
HookResult
=
UseQueryResult
<
TxsResponse
,
ResourceError
<
unknown
>>
&
{
sorting
:
SortingValue
;
...
...
@@ -29,11 +29,11 @@ export default function useTxsSort(
queryResult
:
UseQueryResult
<
TxsResponse
,
ResourceError
<
unknown
>>
,
):
HookResult
{
const
[
sorting
,
setSorting
]
=
React
.
useState
<
SortingValue
>
(
cookies
.
get
(
cookies
.
NAMES
.
TXS_SORT
)
as
SortingValue
);
const
[
sorting
,
setSorting
]
=
React
.
useState
<
SortingValue
>
(
(
cookies
.
get
(
cookies
.
NAMES
.
TXS_SORT
)
as
SortingValue
|
undefined
)
??
'
default
'
);
const
setSortByValue
=
React
.
useCallback
((
value
:
SortingValue
)
=>
{
setSorting
((
prevVal
:
SortingValue
)
=>
{
let
newVal
:
SortingValue
=
undefined
;
let
newVal
:
SortingValue
=
'
default
'
;
if
(
value
!==
prevVal
)
{
newVal
=
value
as
SortingValue
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment