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
99cb9b03
Commit
99cb9b03
authored
Feb 21, 2025
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sortable table column header
parent
1bf8899f
Changes
26
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
292 additions
and
192 deletions
+292
-192
link-button.tsx
toolkit/chakra/link-button.tsx
+0
-13
table.tsx
toolkit/chakra/table.tsx
+38
-0
button.recipe.ts
toolkit/theme/recipes/button.recipe.ts
+3
-0
link.recipe.ts
toolkit/theme/recipes/link.recipe.ts
+0
-3
ColumnFilter.tsx
ui/advancedFilter/ColumnFilter.tsx
+7
-10
NameDomainHistory.tsx
ui/nameDomain/NameDomainHistory.tsx
+1
-2
NameDomainHistoryTable.tsx
ui/nameDomain/history/NameDomainHistoryTable.tsx
+13
-24
NameDomainsActionBar.tsx
ui/nameDomains/NameDomainsActionBar.tsx
+4
-3
NameDomainsTable.tsx
ui/nameDomains/NameDomainsTable.tsx
+12
-23
Chakra.tsx
ui/pages/Chakra.tsx
+11
-0
NameDomains.tsx
ui/pages/NameDomains.tsx
+1
-2
TableColumnFilter.tsx
ui/shared/filters/TableColumnFilter.tsx
+4
-8
TokenTypeFilter.tsx
ui/shared/filters/TokenTypeFilter.tsx
+4
-3
TxWatchListTags.tsx
ui/shared/tx/TxWatchListTags.tsx
+2
-3
Menu.tsx
ui/showcases/Menu.tsx
+1
-6
Select.tsx
ui/showcases/Select.tsx
+2
-4
Table.tsx
ui/showcases/Table.tsx
+96
-0
TokensBridgedChainsFilter.tsx
ui/tokens/TokensBridgedChainsFilter.tsx
+4
-3
TxInternals.tsx
ui/tx/TxInternals.tsx
+5
-6
TxBlobsTable.tsx
ui/tx/blobs/TxBlobsTable.tsx
+2
-2
TxInternalsTable.tsx
ui/tx/internals/TxInternalsTable.tsx
+21
-19
TxAdditionalInfo.tsx
ui/txs/TxAdditionalInfo.tsx
+0
-1
TxsContent.tsx
ui/txs/TxsContent.tsx
+3
-3
TxsTable.pw.tsx
ui/txs/TxsTable.pw.tsx
+4
-2
TxsTable.tsx
ui/txs/TxsTable.tsx
+31
-27
VerifiedContractsTable.tsx
ui/verifiedContracts/VerifiedContractsTable.tsx
+23
-25
No files found.
toolkit/chakra/link-button.tsx
deleted
100644 → 0
View file @
1bf8899f
'
use client
'
;
import
type
{
HTMLChakraProps
,
RecipeProps
}
from
'
@chakra-ui/react
'
;
import
{
createRecipeContext
}
from
'
@chakra-ui/react
'
;
export
interface
LinkButtonProps
extends
HTMLChakraProps
<
'
a
'
,
RecipeProps
<
'
button
'
>>
{}
const
{
withContext
}
=
createRecipeContext
({
key
:
'
button
'
});
// TODO @tom2drum style and use this component
// Replace "a" with your framework's link component
export
const
LinkButton
=
withContext
<
HTMLAnchorElement
,
LinkButtonProps
>
(
'
a
'
);
toolkit/chakra/table.tsx
View file @
99cb9b03
...
...
@@ -2,6 +2,10 @@ import { Table as ChakraTable } from '@chakra-ui/react';
import
{
throttle
}
from
'
es-toolkit
'
;
import
*
as
React
from
'
react
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
Link
}
from
'
./link
'
;
export
const
TableRoot
=
ChakraTable
.
Root
;
export
const
TableBody
=
ChakraTable
.
Body
;
export
const
TableHeader
=
ChakraTable
.
Header
;
...
...
@@ -27,6 +31,40 @@ export const TableColumnHeader = (props: TableColumnHeaderProps) => {
return
<
ChakraTable
.
ColumnHeader
textAlign=
{
isNumeric
?
'
right
'
:
undefined
}
{
...
rest
}
/>;
};
export
interface
TableColumnHeaderSortableProps
<
F
extends
string
>
extends
TableColumnHeaderProps
{
sortField
:
F
;
sortValue
:
string
;
onSortToggle
:
(
sortField
:
F
)
=>
void
;
disabled
?:
boolean
;
}
export
const
TableColumnHeaderSortable
=
<
F
extends
string
>
(props: TableColumnHeaderSortableProps
<
F
>
) =
>
{
const
{
sortField
,
sortValue
,
onSortToggle
,
children
,
disabled
,
...
rest
}
=
props
;
const
handleSortToggle
=
React
.
useCallback
(()
=>
{
onSortToggle
(
sortField
);
},
[
onSortToggle
,
sortField
]);
return
(
<
TableColumnHeader
{
...
rest
}
>
<
Link
onClick=
{
disabled
?
undefined
:
handleSortToggle
}
position=
"relative"
>
{
sortValue
.
includes
(
sortField
)
&&
(
<
IconSvg
name=
"arrows/east"
w=
{
4
}
h=
"100%"
transform=
{
sortValue
.
toLowerCase
().
includes
(
'
asc
'
)
?
'
rotate(-90deg)
'
:
'
rotate(90deg)
'
}
position=
"absolute"
left=
{
-
5
}
top=
{
0
}
/>
)
}
{
children
}
</
Link
>
</
TableColumnHeader
>
);
}
;
export interface TableHeaderProps extends ChakraTable.HeaderProps
{
top
?:
number
;
}
...
...
toolkit/theme/recipes/button.recipe.ts
View file @
99cb9b03
...
...
@@ -210,6 +210,9 @@ export const recipe = defineRecipe({
bg
:
'
transparent
'
,
color
:
'
link.primary.hover
'
,
},
_disabled
:
{
color
:
'
text.secondary
'
,
},
},
},
size
:
{
...
...
toolkit/theme/recipes/link.recipe.ts
View file @
99cb9b03
...
...
@@ -15,9 +15,6 @@ export const recipe = defineRecipe({
textDecoration
:
'
none
'
,
color
:
'
link.primary.hover
'
,
},
_disabled
:
{
color
:
'
text.secondary
'
,
},
},
secondary
:
{
color
:
'
link.secondary
'
,
...
...
ui/advancedFilter/ColumnFilter.tsx
View file @
99cb9b03
...
...
@@ -2,11 +2,11 @@ import {
chakra
,
Flex
,
Text
,
Link
,
Button
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
ColumnFilterWrapper
from
'
./ColumnFilterWrapper
'
;
type
Props
=
{
...
...
@@ -40,20 +40,17 @@ const ColumnFilterContent = ({ title, isFilled, onFilter, onReset, onClose, chil
<>
<
Flex
alignItems=
"center"
justifyContent=
"space-between"
mb=
{
3
}
>
<
Text
color=
"text_secondary"
fontWeight=
"600"
>
{
title
}
</
Text
>
<
Link
<
Button
variant=
"link"
onClick=
{
onReset
}
cursor=
{
isFilled
?
'
pointer
'
:
'
unset
'
}
opacity=
{
isFilled
?
1
:
0.2
}
_hover=
{
{
color
:
isFilled
?
'
link_hovered
'
:
'
none
'
,
}
}
disabled=
{
!
isFilled
}
>
Reset
</
Link
>
</
Button
>
</
Flex
>
{
children
}
<
Button
isD
isabled=
{
!
isFilled
}
d
isabled=
{
!
isFilled
}
mt=
{
4
}
onClick=
{
onFilterClick
}
w=
"fit-content"
...
...
ui/nameDomain/NameDomainHistory.tsx
View file @
99cb9b03
...
...
@@ -31,11 +31,10 @@ const NameDomainHistory = ({ domain }: Props) => {
},
});
const
handleSortToggle
=
React
.
useCallback
((
event
:
React
.
MouseEvent
)
=>
{
const
handleSortToggle
=
React
.
useCallback
((
field
:
SortField
)
=>
{
if
(
isPlaceholderData
)
{
return
;
}
const
field
=
(
event
.
currentTarget
as
HTMLDivElement
).
getAttribute
(
'
data-field
'
)
as
SortField
|
undefined
;
if
(
field
)
{
setSort
(
getNextSortValue
(
field
));
...
...
ui/nameDomain/history/NameDomainHistoryTable.tsx
View file @
99cb9b03
...
...
@@ -2,46 +2,35 @@ import React from 'react';
import
type
*
as
bens
from
'
@blockscout/bens-types
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
TableBody
,
TableColumnHeader
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
TableBody
,
TableColumnHeader
,
TableColumnHeaderSortable
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
NameDomainHistoryTableItem
from
'
./NameDomainHistoryTableItem
'
;
import
type
{
Sort
}
from
'
./utils
'
;
import
type
{
Sort
Field
,
Sort
}
from
'
./utils
'
;
import
{
sortFn
}
from
'
./utils
'
;
interface
Props
{
history
:
bens
.
ListDomainEventsResponse
|
undefined
;
domain
:
bens
.
DetailedDomain
|
undefined
;
isLoading
?:
boolean
;
sort
:
Sort
|
undefined
;
onSortToggle
:
(
event
:
React
.
MouseEvent
)
=>
void
;
sort
:
Sort
;
onSortToggle
:
(
field
:
SortField
)
=>
void
;
}
const
NameDomainHistoryTable
=
({
history
,
domain
,
isLoading
,
sort
,
onSortToggle
}:
Props
)
=>
{
const
sortIconTransform
=
sort
?.
includes
(
'
asc
'
)
?
'
rotate(-90deg)
'
:
'
rotate(90deg)
'
;
return
(
<
TableRoot
>
<
TableHeaderSticky
top=
{
0
}
>
<
TableRow
>
<
TableColumnHeader
width=
"25%"
>
Txn hash
</
TableColumnHeader
>
<
TableColumnHeader
width=
"25%"
pl=
{
9
}
>
<
Link
display=
"flex"
alignItems=
"center"
justifyContent=
"flex-start"
position=
"relative"
data
-
field=
"timestamp"
onClick=
{
onSortToggle
}
>
{
sort
?.
includes
(
'
timestamp
'
)
&&
(
<
IconSvg
name=
"arrows/east"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
color=
"link.primary"
position=
"absolute"
left=
{
-
5
}
top=
{
0
}
/>
)
}
<
span
>
Age
</
span
>
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeaderSortable
width=
"25%"
pl=
{
9
}
sortField=
"timestamp"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
>
Age
</
TableColumnHeaderSortable
>
<
TableColumnHeader
width=
"25%"
>
From
</
TableColumnHeader
>
<
TableColumnHeader
width=
"25%"
>
Method
</
TableColumnHeader
>
</
TableRow
>
...
...
ui/nameDomains/NameDomainsActionBar.tsx
View file @
99cb9b03
...
...
@@ -6,9 +6,9 @@ import type { EnsDomainLookupFiltersOptions } from 'types/api/ens';
import
type
{
PaginationParams
}
from
'
ui/shared/pagination/types
'
;
import
useIsInitialLoading
from
'
lib/hooks/useIsInitialLoading
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
Checkbox
}
from
'
toolkit/chakra/checkbox
'
;
import
{
Image
}
from
'
toolkit/chakra/image
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
FilterInput
from
'
ui/shared/filters/FilterInput
'
;
import
PopoverFilter
from
'
ui/shared/filters/PopoverFilter
'
;
...
...
@@ -87,12 +87,13 @@ const NameDomainsActionBar = ({
<>
<
Flex
justifyContent=
"space-between"
textStyle=
"sm"
mb=
{
3
}
>
<
Text
fontWeight=
{
600
}
color=
"text.secondary"
>
Protocol
</
Text
>
<
Link
<
Button
variant=
"link"
onClick=
{
handleProtocolReset
}
disabled=
{
protocolsFilterValue
.
length
===
0
}
>
Reset
</
Link
>
</
Button
>
</
Flex
>
<
Fieldset
.
Root
>
<
CheckboxGroup
defaultValue=
{
protocolsFilterValue
}
onValueChange=
{
onProtocolsFilterChange
}
value=
{
protocolsFilterValue
}
name=
"token_type"
>
...
...
ui/nameDomains/NameDomainsTable.tsx
View file @
99cb9b03
...
...
@@ -2,46 +2,35 @@ import React from 'react';
import
type
*
as
bens
from
'
@blockscout/bens-types
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
TableBody
,
TableColumnHeader
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
{
TableBody
,
TableColumnHeader
,
TableColumnHeaderSortable
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
{
ACTION_BAR_HEIGHT_DESKTOP
}
from
'
ui/shared/ActionBar
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
NameDomainsTableItem
from
'
./NameDomainsTableItem
'
;
import
{
type
Sort
}
from
'
./utils
'
;
import
type
{
SortField
,
Sort
}
from
'
./utils
'
;
interface
Props
{
data
:
bens
.
LookupDomainNameResponse
|
undefined
;
isLoading
?:
boolean
;
sort
:
Sort
;
onSortToggle
:
(
event
:
React
.
MouseEvent
)
=>
void
;
onSortToggle
:
(
field
:
SortField
)
=>
void
;
}
const
NameDomainsTable
=
({
data
,
isLoading
,
sort
,
onSortToggle
}:
Props
)
=>
{
const
sortIconTransform
=
sort
?.
toLowerCase
().
includes
(
'
asc
'
)
?
'
rotate(-90deg)
'
:
'
rotate(90deg)
'
;
return
(
<
TableRoot
>
<
TableHeaderSticky
top=
{
ACTION_BAR_HEIGHT_DESKTOP
}
>
<
TableRow
>
<
TableColumnHeader
width=
"25%"
>
Domain
</
TableColumnHeader
>
<
TableColumnHeader
width=
"25%"
>
Address
</
TableColumnHeader
>
<
TableColumnHeader
width=
"25%"
pl=
{
9
}
>
<
Link
display=
"flex"
alignItems=
"center"
justifyContent=
"flex-start"
position=
"relative"
data
-
field=
"registration_date"
onClick=
{
onSortToggle
}
>
{
sort
?.
includes
(
'
registration_date
'
)
&&
(
<
IconSvg
name=
"arrows/east"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
color=
"link.primary"
position=
"absolute"
left=
{
-
5
}
top=
{
0
}
/>
)
}
<
span
>
Registered on
</
span
>
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeaderSortable
width=
"25%"
pl=
{
9
}
sortField=
"registration_date"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
>
Registered on
</
TableColumnHeaderSortable
>
<
TableColumnHeader
width=
"25%"
>
Expiration date
</
TableColumnHeader
>
</
TableRow
>
</
TableHeaderSticky
>
...
...
ui/pages/Chakra.tsx
View file @
99cb9b03
...
...
@@ -21,12 +21,22 @@ import PinInputShowcase from 'ui/showcases/PinInput';
import
ProgressCircleShowcase
from
'
ui/showcases/ProgressCircle
'
;
import
RadioShowcase
from
'
ui/showcases/Radio
'
;
import
SelectShowcase
from
'
ui/showcases/Select
'
;
import
TableShowcase
from
'
ui/showcases/Table
'
;
import
TabsShowcase
from
'
ui/showcases/Tabs
'
;
import
TagShowcase
from
'
ui/showcases/Tag
'
;
import
TextareaShowcase
from
'
ui/showcases/Textarea
'
;
import
ToastShowcase
from
'
ui/showcases/Toast
'
;
import
TooltipShowcase
from
'
ui/showcases/Tooltip
'
;
// Drawer
// CloseButton
// IconButton
// EmptyState ?
// Rating
// Switch
// ToggleTip
// Popover
const
tabs
=
[
{
label
:
'
Accordion
'
,
value
:
'
accordion
'
,
component
:
<
AccordionsShowcase
/>
},
{
label
:
'
Alert
'
,
value
:
'
alert
'
,
component
:
<
AlertShowcase
/>
},
...
...
@@ -44,6 +54,7 @@ const tabs = [
{
label
:
'
Radio
'
,
value
:
'
radio
'
,
component
:
<
RadioShowcase
/>
},
{
label
:
'
Pin input
'
,
value
:
'
pin-input
'
,
component
:
<
PinInputShowcase
/>
},
{
label
:
'
Select
'
,
value
:
'
select
'
,
component
:
<
SelectShowcase
/>
},
{
label
:
'
Table
'
,
value
:
'
table
'
,
component
:
<
TableShowcase
/>
},
{
label
:
'
Tabs
'
,
value
:
'
tabs
'
,
component
:
<
TabsShowcase
/>
},
{
label
:
'
Tag
'
,
value
:
'
tag
'
,
component
:
<
TagShowcase
/>
},
{
label
:
'
Textarea
'
,
value
:
'
textarea
'
,
component
:
<
TextareaShowcase
/>
},
...
...
ui/pages/NameDomains.tsx
View file @
99cb9b03
...
...
@@ -110,11 +110,10 @@ const NameDomains = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[
isAddressSearch
]);
const
handleSortToggle
=
React
.
useCallback
((
event
:
React
.
MouseEvent
)
=>
{
const
handleSortToggle
=
React
.
useCallback
((
field
:
SortField
)
=>
{
if
(
isLoading
)
{
return
;
}
const
field
=
(
event
.
currentTarget
as
HTMLDivElement
).
getAttribute
(
'
data-field
'
)
as
SortField
|
undefined
;
if
(
field
)
{
setSort
((
prevValue
)
=>
{
...
...
ui/shared/filters/TableColumnFilter.tsx
View file @
99cb9b03
...
...
@@ -6,7 +6,6 @@ import {
import
React
from
'
react
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
PopoverCloseTriggerWrapper
}
from
'
toolkit/chakra/popover
'
;
type
Props
=
{
...
...
@@ -28,16 +27,13 @@ const TableColumnFilter = ({ title, isFilled, isTouched, hasReset, onFilter, onR
<
Flex
alignItems=
"center"
justifyContent=
"space-between"
>
<
Text
color=
"text.secondary"
fontWeight=
"600"
>
{
title
}
</
Text
>
{
hasReset
&&
(
<
Link
<
Button
variant=
"link"
onClick=
{
onReset
}
cursor=
{
isFilled
?
'
pointer
'
:
'
unset
'
}
opacity=
{
isFilled
?
1
:
0.2
}
_hover=
{
{
color
:
isFilled
?
'
link_hovered
'
:
'
none
'
,
}
}
disabled=
{
!
isFilled
}
>
Reset
</
Link
>
</
Button
>
)
}
</
Flex
>
{
children
}
...
...
ui/shared/filters/TokenTypeFilter.tsx
View file @
99cb9b03
...
...
@@ -4,8 +4,8 @@ import React from 'react';
import
type
{
NFTTokenType
,
TokenType
}
from
'
types/api/token
'
;
import
{
TOKEN_TYPES
,
TOKEN_TYPE_IDS
,
NFT_TOKEN_TYPE_IDS
}
from
'
lib/token/tokenTypes
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
Checkbox
}
from
'
toolkit/chakra/checkbox
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
type
Props
<
T
extends
TokenType
|
NFTTokenType
>
=
{
onChange
:
(
nextValue
:
Array
<
T
>
)
=>
void
;
...
...
@@ -32,12 +32,13 @@ const TokenTypeFilter = <T extends TokenType | NFTTokenType>({ nftOnly, onChange
<>
<
Flex
justifyContent=
"space-between"
fontSize=
"sm"
>
<
Text
fontWeight=
{
600
}
color=
"text.secondary"
>
Type
</
Text
>
<
Link
<
Button
variant=
"link"
onClick=
{
handleReset
}
disabled=
{
value
.
length
===
0
}
>
Reset
</
Link
>
</
Button
>
</
Flex
>
<
Fieldset
.
Root
>
<
CheckboxGroup
defaultValue=
{
defaultValue
}
onValueChange=
{
handleChange
}
value=
{
value
}
name=
"token_type"
>
...
...
ui/shared/tx/TxWatchListTags.tsx
View file @
99cb9b03
...
...
@@ -26,9 +26,8 @@ const TxWatchListTags = ({ tx, isLoading }: Props) => {
<
Badge
key=
{
tag
.
label
}
loading=
{
isLoading
}
truncate
// TODO @tom2drum check these styles
// maxW=
{{
base
:
'115
px
',
lg
:
'
initial
'
}}
truncated
maxW=
{
{
base
:
'
115px
'
,
lg
:
'
initial
'
}
}
colorPalette=
"gray"
>
{
tag
.
display_name
}
...
...
ui/showcases/Menu.tsx
View file @
99cb9b03
...
...
@@ -4,7 +4,7 @@ import { IconButton } from 'toolkit/chakra/icon-button';
import
{
MenuContent
,
MenuItem
,
MenuRoot
,
MenuTrigger
}
from
'
toolkit/chakra/menu
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
Section
,
Container
,
SectionHeader
,
SamplesStack
,
Sample
,
SectionSubHeader
}
from
'
./parts
'
;
import
{
Section
,
Container
,
SectionHeader
,
SamplesStack
,
Sample
}
from
'
./parts
'
;
const
MenuShowcase
=
()
=>
{
...
...
@@ -44,11 +44,6 @@ const MenuShowcase = () => {
</
Sample
>
</
SamplesStack
>
</
Section
>
<
Section
>
<
SectionHeader
>
Examples
</
SectionHeader
>
<
SectionSubHeader
>
Example 1
</
SectionSubHeader
>
</
Section
>
</
Container
>
);
};
...
...
ui/showcases/Select.tsx
View file @
99cb9b03
...
...
@@ -23,8 +23,6 @@ const txSortingOptions = createListCollection({
items
:
SORT_OPTIONS
,
});
// TODO @tom2drum + tanya: select with search
const
SelectShowcase
=
()
=>
{
const
[
hasActiveFilter
,
setHasActiveFilter
]
=
React
.
useState
(
false
);
...
...
@@ -52,8 +50,8 @@ const SelectShowcase = () => {
</
SelectRoot
>
</
Sample
>
<
Sample
label=
"variant: filter"
>
<
SelectRoot
collection=
{
frameworks
}
variant=
"filter"
multiple
>
<
SelectControl
w=
"200px"
>
<
SelectRoot
collection=
{
frameworks
}
variant=
"filter"
>
<
SelectControl
w=
"200px"
noIndicator
>
<
SelectValueText
placeholder=
"Select framework"
/>
</
SelectControl
>
<
SelectContent
>
...
...
ui/showcases/Table.tsx
0 → 100644
View file @
99cb9b03
import
{
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
TableColumnHeader
,
TableHeaderSticky
,
TableRoot
,
TableRow
,
TableCell
,
TableBody
,
TableColumnHeaderSortable
}
from
'
toolkit/chakra/table
'
;
import
getNextSortValue
from
'
ui/shared/sort/getNextSortValue
'
;
import
{
Section
,
Container
,
SectionHeader
,
SamplesStack
,
Sample
}
from
'
./parts
'
;
const
ITEMS
=
[
{
id
:
1
,
name
:
'
Laptop
'
,
category
:
'
Electronics
'
,
price
:
999.99
},
{
id
:
2
,
name
:
'
Coffee Maker
'
,
category
:
'
Home Appliances
'
,
price
:
49.99
},
{
id
:
3
,
name
:
'
Desk Chair
'
,
category
:
'
Furniture
'
,
price
:
150.0
},
{
id
:
4
,
name
:
'
Smartphone
'
,
category
:
'
Electronics
'
,
price
:
799.99
},
{
id
:
5
,
name
:
'
Headphones
'
,
category
:
'
Accessories
'
,
price
:
199.99
},
];
type
Item
=
typeof
ITEMS
[
number
];
type
SortField
=
'
category
'
|
'
price
'
;
type
SortValue
=
'
category-asc
'
|
'
category-desc
'
|
'
price-asc
'
|
'
price-desc
'
|
'
default
'
;
const
SORT_SEQUENCE
:
Record
<
SortField
,
Array
<
SortValue
>>
=
{
category
:
[
'
category-desc
'
,
'
category-asc
'
,
'
default
'
],
price
:
[
'
price-desc
'
,
'
price-asc
'
,
'
default
'
],
};
const
TableShowcase
=
()
=>
{
const
[
sort
,
setSort
]
=
React
.
useState
<
SortValue
>
(
'
default
'
);
const
handleSortToggle
=
React
.
useCallback
((
sortField
:
string
)
=>
{
const
value
=
getNextSortValue
<
SortField
,
SortValue
>
(
SORT_SEQUENCE
,
sortField
as
SortField
)(
sort
);
setSort
(
value
);
},
[
sort
,
setSort
]);
const
sortFn
=
(
a
:
Item
,
b
:
Item
)
=>
{
if
(
sort
===
'
category-asc
'
)
{
return
a
.
category
.
localeCompare
(
b
.
category
);
}
if
(
sort
===
'
category-desc
'
)
{
return
b
.
category
.
localeCompare
(
a
.
category
);
}
if
(
sort
===
'
price-asc
'
)
{
return
a
.
price
-
b
.
price
;
}
if
(
sort
===
'
price-desc
'
)
{
return
b
.
price
-
a
.
price
;
}
return
0
;
};
return
(
<
Container
value=
"table"
>
<
Section
>
<
SectionHeader
>
Variant
</
SectionHeader
>
<
SamplesStack
>
<
Sample
label=
"variant: line"
>
<
TableRoot
>
<
TableHeaderSticky
>
<
TableRow
>
<
TableColumnHeader
>
Product
</
TableColumnHeader
>
<
TableColumnHeaderSortable
sortField=
"category"
sortValue=
{
sort
}
onSortToggle=
{
handleSortToggle
}
>
Category
</
TableColumnHeaderSortable
>
<
TableColumnHeaderSortable
sortField=
"price"
sortValue=
{
sort
}
onSortToggle=
{
handleSortToggle
}
isNumeric
>
Price
</
TableColumnHeaderSortable
>
</
TableRow
>
</
TableHeaderSticky
>
<
TableBody
>
{
ITEMS
.
slice
().
sort
(
sortFn
).
map
((
item
)
=>
(
<
TableRow
key=
{
item
.
id
}
>
<
TableCell
>
{
item
.
name
}
</
TableCell
>
<
TableCell
>
{
item
.
category
}
</
TableCell
>
<
TableCell
isNumeric
>
{
item
.
price
}
</
TableCell
>
</
TableRow
>
))
}
</
TableBody
>
</
TableRoot
>
<
Box
h=
"1000px"
/>
</
Sample
>
</
SamplesStack
>
</
Section
>
</
Container
>
);
};
export
default
React
.
memo
(
TableShowcase
);
ui/tokens/TokensBridgedChainsFilter.tsx
View file @
99cb9b03
...
...
@@ -2,8 +2,8 @@ import { CheckboxGroup, Text, Flex, useCheckboxGroup, chakra, Fieldset } from '@
import
React
from
'
react
'
;
import
config
from
'
configs/app
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
Checkbox
}
from
'
toolkit/chakra/checkbox
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
const
feature
=
config
.
features
.
bridgedTokens
;
...
...
@@ -36,12 +36,13 @@ const TokensBridgedChainsFilter = ({ onChange, defaultValue }: Props) => {
<>
<
Flex
justifyContent=
"space-between"
fontSize=
"sm"
>
<
Text
fontWeight=
{
600
}
color=
"text.secondary"
>
Show bridged tokens from
</
Text
>
<
Link
<
Button
variant=
"link"
onClick=
{
handleReset
}
disabled=
{
value
.
length
===
0
}
>
Reset
</
Link
>
</
Button
>
</
Flex
>
<
Fieldset
.
Root
>
<
CheckboxGroup
defaultValue=
{
defaultValue
}
onValueChange=
{
handleChange
}
value=
{
value
}
name=
"bridged_token_chain"
>
...
...
ui/tx/TxInternals.tsx
View file @
99cb9b03
...
...
@@ -83,12 +83,11 @@ const TxInternals = ({ txQuery }: Props) => {
// }, []);
const
handleSortToggle
=
React
.
useCallback
((
field
:
SortField
)
=>
{
return
()
=>
{
if
(
isPlaceholderData
)
{
return
;
}
setSort
(
getNextSortValue
(
field
));
};
if
(
isPlaceholderData
)
{
return
;
}
setSort
(
getNextSortValue
(
field
));
},
[
isPlaceholderData
]);
if
(
!
txQuery
.
isPlaceholderData
&&
!
txQuery
.
isError
&&
!
txQuery
.
data
?.
status
)
{
...
...
ui/tx/blobs/TxBlobsTable.tsx
View file @
99cb9b03
...
...
@@ -12,7 +12,7 @@ interface Props {
isLoading
?:
boolean
;
}
const
Tx
Internal
sTable
=
({
data
,
top
,
isLoading
}:
Props
)
=>
{
const
Tx
Blob
sTable
=
({
data
,
top
,
isLoading
}:
Props
)
=>
{
return
(
<
TableRoot
>
...
...
@@ -32,4 +32,4 @@ const TxInternalsTable = ({ data, top, isLoading }: Props) => {
);
};
export
default
Tx
Internal
sTable
;
export
default
Tx
Blob
sTable
;
ui/tx/internals/TxInternalsTable.tsx
View file @
99cb9b03
...
...
@@ -4,23 +4,19 @@ import type { InternalTransaction } from 'types/api/internalTransaction';
import
{
AddressHighlightProvider
}
from
'
lib/contexts/addressHighlight
'
;
import
{
currencyUnits
}
from
'
lib/units
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
TableBody
,
TableColumnHeader
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
TableBody
,
TableColumnHeader
,
TableColumnHeaderSortable
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
TxInternalsTableItem
from
'
ui/tx/internals/TxInternalsTableItem
'
;
import
type
{
Sort
,
SortField
}
from
'
ui/tx/internals/utils
'
;
interface
Props
{
data
:
Array
<
InternalTransaction
>
;
sort
:
Sort
|
undefined
;
onSortToggle
:
(
field
:
SortField
)
=>
()
=>
void
;
sort
:
Sort
;
onSortToggle
:
(
field
:
SortField
)
=>
void
;
top
:
number
;
isLoading
?:
boolean
;
}
const
TxInternalsTable
=
({
data
,
sort
,
onSortToggle
,
top
,
isLoading
}:
Props
)
=>
{
const
sortIconTransform
=
sort
?.
includes
(
'
asc
'
)
?
'
rotate(-90deg)
'
:
'
rotate(90deg)
'
;
return
(
<
AddressHighlightProvider
>
<
TableRoot
>
...
...
@@ -28,18 +24,24 @@ const TxInternalsTable = ({ data, sort, onSortToggle, top, isLoading }: Props) =
<
TableRow
>
<
TableColumnHeader
width=
"28%"
>
Type
</
TableColumnHeader
>
<
TableColumnHeader
width=
"40%"
>
From/To
</
TableColumnHeader
>
<
TableColumnHeader
width=
"16%"
isNumeric
>
<
Link
display=
"flex"
alignItems=
"center"
justifyContent=
"flex-end"
onClick=
{
onSortToggle
(
'
value
'
)
}
columnGap=
{
1
}
>
{
sort
?.
includes
(
'
value
'
)
&&
<
IconSvg
name=
"arrows/east"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
Value
{
currencyUnits
.
ether
}
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeader
width=
"16%"
isNumeric
>
<
Link
display=
"flex"
alignItems=
"center"
justifyContent=
"flex-end"
onClick=
{
onSortToggle
(
'
gas-limit
'
)
}
columnGap=
{
1
}
>
{
sort
?.
includes
(
'
gas-limit
'
)
&&
<
IconSvg
name=
"arrows/east"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
Gas limit
{
currencyUnits
.
ether
}
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeaderSortable
width=
"16%"
isNumeric
sortField=
"value"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
>
Value
{
currencyUnits
.
ether
}
</
TableColumnHeaderSortable
>
<
TableColumnHeaderSortable
width=
"16%"
isNumeric
sortField=
"gas-limit"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
>
Gas limit
{
currencyUnits
.
ether
}
</
TableColumnHeaderSortable
>
</
TableRow
>
</
TableHeaderSticky
>
<
TableBody
>
...
...
ui/txs/TxAdditionalInfo.tsx
View file @
99cb9b03
...
...
@@ -25,7 +25,6 @@ type Props =
className
?:
string
;
};
// TODO @tom2drum fix other popovers
const
TxAdditionalInfo
=
({
hash
,
tx
,
isMobile
,
isLoading
,
className
}:
Props
)
=>
{
const
content
=
hash
!==
undefined
?
<
TxAdditionalInfoContainer
hash=
{
hash
}
/>
:
<
TxAdditionalInfoContent
tx=
{
tx
}
/>;
...
...
ui/txs/TxsContent.tsx
View file @
99cb9b03
...
...
@@ -60,7 +60,7 @@ const TxsContent = ({
}:
Props
)
=>
{
const
isMobile
=
useIsMobile
();
const
onSortToggle
=
React
.
useCallback
((
field
:
TransactionsSortingField
)
=>
()
=>
{
const
onSortToggle
=
React
.
useCallback
((
field
:
TransactionsSortingField
)
=>
{
const
value
=
getNextSortValue
<
TransactionsSortingField
,
TransactionsSortingValue
>
(
SORT_SEQUENCE
,
field
)(
sort
);
setSorting
(
value
);
},
[
sort
,
setSorting
]);
...
...
@@ -84,8 +84,8 @@ const TxsContent = ({
<
Box
hideBelow=
"lg"
>
<
TxsTable
txs=
{
itemsWithTranslation
}
sort=
{
onSortToggle
}
sorting=
{
sort
}
sort=
{
sort
}
onSortToggle=
{
onSortToggle
}
showBlockInfo=
{
showBlockInfo
}
showSocketInfo=
{
showSocketInfo
}
socketInfoAlert=
{
socketInfoAlert
}
...
...
ui/txs/TxsTable.pw.tsx
View file @
99cb9b03
...
...
@@ -10,8 +10,9 @@ test('base view +@dark-mode', async({ render }) => {
const
component
=
await
render
(
<
TxsTable
txs=
{
[
txMock
.
base
,
txMock
.
withWatchListNames
]
}
sort=
"default"
// eslint-disable-next-line react/jsx-no-bind
sort=
{
()
=>
()
=>
{}
}
onSortToggle=
{
()
=>
{}
}
top=
{
0
}
showBlockInfo
showSocketInfo=
{
false
}
...
...
@@ -30,8 +31,9 @@ test.describe('screen xl', () => {
const
component
=
await
render
(
<
TxsTable
txs=
{
[
txMock
.
base
,
txMock
.
withWatchListNames
]
}
sort=
"default"
// eslint-disable-next-line react/jsx-no-bind
sort=
{
()
=>
()
=>
{}
}
onSortToggle=
{
()
=>
{}
}
top=
{
0
}
showBlockInfo
showSocketInfo=
{
false
}
...
...
ui/txs/TxsTable.tsx
View file @
99cb9b03
...
...
@@ -7,17 +7,15 @@ import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import
useInitialList
from
'
lib/hooks/useInitialList
'
;
import
useLazyRenderedList
from
'
lib/hooks/useLazyRenderedList
'
;
import
{
currencyUnits
}
from
'
lib/units
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
TableBody
,
TableColumnHeader
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
TableBody
,
TableColumnHeader
,
TableColumnHeaderSortable
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
*
as
SocketNewItemsNotice
from
'
ui/shared/SocketNewItemsNotice
'
;
import
TxsTableItem
from
'
./TxsTableItem
'
;
type
Props
=
{
txs
:
Array
<
Transaction
>
;
sort
:
(
field
:
TransactionsSortingField
)
=>
()
=>
void
;
sorting
?:
TransactionsSortingValue
;
sort
:
TransactionsSortingValue
;
onSortToggle
:
(
field
:
TransactionsSortingField
)
=>
void
;
top
:
number
;
showBlockInfo
:
boolean
;
showSocketInfo
:
boolean
;
...
...
@@ -31,7 +29,7 @@ type Props = {
const
TxsTable
=
({
txs
,
sort
,
sorting
,
onSortToggle
,
top
,
showBlockInfo
,
showSocketInfo
,
...
...
@@ -62,32 +60,38 @@ const TxsTable = ({
<
TableColumnHeader
width=
"160px"
>
Type
</
TableColumnHeader
>
<
TableColumnHeader
width=
"20%"
>
Method
</
TableColumnHeader
>
{
showBlockInfo
&&
(
<
TableColumnHeader
width=
"18%"
>
<
Link
onClick=
{
isLoading
?
undefined
:
sort
(
'
block_number
'
)
}
display=
"flex"
alignItems=
"center"
>
{
sorting
===
'
block_number-asc
'
&&
<
IconSvg
boxSize=
{
5
}
name=
"arrows/east"
transform=
"rotate(-90deg)"
/>
}
{
sorting
===
'
block_number-desc
'
&&
<
IconSvg
boxSize=
{
5
}
name=
"arrows/east"
transform=
"rotate(90deg)"
/>
}
Block
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeaderSortable
width=
"18%"
sortField=
"block_number"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
>
Block
</
TableColumnHeaderSortable
>
)
}
<
TableColumnHeader
width=
"224px"
>
From/To
</
TableColumnHeader
>
{
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
value
&&
(
<
TableColumnHeader
width=
"20%"
isNumeric
>
<
Link
onClick=
{
isLoading
?
undefined
:
sort
(
'
value
'
)
}
display=
"flex"
alignItems=
"center"
justifyContent=
"end"
>
{
sorting
===
'
value-asc
'
&&
<
IconSvg
boxSize=
{
5
}
name=
"arrows/east"
transform=
"rotate(-90deg)"
/>
}
{
sorting
===
'
value-desc
'
&&
<
IconSvg
boxSize=
{
5
}
name=
"arrows/east"
transform=
"rotate(90deg)"
/>
}
{
`Value ${ currencyUnits.ether }`
}
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeaderSortable
width=
"20%"
isNumeric
sortField=
"value"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
>
{
`Value ${ currencyUnits.ether }`
}
</
TableColumnHeaderSortable
>
)
}
{
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
tx_fee
&&
(
<
TableColumnHeader
width=
"20%"
isNumeric
pr=
{
5
}
>
<
Link
onClick=
{
isLoading
?
undefined
:
sort
(
'
fee
'
)
}
display=
"flex"
alignItems=
"center"
justifyContent=
"end"
>
{
sorting
===
'
fee-asc
'
&&
<
IconSvg
boxSize=
{
5
}
name=
"arrows/east"
transform=
"rotate(-90deg)"
/>
}
{
sorting
===
'
fee-desc
'
&&
<
IconSvg
boxSize=
{
5
}
name=
"arrows/east"
transform=
"rotate(90deg)"
/>
}
{
`Fee${ feeCurrency }`
}
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeaderSortable
width=
"20%"
isNumeric
pr=
{
5
}
sortField=
"fee"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
>
{
`Fee${ feeCurrency }`
}
</
TableColumnHeaderSortable
>
)
}
</
TableRow
>
</
TableHeaderSticky
>
...
...
ui/verifiedContracts/VerifiedContractsTable.tsx
View file @
99cb9b03
import
React
from
'
react
'
;
import
type
{
VerifiedContract
}
from
'
types/api/contracts
'
;
import
type
{
VerifiedContractsSorting
,
VerifiedContractsSorting
Field
,
VerifiedContractsSortingValue
}
from
'
types/api/verifiedContracts
'
;
import
type
{
VerifiedContractsSortingField
,
VerifiedContractsSortingValue
}
from
'
types/api/verifiedContracts
'
;
import
{
currencyUnits
}
from
'
lib/units
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
TableBody
,
TableColumnHeader
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
{
TableBody
,
TableColumnHeader
,
TableColumnHeaderSortable
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
{
ACTION_BAR_HEIGHT_DESKTOP
}
from
'
ui/shared/ActionBar
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
getNextSortValue
from
'
ui/shared/sort/getNextSortValue
'
;
import
{
SORT_SEQUENCE
}
from
'
ui/verifiedContracts/utils
'
;
...
...
@@ -21,9 +19,7 @@ interface Props {
}
const
VerifiedContractsTable
=
({
data
,
sort
,
setSorting
,
isLoading
}:
Props
)
=>
{
const
sortIconTransform
=
sort
?.
includes
(
'
asc
'
as
VerifiedContractsSorting
[
'
order
'
])
?
'
rotate(-90deg)
'
:
'
rotate(90deg)
'
;
const
onSortToggle
=
React
.
useCallback
((
field
:
VerifiedContractsSortingField
)
=>
()
=>
{
const
onSortToggle
=
React
.
useCallback
((
field
:
VerifiedContractsSortingField
)
=>
{
const
value
=
getNextSortValue
<
VerifiedContractsSortingField
,
VerifiedContractsSortingValue
>
(
SORT_SEQUENCE
,
field
)(
sort
);
setSorting
({
value
:
[
value
]
});
},
[
sort
,
setSorting
]);
...
...
@@ -33,24 +29,26 @@ const VerifiedContractsTable = ({ data, sort, setSorting, isLoading }: Props) =>
<
TableHeaderSticky
top=
{
ACTION_BAR_HEIGHT_DESKTOP
}
>
<
TableRow
>
<
TableColumnHeader
width=
"50%"
>
Contract
</
TableColumnHeader
>
<
TableColumnHeader
width=
"130px"
isNumeric
>
<
Link
display=
"flex"
alignItems=
"center"
justifyContent=
"flex-end"
onClick=
{
isLoading
?
undefined
:
onSortToggle
(
'
balance
'
)
}
columnGap=
{
1
}
>
{
sort
?.
includes
(
'
balance
'
)
&&
<
IconSvg
name=
"arrows/east"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
Balance
{
currencyUnits
.
ether
}
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeader
width=
"130px"
isNumeric
>
<
Link
display=
"flex"
alignItems=
"center"
justifyContent=
"flex-end"
onClick=
{
isLoading
?
undefined
:
onSortToggle
(
'
transactions_count
'
)
}
columnGap=
{
1
}
>
{
sort
?.
includes
(
'
transactions_count
'
)
&&
<
IconSvg
name=
"arrows/east"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
Txs
</
Link
>
</
TableColumnHeader
>
<
TableColumnHeaderSortable
width=
"130px"
isNumeric
sortField=
"balance"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
disabled=
{
isLoading
}
>
Balance
{
currencyUnits
.
ether
}
</
TableColumnHeaderSortable
>
<
TableColumnHeaderSortable
width=
"130px"
isNumeric
sortField=
"transactions_count"
sortValue=
{
sort
}
onSortToggle=
{
onSortToggle
}
disabled=
{
isLoading
}
>
Txs
</
TableColumnHeaderSortable
>
<
TableColumnHeader
width=
"50%"
>
Language / Compiler version
</
TableColumnHeader
>
<
TableColumnHeader
width=
"80px"
>
Settings
</
TableColumnHeader
>
<
TableColumnHeader
width=
"150px"
>
Verified
</
TableColumnHeader
>
...
...
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