Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: blocks page and search #540

Merged
merged 43 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ae5f828
fix: show only search type on results
arthurgeron Sep 16, 2024
e9bc223
chore: update graphql codegen
arthurgeron Sep 16, 2024
f2c0b44
chore: update storybook minor
arthurgeron Sep 16, 2024
e25a9d9
feat: mock next navigation and link on ui's storybook
arthurgeron Sep 16, 2024
ffd234d
feat: make entire search result clickable
arthurgeron Sep 16, 2024
bf93f21
feat: always show hash in block descriptiong
arthurgeron Sep 16, 2024
eda9e23
feat: add missing block _id field to query data
arthurgeron Sep 16, 2024
813ddb4
feat: add block height card to page
arthurgeron Sep 16, 2024
0b64783
chore: add storybook log to gitignore
arthurgeron Sep 16, 2024
9981af8
feat: expose block height instead of _id
arthurgeron Sep 16, 2024
53815a9
feat: improve block data display on different breakpoints
arthurgeron Sep 16, 2024
373005d
fix: search result spaced away from input field
arthurgeron Sep 16, 2024
df8a104
fix: vertical alignment of search input when focused mobile
arthurgeron Sep 16, 2024
ecd3178
feat: animate and expand search bar on focus mobile
arthurgeron Sep 16, 2024
5d2cb86
fix: align dropdown popover border color with search inputs
arthurgeron Sep 16, 2024
e944273
chore: remove console log
arthurgeron Sep 16, 2024
e1c6ff1
chore: change height to first item in the grid
arthurgeron Sep 16, 2024
0ac20c9
feat: use max width when focused on mobile
arthurgeron Sep 16, 2024
0fc3781
fix: remove input outline when focused
arthurgeron Sep 16, 2024
6535e65
fix: properly unfocus search field on blur
arthurgeron Sep 16, 2024
631a87f
feat: expand search to entire width on focus
arthurgeron Sep 16, 2024
545b86d
feat: remove rounded borders on focus on mobile
arthurgeron Sep 16, 2024
fed4579
revert: calling close on blur
arthurgeron Sep 16, 2024
82dfc6e
fix: border and positioning adjustments
arthurgeron Sep 16, 2024
df17b94
refactor: SearchInput to resolve odd behaviors and confusing var names
arthurgeron Sep 17, 2024
b1ba75b
fix: clear button not working
arthurgeron Sep 17, 2024
c65dfb0
fix: open close behavior of input
arthurgeron Sep 17, 2024
ee24d82
chore: remove expandOnFocus prop
arthurgeron Sep 17, 2024
3ac19b3
fix: type errors
arthurgeron Sep 17, 2024
8b61ec6
fix: dropdown alignment on mobile
arthurgeron Sep 17, 2024
967c8e3
fix: having double click input when dropdown is open
arthurgeron Sep 17, 2024
f7a820f
chore: move search input to its own folder
arthurgeron Sep 17, 2024
9d2f5f5
refactor: move search input components to their own folders
arthurgeron Sep 17, 2024
42de22c
fix: double tap issue on input on mobile
arthurgeron Sep 17, 2024
d65abb5
Merge branch 'main' into ag/fix/block-search-views
arthurgeron Sep 17, 2024
1269241
fix: search input jumping height on home
arthurgeron Sep 18, 2024
a3a472f
Merge branch 'main' of github.com:FuelLabs/fuel-explorer into ag/fix/…
arthurgeron Sep 19, 2024
ec8cf13
fix: add more styles locked behind to variable position var
arthurgeron Sep 19, 2024
9a8f04c
fix: home hero jumping height
arthurgeron Sep 19, 2024
1002ad1
chore: log docker compose outputs
arthurgeron Sep 19, 2024
46b1610
Merge branch 'main' into ag/fix/block-search-views
LuizAsFight Sep 19, 2024
8964ffd
Merge branch 'main' of github.com:FuelLabs/fuel-explorer into ag/fix/…
arthurgeron Sep 20, 2024
3e0f14f
revert: docker debug logs
arthurgeron Sep 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,5 @@ act-actions

