react-transition-group#TransitionGroup TypeScript Examples
The following examples show how to use
react-transition-group#TransitionGroup.
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 polkabtc-ui with Apache License 2.0 | 6 votes |
TransitionWrapper = ({ location, children }: Props): JSX.Element => ( <TransitionGroup> <CSSTransition key={location.key} classNames='fade' timeout={300}> {children} </CSSTransition> </TransitionGroup> )
Example #2
Source File: Layout.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 6 votes |
Layout: FC = ({ children }) => {
return (
<ModalDataProvider>
<ModalProvider rootComponent={TransitionGroup}>
<Background />
<BannerMessage />
<AppBar />
<Container>
<Main>{children}</Main>
</Container>
<Footer />
<Toasts />
<StyledTooltip tip="" hideIcon />
<ReactTooltip id="global" place="top" html={true} />
<GlobalStyle />
</ModalProvider>
</ModalDataProvider>
)
}
Example #3
Source File: Toasts.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 6 votes |
Toasts: FC = () => {
const notifications = useNotificationsState()
const txs = useTransactionsState()
return (
<Container>
<TransitionGroup>
{Object.keys(txs)
.filter(id => txs[id].status === TransactionStatus.Pending || txs[id].status === TransactionStatus.Sent)
.sort((a, b) => txs[b].manifest.createdAt - txs[a].manifest.createdAt)
.map(id => (
<Animation timeout={TIMEOUT.default} classNames="item" key={id}>
<div>
<TransactionGasProvider id={id}>
<PendingTransaction id={id} />
</TransactionGasProvider>
</div>
</Animation>
))}
{notifications
.filter(n => !(n.hideToast || n.read))
.map(notification => (
<Animation
isQuest={notification.type === NotificationType.Quest}
timeout={notification.type === NotificationType.Quest ? TIMEOUT.quest : TIMEOUT.default}
classNames="item"
key={notification.id}
>
<NotificationItem notification={notification} />
</Animation>
))}
</TransitionGroup>
</Container>
)
}
Example #4
Source File: MinimizedChats.tsx From foodie with MIT License | 6 votes |
MinimizedChats: React.FC<IProps> = ({ users }) => {
const dispatch = useDispatch();
return (
<div className="p-4 absolute bottom-0 right-0">
<TransitionGroup component={null}>
{users.map(chat => chat.minimized && (
<CSSTransition
timeout={500}
classNames="fade"
key={chat.username}
>
<div
key={chat.username}
onClick={() => dispatch(initiateChat(chat))}
title={chat.username}
>
<Avatar
url={chat.profilePicture?.url}
size="lg"
className="cursor-pointer shadow-md hover:border-2 hover:border-indigo-500 hover:opacity-90 mr-2 my-4 border border-indigo-700"
/>
</div>
</CSSTransition>
))}
</TransitionGroup>
</div>
);
}
Example #5
Source File: TransitionCard.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 6 votes |
TransitionCard: FC<{
components: Record<string, ReactElement>
selection?: string
}> = ({ components, selection, children }) => {
return (
<Container>
<Header showBorder={!!selection}>{children}</Header>
<Content open={!!selection}>
<TransitionGroup>
{Object.keys(components)
.filter(type => type === selection)
.map(type => {
const Comp = components[type]
return (
<CSSTransition timeout={{ enter: 500, exit: 200 }} classNames="item" key={type}>
{Comp}
</CSSTransition>
)
})}
</TransitionGroup>
</Content>
</Container>
)
}
Example #6
Source File: index.tsx From oasis-wallet-web with Apache License 2.0 | 6 votes |
export function App() {
useRouteRedirects()
const { i18n } = useTranslation()
const size = useContext(ResponsiveContext)
return (
<ModalProvider>
<Helmet
titleTemplate="%s - Oasis Wallet"
defaultTitle="Oasis Wallet"
htmlAttributes={{ lang: i18n.language }}
>
<meta name="description" content="A wallet for Oasis" />
</Helmet>
<Box direction="row-responsive" background="background-back" fill style={{ minHeight: '100vh' }}>
<Navigation />
<Box flex pad={{ top: size === 'small' ? '64px' : undefined }}>
<AppMain>
<FatalErrorHandler />
<Toolbar />
<TransitionGroup>
<Switch>
<TransitionRoute exact path="/" component={HomePage} />
<TransitionRoute exact path="/create-wallet" component={CreateWalletPage} />
<TransitionRoute path="/open-wallet" component={OpenWalletPage} />
<TransitionRoute exact path="/account/:address/stake" component={AccountPage} />
<TransitionRoute path="/account/:address" component={AccountPage} />
</Switch>
</TransitionGroup>
<Footer />
</AppMain>
</Box>
</Box>
</ModalProvider>
)
}
Example #7
Source File: Modals.tsx From flood with GNU General Public License v3.0 | 6 votes |
Modals: FC = observer(() => {
const {id} = UIStore.activeModal || {};
useKeyPressEvent('Escape', () => UIStore.setActiveModal(null));
let modal;
if (id != null) {
modal = (
<CSSTransition key={id} classNames="modal__animation" timeout={{enter: 500, exit: 500}}>
<div className="modal">
<div
className="modal__overlay"
role="none"
onClick={() => {
UIStore.setActiveModal(null);
}}
/>
{createModal(id)}
</div>
</CSSTransition>
);
}
return <TransitionGroup>{modal}</TransitionGroup>;
})
Example #8
Source File: index.tsx From oasis-wallet-web with Apache License 2.0 | 6 votes |
export function OpenWalletPage(props: Props) {
return (
<TransitionGroup>
<Switch>
<TransitionRoute exact path="/open-wallet" component={SelectOpenMethod} />
<TransitionRoute exact path="/open-wallet/mnemonic" component={FromMnemonic} />
<TransitionRoute exact path="/open-wallet/private-key" component={FromPrivateKey} />
<TransitionRoute exact path="/open-wallet/ledger" component={FromLedger} />
</Switch>
</TransitionGroup>
)
}
Example #9
Source File: Alerts.tsx From flood with GNU General Public License v3.0 | 6 votes |
Alerts: FC = observer(() => {
const {sortedAlerts} = AlertStore;
return (
<TransitionGroup>
{sortedAlerts != null && sortedAlerts.length > 0 ? (
<CSSTransition classNames="alerts__list" timeout={{enter: 250, exit: 250}}>
<ul className="alerts__list" key="alerts-list">
{sortedAlerts.map((alert) => (
<Alert key={alert.id} id={alert.id} />
))}
</ul>
</CSSTransition>
) : null}
</TransitionGroup>
);
})
Example #10
Source File: App.transitions.tsx From tezos-academy with MIT License | 6 votes |
AppTransitions = ({ pageKey, children, reverse }: { pageKey: any; children: any; reverse: boolean }) => {
const { pathname } = useLocation()
useEffect(() => {
window.scrollTo(0, 0)
}, [pathname])
const animation = reverse ? 'slide-right' : 'slide-left'
return (
<TransitionGroup
childFactory={childFactoryCreator({
classNames: animation,
timeout: 300,
})}
>
<CSSTransition timeout={0} key={pageKey}>
<AppWrapper>{children}</AppWrapper>
</CSSTransition>
</TransitionGroup>
)
}
Example #11
Source File: index.tsx From interactsh-web with MIT License | 6 votes |
AnimatedSwitch = withRouter(({ location }) => {
window.scrollTo(0, 0);
document.getElementsByTagName("html")[0].style.overflow = "visible";
return (
<TransitionGroup>
<CSSTransition key={location.pathname} classNames="slide slide" timeout={10}>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/terms" component={TermsPage} />
</Switch>
</CSSTransition>
</TransitionGroup>
);
})
Example #12
Source File: index.tsx From vagasExplorer with MIT License | 6 votes |
Routes: React.FC<ToggleTheme> = ({ toggleTheme }) => (
<Route
render={({ location }) => (
<TransitionGroup>
<CSSTransition key={location.key} timeout={300} classNames="fade">
<Switch location={location}>
<Route
exact
path="/"
component={() => <Home toggleTheme={toggleTheme} />}
/>
<Route
exact
path="/dashboard"
component={() => <Dashboard toggleTheme={toggleTheme} />}
/>
<Route
path="/repository/:repository+"
component={() => <Repository toggleTheme={toggleTheme} />}
/>
</Switch>
</CSSTransition>
</TransitionGroup>
)}
/>
)
Example #13
Source File: ToastContainer.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
ToastContainer: React.FC<ToastContainerProps> = ({ toasts, onRemove, ttl = 6000, stackSpacing = 24 }) => {
return (
<StyledToastContainer>
<TransitionGroup>
{toasts.map((toast, index) => {
const zIndex = (ZINDEX - index).toString()
const top = TOP_POSITION + index * stackSpacing
return (
<Toast key={toast.id} toast={toast} onRemove={onRemove} ttl={ttl} style={{ top: `${top}px`, zIndex }} />
)
})}
</TransitionGroup>
</StyledToastContainer>
)
}
Example #14
Source File: index.tsx From hive with MIT License | 6 votes |
function Page({ page, index, common, dashboard }: Props) {
const currentKey = index;
const timeout = { enter: 300, exit: 200 };
const wrapClass = cn(styles.wrap, { [styles.mobile]: common.isMobile });
return (
<TransitionGroup component="div" className={styles.mainTransition}>
<CSSTransition key={currentKey} timeout={timeout} classNames="animated-fade" appear>
<div className={wrapClass}>
<LoaderSpinner loading={dashboard.loading} />
<Header page={page} />
<div className={styles.content}>
<div className={styles.background} />
<div className={styles.internalContent}>
<Content />
</div>
</div>
</div>
</CSSTransition>
</TransitionGroup>
);
}
Example #15
Source File: index.tsx From hive with MIT License | 6 votes |
render() {
const { model, isDragging, connectDragSource, connectDropTarget } = this.props;
const timeout = { enter: 500, exit: 500 };
return (
<TransitionGroup component={null}>
<CSSTransition
timeout={timeout}
classNames={{
appear: styles.appear,
appearActive: styles.appearActive,
enter: styles.enter,
enterActive: styles.enterActive,
exit: styles.exit,
exitActive: styles.exitActive,
}}
appear
>
{connectDropTarget(
<div>
<Module
service={this.service}
connectDragSource={connectDragSource}
isDragging={isDragging}
model={model}
onRemoveWidget={this.removeWidget}
onOpenDrawer={this.openDrawer}
/>
</div>
)}
</CSSTransition>
</TransitionGroup>
);
}
Example #16
Source File: index.tsx From hive with MIT License | 6 votes |
render() {
const { location } = this.props;
const currentKey = location.pathname || '/';
const timeout = { enter: 300, exit: 200 };
return (
<Fragment>
<WidthCalculator />
<Tabs location={location} />
<TransitionGroup component="div" className={styles.mainTransition}>
<CSSTransition
key={currentKey}
timeout={timeout}
classNames="animated-fade"
appear
>
<div className={styles.transition}>
<Switch location={location}>
<AuthorizedRoute path={constants.paths.admin} component={Admin} />
<AuthorizedRoute
path={constants.paths.dashboard}
component={Dashboard}
/>
</Switch>
</div>
</CSSTransition>
</TransitionGroup>
</Fragment>
);
}
Example #17
Source File: confirmationModal.tsx From atlas with GNU General Public License v3.0 | 6 votes |
ConfirmationModalProvider: React.FC = ({ children }) => {
const [modals, setModals] = useState<Record<string, React.FC>>({})
const openModal = useCallback(
(key: string, modal: React.FC) =>
setModals((modals) => ({
...modals,
[key]: modal,
})),
[]
)
const closeModal = useCallback(
(key: string) =>
setModals((modals) => {
const { [key]: _, ...filteredModals } = modals
return filteredModals
}),
[]
)
const contextValue = useMemo(() => ({ openModal, closeModal }), [closeModal, openModal])
return (
<ConfirmationModalContext.Provider value={contextValue}>
{children}
<TransitionGroup>
{Object.keys(modals).map((key) => {
const Component = modals[key]
return <Component key={key} />
})}
</TransitionGroup>
</ConfirmationModalContext.Provider>
)
}
Example #18
Source File: Products.tsx From next-shopping-cart with MIT License | 5 votes |
Products = ({ searchTerm, productsList, openModal }: Props) => {
const { addProduct } = useContext<Init>(CartContext);
const term = searchTerm;
const searchingFor = (searchText: string) => {
return (x) => {
return (
x.name.toLowerCase().includes(searchText.toLowerCase()) || !searchText
);
};
};
const productsData = productsList
.filter(searchingFor(term))
.map((product) => {
return (
<CSSTransition
key={product.id}
classNames="fadeIn"
timeout={{
enter: 300,
exit: 500,
}}
>
<ProductItem
// key={product.id}
price={product.price}
name={product.name}
image={product.image}
id={parseInt(product.id, 10)}
unit={product.unit}
addToCart={addProduct}
// productQuantity={props.productQuantity}
openModal={openModal}
/>
</CSSTransition>
);
});
// Empty and Loading States
let view;
// if (productsData.length <= 0 && !term) {
// view = <LoadingProducts />;
// } else
if (productsData.length <= 0 && term) {
view = <NoResults />;
} else {
view = (
<TransitionGroup component="div" className={styles.products}>
{productsData}
</TransitionGroup>
);
}
return <div className={styles.productsWrapper}>{view}</div>;
}
Example #19
Source File: index.tsx From questdb.io with Apache License 2.0 | 5 votes |
Subscribe: React.FunctionComponent<Props> = ({
placeholder = "Email address",
provider = "enterprise",
submitButtonText = "SUBMIT",
submitButtonVariant,
className,
}) => {
const [loading, setLoading] = useState(false)
const [sent, setSent] = useState(false)
const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault()
setLoading(true)
const target = event.target as HTMLFormElement
const email = new FormData(target).get("email") as string
try {
if (provider === "newsletter") {
await fetch(
`${providers.newsletter}&EMAIL=${encodeURIComponent(email)}`,
{ method: "GET" },
)
} else {
await fetch(providers[provider], {
body: JSON.stringify({ email }),
headers: { "Content-Type": "application/json" },
method: "POST",
})
}
} catch (e) {}
setSent(true)
}
return (
<form className={clsx(style.root, className)} onSubmit={onSubmit}>
<TransitionGroup>
<CSSTransition key={sent.toString()} timeout={200} classNames="item">
{sent ? (
<p className={style.success}>
Thank you, we will be in touch soon!
</p>
) : (
<div className={style.inputs}>
<Input
className={style.input}
name="email"
type="email"
title="Email address should be valid"
placeholder={placeholder}
required
pattern={emailPattern}
/>
<Button
className={style.submit}
variant={submitButtonVariant}
type="submit"
>
{loading ? <span className={style.loader} /> : submitButtonText}
</Button>
</div>
)}
</CSSTransition>
</TransitionGroup>
</form>
)
}
Example #20
Source File: ChannelCover.tsx From atlas with GNU General Public License v3.0 | 5 votes |
ChannelCover: React.FC<ChannelCoverProps> = ({
assetUrl,
hasCoverUploadFailed,
editable,
disabled,
onCoverEditClick,
}) => {
return (
<CoverWrapper>
<MediaWrapper>
{editable && !disabled && (
<EditableControls>
<EditCoverDesktopOverlay onClick={onCoverEditClick}>
<SvgActionImage />
<EditButtonMessage variant="t200-strong">{`${
assetUrl ? 'Edit ' : 'Add '
} cover image`}</EditButtonMessage>
</EditCoverDesktopOverlay>
<EditCoverMobileButton onClick={onCoverEditClick} variant="tertiary">
<SvgActionImageFile />
</EditCoverMobileButton>
</EditableControls>
)}
<Media>
<TransitionGroup>
<CSSTransition
key={assetUrl ? 'cover' : 'pattern'}
timeout={parseInt(transitions.timings.loading)}
classNames={transitions.names.fade}
>
{assetUrl ? (
<CoverImage src={assetUrl} />
) : hasCoverUploadFailed ? (
<FailedUploadContainer>
<StyledSvgIllustrativeFileFailed />
<Text variant="t100" secondary>
Failed upload
</Text>
</FailedUploadContainer>
) : (
<StyledBackgroundPattern />
)}
</CSSTransition>
</TransitionGroup>
</Media>
</MediaWrapper>
</CoverWrapper>
)
}
Example #21
Source File: snackbar.tsx From atlas with GNU General Public License v3.0 | 5 votes |
Snackbars: React.FC = () => {
const { closeSnackbar, cancelSnackbarTimeout, restartSnackbarTimeout } = useSnackbar()
const snackbars = useSnackbarStore((state) => state.snackbars)
const { cookiesAccepted } = usePersonalDataStore((state) => ({
cookiesAccepted: state.cookiesAccepted,
}))
const bottomNavOpen = useBottomNavStore((state) => state.open)
useEffect(() => {
if (snackbars.length > SNACKBARS_LIMIT) {
setTimeout(() => {
closeSnackbar(snackbars[0].id)
}, 500)
}
}, [snackbars, closeSnackbar])
return (
<SnackbarsContainer cookiesBannerOpen={cookiesAccepted === undefined} bottomNavOpen={bottomNavOpen}>
<TransitionGroup>
{snackbars.map(({ id, iconType, onActionClick, onExit, ...snackbarProps }) => (
<CSSTransition key={id} timeout={parseInt(cVar('animationTimingMedium', true)) * 2} classNames="snackbar">
<Snackbar
{...snackbarProps}
onActionClick={() => {
onActionClick?.()
closeSnackbar(id)
}}
onMouseEnter={() => {
cancelSnackbarTimeout(id)
}}
onMouseLeave={() => {
restartSnackbarTimeout(id)
}}
icon={iconType && ICON_TYPE_TO_ICON[iconType]}
onClick={() => {
onExit?.()
closeSnackbar(id)
}}
/>
</CSSTransition>
))}
</TransitionGroup>
</SnackbarsContainer>
)
}
Example #22
Source File: MessagesList.tsx From foodie with MIT License | 5 votes |
MessagesList: React.FC<IProps> = (props) => {
const { messages, handleReadMessage, infiniteScrollRef } = props;
return (
<div>
{messages.length === 0 ? (
<div className="text-center p-4">
<p className="text-gray-400 italic">No Messages.</p>
</div>
) : (
<div className="max-h-80vh laptop:max-h-70vh overflow-y-scroll divide-y divide-gray-100 scrollbar">
<TransitionGroup component={null}>
<div ref={infiniteScrollRef as React.RefObject<HTMLDivElement>}>
{messages.map(message => (message.from && message.to) && (
<CSSTransition
timeout={500}
classNames="fade"
key={message.id}
>
<div
className={`flex justify-start cursor-pointer hover:bg-gray-100 dark:hover:bg-indigo-1100 border border-transparent dark:hover:border-indigo-700 px-2 py-3 relative ${(!message.seen && !message.isOwnMessage) && 'bg-indigo-100 dark:bg-indigo-1100 hover:bg-indigo-200'}`}
key={message.id}
onClick={() => handleReadMessage(message.isOwnMessage ? message.to : message.from)}
>
{/* --- IMAGE--- */}
<Avatar
url={!message.isOwnMessage ? message.from.profilePicture?.url : message.to.profilePicture?.url}
size="lg"
className="flex-shrink-0 mr-4"
/>
<div className="relative flex-grow">
{/* --- USERNAME --- */}
<h5 className={`${(!message.seen && !message.isOwnMessage) && 'font-bold text-gray-800 dark:text-white'} text-gray-500`}>
{!message.isOwnMessage ? message.from.username : message.to.username}
</h5>
{/* -- MESSAGE--- */}
<span className={`block max-w-16rem laptop:max-w-xs whitespace-nowrap overflow-hidden overflow-ellipsis ${(message.seen || message.isOwnMessage) ? 'text-gray-400' : 'text-indigo-600 dark:text-indigo-400 font-medium'} text-sm`}>
{message.isOwnMessage && 'You:'} {message.text}
</span>
{/* --- DATE --- */}
<span className="absolute right-4 top-0 text-1xs text-gray-400">
{displayTime(message.createdAt)}
</span>
{/* ---- SEEN ---- */}
{(message.isOwnMessage && message.seen) && (
<Avatar
className="absolute right-4 bottom-0"
size="xs"
url={message.to.profilePicture?.url}
/>
)}
{/* --- BADGE ---- */}
{(!message.isOwnMessage && !message.seen) && (
<div className="absolute rounded-full bottom-0 top-0 right-4 my-auto w-2 h-2 bg-red-600" />
)}
</div>
</div>
</CSSTransition>
)
)}
</div>
</TransitionGroup>
</div>
)}
</div>
);
}
Example #23
Source File: CommentList.tsx From foodie with MIT License | 5 votes |
CommentList: React.FC<IProps> = ({ comments, updateCommentCallback }) => {
const didMount = useDidMount();
const dispatch = useDispatch();
const [replies, setReplies] = useState<IComment[]>(comments);
const { isOpen, closeModal, openModal } = useModal();
useEffect(() => {
didMount && setReplies(comments);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [comments]);
const deleteSuccessCallback = (comment: IComment) => {
if (didMount) {
(updateCommentCallback) && updateCommentCallback(comment); // For updating the base/parent comment
dispatch(setTargetComment(null));
setReplies(oldComments => oldComments.filter((cmt) => cmt.id !== comment.id));
}
}
return (
<TransitionGroup component={null}>
{replies.map(comment => (
<CSSTransition
timeout={500}
classNames="fade"
key={comment.id}
>
<CommentItem openDeleteModal={openModal} comment={comment} />
</CSSTransition>
))}
{/* ---- DELETE MODAL ---- */}
<Suspense fallback={<LoadingOutlined className="text-gray-800 dark:text-white" />}>
{isOpen && (
<DeleteCommentModal
isOpen={isOpen}
closeModal={closeModal}
deleteSuccessCallback={deleteSuccessCallback}
/>
)}
</Suspense>
</TransitionGroup>
);
}
Example #24
Source File: AppWrapper.tsx From flood with GNU General Public License v3.0 | 5 votes |
AppWrapper: FC<AppWrapperProps> = observer(({children, className}: AppWrapperProps) => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
useEffectOnce(() => {
AuthActions.verify().then(
({initialUser}: {initialUser?: boolean}): void => {
if (initialUser) {
navigate('/register', {replace: true});
} else {
navigate('/overview', {replace: true});
}
},
(): void => {
navigate('/login', {replace: true});
},
);
});
if (searchParams.has('action')) {
if (searchParams.get('action') === 'add-urls') {
if (searchParams.has('url')) {
UIStore.setActiveModal({
id: 'add-torrents',
tab: 'by-url',
urls: [{id: 0, value: searchParams.get('url') as string}],
});
}
}
}
let overlay: ReactNode = null;
if (!AuthStore.isAuthenticating || (AuthStore.isAuthenticated && !UIStore.haveUIDependenciesResolved)) {
overlay = <LoadingOverlay dependencies={UIStore.dependencies} />;
}
if (AuthStore.isAuthenticated && !ClientStatusStore.isConnected && ConfigStore.authMethod !== 'none') {
overlay = (
<div className="application__loading-overlay">
<div className="application__entry-barrier">
<LogoutButton className={css({position: 'absolute', left: '5px', top: '5px'})} />
<ClientConnectionInterruption />
</div>
</div>
);
}
return (
<div className={classnames('application', className)}>
<WindowTitle />
<TransitionGroup>
{overlay != null ? (
<CSSTransition timeout={{enter: 1000, exit: 1000}} classNames="application__loading-overlay">
{overlay}
</CSSTransition>
) : null}
</TransitionGroup>
{children}
</div>
);
})
Example #25
Source File: NotificationList.tsx From foodie with MIT License | 5 votes |
NotificationList: React.FC<IProps> = (props) => {
const { toggleNotification, notifications, readNotification, infiniteScrollRef } = props;
const history = useHistory();
const handleNotificationClick = (link: string, id: string) => {
readNotification(id);
toggleNotification(false);
history.push(link);
};
return (
<div className="relative">
{notifications.length === 0 ? (
<div className="text-center p-4">
<p className="text-gray-400 italic">No new notifications</p>
</div>
) : (
<div
className="max-h-80vh laptop:max-h-70vh relative overflow-y-scroll divide-y divide-gray-100 scrollbar"
>
<TransitionGroup component={null}>
<div ref={infiniteScrollRef as React.RefObject<HTMLDivElement>}>
{notifications.map((notif) => notif.initiator && (
<CSSTransition
timeout={500}
classNames="fade"
key={notif.id}
>
<div
className={`border border-transparent dark:hover:border-indigo-700 ${notif.unread ? 'bg-indigo-100 dark:bg-indigo-1100 hover:bg-indigo-200' : 'bg-white dark:bg-indigo-1000 dark:hover:bg-indigo-1100'} p-4 hover:bg-gray-100 dark:hover:bg-indigo-1100 hover:opacity-95 divide-y divide-y-2 divide-gray-100`}
key={notif.id}
onClick={() => handleNotificationClick(notif.link, notif.id)}
>
<div className="relative">
<div className="flex items-start">
<Avatar
url={notif.initiator.profilePicture?.url}
size={window.screen.width < 1024 ? 'sm' : 'lg'}
className="mr-2 flex-shrink-0"
/>
<div>
<span className="text-indigo-700 dark:text-indigo-400 font-medium break-all">
{notif.initiator.username}
</span>
<span className="text-gray-600 dark:text-gray-400 break-all">
{
notif.type === 'like' ? 'likes your post.'
: notif.type === 'comment' ? 'commented on your post.'
: notif.type === 'comment-like' ? 'likes your comment.'
: notif.type === 'follow' ? 'started following you.'
: notif.type === 'reply' ? 'replied to your comment'
: ''
}
</span>
<br />
<span className="text-gray-500 text-1xs block">
{displayTime(notif.createdAt)}
</span>
</div>
</div>
{(notif.type === 'like' || notif.type === 'comment-like') ? (
<LikeOutlined className="text-2xl text-indigo-700 dark:text-indigo-400 absolute right-4 top-0 bottom-0 my-auto" />
) : (notif.type === 'comment' || notif.type === 'reply') ? (
<CommentOutlined className="text-2xl text-indigo-700 dark:text-indigo-400 absolute right-4 top-0 bottom-0 my-auto" />
) : (
<UserAddOutlined className="text-2xl text-indigo-700 dark:text-indigo-400 absolute right-4 top-0 bottom-0 my-auto" />
)}
</div>
</div>
</CSSTransition>
))}
</div>
</TransitionGroup>
</div>
)}
</div>
);
}
Example #26
Source File: AuthTab.tsx From flood with GNU General Public License v3.0 | 4 votes |
AuthTab: FC = observer(() => {
const formRef = useRef<Form>(null);
const clientConnectionSettingsRef = useRef<ClientConnectionSettings | null>(null);
const [error, setError] = useState<string | null>(null);
const [isUserListFetched, setIsUserListFetched] = useState<boolean>(false);
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
const {i18n} = useLingui();
useEffect(() => {
if (AuthStore.currentUser.isAdmin) {
AuthActions.fetchUsers().then(() => {
setIsUserListFetched(true);
});
}
}, []);
if (!AuthStore.currentUser.isAdmin) {
return (
<Form>
<ModalFormSectionHeader>
<Trans id="auth.user.accounts" />
</ModalFormSectionHeader>
<FormRow>
<FormError>
<Trans id="auth.message.not.admin" />
</FormError>
</FormRow>
</Form>
);
}
const isLoading = !isUserListFetched && AuthStore.users.length === 0;
const interactiveListClasses = classnames('interactive-list', {
'interactive-list--loading': isLoading,
});
return (
<Form
onSubmit={() => {
if (formRef.current == null || clientConnectionSettingsRef.current == null) {
return;
}
const formData = formRef.current.getFormData() as Partial<AuthTabFormData>;
if (formData.username == null || formData.username === '') {
setError('auth.error.username.empty');
} else if (formData.password == null || formData.password === '') {
setError('auth.error.password.empty');
} else {
setIsSubmitting(true);
const connectionSettings = clientConnectionSettingsRef.current;
if (connectionSettings == null) {
setError('connection.settings.error.empty');
setIsSubmitting(false);
return;
}
AuthActions.createUser({
username: formData.username,
password: formData.password,
client: connectionSettings,
level: formData.isAdmin === true ? AccessLevel.ADMINISTRATOR : AccessLevel.USER,
})
.then(
() => {
if (formRef.current != null) {
formRef.current.resetForm();
}
setError(null);
setIsSubmitting(false);
},
() => {
setError('general.error.unknown');
setIsSubmitting(false);
},
)
.then(AuthActions.fetchUsers);
}
}}
ref={formRef}
>
<ModalFormSectionHeader>
<Trans id="auth.user.accounts" />
</ModalFormSectionHeader>
<FormRow>
<FormRowItem>
<ul className={interactiveListClasses}>
<TransitionGroup>
{isLoading && (
<CSSTransition classNames="interactive-list__loading-indicator" timeout={{enter: 250, exit: 250}}>
<div className="interactive-list__loading-indicator" key="loading-indicator">
<LoadingRing />
</div>
</CSSTransition>
)}
</TransitionGroup>
{AuthStore.users
.slice()
.sort((a: Credentials, b: Credentials) => a.username.localeCompare(b.username))
.map((user: Credentials) => {
const isCurrentUser = user.username === AuthStore.currentUser.username;
let badge = null;
let removeIcon = null;
if (!isCurrentUser) {
removeIcon = (
<button
className="interactive-list__icon interactive-list__icon--action interactive-list__icon--action--warning"
type="button"
onClick={() => AuthActions.deleteUser(user.username).then(AuthActions.fetchUsers)}
>
<Close />
</button>
);
} else {
badge = (
<span className="interactive-list__label__tag tag">
<Trans id="auth.current.user" />
</span>
);
}
const classes = classnames('interactive-list__item', {
'interactive-list__item--disabled': isCurrentUser,
});
return (
<li className={classes} key={user.username}>
<span className="interactive-list__label">
<div className="interactive-list__label__text">{user.username}</div>
{badge}
</span>
{removeIcon}
</li>
);
})}
</ul>
</FormRowItem>
</FormRow>
<ModalFormSectionHeader>
<Trans id="auth.add.user" />
</ModalFormSectionHeader>
{error && (
<FormRow>
<FormError>{i18n._(error)}</FormError>
</FormRow>
)}
<FormRow>
<Textbox
id="username"
label={<Trans id="auth.username" />}
placeholder={i18n._('auth.username')}
autoComplete="username"
/>
<Textbox
id="password"
label={<Trans id="auth.password" />}
placeholder={i18n._('auth.password')}
autoComplete="new-password"
/>
<Checkbox grow={false} id="isAdmin" labelOffset matchTextboxHeight>
<Trans id="auth.admin" />
</Checkbox>
</FormRow>
<ClientConnectionSettingsForm
onSettingsChange={(settings) => {
clientConnectionSettingsRef.current = settings;
}}
/>
<p />
<FormRow justify="end">
<Button isLoading={isSubmitting} priority="primary" type="submit">
<Trans id="button.add" />
</Button>
</FormRow>
</Form>
);
})
Example #27
Source File: Header.tsx From next-shopping-cart with MIT License | 4 votes |
Header = ({ handleSearch, resetSearch, searchValue }: Props) => {
const [showCart, flipState] = useState<boolean>(false);
const [mobileSearch, setSearch] = useState<boolean>(false);
const {
cart,
totalItems,
totalAmount,
removeProduct,
bounce,
bouceEnd,
} = useContext<Init>(CartContext);
const cartPreview = useRef<HTMLDivElement>();
useEffect(() => {
if (bounce) {
const timer1 = setTimeout(() => bouceEnd(), 1000);
// this will clear Timeout when component unmount like in willComponentUnmount
return () => {
clearTimeout(timer1);
};
}
}, [bounce, bouceEnd]);
const handleCart = () => {
flipState((prevCart) => !prevCart);
};
const handleSubmit = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
};
const handleMobileSearch = () => {
setSearch(true);
};
const handleSearchNav = () => {
setSearch(false);
resetSearch();
};
useClickOutside(() => flipState(false), cartPreview, true);
const cartItems = cart.map((product: ProductLocal) => {
return (
<CSSTransition
key={product.id}
classNames="fadeIn"
timeout={{
enter: 500,
exit: 300,
}}
>
<li className={styles.cartItem} key={product.name}>
<img
className={styles.productImage}
src={product.image}
alt="product"
/>
<div className={styles.productInfo}>
<p className={styles.productName}>{product.name}</p>
<p className={styles.productPrice}>{product.price}</p>
</div>
<div className={styles.productTotal}>
<p className={styles.quantity}>
{product.quantity} {product.quantity > 1 ? "Nos." : "No."}{" "}
</p>
<p className={styles.amount}>{product.quantity * product.price}</p>
</div>
<button
className={styles.productRemove}
onClick={() => removeProduct(product.id)}
type="button"
>
×
</button>
</li>
</CSSTransition>
);
});
let view;
if (cartItems.length <= 0) {
view = <EmptyCart />;
} else {
view = (
<TransitionGroup component="ul" className={styles.cartItems}>
{cartItems}
</TransitionGroup>
);
}
let cartBox = null;
if (showCart)
cartBox = (
<div
className={`${styles.cartPreview} ${styles.active}`}
ref={cartPreview}
>
<CartScrollBar>{view}</CartScrollBar>
<div className={styles.actionBlock}>
<button
type="button"
className={cart.length > 0 ? " " : styles.disabled}
>
PROCEED TO CHECKOUT
</button>
</div>
</div>
);
return (
<header className={styles.header}>
<div className={styles.container}>
<div className={styles.brand}>
<img
className={styles.logo}
src="https://res.cloudinary.com/sivadass/image/upload/v1493547373/dummy-logo/Veggy.png"
alt="Veggy Brand Logo"
/>
</div>
<div className={styles.search}>
<button
className={styles.mobileSearch}
onClick={handleMobileSearch}
type="button"
>
<img
src="https://res.cloudinary.com/sivadass/image/upload/v1494756966/icons/search-green.png"
alt="search"
/>
</button>
<form
action="#"
method="get"
className={
mobileSearch
? `${styles.searchForm} ${styles.active}`
: `${styles.searchForm}`
}
>
<button
className={styles.backButton}
onClick={handleSearchNav}
type="button"
>
<img
src="https://res.cloudinary.com/sivadass/image/upload/v1494756030/icons/back.png"
alt="back"
/>
</button>
<input
type="search"
placeholder="Search for Vegetables and Fruits"
className={styles.searchKeyword}
value={searchValue}
onChange={handleSearch}
/>
<button
className={styles.searchButton}
type="submit"
onClick={handleSubmit}
aria-label="submit"
/>
</form>
</div>
<div className={styles.cart}>
<div className={styles.cartInfo}>
<table>
<tbody>
<tr>
<td>No. of items</td>
<td>:</td>
<td>
<strong>{totalItems}</strong>
</td>
</tr>
<tr>
<td>Sub Total</td>
<td>:</td>
<td>
<strong>{totalAmount}</strong>
</td>
</tr>
</tbody>
</table>
</div>
<button
className={styles.cartIcon}
onClick={handleCart}
type="button"
>
<img
className={bounce ? styles.tada : " "}
src="https://res.cloudinary.com/sivadass/image/upload/v1493548928/icons/bag.png"
alt="Cart"
/>
{totalItems ? (
<span className={styles.cartCount}>{totalItems}</span>
) : (
""
)}
</button>
{cartBox}
</div>
</div>
</header>
);
}
Example #28
Source File: Alert.tsx From gear-js with GNU General Public License v3.0 | 4 votes |
AlertProvider = ({ children, template: Template, containerClassName }: Props) => {
const root = useRef<HTMLDivElement | null>(null);
const timers = useRef<AlertTimer>(new Map());
const [alerts, setAlerts] = useState<AlertInstance[]>([]);
const removeTimer = useCallback((alertId: string) => {
const timerId = timers.current.get(alertId);
if (timerId) {
clearTimeout(timerId);
timers.current.delete(alertId);
}
}, []);
const remove = useCallback(
(alertId: string) => {
removeTimer(alertId);
setAlerts((prevState) => prevState.filter((alert) => alert.id !== alertId));
},
[removeTimer],
);
const createTimer = useCallback(
(alertId: string, timeout = 0) => {
if (timeout > 0) {
const timerId = setTimeout(() => remove(alertId), timeout);
timers.current.set(alertId, timerId);
}
},
[remove],
);
const show = useCallback(
(content: ReactNode, options: AlertOptions): string => {
const id = nanoid(6);
createTimer(id, options.timeout);
setAlerts((prevState) => [
...prevState,
{
id,
content,
options,
},
]);
return id;
},
[createTimer],
);
const update = useCallback(
(alertId: string, content: ReactNode, options?: AlertOptions) => {
removeTimer(alertId);
setAlerts((prevState) =>
prevState.map((alert) => {
if (alert.id !== alertId) return alert;
const updatedAlert = {
id: alert.id,
content,
options: {
...alert.options,
...options,
},
};
createTimer(updatedAlert.id, updatedAlert.options.timeout);
return updatedAlert;
}),
);
},
[removeTimer, createTimer],
);
const getAlertTemplate = useCallback(
(templateOptions: AlertOptions) => (content: ReactNode, options?: TemplateAlertOptions) =>
show(content, {
...templateOptions,
...options,
}),
[show],
);
const alertContext = useMemo(
() => ({
update,
remove,
info: getAlertTemplate(DEFAULT_INFO_OPTIONS),
error: getAlertTemplate(DEFAULT_ERROR_OPTIONS),
success: getAlertTemplate(DEFAULT_SUCCESS_OPTIONS),
loading: getAlertTemplate(DEFAULT_LOADING_OPTIONS),
}),
[update, remove, getAlertTemplate],
);
useEffect(() => {
root.current = document.createElement('div');
root.current.id = 'alert-root';
containerClassName && root.current.classList.add(containerClassName);
document.body.appendChild(root.current);
}, []);
return (
<>
<AlertContext.Provider value={alertContext}>{children}</AlertContext.Provider>
{root.current &&
createPortal(
<TransitionGroup appear>
{alerts.map((alert) => (
<Transition key={alert.id}>
<Template alert={alert} close={() => remove(alert.id)} />
</Transition>
))}
</TransitionGroup>,
root.current,
)}
</>
);
}
Example #29
Source File: enterprise.tsx From questdb.io with Apache License 2.0 | 4 votes |
Enterprise = () => {
const title = "QuestDB Enterprise"
const description =
"The fastest open source time-series database for organizations, on premise or on the cloud."
const { ref, width } = useResizeObserver<HTMLDivElement>()
// An "item" is a quote
// Index in the array of quotes of the item that is "focused"
const [index, setIndex] = useState(0)
// How many items we can show on the screen
const viewportSize = Math.max(1, Math.floor((width ?? 0) / QUOTE_WIDTH))
// How many items will actually be displayed (can be smaller than viewportSize)
const viewportCount =
viewportSize === 0 ? 0 : Math.ceil(quotes.length / viewportSize)
// Page number
const page = Math.floor(index / viewportSize)
// The quotes to show
const viewportQuotes = quotes.slice(
page * viewportSize,
(page + 1) * viewportSize,
)
const increaseIndex = useCallback(() => {
setIndex((index) => Math.min(index + viewportSize, quotes.length - 1))
}, [viewportSize])
const decreaseIndex = useCallback(() => {
setIndex((index) => Math.max(index - viewportSize, 0))
}, [viewportSize])
return (
<Layout canonical="/enterprise" description={description} title={title}>
<section className={seCss["section--inner"]}>
<div className={seCss.section__header}>
<h1
className={clsx(
seCss.section__title,
seCss["section__title--accent"],
)}
>
QuestDB Enterprise
</h1>
<p
className={clsx(
seCss.section__subtitle,
seCss["section__subtitle--accent"],
"text--center",
)}
>
The fastest open source time-series database for organizations, on
premise or on the cloud.
</p>
<Subscribe
placeholder="Work Email"
submitButtonText="Contact Us"
provider="enterprise"
className={style.subscribe}
/>
<img
alt="Artistic view of the console with sub-queries"
className={ilCss.illustration}
height={394}
src="/img/pages/enterprise/banner.svg"
width={900}
/>
<p
className={clsx(
seCss.section__subtitle,
seCss["section__subtitle--accent"],
"text--center",
)}
>
QuestDB Enterprise is the best way to run QuestDB on your own
infrastructure at any scale. The software can be deployed on-premise
or in the cloud on AWS, GCP or Azure.
</p>
<div className={clsx(clCss.cloud)}>
<SvgImage
image={<AwsLogo width="73" height="44" />}
title="AWS logo"
/>
<SvgImage
image={<GoogleCloudLogo width="219" height="34" />}
title="Google Cloud logo"
/>
<SvgImage
image={<AzureLogo width="116" height="34" />}
title="Google Cloud logo"
/>
</div>
</div>
</section>
<section className={seCss["section--flex-wrap"]}>
<div className={caCss.card}>
<div className={caCss.card__image}>
<img
alt="Chat icon"
height={52}
src="/img/pages/enterprise/chat.svg"
width={62}
/>
</div>
<h2 className={caCss.card__title}>Support</h2>
<ul className={caCss.card__list}>
<li className={clsx(prCss.property, caCss.card__item)}>
Enterprise support: 24x7 technical support from high-quality
engineers via phone, chat, and email
</li>
<li className={clsx(prCss.property, caCss.card__item)}>
On demand training
</li>
</ul>
</div>
<div className={caCss.card}>
<div className={caCss.card__image}>
<img
alt="Lock icon"
height={58}
src="/img/pages/enterprise/lock.svg"
width={42}
/>
</div>
<h2 className={caCss.card__title}>Security and authentication</h2>
<ul className={caCss.card__list}>
<li className={clsx(prCss.property, caCss.card__item)}>
Advanced security
</li>
<li className={clsx(prCss.property, caCss.card__item)}>
Access control
</li>
<li className={clsx(prCss.property, caCss.card__item)}>
Authentication
</li>
</ul>
</div>
<div className={caCss.card}>
<div className={caCss.card__image}>
<img
alt="Cog icon"
height={48}
src="/img/pages/enterprise/cog.svg"
width={45}
/>
</div>
<h2 className={caCss.card__title}>Management</h2>
<ul className={caCss.card__list}>
<li className={clsx(prCss.property, caCss.card__item)}>
Automation
</li>
<li className={clsx(prCss.property, caCss.card__item)}>
Database monitoring
</li>
<li className={clsx(prCss.property, caCss.card__item)}>
Analytics and visualization
</li>
</ul>
</div>
<div className={caCss.card}>
<div className={caCss.card__image}>
<img
alt="Rocket icon"
height={56}
src="/img/pages/enterprise/rocket.svg"
width={56}
/>
</div>
<h2 className={caCss.card__title}>Unlimited scale</h2>
<ul className={caCss.card__list}>
<li className={clsx(prCss.property, caCss.card__item)}>
High throughput replication
</li>
<li className={clsx(prCss.property, caCss.card__item)}>
Horizontal scalability (high-performance clusters, sharding)
</li>
</ul>
</div>
</section>
<section className={seCss["section--inner"]}>
<div className={peCss.performance__left}>
<h2 className={peCss.performance__title}>Superior performance</h2>
<p className={peCss.performance__item}>
<span className={peCss.performance__bullet} />
Fast ingestion - O(1) complexity, heavy parallelization, out of
order inserts
</p>
<p
className={clsx(
peCss.performance__item,
peCss["performance__item--important"],
)}
>
Downsize your instance, reduce hardware costs
</p>
<p className={peCss.performance__item}>
<span className={peCss.performance__bullet} />
SIMD accelerated SQL queries for lightning fast data retrieval
</p>
<p
className={clsx(
peCss.performance__item,
peCss["performance__item--important"],
)}
>
Real-time analytics, correlate events over time
</p>
<Button className={peCss.performance__cta} href="/case-study/toggle/">
View case study
</Button>
</div>
<div className={peCss.performance__right}>
<img
alt="Charts showing the performance improvments when using QuestDB"
height={411}
src="/img/pages/enterprise/performance.svg"
width={661}
/>
</div>
</section>
<section
className={clsx(seCss["section--inner"], seCss["section--column"])}
>
<h2 className={quCss.title}>The word on QuestDB</h2>
<div className={quCss.carousel} ref={ref}>
<TransitionGroup component={null}>
<CSSTransition key={page} timeout={200} classNames="item">
<div className={quCss.carousel__group}>
{viewportQuotes.map((Quote) => (
<Quote key={quotes.indexOf(Quote)} />
))}
</div>
</CSSTransition>
</TransitionGroup>
</div>
<div className={quCss.controls}>
<div
className={clsx(
quCss["controls__chevron-wrapper"],
quCss["controls__chevron-wrapper--left"],
{
[quCss["controls__chevron-wrapper--hidden"]]: page === 0,
},
)}
onClick={decreaseIndex}
>
<Chevron className={quCss.controls__chevron} side="left" />
</div>
<div className={quCss.controls__middle}>
{Array(viewportCount)
.fill(0)
.map((_, idx) => (
<Bullet
index={idx}
key={idx}
onClick={setIndex}
page={page}
viewportSize={viewportSize}
/>
))}
</div>
<div
className={clsx(
quCss["controls__chevron-wrapper"],
quCss["controls__chevron-wrapper--right"],
{
[quCss["controls__chevron-wrapper--hidden"]]:
page === viewportCount - 1,
},
)}
onClick={increaseIndex}
>
<Chevron className={quCss.controls__chevron} side="right" />
</div>
</div>
</section>
</Layout>
)
}