react-icons/ai#AiOutlineSearch TypeScript Examples
The following examples show how to use
react-icons/ai#AiOutlineSearch.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From dxvote with GNU Affero General Public License v3.0 | 5 votes |
Filter = () => {
const { guild_id: guildId } =
useParams<{ chain_name?: string; guild_id?: string }>();
const [viewFilter, setViewFilter] = useState(false);
const { totalFilters } = useFilter();
const history = useHistory();
const location = useLocation();
const { account } = useWeb3React();
const { data: votingPower } = useVotingPowerOf({
contractAddress: guildId,
userAddress: account,
});
const { data: guildConfig } = useGuildConfig(guildId);
const isProposalCreationAllowed = useMemo(() => {
if (!guildConfig || !votingPower) {
return false;
}
if (votingPower.gte(guildConfig.votingPowerForProposalCreation)) {
return true;
}
return false;
}, [votingPower, guildConfig]);
const [openSearchBar, setOpenSearchBar] = useState(false);
return (
<FilterContainer>
<FilterRow>
{isMobile && !isProposalCreationAllowed && (
<FilterButton
onClick={() => setViewFilter(!viewFilter)}
active={viewFilter || totalFilters > 0}
>
Filter
{totalFilters > 0 && <FilterBadge>{totalFilters}</FilterBadge>}
</FilterButton>
)}
{isDesktop && <FilterMenu />}
<ButtonContainer>
<StyledIconButton
variant="secondary"
padding="0.4rem"
onClick={() => setOpenSearchBar(!openSearchBar)}
>
<AiOutlineSearch size={20} />
</StyledIconButton>
{isProposalCreationAllowed && (
<Button
variant="secondary"
onClick={() => history.push(location.pathname + '/proposalType')}
data-testid="create-proposal-button"
>
Create Proposal
</Button>
)}
</ButtonContainer>
</FilterRow>
{isMobile && viewFilter && <FilterMenu />}
{openSearchBar ? (
<StyledInputWrapper>
<Input
icon={<AiOutlineSearch size={24} />}
placeholder="Search title, ENS, address"
/>
</StyledInputWrapper>
) : null}
</FilterContainer>
);
}
Example #2
Source File: LandingPage.tsx From dxvote with GNU Affero General Public License v3.0 | 5 votes |
LandingPage: React.FC = () => {
const { chainId } = useWeb3React();
const chainName =
getChains().find(chain => chain.id === chainId)?.name || null;
const { data: allGuilds } = useGuildRegistry(
configs[chainName].contracts.utils.guildRegistry
);
/*TODO:
1. Members should be dynamic
2. Amount of proposals should be dynamic
3. Logo should be dynamic
*/
return (
<>
<InputContainer>
<Input
icon={<AiOutlineSearch size={24} />}
placeholder="Search Guild"
/>
<StyledButton data-testid="create-guild-button">
{' '}
<StyledLink to={location => `${location.pathname}/createGuild`}>
Create Guild
</StyledLink>
</StyledButton>
</InputContainer>
<CardContainer>
{allGuilds
? allGuilds.map(guildAddress => (
<GuildCard key={guildAddress} guildAddress={guildAddress}>
<GuildCardHeader>
<MemberWrapper>
<MdOutlinePeopleAlt size={24} />
500
</MemberWrapper>
<ProposalsInformation proposals={'active'}>
4 Proposals
</ProposalsInformation>
</GuildCardHeader>
<GuildCardContent>
<DaoIcon src={dxDaoIcon} />
<Title guildAddress={guildAddress} />
</GuildCardContent>
</GuildCard>
))
: null}
</CardContainer>
</>
);
}
Example #3
Source File: ContactsLayout.tsx From bluebubbles-server with Apache License 2.0 | 4 votes |
ContactsLayout = (): JSX.Element => {
const [search, setSearch] = useState('' as string);
const [isLoading, setIsLoading] = useBoolean(true);
const [contacts, setContacts] = useState([] as any[]);
const [permission, setPermission] = useState((): string | null => {
return null;
});
const dialogRef = useRef(null);
const inputFile = useRef(null);
const [dialogOpen, setDialogOpen] = useBoolean();
const alertRef = useRef(null);
const [requiresConfirmation, confirm] = useState((): string | null => {
return null;
});
let filteredContacts = contacts;
if (search && search.length > 0) {
filteredContacts = filteredContacts.filter((c) => buildIdentifier(c).includes(search.toLowerCase()));
}
const {
currentPage,
setCurrentPage,
pagesCount,
pages
} = usePagination({
pagesCount: Math.ceil(filteredContacts.length / perPage),
initialState: { currentPage: 1 },
});
const refreshPermissionStatus = async (): Promise<void> => {
setPermission(null);
await waitMs(500);
ipcRenderer.invoke('contact-permission-status').then((status: string) => {
setPermission(status);
}).catch(() => {
setPermission('Unknown');
});
};
const requestContactPermission = async (): Promise<void> => {
setPermission(null);
ipcRenderer.invoke('request-contact-permission').then((status: string) => {
setPermission(status);
}).catch(() => {
setPermission('Unknown');
});
};
const loadContacts = (showToast = false) => {
ipcRenderer.invoke('get-contacts').then((contactList: any[]) => {
setContacts(contactList.map((e: any) => {
// Patch the ID as a string
e.id = String(e.id);
return e;
}));
setIsLoading.off();
}).catch(() => {
setIsLoading.off();
});
if (showToast) {
showSuccessToast({
id: 'contacts',
description: 'Successfully refreshed Contacts!'
});
}
};
useEffect(() => {
loadContacts();
refreshPermissionStatus();
}, []);
const getEmptyContent = () => {
const wrap = (child: JSX.Element) => {
return (
<section style={{marginTop: 20}}>
{child}
</section>
);
};
if (isLoading) {
return wrap(<CircularProgress isIndeterminate />);
}
if (contacts.length === 0) {
return wrap(<Text fontSize="md">BlueBubbles found no contacts in your Mac's Address Book!</Text>);
}
return null;
};
const filterContacts = () => {
return filteredContacts.slice((currentPage - 1) * perPage, currentPage * perPage);
};
const onCreate = async (contact: ContactItem) => {
const newContact = await createContact(
contact.firstName,
contact.lastName,
{
emails: contact.emails.map((e: NodeJS.Dict<any>) => e.address),
phoneNumbers: contact.phoneNumbers.map((e: NodeJS.Dict<any>) => e.address)
}
);
if (newContact) {
// Patch the contact using a string ID & source type
newContact.id = String(newContact.id);
newContact.sourceType = 'db';
// Patch the addresses
(newContact as any).phoneNumbers = (newContact as any).addresses.filter((e: any) => e.type === 'phone');
(newContact as any).emails = (newContact as any).addresses.filter((e: any) => e.type === 'email');
setContacts([newContact, ...contacts]);
}
};
const onUpdate = async (contact: NodeJS.Dict<any>) => {
const cId = typeof(contact.id) === 'string' ? Number.parseInt(contact.id) : contact.id as number;
const newContact = await updateContact(
cId,
{
firstName: contact.firstName,
lastName: contact.lastName,
displayName: contact.displayName
}
);
const copiedContacts = [...contacts];
let updated = false;
for (let i = 0; i < copiedContacts.length; i++) {
if (copiedContacts[i].id === String(cId)) {
copiedContacts[i].firstName = newContact.firstName;
copiedContacts[i].lastName = newContact.lastName;
copiedContacts[i].displayName = newContact.displayName;
updated = true;
}
}
if (updated) {
setContacts(copiedContacts);
}
};
const onDelete = async (contactId: number | string) => {
await deleteContact(typeof(contactId) === 'string' ? Number.parseInt(contactId as string) : contactId);
setContacts(contacts.filter((e: ContactItem) => {
return e.id !== String(contactId);
}));
};
const onAddAddress = async (contactId: number | string, address: string) => {
const cId = typeof(contactId) === 'string' ? Number.parseInt(contactId as string) : contactId;
const addr = await addAddressToContact(cId, address, address.includes('@') ? 'email' : 'phone');
if (addr) {
setContacts(contacts.map((e: ContactItem) => {
if (e.id !== String(contactId)) return e;
if (address.includes('@')) {
e.emails = [...e.emails, addr];
} else {
e.phoneNumbers = [...e.phoneNumbers, addr];
}
return e;
}));
}
};
const onDeleteAddress = async (contactAddressId: number) => {
await deleteContactAddress(contactAddressId);
setContacts(contacts.map((e: ContactItem) => {
e.emails = e.emails.filter((e: ContactAddress) => e.id !== contactAddressId);
e.phoneNumbers = e.phoneNumbers.filter((e: ContactAddress) => e.id !== contactAddressId);
return e;
}));
};
const clearLocalContacts = async () => {
// Delete the contacts, then filter out the DB items
await deleteLocalContacts();
setContacts(contacts.filter(e => e.sourceType !== 'db'));
};
const confirmationActions: ConfirmationItems = {
clearLocalContacts: {
message: (
'Are you sure you want to clear/delete all local Contacts?<br /><br />' +
'This will remove any Contacts added manually, via the API, or via the import process'
),
func: clearLocalContacts
}
};
return (
<Box p={3} borderRadius={10}>
<Stack direction='column' p={5}>
<Text fontSize='2xl'>Controls</Text>
<Divider orientation='horizontal' />
<Box>
<Menu>
<MenuButton
as={Button}
rightIcon={<BsChevronDown />}
width="12em"mr={5}
>
Manage
</MenuButton>
<MenuList>
<MenuItem icon={<BsPersonPlus />} onClick={() => setDialogOpen.on()}>
Add Contact
</MenuItem>
<MenuItem icon={<BiRefresh />} onClick={() => loadContacts(true)}>
Refresh Contacts
</MenuItem>
<MenuItem
icon={<BiImport />}
onClick={() => {
if (inputFile && inputFile.current) {
(inputFile.current as HTMLElement).click();
}
}}
>
Import VCF
<input
type='file'
id='file'
ref={inputFile}
accept=".vcf"
style={{display: 'none'}}
onChange={(e) => {
const files = e?.target?.files ?? [];
for (const i of files) {
ipcRenderer.invoke('import-vcf', i.webkitRelativePath);
}
}}
/>
</MenuItem>
<MenuDivider />
<MenuItem icon={<FiTrash />} onClick={() => confirm('clearLocalContacts')}>
Clear Local Contacts
</MenuItem>
</MenuList>
</Menu>
<Menu>
<MenuButton
as={Button}
rightIcon={<BsChevronDown />}
width="12em"
mr={5}
>
Permissions
</MenuButton>
<MenuList>
<MenuItem icon={<BiRefresh />} onClick={() => refreshPermissionStatus()}>
Refresh Permission Status
</MenuItem>
{(permission !== null && permission !== 'Authorized') ? (
<MenuItem icon={<BsUnlockFill />} onClick={() => requestContactPermission()}>
Request Permission
</MenuItem>
) : null}
</MenuList>
</Menu>
<Text as="span" verticalAlign="middle">
Status: <Text as="span" color={getPermissionColor(permission)}>
{permission ? permission : 'Checking...'}
</Text>
</Text>
</Box>
</Stack>
<Stack direction='column' p={5}>
<Flex flexDirection='row' justifyContent='flex-start' alignItems='center'>
<Text fontSize='2xl'>Contacts ({filteredContacts.length})</Text>
<Popover trigger='hover'>
<PopoverTrigger>
<Box ml={2} _hover={{ color: 'brand.primary', cursor: 'pointer' }}>
<AiOutlineInfoCircle />
</Box>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Information</PopoverHeader>
<PopoverBody>
<Text>
Here are the contacts on your macOS device that BlueBubbles knows about,
and will serve to any clients that want to know about them. These include
contacts from this Mac's Address Book, as well as contacts from uploads/imports
or manual entry.
</Text>
</PopoverBody>
</PopoverContent>
</Popover>
</Flex>
<Divider orientation='horizontal' />
<Flex flexDirection='row' justifyContent='flex-end' alignItems='center' pt={3}>
<InputGroup width="xxs">
<InputLeftElement pointerEvents='none'>
<AiOutlineSearch color='gray.300' />
</InputLeftElement>
<Input
placeholder='Search Contacts'
onChange={(e) => {
if (currentPage > 1) {
setCurrentPage(1);
}
setSearch(e.target.value);
}}
value={search}
/>
</InputGroup>
</Flex>
<Flex justifyContent="center" alignItems="center">
{getEmptyContent()}
</Flex>
{(contacts.length > 0) ? (
<ContactsTable
contacts={filterContacts()}
onCreate={onCreate}
onDelete={onDelete}
onUpdate={onUpdate}
onAddressAdd={onAddAddress}
onAddressDelete={onDeleteAddress}
/>
) : null}
<Pagination
pagesCount={pagesCount}
currentPage={currentPage}
onPageChange={setCurrentPage}
>
<PaginationContainer
align="center"
justify="space-between"
w="full"
pt={2}
>
<PaginationPrevious minWidth={'75px'}>Previous</PaginationPrevious>
<Box ml={1}></Box>
<PaginationPageGroup flexWrap="wrap" justifyContent="center">
{pages.map((page: number) => (
<PaginationPage
key={`pagination_page_${page}`}
page={page}
my={1}
px={3}
fontSize={14}
/>
))}
</PaginationPageGroup>
<Box ml={1}></Box>
<PaginationNext minWidth={'50px'}>Next</PaginationNext>
</PaginationContainer>
</Pagination>
</Stack>
<ContactDialog
modalRef={dialogRef}
isOpen={dialogOpen}
onCreate={onCreate}
onDelete={onDelete}
onAddressAdd={onAddAddress}
onAddressDelete={onDeleteAddress}
onClose={() => setDialogOpen.off()}
/>
<ConfirmationDialog
modalRef={alertRef}
onClose={() => confirm(null)}
body={confirmationActions[requiresConfirmation as string]?.message}
onAccept={() => {
confirmationActions[requiresConfirmation as string].func();
}}
isOpen={requiresConfirmation !== null}
/>
</Box>
);
}
Example #4
Source File: youtubeWrapper.tsx From podcast-maker with MIT License | 4 votes |
YoutubeWrapper: React.FC<WrapperProps> = ({children, title}) => {
const {
width: videoWidth,
height: videoHeight,
durationInFrames,
} = useVideoConfig();
const frame = useCurrentFrame();
const startScaleAnimationAtFrame = 30;
const startClickAnimationAtFrame = 50 + startScaleAnimationAtFrame;
//Mouse movement
const moveY = interpolate(
frame,
[0, 50, 57, 73, 90, 110, 115, 125, 150].map(
(value) => value + startClickAnimationAtFrame
),
[-50, 95, 93, 97, 20, 10, 15, 12, -50]
);
const moveX = interpolate(
frame,
[0, 50, 57, 73, 90, 110, 115, 125, 150].map(
(value) => value + startClickAnimationAtFrame
),
[370, 650, 657, 655, 40, 50, 45, 48, 150]
);
const colorsClick = interpolateColors(
frame,
[0, 50, 57, 73, 90, 110, 115, 125, 150].map(
(value) => value + startClickAnimationAtFrame
),
['#fff', '#fff', '#aaa', '#fff', '#fff', '#fff', '#aaa', '#fff', '#fff']
);
//Scale change
const scale = interpolate(
frame,
[
0,
0 + startScaleAnimationAtFrame,
startClickAnimationAtFrame,
200 + startScaleAnimationAtFrame,
250 + startScaleAnimationAtFrame,
durationInFrames,
],
[1.57, 1.57, 1, 1, 1.57, 1.57]
);
const translateX = interpolate(
frame,
[
0,
0 + startScaleAnimationAtFrame,
startClickAnimationAtFrame,
200 + startScaleAnimationAtFrame,
250 + startScaleAnimationAtFrame,
durationInFrames,
],
[16.3, 16.3, 0, 0, 16.3, 16.3]
);
const translateY = interpolate(
frame,
[
0,
0 + startScaleAnimationAtFrame,
startClickAnimationAtFrame,
200 + startScaleAnimationAtFrame,
250 + startScaleAnimationAtFrame,
durationInFrames,
],
[7.3, 7.3, 0, 0, 7.3, 7.3]
);
return (
<div
style={{
transform: `scale(${scale}) translate(${translateX}%, ${translateY}%)`,
background: '#212121',
}}
>
<Sequence
from={47 + startClickAnimationAtFrame}
durationInFrames={Infinity}
>
<Audio src={clickSound} startFrom={30} />
</Sequence>
<Sequence
from={105 + startClickAnimationAtFrame}
durationInFrames={Infinity}
>
<Audio src={clickSound} startFrom={30} />
</Sequence>
<header
style={{
background: '#202020',
padding: '1rem',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: videoWidth,
}}
>
<div
style={{display: 'flex', alignItems: 'center', gap: '2rem'}}
>
<AiOutlineMenu size="3rem" color="#fff" />
<img src={ytLogo} />
</div>
<div style={{display: 'flex', alignItems: 'center', gap: '0'}}>
<div
style={{
height: '3rem',
width: 700,
background: '#121212',
border: '1px solid #323232',
borderRadius: '3px 0 0 3px',
}}
></div>
<div
style={{
height: '3rem',
width: 130,
background: '#323232',
border: '1px solid #323232',
borderRadius: '0 3px 3px 0',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<AiOutlineSearch color="#999" size="1.8rem" />
</div>
<IoMdMic
style={{marginLeft: '1rem'}}
size="2rem"
color="#fff"
/>
</div>
<div
style={{display: 'flex', alignItems: 'center', gap: '2rem'}}
>
<img
src={avatar}
style={{
width: '2.75rem',
height: '2.75rem',
borderRadius: '2rem',
marginRight: '2rem',
}}
/>
</div>
</header>
<div style={{display: 'flex', flexDirection: 'row'}}>
<main>
<VideoWrapper
videoWidth={videoWidth}
videoHeight={videoHeight}
>
{children}
</VideoWrapper>
<Footer videoWidth={videoWidth}>
<h1>[CodeStack News] {title}</h1>
<div>
<p>
<span>
{Math.round(frame / 3)} Visualizações
</span>
<span>
{format(
new Date(),
"dd 'de' MMM. 'de' yyyy",
{
locale: ptBR,
}
)}
</span>
</p>
<div>
<section
style={{
borderBottom: `3px solid ${
frame >=
57 + startClickAnimationAtFrame
? '#3EA6FF'
: ''
}`,
}}
>
<text
style={{
color:
frame >=
57 + startClickAnimationAtFrame
? '#3EA6FF'
: '',
}}
>
<IoMdThumbsUp size="3rem" />
{Math.round(frame / 10)}
</text>
<text>
<IoMdThumbsDown size="3rem" /> 0
</text>
</section>
<text>
<IoIosShareAlt size="3rem" />
Compartilhar
</text>
<text>
<RiPlayListAddLine size="2rem" />
Salvar
</text>
<BsThreeDots size="3rem" />
</div>
</div>
<div style={{margin: '0.5rem 0'}}>
<div>
<img
src={avatar}
style={{
width: '4.5rem',
height: '4.5rem',
borderRadius: '2.5rem',
marginRight: '0rem',
}}
/>
<p
style={{
display: 'flex',
flexDirection: 'column',
}}
>
<strong
style={{
fontSize: '1.5rem',
color: '#fff',
}}
>
CodeStack
</strong>
<span>
{Math.round(frame / 15)} inscritos
</span>
</p>
</div>
<p
style={{
background:
frame >=
115 + startClickAnimationAtFrame
? '#303030'
: '#CC0000',
color: '#fff',
fontSize: '1.7rem',
textTransform: 'uppercase',
padding: '1rem 2rem',
margin: 0,
borderRadius: 5,
}}
>
{frame >= 115 + startClickAnimationAtFrame
? 'Inscrito'
: 'Inscreva-se'}
</p>
</div>
<div
style={{
position: 'absolute',
bottom: moveY, //-50 -> 95 -> 10 -> -50
right: moveX, //370 -> 670 -> 50 -> 150
}}
>
<svg
width="3rem"
height="3rem"
viewBox="0 0 23 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#prefix__clip0)">
<path
d="M22.326 11.773v4.5c0 .145-.018.29-.053.43l-1.571 6.375c-.209.847-1 1.445-1.912 1.445H8.576c-.31 0-.616-.07-.892-.204a1.944 1.944 0 01-.697-.568l-6.285-8.25c-.639-.837-.445-2.01.433-2.619.877-.609 2.106-.424 2.744.414l1.554 2.04V2.398c0-1.035.88-1.875 1.964-1.875 1.085 0 1.964.84 1.964 1.875v9.375h.393V9.898c0-1.035.88-1.875 1.965-1.875 1.084 0 1.964.84 1.964 1.875v1.875h.393v-1.125c0-1.035.88-1.875 1.964-1.875 1.085 0 1.964.84 1.964 1.875v1.125h.393c0-1.035.88-1.875 1.964-1.875 1.085 0 1.965.84 1.965 1.875zm-12.572 3.75h-.393v4.5h.393v-4.5zm4.322 0h-.393v4.5h.393v-4.5zm4.321 0h-.393v4.5h.393v-4.5z"
fill={colorsClick}
/>
</g>
</svg>
</div>
</Footer>
</main>
<Aside>
{new Array(7).fill(0).map((_, i) => {
return (
<div key={i}>
<main></main>
<p>
<strong></strong>
<span></span>
</p>
</div>
);
})}
</Aside>
</div>
</div>
);
}
Example #5
Source File: SearchForm.tsx From game-store-monorepo-app with MIT License | 4 votes |
SearchForm: React.FC<SearchFormProps> = ({ className, ...rest }) => {
const navigate = useNavigate();
const [searchTerm, setSearchTerm] = React.useState('');
const [searchVisible, setSearchVisible] = React.useState(false);
const debouncedSearchTerm = useDebounce(searchTerm);
const [searchGames, { data, loading }] = useLazyQuery<SearchGamesQueryResponse>(SEARCH_GAMES);
const listClassName = cn({
hidden: !searchVisible,
});
React.useEffect(() => {
if (debouncedSearchTerm) {
setSearchVisible(true);
} else {
setSearchVisible(false);
}
}, [debouncedSearchTerm]);
React.useEffect(() => {
if (!debouncedSearchTerm) {
return;
}
const queryParams: GamesQueryParams = {
variables: {
page: 1,
pageSize: 10,
search: debouncedSearchTerm,
},
};
searchGames(queryParams);
}, [debouncedSearchTerm, searchGames, searchVisible]);
const gameResults = data?.searchGames?.results;
const listData: ListItem[] = React.useMemo(() => {
if (!gameResults) {
return [];
}
return gameResults.map((item): ListItem => {
return {
id: item.id,
avatarUrl: item.thumbnailImage,
title: item.name,
content: (
<div>
<PlatformLogos data={item.parentPlatforms} className="mt-1" />
<p className="mt-2 text-sm text-base-content-secondary truncate">{`${getMultipleItemNames(
item.genres,
3,
)}`}</p>
</div>
),
};
});
}, [gameResults]);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearchTerm(e.target.value);
};
const handleBlur = () => {
setTimeout(() => {
setSearchVisible(false);
}, 200);
};
const handleFocus = () => {
if (!gameResults?.length) {
return;
}
setSearchVisible(true);
};
const onItemClick = (value: ListItem) => {
navigate(`${ROUTES.GAMES}/${value.id}`);
};
const onSearchButtonClick = () => {
navigate(`${ROUTES.GAMES}?search=${searchTerm}`);
};
return (
<div className={cn(className)} {...rest}>
<FormInput
value={searchTerm}
onChange={handleChange}
placeholder="Search games..."
addonElement={
<Button variant="primary" className="font-bold btn-addon-right" onClick={onSearchButtonClick}>
<AiOutlineSearch size={16} />
</Button>
}
onBlur={handleBlur}
onFocus={handleFocus}
/>
<List
data={listData}
onItemClick={onItemClick}
isLoading={loading}
className={cn(
'absolute w-full max-h-96 min-h-12 top-[55px] bg-base-100 overflow-y-auto rounded-xl shadow-2xl',
listClassName,
)}
/>
</div>
);
}