react-icons/fa#FaRegQuestionCircle TypeScript Examples
The following examples show how to use
react-icons/fa#FaRegQuestionCircle.
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: Section.tsx From slice-machine with Apache License 2.0 | 6 votes |
Section: React.FC<{
children: React.ReactNode;
heading: React.ReactNode;
}> = ({ children, heading }) => (
<Flex sx={{ padding: "16px 20px" }}>
<Flex
sx={{
padding: 3,
backgroundColor: (t) => t.colors?.gray,
borderRadius: 8,
flexDirection: "column",
}}
>
<Flex sx={{ alignItems: "center", mb: 3 }}>
<Flex sx={{ mr: 2 }}>
<FaRegQuestionCircle size={20} color="grey05" />
</Flex>
<Text sx={{ fontSize: 2, fontWeight: 500 }}>{heading}</Text>
</Flex>
<Text sx={{ color: (t) => t.colors?.textClear }}>{children}</Text>
</Flex>
</Flex>
)
Example #2
Source File: RepositoryWarningModal.tsx From hub with Apache License 2.0 | 5 votes |
RepositoryWarningModal = () => {
const [openStatus, setOpenStatus] = useState<boolean>(false);
return (
<>
<button
className={`d-inline-block ps-0 pe-1 py-0 btn btn-link btn-sm fs-6 text-dark ${styles.trackingWarningBtn}`}
onClick={() => setOpenStatus(true)}
aria-label="Open repository warning modal"
>
<small>
<FaRegQuestionCircle className={`position-relative ${styles.icon}`} />
</small>
</button>
{openStatus && (
<Modal className="d-inline-block" noFooter onClose={() => setOpenStatus(false)} open={openStatus}>
<div className="mw-100 text-start text-dark">
<div className="d-flex flex-row justify-content-between mb-4">
<div className={`h3 d-flex flex-row align-items-baseline ${styles.title}`}>Warning info</div>
<div>
<button
type="button"
className={`btn-close p-3 ${styles.closeModalBtn}`}
onClick={() => {
setOpenStatus(false);
}}
aria-label="Close"
></button>
</div>
</div>
<div className="fs-6">
<p>
This warning sign indicates that the tracking operation that took place at the processed time displayed
failed. You can see more details about why it failed by opening the tracking errors log modal.
</p>
<p>
Please note that <span className="fw-bold">this warning will remain visible</span> until the next time
the repository is processed successfully. Repositories are checked for updates every{' '}
<span className="fst-italic">30 minutes approximately</span>, but they are only
<span className="fst-italic mx-1">processed</span> if they have{' '}
<span className="fw-bold">changed since the last time they were processed</span>.
</p>
<p>
Depending on the nature of the error, an action on your side may be required or not. In the case of
isolated network errors, you can ignore the warning and it'll be cleaned up automatically on the next
successful tracking operation.
</p>
</div>
</div>
</Modal>
)}
</>
);
}
Example #3
Source File: SearchBar.tsx From hub with Apache License 2.0 | 4 votes |
SearchBar = (props: Props) => {
const history = useHistory();
const dropdownRef = useRef(null);
const [value, setValue] = useState(props.tsQueryWeb || '');
const inputEl = useRef<HTMLInputElement>(null);
const [packages, setPackages] = useState<Package[] | null>(null);
const [totalPackagesNumber, setTotalPackagesNumber] = useState<number | null>(null);
const [visibleDropdown, setVisibleDropdown] = useState<boolean>(false);
const point = useBreakpointDetect();
const [highlightedItem, setHighlightedItem] = useState<number | null>(null);
const [dropdownTimeout, setDropdownTimeout] = useState<NodeJS.Timeout | null>(null);
useOutsideClick([dropdownRef], visibleDropdown, () => {
cleanSearch();
});
const onChange = (e: ChangeEvent<HTMLInputElement>): void => {
setValue(e.target.value);
};
const cleanSearchBox = (): void => {
setValue('');
forceFocus();
};
const forceFocus = (): void => {
if (!isNull(inputEl) && !isNull(inputEl.current)) {
inputEl.current.focus();
}
};
const forceBlur = (): void => {
if (!isNull(inputEl) && !isNull(inputEl.current)) {
inputEl.current.blur();
}
};
const goToSearch = () => {
cleanTimeout();
forceBlur();
cleanSearch();
history.push({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
tsQueryWeb: value || undefined,
}),
});
};
const cleanTimeout = () => {
if (!isNull(dropdownTimeout)) {
clearTimeout(dropdownTimeout);
setDropdownTimeout(null);
}
};
const cleanSearch = () => {
setPackages(null);
setTotalPackagesNumber(null);
setVisibleDropdown(false);
setHighlightedItem(null);
};
const onKeyDown = (e: KeyboardEvent<HTMLInputElement>): void => {
switch (e.key) {
case 'Escape':
cleanSearch();
return;
case 'ArrowDown':
updateHighlightedItem('down');
return;
case 'ArrowUp':
updateHighlightedItem('up');
return;
case 'Enter':
e.preventDefault();
if (!isNull(packages) && !isNull(highlightedItem)) {
if (highlightedItem === packages.length) {
goToSearch();
} else {
const selectedPackage = packages[highlightedItem];
if (selectedPackage) {
goToPackage(selectedPackage);
}
}
} else {
goToSearch();
}
return;
default:
return;
}
};
const updateHighlightedItem = (arrow: 'up' | 'down') => {
if (!isNull(packages) && visibleDropdown) {
if (!isNull(highlightedItem)) {
let newIndex: number = arrow === 'up' ? highlightedItem - 1 : highlightedItem + 1;
if (newIndex > packages.length) {
newIndex = 0;
}
if (newIndex < 0) {
newIndex = packages.length;
}
setHighlightedItem(newIndex);
} else {
if (packages && packages.length > 0) {
const newIndex = arrow === 'up' ? packages.length : 0; // We don't subtract 1 because See all results (x) has to be count
setHighlightedItem(newIndex);
}
}
}
};
const goToPackage = (selectedPackage: Package) => {
forceBlur();
setValue('');
cleanSearch();
history.push({
pathname: buildPackageURL(selectedPackage.normalizedName, selectedPackage.repository, selectedPackage.version!),
});
};
useEffect(() => {
setValue(props.tsQueryWeb || '');
}, [props.tsQueryWeb]);
async function searchPackages() {
try {
const searchResults = await API.searchPackages(
{
tsQueryWeb: value,
filters: {},
limit: 5,
offset: 0,
},
false
);
const total = parseInt(searchResults.paginationTotalCount);
if (total > 0) {
const isInputFocused = inputEl.current === document.activeElement;
// We have to be sure that input has focus to display results
if (isInputFocused) {
setPackages(searchResults.packages);
setTotalPackagesNumber(total);
setVisibleDropdown(true);
} else {
cleanSearch();
}
} else {
cleanSearch();
}
} catch (err: any) {
cleanSearch();
}
}
useEffect(() => {
// Don't display search options for mobile devices
if (point !== 'xs') {
const isInputFocused = inputEl.current === document.activeElement;
if (value.length >= MIN_CHARACTERS_SEARCH && isInputFocused) {
cleanTimeout();
setDropdownTimeout(
setTimeout(() => {
setHighlightedItem(null);
searchPackages();
}, SEARCH_DELAY)
);
} else {
cleanSearch();
}
}
return () => {
if (!isNull(dropdownTimeout)) {
clearTimeout(dropdownTimeout);
}
};
}, [value]); /* eslint-disable-line react-hooks/exhaustive-deps */
return (
<>
<div className={`position-relative ${props.formClassName}`}>
<div
className={`d-flex align-items-center overflow-hidden searchBar lh-base bg-white ${styles.searchBar} ${
styles[props.size]
}`}
role="combobox"
aria-haspopup="listbox"
aria-owns="search-list"
aria-expanded={visibleDropdown && !isNull(packages)}
aria-controls="search-list"
>
<div
data-testid="searchBarIcon"
className={`d-flex align-items-center ${styles.iconWrapper}`}
onClick={forceFocus}
>
<FiSearch />
</div>
<input
ref={inputEl}
className={`flex-grow-1 ps-2 ps-md-0 border-0 shadow-none bg-transparent ${styles.input}`}
type="text"
autoComplete="off"
autoCorrect="off"
autoCapitalize="none"
spellCheck="false"
placeholder="Search packages"
aria-label="Search packages"
value={value}
onChange={onChange}
onKeyDown={onKeyDown}
disabled={props.isSearching}
/>
<div className="d-none" tabIndex={0}>
<div aria-live="polite">{!isNull(packages) ? `${packages.length} results found` : ''}</div>
</div>
{props.isSearching && (
<div
className={classnames('position-absolute text-secondary', styles.loading, {
[styles.bigLoading]: props.size === 'big',
})}
>
<span data-testid="searchBarSpinning" className="spinner-border spinner-border-sm" />
</div>
)}
<button
type="button"
className={classnames('btn-close lh-lg ps-2 pe-3', styles.inputClean, {
invisible: value === '' || props.isSearching,
})}
onClick={cleanSearchBox}
aria-label="Close"
></button>
<div
className={classnames('position-absolute text-dark', styles.tipIcon, {
[styles.bigTipIcon]: props.size === 'big',
})}
>
<button
onClick={() => props.setOpenTips(true)}
className={classnames('btn btn-link p-2 text-light', {
'btn-lg': props.size === 'big',
})}
aria-label="Open search tips modal"
>
<FaRegQuestionCircle />
</button>
</div>
</div>
{visibleDropdown && !isNull(packages) && (
<div
ref={dropdownRef}
className={`dropdown-menu dropdown-menu-left p-0 shadow-sm w-100 show noFocus ${styles.dropdown}`}
role="listbox"
id="search-list"
aria-activedescendant={highlightedItem ? `sl-opt${highlightedItem}` : ''}
tabIndex={0}
aria-roledescription="Packages list"
>
<HoverableItem onLeave={() => setHighlightedItem(null)}>
<>
{packages.map((pkg: Package, index: number) => {
return (
<HoverableItem
key={`pkg_${pkg.packageId}`}
onHover={() => setHighlightedItem(index)}
onLeave={() => setHighlightedItem(null)}
>
<button
type="button"
className={classnames(
'btn btn-link w-100 border-bottom rounded-0 d-flex flex-row align-items-stretch text-decoration-none text-dark p-3',
{ [styles.activeDropdownItem]: index === highlightedItem }
)}
onClick={() => {
goToPackage(pkg);
}}
aria-label={`Open package ${pkg.displayName || pkg.name} detail`}
role="option"
aria-selected={index === highlightedItem}
id={`sl-opt${index}`}
>
<div
className={`d-none d-md-flex align-items-center justify-content-center overflow-hidden rounded-circle p-1 border border-2 bg-white position-relative ${styles.imageWrapper} imageWrapper`}
>
<Image
imageId={pkg.logoImageId}
alt={`Logo ${pkg.displayName || pkg.name}`}
className={styles.image}
kind={pkg.repository.kind}
/>
</div>
<div className={`ms-0 ms-md-3 flex-grow-1 ${styles.truncateWrapper}`}>
<div className="d-flex flex-row align-items-center">
<div className={`text-truncate fw-bold ${styles.title}`}>{pkg.displayName || pkg.name}</div>
<div
className={`align-self-start d-flex align-items-center text-uppercase ms-auto ps-2 ${styles.midText}`}
>
<StarBadge className="me-1" starsNumber={pkg.stars} />
<RepositoryIconLabel kind={pkg.repository.kind} iconClassName={styles.kindIcon} />
</div>
</div>
<div className="d-flex flex-row align-items-center mt-2">
<div className={`text-truncate ${styles.smallText}`}>
<small className="text-muted text-uppercase">
{pkg.repository.userAlias ? 'User' : 'Org'}:
</small>
<span className="ms-1 me-2">
{pkg.repository.userAlias ||
pkg.repository.organizationDisplayName ||
pkg.repository.organizationName}
</span>
<small className="text-muted text-uppercase">Repo:</small>
<span className="text-truncate ms-1">{pkg.repository.name}</span>
</div>
<div className="ms-auto d-flex flex-nowrap ps-2">
<OfficialBadge
official={isPackageOfficial(pkg)}
className="d-inline"
type="package"
withoutTooltip
/>
</div>
</div>
</div>
</button>
</HoverableItem>
);
})}
<HoverableItem
onHover={() => setHighlightedItem(packages.length)}
onLeave={() => setHighlightedItem(null)}
>
<button
type="button"
className={classnames('btn btn-link w-100 text-dark p-2', styles.dropdownItem, {
[styles.activeDropdownItem]: packages.length === highlightedItem,
})}
onClick={goToSearch}
aria-label="See all results"
role="option"
aria-selected={packages.length === highlightedItem}
id={`sl-opt${packages.length}`}
>
See all results ({totalPackagesNumber})
</button>
</HoverableItem>
</>
</HoverableItem>
</div>
)}
</div>
</>
);
}