Skip to content

Commit d951b08

Browse files
committed
feat: add search section to landing page
See: FE-92
1 parent 2dda099 commit d951b08

File tree

18 files changed

+922
-9
lines changed

18 files changed

+922
-9
lines changed

frontend/i18n/locales/en.json

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"beaconchain_homepage": "Beaconchain Homepage",
77
"common": {
88
"close": "Close",
9+
"error_retry": "An error occurred. Please try again.",
910
"log_in": "Log in",
11+
"no_results": "No results found.",
1012
"open_navigation": "Open Navigation",
1113
"side_navigation": "Side Navigation"
1214
},
@@ -1157,7 +1159,23 @@
11571159
}
11581160
},
11591161
"search": {
1160-
"title": "Explore Transactions & Validator Staking on"
1162+
"input_label": "Search by Address / Tx hash / Block / Token / ENS",
1163+
"input_placeholder": "Search anything...",
1164+
"loading_message": "Loading search results...",
1165+
"title": "Explore Transactions & Validator Staking on",
1166+
"types": {
1167+
"addresses": "Addresses",
1168+
"blocks": "Blocks",
1169+
"ens_names": "ENS Names",
1170+
"epochs": "Epochs",
1171+
"slots": "Slots",
1172+
"tokens": "Tokens",
1173+
"transactions": "Tx Hashes",
1174+
"validator_deposit_addresses": "Validator Deposit Addresses",
1175+
"validator_graffiti": "Validator Graffiti",
1176+
"validator_withdrawal_credentials": "Validator Withdrawal Credentials",
1177+
"validators": "Validators"
1178+
}
11611179
},
11621180
"staking_hub": {
11631181
"action": {

frontend/layers/base/app/assets/css/main.css

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111
@theme {
1212
--*: initial;
1313

14+
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
15+
1416
--breakpoint-sm: 40rem; /* 640px */
1517
--breakpoint-md: 48rem; /* 768px */
1618
--breakpoint-lg: 64rem; /* 1024px */
1719
/* --breakpoint-xl: 80rem; */
1820
/* --breakpoint-2xl: 96rem; */
1921

2022

23+
--color-charcoal-50: #555555;
24+
--color-charcoal-500: #303030;
2125
--color-charcoal-600: #282828;
2226
--color-charcoal-700: #212121;
2327

@@ -34,6 +38,7 @@
3438
--color-gray-200: #BDBDBD;
3539
--color-gray-300: #A8A8A8;
3640
--color-gray-400: #888888;
41+
--color-gray-500: #666666;
3742
--color-gray-700: #3B3B3B;
3843
--color-gray-900: #262626;
3944
--color-gray-950: #1A1919;
@@ -47,8 +52,9 @@
4752
--container-3xs: 16rem; /* 256px */
4853
/* --container-7xl: 80rem; 1280px -> this is in conflict with --spacing-7xl */
4954
--container-8xl: 90rem; /* 1440px */
55+
--container-24xl: 80rem; /* 1280px */
56+
--container-30xl: 120rem; /* 1920px */
5057

51-
--container-24xl: 80rem; /* 144px */
5258

5359
/* --ease-in: cubic-bezier(0.4, 0, 1, 1); */
5460
/* --ease-out: cubic-bezier(0, 0, 0.2, 1); */
@@ -59,7 +65,9 @@
5965
--font-weight-semibold: 600;
6066

6167
--radius-xl: .75rem; /* 12px */
68+
--radius-3xl: 1.25rem; /* 20px */
6269
--radius-4xl: 1.5rem; /* 24px */
70+
--radius-7xl: 1.5rem; /* 24px */
6371
--radius-full: 2rem; /* 32px */
6472

6573
--spacing-unset: unset;
@@ -79,8 +87,8 @@
7987

8088
--text-xs: .75rem; /* 12px */
8189
--text-xs--line-height: 1rem; /* 16px */
82-
/* --text-sm-tight: .875rem; 14px */
83-
/* --text-sm-tight--line-height: 1rem; 16px */
90+
--text-sm-tight: .875rem; /* 14px */
91+
--text-sm-tight--line-height: 1rem; /* 16px */
8492
--text-sm: .875rem; /* 14px */
8593
--text-sm--line-height: 1.25rem; /* 20px */
8694
--text-md: 1rem; /* 16px */
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script setup lang="ts">
2+
import type { ChainId } from '~/types/network'
3+
import { useNetwork } from '~/layers/base/app/composables/useNetwork'
4+
5+
const { id } = defineProps<{
6+
id: ChainId,
7+
}>()
8+
9+
const { getNetworkName } = useNetwork()
10+
11+
const networkName = computed(() => getNetworkName(id))
12+
</script>
13+
14+
<template>
15+
<LazyNetworkIconCryptoEth
16+
v-if="networkName === 'Ethereum'"
17+
class="w-2xl"
18+
/>
19+
<LazyNetworkIconCryptoHoodi
20+
v-if="networkName === 'Ethereum Hoodi'"
21+
class="w-2xl"
22+
/>
23+
</template>
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<script setup lang="ts" generic="SearchResultType">
2+
type GroupBy = keyof SearchResultType
3+
type SearchParams = any & { input: string }
4+
5+
const {
6+
groupBy,
7+
hasError,
8+
isLoading,
9+
results,
10+
} = defineProps<{
11+
groupBy?: GroupBy,
12+
hasError?: boolean,
13+
isLoading: boolean,
14+
label: string,
15+
placeholder?: string,
16+
results?: SearchResultType[],
17+
}>()
18+
19+
const emit = defineEmits<{
20+
(e: 'search', searchParams: SearchParams): void,
21+
}>()
22+
23+
const { t: $t } = useTranslation()
24+
25+
const hasSearched = ref(false)
26+
const searchParams = defineModel<SearchParams>({
27+
required: true,
28+
})
29+
30+
watchDebounced(
31+
searchParams,
32+
async () => {
33+
if (searchParams.value.input?.length) {
34+
emit('search', searchParams.value)
35+
hasSearched.value = true
36+
}
37+
},
38+
{
39+
deep: true,
40+
immediate: false,
41+
},
42+
)
43+
44+
const showDropdown = computed(() => isLoading || hasSearched.value)
45+
const groupedResults = computed(() => {
46+
if (!results?.length) return
47+
if (!groupBy) return
48+
49+
const groupedResults = Object.groupBy(results, result => result[groupBy] as PropertyKey)
50+
51+
return Object.entries(groupedResults) as [SearchResultType[GroupBy], SearchResultType[]][]
52+
})
53+
</script>
54+
55+
<template>
56+
<form
57+
role="search"
58+
class="p-2xl dark:bg-[rgba(16,16,16,0.2)] rounded-3xl"
59+
>
60+
<RkComboboxRoot
61+
v-model:open="showDropdown"
62+
class="relative"
63+
ignore-filter
64+
>
65+
<RkLabel
66+
for="blockchain-search-input"
67+
class="absolute bottom-2xl left-2xl dark:text-gray-400 text-sm-tight"
68+
>
69+
{{ label }}
70+
</RkLabel>
71+
<RkComboboxInput
72+
id="blockchain-search-input"
73+
v-model.trim="searchParams.input"
74+
type="search"
75+
auto-focus
76+
:aria-busy="isLoading"
77+
:placeholder
78+
class="search-input w-full text-2xl font-semibold rounded-3xl pt-3xl pr-5xl pb-6xl pl-2xl dark:bg-gray-950
79+
dark:focus:bg-black placeholder:dark:text-gray-500 dark:text-white border-1 dark:border-charcoal-500
80+
dark:focus:border-charcoal-50 dark:focus-within:outline-0"
81+
@update:model-value="(value) => { if (!value) hasSearched = false }"
82+
/>
83+
84+
<RkComboboxContent class="absolute dark:bg-gray-950 mt-xl rounded-xl w-full max-h-[400px] overflow-y-auto">
85+
<RkComboboxViewport>
86+
<!-- HISTORY AND FILTERS GO HERE -->
87+
88+
<div class="py-lg">
89+
<slot
90+
v-if="isLoading"
91+
name="loading-content"
92+
>
93+
<BlockchainSearchLoadingSkeleton />
94+
</slot>
95+
96+
<slot
97+
v-else-if="hasError"
98+
name="error-content"
99+
>
100+
<div
101+
role="alert"
102+
class="px-2xl py-md dark:text-gray-400 "
103+
>
104+
{{ $t('base.common.error_try_again') }}
105+
</div>
106+
</slot>
107+
108+
<slot v-else-if="!results?.length">
109+
<RkComboboxEmpty>
110+
<div class="dark:text-gray-400 px-2xl py-md font-semibold">
111+
{{ $t('base.common.no_results') }}
112+
</div>
113+
</RkComboboxEmpty>
114+
</slot>
115+
116+
<template v-else-if="results?.length && groupBy">
117+
<RkComboboxGroup
118+
v-for="[groupKey, groupItems] in groupedResults"
119+
:key="groupKey as string"
120+
>
121+
<RkComboboxLabel class="px-2xl py-md dark:text-gray-400">
122+
<slot
123+
name="result-group-label"
124+
:label="groupKey"
125+
/>
126+
</RkComboboxLabel>
127+
128+
<RkComboboxItem
129+
v-for="result in groupItems"
130+
:key="JSON.stringify(result)"
131+
as-child
132+
:value="JSON.stringify(result)"
133+
class="dark:data-[highlighted]:bg-gray-900 px-2xl py-md font-semibold"
134+
@select.prevent
135+
>
136+
<slot
137+
name="result-item"
138+
:result
139+
/>
140+
</RkComboboxItem>
141+
</RkComboboxGroup>
142+
</template>
143+
144+
<template v-else-if="results?.length && !groupBy">
145+
<RkComboboxItem
146+
v-for="result in results"
147+
:key="JSON.stringify(result)"
148+
as-child
149+
:value="JSON.stringify(result)"
150+
class="dark:data-[highlighted]:bg-gray-900 px-2xl py-md font-semibold"
151+
@select.prevent
152+
>
153+
<slot
154+
name="result-item"
155+
:result
156+
/>
157+
</RkComboboxItem>
158+
</template>
159+
</div>
160+
</RkComboboxViewport>
161+
</RkComboboxContent>
162+
</RkComboboxRoot>
163+
</form>
164+
</template>
165+
166+
<style lang="scss" scoped>
167+
.search-input::-webkit-search-cancel-button {
168+
display: none;
169+
}
170+
</style>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script setup lang="ts">
2+
</script>
3+
4+
<template>
5+
<svg
6+
xmlns="http://www.w3.org/2000/svg"
7+
fill="none"
8+
viewBox="0 0 24 24"
9+
>
10+
<path
11+
fill="currentColor"
12+
d="m12 0-.16.55v15.87l.15.16 7-4.36-7-12.22Z"
13+
/>
14+
<path
15+
fill="currentColor"
16+
d="M12 0 5 12.22l7 4.36V0Zm0 17.97-.1.11v5.65l.1.27 7-10.38-7 4.35Z"
17+
/>
18+
<path
19+
fill="currentColor"
20+
d="M12 24v-6.03l-7-4.35L12 24Zm0-7.42 6.99-4.36-7-3.35v7.7Z"
21+
/>
22+
<path
23+
fill="currentColor"
24+
d="m5 12.22 7 4.36v-7.7l-7 3.34Z"
25+
/>
26+
</svg>
27+
</template>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<template>
2+
<svg
3+
xmlns="http://www.w3.org/2000/svg"
4+
viewBox="0 0 24 24"
5+
fill="none"
6+
>
7+
<path
8+
fill="currentColor"
9+
d="m11.994 0-.153.547v15.87l.153.16 6.995-4.354L11.994 0Z"
10+
/>
11+
<path
12+
fill="currentColor"
13+
d="M11.996 0 5 12.223l6.996 4.354V0ZM11.994 17.971l-.087.11v5.654l.087.265 7-10.38-7 4.351Z"
14+
/>
15+
<path
16+
fill="currentColor"
17+
d="M11.996 24V17.97L5 13.619 11.996 24ZM11.995 16.578l6.995-4.355-6.995-3.348v7.703Z"
18+
/>
19+
<path
20+
fill="currentColor"
21+
d="m5 12.223 6.996 4.354V8.874L5 12.223Z"
22+
/>
23+
<circle
24+
cx="5.667"
25+
cy="17.667"
26+
r="5.333"
27+
fill="#2861C1"
28+
stroke="currentColor"
29+
stroke-width=".667"
30+
/>
31+
<path
32+
fill="currentColor"
33+
d="M6.753 15h.914v5.333h-.914v-2.392H4.58v2.392h-.914V15h.914v2.011h2.172V15Z"
34+
/>
35+
</svg>
36+
</template>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export const useBaseUrls = () => {
2+
const config = useRuntimeConfig()
3+
const {
4+
apiClientHoodi,
5+
apiClientMainnet,
6+
} = config.public
7+
8+
const hoodiUrl = new URL(apiClientHoodi as string)
9+
const mainnetUrl = new URL(apiClientMainnet as string)
10+
11+
return {
12+
hoodi: hoodiUrl.origin,
13+
mainnet: mainnetUrl.origin,
14+
}
15+
}

0 commit comments

Comments
 (0)