# playwright report
**/**/playwright-report/*
**/**/playwright-html/*
**/**/playwright-html/*
*storybook.log
2 changes: 1 addition & 1 deletion docker/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build:
docker compose --profile $(PROFILE) --env-file $(ENV_FILE) build

start:
docker compose --profile $(PROFILE) --env-file $(ENV_FILE) up -d --build
docker compose --profile $(PROFILE) --env-file $(ENV_FILE) up --build

stop:
docker compose --profile $(PROFILE) --env-file $(ENV_FILE) stop
Expand Down
2 changes: 1 addition & 1 deletion packages/app-explorer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"autoprefixer": "10.4.17",
"postcss": "8.4.35",
"postcss-import": "16.0.1",
"storybook": "^8.0.8",
"storybook": "8.3.0",
"storybook-addon-theme": "workspace:*",
"tailwindcss": "3.4.4",
"tailwindcss-animate": "1.0.7",
Expand Down
6 changes: 4 additions & 2 deletions packages/app-explorer/src/app/block/[id]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import type { ReactNode } from 'react';
import { getBlock } from '~/systems/Block/actions/get-block';
import { BlockHeader } from '~/systems/Block/components/BlockHeader';
import type { BlockRouteParams } from '~/systems/Block/types';

export default function BlockLayout({
export default async function BlockLayout({
children,
params: { id },
}: {
children: ReactNode;
params: BlockRouteParams;
}) {
const { producer } = await getBlock({ id });
return (
<>
<BlockHeader id={id} />
<BlockHeader producer={producer} />
{children}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export async function Block({
}: BlockScreenProps) {
return (
<>
<BlockHeader isLoading={isLoading} id={id} />
<BlockHeader isLoading={isLoading} producer={id} />
{viewMode === ViewModes.Simple && (
<BlockScreenSimple
block={block}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import type { ViewModes } from '~/systems/Core/components/ViewMode/constants';
import { isValidAddress } from '~/systems/Core/utils/address';

export function BlockHeader({
id,
producer,
isLoading,
}: {
id: string;
producer: string | null | undefined;
isLoading?: boolean;
}) {
const { mode } = useParams<{ mode: ViewModes }>();
Expand All @@ -23,10 +23,11 @@ export function BlockHeader({
isLoading={isLoading}
loadingEl={<LoadingBox className="w-20 h-5 mt-1" />}
regularEl={
isValidAddress(id) ? (
<Address full value={id || ''} fixed="b256" />
//
isValidAddress(producer) ? (
<Address full value={producer || ''} fixed="b256" />
) : (
<>#{id}</>
<>#{producer}</>
)
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ export function BlockScreenSimple({
}: BlockScreenSimpleProps) {
return (
<VStack>
<Grid className="grid-rows-3 tablet:grid-rows-1 tablet:grid-cols-3 gap-6 mb-8">
<Grid className="grid-rows-3 tablet:grid-rows-2 tablet:grid-cols-2 desktop:grid-cols-4 gap-6 mb-8">
<CardInfo name="Height" className="flex-1">
<LoadingWrapper
isLoading={isLoading}
loadingEl={<LoadingBox className="w-12 h-6" />}
regularEl={block?.height}
/>
</CardInfo>
<CardInfo name="Producer" className="flex-1">
<Address
value={producer || ''}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import { styles } from './styles';
type SearchFormProps = {
className: string;
autoFocus?: boolean;
expandOnFocus?: boolean;
variablePosition?: boolean;
};

export function SearchForm({
className,
autoFocus,
expandOnFocus,
variablePosition,
}: SearchFormProps) {
const classes = styles();
const [results, action] = useFormState(
Expand All @@ -27,10 +27,10 @@ export function SearchForm({
return (
<form action={action} className={classes.searchSize()}>
<SearchInput
variablePosition={variablePosition}
className={className}
searchResult={results}
autoFocus={autoFocus}
expandOnFocus={expandOnFocus}
/>
</form>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
'use client';

import type { GQLSearchResult, Maybe } from '@fuel-explorer/graphql';
import type { BaseProps, InputProps } from '@fuels/ui';
import { Focus, Icon, IconButton, Input, Tooltip, VStack } from '@fuels/ui';
import { IconCheck, IconSearch, IconX } from '@tabler/icons-react';
import type { KeyboardEvent } from 'react';
import { useContext, useRef, useState } from 'react';
import { useFormStatus } from 'react-dom';

import { cx } from '../../../utils/cx';

import { SearchResultDropdown } from '../SearchResultDropdown';
import { SearchContext } from '../SearchWidget';
import { usePropagateInputMouseClick } from '../hooks/usePropagateInputMouseClick';
import { DEFAULT_SEARCH_INPUT_WIDTH } from './constants';
import { styles } from './styles';

type SearchInputProps = BaseProps<InputProps> & {
onSubmit?: (value: string) => void;
searchResult?: Maybe<GQLSearchResult>;
alwaysDisplayActionButtons?: boolean;
variablePosition?: boolean;
};

export function SearchInput({
value: initialValue = '',
className,
autoFocus,
placeholder = 'Search here...',
searchResult,
variablePosition,
...props
}: SearchInputProps) {
const classes = styles();
const [value, setValue] = useState<string>(initialValue as string);
const [isFocused, setIsFocused] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const [hasSubmitted, setHasSubmitted] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const { pending } = useFormStatus();
const { dropdownRef } = useContext(SearchContext);
const openDropdown = hasSubmitted
? !pending
: isOpen && !pending && !!searchResult;

usePropagateInputMouseClick({
containerRef,
inputRef,
enabled: openDropdown,
});

function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
setValue(event.target.value);
}

function handleSubmit() {
setIsOpen(true);
setHasSubmitted(true);
}

function close() {
setIsOpen(false);
setHasSubmitted(false);
}

function handleClear() {
setValue('');
close();
}

function handleFocus() {
setIsFocused(true);
}

function handleBlur() {
setIsFocused(false);
}

function onKeyDown(e: KeyboardEvent<HTMLInputElement>) {
if (e.key === 'Enter') {
e.preventDefault();
(e.target as HTMLFormElement).form?.dispatchEvent(
new Event('submit', { cancelable: true, bubbles: true }),
);
handleSubmit();
}
}

return (
<div className="relative">
<VStack
gap="0"
data-variable-position={variablePosition}
className={classes.searchBox()}
data-active={isFocused || openDropdown}
>
<Focus.ArrowNavigator autoFocus={autoFocus}>
<div ref={containerRef} className={classes.inputContainer()}>
<Input
{...props}
ref={inputRef}
name="query"
placeholder={placeholder}
value={value}
onChange={handleChange}
variant="surface"
radius="large"
size="3"
data-active={isFocused || openDropdown}
className={cx(className, classes.inputWrapper())}
type="search"
onFocus={handleFocus}
onBlur={handleBlur}
onKeyDown={onKeyDown}
>
<div
data-show={isFocused}
className={classes.inputActionsContainer()}
>
<Input.Slot side="right">
<Tooltip content="Submit">
<IconButton
type="submit"
aria-label="Submit"
icon={IconCheck}
iconColor="text-brand"
variant="link"
className="!ml-0 tablet:ml-2"
isLoading={pending}
onClick={handleSubmit}
/>
</Tooltip>
<IconButton
aria-label="Clear"
icon={IconX}
iconColor="text-gray-11"
variant="link"
className="m-0"
onClick={handleClear}
/>
</Input.Slot>
</div>

<Input.Slot
data-show={!isFocused}
side="right"
className="[&[data-show=false]]:hidden"
>
<Icon icon={IconSearch} size={16} />
</Input.Slot>
</Input>
</div>
</Focus.ArrowNavigator>
<SearchResultDropdown
ref={dropdownRef}
width={
containerRef.current?.offsetWidth || DEFAULT_SEARCH_INPUT_WIDTH
}
searchResult={searchResult}
searchValue={value}
openDropdown={openDropdown}
isFocused={isFocused}
onSelectItem={() => {
handleClear();
}}
onOpenChange={(open) => {
setIsOpen(open);
if (!open) {
close();
}
}}
/>
</VStack>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DEFAULT_SEARCH_INPUT_WIDTH = 400;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './SearchInput';
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { tv } from 'tailwind-variants';

export const styles = tv({
slots: {
searchBox: [
'transition-all duration-200 [&[data-active=false]]:ease-in [&[data-active=true]]:ease-out',
'group justify-center items-center',
'block left-0 w-full', // needed for properly execution of transitions
'[&[data-variable-position=true]]:[&[data-active=true]]:w-[calc(100vw+1px)] [&[data-variable-position=true]]:[&[data-active=true]]:left-[-64px] tablet:[&[data-active=true]]:w-full',
'[&[data-active=true]]:absolute tablet:[&[data-active=true]]:left-0 [&[data-active=true]]:right-0',
'[&[data-variable-position=true]]:[&[data-active=true]]:top-[-14px] [&[data-variable-position=true]]:tablet:[&[data-active=true]]:top-[-4px] [&[data-variable-position=true]]:desktop:[&[data-active=true]]:top-[-20px]',
'[&[data-active=true]]:z-50',
],
inputContainer: 'w-full',
inputWrapper: [
'outline-none h-[40px] group-[&[data-active=true]]:h-[60px] tablet:group-[&[data-active=true]]:h-[40px]',
'group-[&[data-active=true]]:rounded-none tablet:group-[&[data-active=true]]:rounded-[var(--text-field-border-radius)] ',
'border-x-[1px] border-y-[1px] group-[&[data-active=true]]:border-x-0 group-[&[data-active=true]]:border-y-0 tablet:group-[&[data-active=true]]:border-x-[1px] tablet:group-[&[data-active=true]]:border-y-[1px]',
'border-[var(--color-border)] shadow-none',
'bg-none dark:bg-[var(--color-surface)] group-[&[data-active=true]]:bg-[var(--color-panel-solid)]',
'[&_.rt-TextFieldChrome]:bg-gray-1 [&_.rt-TextFieldChrome]:outline-none',
'[&_.rt-TextFieldChrome]:[&[data-opened=true]]:rounded-b-none',
'group-[&[data-active=true]]:[&_.rt-TextFieldChrome]:shadow-none',
],
inputActionsContainer:
'[&[data-show=false]]:hidden absolute flex items-center h-full right-0 top-0 transform',
},
});
Loading
Loading