diff --git a/apps/web/styles/app.css b/apps/web/styles/app.css
index cfecd650..f4280fb8 100644
--- a/apps/web/styles/app.css
+++ b/apps/web/styles/app.css
@@ -77,3 +77,15 @@ body,
display: none;
}
}
+
+@keyframes gradient {
+ 0% {
+ background-position: 0% 50%;
+ }
+ 50% {
+ background-position: 100% 50%;
+ }
+ 100% {
+ background-position: 0% 50%;
+ }
+}
diff --git a/packages/components/.storybook/components.css b/packages/components/.storybook/components.css
new file mode 100644
index 00000000..2fbe765c
--- /dev/null
+++ b/packages/components/.storybook/components.css
@@ -0,0 +1,12 @@
+/* Animation for skeleton placeholder */
+@keyframes gradient {
+ 0% {
+ background-position: 0% 50%;
+ }
+ 50% {
+ background-position: 100% 50%;
+ }
+ 100% {
+ background-position: 0% 50%;
+ }
+}
diff --git a/packages/components/.storybook/preview.tsx b/packages/components/.storybook/preview.tsx
index 2941a73d..efb6b18d 100644
--- a/packages/components/.storybook/preview.tsx
+++ b/packages/components/.storybook/preview.tsx
@@ -1,7 +1,9 @@
+import React from 'react'
import { Provider, ToastContainer } from '../src'
import { Parameters, Decorator } from '@storybook/react'
import './reset.css'
+import './components.css'
export const parameters: Parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
diff --git a/packages/components/src/banner/banner.stories.tsx b/packages/components/src/banner/banner.stories.tsx
index 3a78021f..c5b5043c 100644
--- a/packages/components/src/banner/banner.stories.tsx
+++ b/packages/components/src/banner/banner.stories.tsx
@@ -1,4 +1,4 @@
-import { PinIcon } from '@status-im/icons/20'
+import { AlertIcon, PinIcon, RecentIcon } from '@status-im/icons/20'
import { Stack } from '@tamagui/core'
import { Banner } from './banner'
@@ -38,6 +38,22 @@ export const NoCount: Story = {
},
}
+export const NetworkStateConnecting: Story = {
+ args: {
+ backgroundColor: '$neutral-80-opa-5',
+ icon: ,
+ children: 'Connecting...',
+ },
+}
+
+export const NetworkStateError: Story = {
+ args: {
+ backgroundColor: '$danger-50-opa-20',
+ icon: ,
+ children: 'Network is down',
+ },
+}
+
export const AllVariants: Story = {
args: {},
render: () => (
@@ -46,6 +62,12 @@ export const AllVariants: Story = {
Banner message
Banner message
+ }>
+ Connecting...
+
+ }>
+ Network is down
+
}>Banner message
),
diff --git a/packages/components/src/banner/banner.tsx b/packages/components/src/banner/banner.tsx
index 0b1de159..c8bd549c 100644
--- a/packages/components/src/banner/banner.tsx
+++ b/packages/components/src/banner/banner.tsx
@@ -4,17 +4,25 @@ import { View } from 'react-native'
import { Counter } from '../counter'
import { Text } from '../text'
+import type { ColorTokens } from '@tamagui/core'
+
type Props = {
children: React.ReactNode
icon?: React.ReactNode
count?: number
+ backgroundColor?: ColorTokens
}
const Banner = (props: Props) => {
- const { icon, children, count } = props
+ const {
+ icon,
+ children,
+ count,
+ backgroundColor = '$primary-50-opa-20',
+ } = props
return (
-
+
{icon}
@@ -30,7 +38,6 @@ export { Banner }
export type { Props as BannerProps }
const Base = styled(View, {
- backgroundColor: '$primary-50-opa-20',
padding: 12,
flexDirection: 'row',
alignItems: 'center',
diff --git a/packages/components/src/context-tag/context-tag.tsx b/packages/components/src/context-tag/context-tag.tsx
index 5f4711ee..3eee5430 100644
--- a/packages/components/src/context-tag/context-tag.tsx
+++ b/packages/components/src/context-tag/context-tag.tsx
@@ -55,7 +55,7 @@ const ContextTag = (props: Props) => {
src,
icon,
label,
- type = 'default',
+ // type = 'default', // this is commented because it's not being used
size = 24,
blur = false,
outline,
diff --git a/packages/components/src/gap-messages/gap-messages.stories.tsx b/packages/components/src/gap-messages/gap-messages.stories.tsx
new file mode 100644
index 00000000..108201ff
--- /dev/null
+++ b/packages/components/src/gap-messages/gap-messages.stories.tsx
@@ -0,0 +1,30 @@
+import { GapMessages } from './gap-messages'
+
+import type { Meta, StoryObj } from '@storybook/react'
+
+// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
+const meta: Meta = {
+ title: 'gap-messages',
+ component: GapMessages,
+ argTypes: {},
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Desktop%2FWeb?node-id=5187-181408&t=5dgANDld90Qfd00V-0',
+ },
+ },
+}
+
+type Story = StoryObj
+
+// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
+export const Default: Story = {
+ args: {
+ message: 'This is a simple message.',
+ startDate: 'Jan 8 · 09:12',
+ endDate: 'Mar 8 · 22:42',
+ tooltipMessage: 'This is some tooltip message.',
+ },
+}
+
+export default meta
diff --git a/packages/components/src/gap-messages/gap-messages.tsx b/packages/components/src/gap-messages/gap-messages.tsx
new file mode 100644
index 00000000..cae477cc
--- /dev/null
+++ b/packages/components/src/gap-messages/gap-messages.tsx
@@ -0,0 +1,110 @@
+import { InfoIcon } from '@status-im/icons/16'
+import { Stack, styled } from '@tamagui/core'
+
+import { Text } from '../text'
+import { Tooltip } from '../tooltip'
+
+const NUM_CIRCLES = 200
+
+type Props = {
+ startDate: string
+ endDate: string
+ message: string
+ tooltipMessage: string
+}
+
+// TODO try to find a solution for the inset shadow
+const GapMessages = (props: Props) => {
+ const { startDate, endDate, message, tooltipMessage } = props
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {startDate}
+
+
+
+ {message}
+
+
+
+ {endDate}
+
+
+
+
+ {tooltipMessage}>}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export { GapMessages }
+export type { Props as GapMessageProps }
+
+// TODO try to find a responsive solution if we need to keep the circles in the future
+const Circles = () => {
+ return (
+ <>
+ {[...Array(NUM_CIRCLES)].map((_, i) => (
+
+ ))}
+ >
+ )
+}
+
+const Circle = styled(Stack, {
+ name: 'Circle',
+ width: 8,
+ height: 8,
+ borderRadius: 4,
+ backgroundColor: '$neutral-5',
+ marginRight: 7,
+})
+
+const EmptyCircle = styled(Stack, {
+ name: 'EmptyCircle',
+ width: 8,
+ height: 8,
+ borderRadius: 4,
+ backgroundColor: 'transparent',
+ borderWidth: 1,
+ borderColor: '$neutral-40',
+})
+
+const Divider = styled(Stack, {
+ name: 'Divider',
+ backgroundColor: '$neutral-40',
+ borderWidth: 1,
+ borderColor: '$neutral-5',
+ borderStyle: 'dashed',
+ width: 1,
+ height: 'auto',
+})
diff --git a/packages/components/src/gap-messages/index.tsx b/packages/components/src/gap-messages/index.tsx
new file mode 100644
index 00000000..5648edaa
--- /dev/null
+++ b/packages/components/src/gap-messages/index.tsx
@@ -0,0 +1 @@
+export { GapMessages } from './gap-messages'
diff --git a/packages/components/src/index.tsx b/packages/components/src/index.tsx
index f158813f..9811cf29 100644
--- a/packages/components/src/index.tsx
+++ b/packages/components/src/index.tsx
@@ -3,14 +3,17 @@ export * from './button'
export * from './composer'
export * from './dividers'
export * from './dynamic-button'
+export * from './gap-messages'
export * from './icon-button'
export * from './image'
+export * from './information-box'
export * from './input'
export * from './messages'
export * from './pinned-message'
export * from './provider'
export * from './sidebar'
export * from './sidebar-members'
+export * from './skeleton'
export * from './text'
export * from './toast'
export * from './topbar'
diff --git a/packages/components/src/information-box/index.tsx b/packages/components/src/information-box/index.tsx
new file mode 100644
index 00000000..1534a617
--- /dev/null
+++ b/packages/components/src/information-box/index.tsx
@@ -0,0 +1 @@
+export { InformationBox } from './information-box'
diff --git a/packages/components/src/information-box/information-box.stories.tsx b/packages/components/src/information-box/information-box.stories.tsx
new file mode 100644
index 00000000..92069e6a
--- /dev/null
+++ b/packages/components/src/information-box/information-box.stories.tsx
@@ -0,0 +1,167 @@
+import { InfoIcon } from '@status-im/icons/16'
+
+import { InformationBox } from './information-box'
+
+import type { Meta, StoryObj } from '@storybook/react'
+
+// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
+const meta: Meta = {
+ title: 'information-box',
+ component: InformationBox,
+ argTypes: {},
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Desktop%2FWeb?node-id=5187-181408&t=5dgANDld90Qfd00V-0',
+ },
+ },
+}
+
+type Story = StoryObj
+
+// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
+export const Default: Story = {
+ args: {
+ message: 'This is a simple message.',
+ },
+}
+
+export const Information: Story = {
+ args: {
+ ...Default.args,
+ variant: 'information',
+ },
+}
+
+export const Error: Story = {
+ args: {
+ ...Default.args,
+ variant: 'error',
+ },
+}
+
+export const DefaultWithIcon: Story = {
+ args: {
+ message: 'This is a simple message with an info icon.',
+ icon: ,
+ },
+}
+
+export const InformationWithIcon: Story = {
+ args: {
+ ...DefaultWithIcon.args,
+ variant: 'information',
+ },
+}
+
+export const ErrorWithIcon: Story = {
+ args: {
+ ...DefaultWithIcon.args,
+ variant: 'error',
+ },
+}
+
+export const WithMaxWidth: Story = {
+ args: {
+ ...Default.args,
+ },
+}
+
+export const WithIconAndTwoLines: Story = {
+ args: {
+ ...DefaultWithIcon.args,
+ message: 'This is a message with an icon and two lines.',
+ },
+}
+
+export const WithButtonAndIconDefault: Story = {
+ args: {
+ ...DefaultWithIcon.args,
+ message: 'This is a message with an icon and a button.',
+ buttonText: 'Button',
+ onButtonPress: () => alert('clicked'),
+ },
+}
+
+export const WithButtonAndIconInformation: Story = {
+ args: {
+ ...WithButtonAndIconDefault.args,
+ variant: 'information',
+ },
+}
+
+export const WithButtonAndIconError: Story = {
+ args: {
+ ...WithButtonAndIconDefault.args,
+ variant: 'error',
+ },
+}
+
+export const DefaultWithDismiss: Story = {
+ args: {
+ message: 'This is a simple message.',
+ onClosePress: () => alert('dismissed'),
+ },
+}
+
+export const InformationWithDismiss: Story = {
+ args: {
+ ...DefaultWithDismiss.args,
+ variant: 'information',
+ },
+}
+
+export const ErrorWithDismiss: Story = {
+ args: {
+ ...DefaultWithDismiss.args,
+ variant: 'error',
+ },
+}
+
+export const DefaultWithIconAndDismiss: Story = {
+ args: {
+ message: 'This is a simple message with an info icon.',
+ icon: ,
+ onClosePress: () => alert('dismissed'),
+ },
+}
+
+export const InformationWithIconAndDismiss: Story = {
+ args: {
+ ...DefaultWithIconAndDismiss.args,
+ variant: 'information',
+ },
+}
+
+export const ErrorWithIconAndDismiss: Story = {
+ args: {
+ ...DefaultWithIconAndDismiss.args,
+ variant: 'error',
+ },
+}
+
+export const WithButtonAndIconAndDismiss: Story = {
+ args: {
+ ...WithButtonAndIconDefault.args,
+ message: 'This is a message with an icon and a button.',
+ buttonText: 'Button',
+ onButtonPress: () => alert('clicked'),
+ onClosePress: () => alert('dismissed'),
+ },
+}
+
+export const WithButtonAndIconAndDismissInformation: Story = {
+ args: {
+ ...WithButtonAndIconAndDismiss.args,
+ variant: 'information',
+ },
+}
+
+export const WithButtonAndIconAndDismissError: Story = {
+ args: {
+ ...WithButtonAndIconAndDismiss.args,
+ variant: 'error',
+ },
+}
+
+export default meta
diff --git a/packages/components/src/information-box/information-box.tsx b/packages/components/src/information-box/information-box.tsx
new file mode 100644
index 00000000..98fd291e
--- /dev/null
+++ b/packages/components/src/information-box/information-box.tsx
@@ -0,0 +1,134 @@
+import { cloneElement } from 'react'
+
+import { CloseIcon } from '@status-im/icons/12'
+import { Stack, styled } from '@tamagui/core'
+
+import { Button } from '../button'
+import { Text } from '../text'
+
+import type { GetVariants, MapColorToken } from '../types'
+
+type Variants = GetVariants
+
+type Props = {
+ message: string
+ variant?: Variants['variant']
+ icon?: React.ReactElement
+ buttonText?: string
+ onButtonPress?: () => void
+ onClosePress?: () => void
+}
+
+type Variant = Props['variant']
+
+const textColors: MapColorToken = {
+ default: '$neutral-100',
+ information: '$neutral-100',
+ error: '$danger-50',
+}
+
+const iconColors: MapColorToken = {
+ default: '$neutral-50',
+ information: '$neutral-50',
+ error: '$danger-50',
+}
+
+const buttonVariants: Record, 'primary' | 'danger'> = {
+ default: 'primary',
+ information: 'primary',
+ error: 'danger',
+}
+
+const InformationBox = (props: Props) => {
+ const {
+ message,
+ variant = 'default',
+ icon,
+ buttonText,
+ onButtonPress,
+ onClosePress,
+ } = props
+
+ const textColor = textColors[variant]
+ const iconColor = iconColors[variant]
+ const buttonVariant = buttonVariants[variant]
+
+ return (
+
+
+ {icon ? (
+
+ {cloneElement(icon, { color: iconColor })}
+
+ ) : null}
+
+
+ {message}
+
+ {buttonText ? (
+
+
+
+ ) : null}
+
+ {onClosePress ? (
+ onClosePress()}
+ cursor="pointer"
+ alignSelf="flex-start"
+ >
+
+
+ ) : null}
+
+
+ )
+}
+
+export { InformationBox }
+export type { Props as InformationBoxProps }
+
+const Base = styled(Stack, {
+ name: 'InformationBox',
+
+ flexDirection: 'column',
+ alignItems: 'flex-start',
+ justifyContent: 'center',
+
+ userSelect: 'none',
+ borderWidth: 1,
+
+ py: 11,
+ px: 16,
+ borderRadius: 12,
+
+ variants: {
+ variant: {
+ default: {
+ backgroundColor: '$white-100',
+ borderColor: '$neutral-20',
+ },
+ information: {
+ backgroundColor: '$blue-50-opa-5',
+ borderColor: '$blue-50-opa-10',
+ },
+ error: {
+ backgroundColor: '$danger-50-opa-5',
+ borderColor: '$danger-50-opa-10',
+ },
+ },
+ },
+})
diff --git a/packages/components/src/sidebar/sidebar.stories.tsx b/packages/components/src/sidebar/sidebar.stories.tsx
index 832972e2..fb07b274 100644
--- a/packages/components/src/sidebar/sidebar.stories.tsx
+++ b/packages/components/src/sidebar/sidebar.stories.tsx
@@ -1,7 +1,19 @@
+import { Stack } from '@tamagui/core'
+
import { CHANNEL_GROUPS } from './mock-data'
import { Sidebar } from './sidebar'
-import type { Meta, StoryObj } from '@storybook/react'
+import type { SidebarProps } from './sidebar'
+import type { Meta } from '@storybook/react'
+
+const COMMUNITY = {
+ name: 'Rarible',
+ description:
+ 'Multichain community-centric NFT marketplace. Create, buy and sell your NFTs.',
+ membersCount: 123,
+ imageUrl:
+ 'https://images.unsplash.com/photo-1574786527860-f2e274867c91?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1764&q=80',
+}
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
const meta: Meta = {
@@ -9,6 +21,7 @@ const meta: Meta = {
component: Sidebar,
args: {
channels: CHANNEL_GROUPS,
+ community: COMMUNITY,
},
argTypes: {},
parameters: {
@@ -19,11 +32,20 @@ const meta: Meta = {
},
}
-type Story = StoryObj
+export const Default = {
+ render: (args: SidebarProps) => (
+
+
+
+ ),
+}
-// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
-export const Default: Story = {
- args: {},
+export const LoadingSidebar = {
+ render: (args: SidebarProps) => (
+
+
+
+ ),
}
export default meta
diff --git a/packages/components/src/sidebar/sidebar.tsx b/packages/components/src/sidebar/sidebar.tsx
index e9c849d9..069ef28a 100644
--- a/packages/components/src/sidebar/sidebar.tsx
+++ b/packages/components/src/sidebar/sidebar.tsx
@@ -6,12 +6,13 @@ import { AccordionItem } from '../accordion/accordionItem'
import { Avatar } from '../avatar'
import { Button } from '../button'
import { Image } from '../image'
+import { SidebarSkeleton } from '../skeleton/sidebar-skeleton'
import { Text } from '../text'
import { CHANNEL_GROUPS } from './mock-data'
import type { ChannelGroup } from './mock-data'
-type Props = {
+export type SidebarProps = {
community: {
name: string
description: string
@@ -21,18 +22,24 @@ type Props = {
channels?: ChannelGroup[]
selectedChannelId?: string
onChannelPress: (channelId: string) => void
+ isLoading?: boolean
}
-const Sidebar = (props: Props) => {
+const Sidebar = (props: SidebarProps) => {
const {
community,
channels = CHANNEL_GROUPS,
selectedChannelId,
onChannelPress,
+ isLoading,
} = props
const { name, description, membersCount, imageUrl } = community
+ if (isLoading) {
+ return
+ }
+
return (
= {
+ component: MessageSkeleton,
+
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/1RN1MFwfSqA6jNFJBeNdEu/Posts-%26-Attachments-for-Web?t=1Xf5496ymHeazodw-0',
+ },
+ },
+}
+
+type Story = StoryObj
+
+export const MessageSkeletonSmallest: Story = {
+ name: 'Smallest',
+ args: {
+ size: 'smallest',
+ },
+}
+export const MessageSkeletonSmall: Story = {
+ name: 'Small',
+ args: {
+ size: 'small',
+ },
+}
+export const MessageSkeletonMedium: Story = {
+ name: 'Medium',
+ args: {
+ size: 'medium',
+ },
+}
+export const MessageSkeletonLarge: Story = {
+ name: 'Large',
+ args: {
+ size: 'large',
+ },
+}
+
+export default meta
diff --git a/packages/components/src/skeleton/message-skeleton.tsx b/packages/components/src/skeleton/message-skeleton.tsx
new file mode 100644
index 00000000..50bd81e4
--- /dev/null
+++ b/packages/components/src/skeleton/message-skeleton.tsx
@@ -0,0 +1,52 @@
+import { Stack } from '@tamagui/core'
+
+import { Skeleton } from './skeleton'
+
+import type { StackProps } from '@tamagui/core'
+
+type SizeVariant = 'smallest' | 'small' | 'medium' | 'large'
+
+type Props = Omit & {
+ size?: SizeVariant
+}
+
+const skeletonTopSize = {
+ smallest: 80,
+ small: 96,
+ medium: 112,
+ large: 124,
+}
+
+const skeletonBottomSizes = {
+ smallest: 144,
+ small: 156,
+ medium: 212,
+ large: 249,
+}
+
+const MessageSkeleton = (props: Props) => {
+ const { size, ...rest } = props
+ return (
+
+ {/* Avatar */}
+
+
+ {/* Text placeholders */}
+
+
+
+
+ )
+}
+
+export { MessageSkeleton }
+export type { Props as MessageSkeletonProps }
diff --git a/packages/components/src/skeleton/sidebar-skeleton.tsx b/packages/components/src/skeleton/sidebar-skeleton.tsx
new file mode 100644
index 00000000..d77124c1
--- /dev/null
+++ b/packages/components/src/skeleton/sidebar-skeleton.tsx
@@ -0,0 +1,152 @@
+import { Stack } from '@tamagui/core'
+
+import { Skeleton } from './skeleton'
+
+const SidebarSkeleton = () => {
+ // Eventually we can in the future abstract some of these components to be reusable if we need to
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export { SidebarSkeleton }
diff --git a/packages/components/src/skeleton/skeleton.stories.tsx b/packages/components/src/skeleton/skeleton.stories.tsx
new file mode 100644
index 00000000..fe835a92
--- /dev/null
+++ b/packages/components/src/skeleton/skeleton.stories.tsx
@@ -0,0 +1,32 @@
+import { Skeleton } from './skeleton'
+
+import type { Meta, StoryObj } from '@storybook/react'
+
+const meta: Meta = {
+ component: Skeleton,
+ argTypes: {},
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/1RN1MFwfSqA6jNFJBeNdEu/Posts-%26-Attachments-for-Web?t=1Xf5496ymHeazodw-0',
+ },
+ },
+}
+
+type Story = StoryObj
+
+export const Avatar: Story = {
+ name: 'Avatar',
+ args: {},
+}
+
+export const Text: Story = {
+ name: 'Text',
+ args: {
+ width: 249,
+ br: 6,
+ height: 8,
+ },
+}
+
+export default meta
diff --git a/packages/components/src/skeleton/skeleton.tsx b/packages/components/src/skeleton/skeleton.tsx
new file mode 100644
index 00000000..ef3d3a5d
--- /dev/null
+++ b/packages/components/src/skeleton/skeleton.tsx
@@ -0,0 +1,57 @@
+import { Stack, useTheme } from '@tamagui/core'
+
+import type { ColorTokens, StackProps } from '@tamagui/core'
+
+type Props = StackProps & {
+ width?: number | string
+ height?: number | string
+ borderRadius?: number
+ variant?: 'primary' | 'secondary'
+}
+
+const skeletonColor: Record, ColorTokens> = {
+ primary: '$neutral-10',
+ secondary: '$neutral-20',
+}
+
+const Skeleton = (props: Props) => {
+ const {
+ width = 32,
+ height = 32,
+ borderRadius = 16,
+ variant = 'primary',
+ ...rest
+ } = props
+
+ const theme = useTheme()
+ /* eslint-disable-next-line @typescript-eslint/ban-ts-comment */
+ // @ts-ignore
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const color = theme[skeletonColor[variant]]?.val
+
+ return (
+
+
+
+ )
+}
+
+export { Skeleton }
+export type { Props as SkeletonProps }
diff --git a/packages/components/src/skeleton/topbar-skeleton.tsx b/packages/components/src/skeleton/topbar-skeleton.tsx
new file mode 100644
index 00000000..5905e0bb
--- /dev/null
+++ b/packages/components/src/skeleton/topbar-skeleton.tsx
@@ -0,0 +1,54 @@
+import { Stack } from '@tamagui/core'
+import { BlurView } from 'expo-blur'
+
+import { Skeleton } from './skeleton'
+
+const TopbarSkeleton = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export { TopbarSkeleton }
diff --git a/packages/components/src/topbar/topbar.stories.tsx b/packages/components/src/topbar/topbar.stories.tsx
index 00caec79..b70a28ca 100644
--- a/packages/components/src/topbar/topbar.stories.tsx
+++ b/packages/components/src/topbar/topbar.stories.tsx
@@ -35,6 +35,13 @@ export const Default: Story = {
args: {},
}
+export const isLoading: Story = {
+ args: {
+ ...Default.args,
+ isLoading: true,
+ },
+}
+
export const WithMembersSelected: Story = {
args: {
...Default.args,
diff --git a/packages/components/src/topbar/topbar.tsx b/packages/components/src/topbar/topbar.tsx
index 9e657081..d9fc77ac 100644
--- a/packages/components/src/topbar/topbar.tsx
+++ b/packages/components/src/topbar/topbar.tsx
@@ -16,6 +16,7 @@ import { BlurView } from 'expo-blur'
import { DropdownMenu } from '../dropdown-menu'
import { IconButton } from '../icon-button'
import { PinnedMessage } from '../pinned-message'
+import { TopbarSkeleton } from '../skeleton/topbar-skeleton'
import { Text } from '../text'
import type { Channel } from '../sidebar/mock-data'
@@ -41,13 +42,19 @@ type Props = {
goBack?: () => void
channel: Channel
blur?: boolean
+ isLoading?: boolean
}
const Topbar = (props: Props) => {
- const { showMembers, onMembersPress, goBack, blur, channel } = props
+ const { showMembers, onMembersPress, goBack, blur, channel, isLoading } =
+ props
const { title, description, emoji } = channel
+ if (isLoading) {
+ return
+ }
+
return (
diff --git a/packages/components/src/types.ts b/packages/components/src/types.ts
index 0e7e3539..070b496b 100644
--- a/packages/components/src/types.ts
+++ b/packages/components/src/types.ts
@@ -28,6 +28,10 @@ export type MapVariant<
[key in V[K] & string]: ColorTokens
}
+export type MapColorToken = {
+ [key in V & string]: ColorTokens
+}
+
export type GetVariants = Required<
GetStyledVariants
>
diff --git a/yarn.lock b/yarn.lock
index e35a37c6..31956389 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -13232,7 +13232,6 @@ node-fetch-native@^1.0.1:
node-fetch@2.6.7, node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7:
version "2.6.7"
- uid "1b5d62978f2ed07b99444f64f0df39f960a6d34d"
resolved "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz#1b5d62978f2ed07b99444f64f0df39f960a6d34d"
node-forge@^1.1.0, node-forge@^1.2.1, node-forge@^1.3.1: