first run: Prompt new users to open groups

For #165

This adds a purple bullet to the groups tile for users who have not yet opened groups. The popover will either show some text about groups or let them know that they've been invited to a group (in the case of onboarding via lure).
This commit is contained in:
Patrick O'Sullivan 2023-05-31 06:27:11 -05:00
parent eb5ff83e0e
commit f9105ff7b9
7 changed files with 279 additions and 44 deletions

188
ui/package-lock.json generated
View File

@ -18,8 +18,9 @@
"@radix-ui/react-portal": "^0.0.15", "@radix-ui/react-portal": "^0.0.15",
"@radix-ui/react-radio-group": "^0.1.5", "@radix-ui/react-radio-group": "^0.1.5",
"@radix-ui/react-toggle": "^0.0.10", "@radix-ui/react-toggle": "^0.0.10",
"@tanstack/react-query": "^4.29.5", "@tanstack/react-query": "^4.29.12",
"@tanstack/react-query-persist-client": "^4.29.5", "@tanstack/react-query-devtools": "^4.29.12",
"@tanstack/react-query-persist-client": "^4.29.12",
"@tlon/sigil-js": "^1.4.4", "@tlon/sigil-js": "^1.4.4",
"@tloncorp/mock-http-api": "^1.2.0", "@tloncorp/mock-http-api": "^1.2.0",
"@types/lodash": "^4.14.172", "@types/lodash": "^4.14.172",
@ -2033,21 +2034,36 @@
"tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
} }
}, },
"node_modules/@tanstack/match-sorter-utils": {
"version": "8.8.4",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz",
"integrity": "sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==",
"dependencies": {
"remove-accents": "0.4.2"
},
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kentcdodds"
}
},
"node_modules/@tanstack/query-core": { "node_modules/@tanstack/query-core": {
"version": "4.29.7", "version": "4.29.11",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.7.tgz", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.11.tgz",
"integrity": "sha512-GXG4b5hV2Loir+h2G+RXhJdoZhJLnrBWsuLB2r0qBRyhWuXq9w/dWxzvpP89H0UARlH6Mr9DiVj4SMtpkF/aUA==", "integrity": "sha512-8C+hF6SFAb/TlFZyS9FItgNwrw4PMa7YeX+KQYe2ZAiEz6uzg6yIr+QBzPkUwZ/L0bXvGd1sufTm3wotoz+GwQ==",
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/tannerlinsley" "url": "https://github.com/sponsors/tannerlinsley"
} }
}, },
"node_modules/@tanstack/query-persist-client-core": { "node_modules/@tanstack/query-persist-client-core": {
"version": "4.29.7", "version": "4.29.11",
"resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-4.29.7.tgz", "resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-4.29.11.tgz",
"integrity": "sha512-/QahvSq9/f8hetCsCd9MaOy6fAoPn0YDGDcl6TTobqdr9kHMgrM9laP9yKJFg2hm5/jIsrCMDO/iCnxBiUhrqw==", "integrity": "sha512-CSmMZchr+446r79NJ/pjD2yfjqNqFV7k8BnqOq4yTZvXsaQLEIn3tsaU45IsPgs4N7g9OBfPUPDdapSQvck2WQ==",
"dependencies": { "dependencies": {
"@tanstack/query-core": "4.29.7" "@tanstack/query-core": "4.29.11"
}, },
"funding": { "funding": {
"type": "github", "type": "github",
@ -2055,11 +2071,11 @@
} }
}, },
"node_modules/@tanstack/react-query": { "node_modules/@tanstack/react-query": {
"version": "4.29.7", "version": "4.29.12",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.29.7.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.29.12.tgz",
"integrity": "sha512-ijBWEzAIo09fB1yd22slRZzprrZ5zMdWYzBnCg5qiXuFbH78uGN1qtGz8+Ed4MuhaPaYSD+hykn+QEKtQviEtg==", "integrity": "sha512-zhcN6+zF6cxprxhTHQajHGlvxgK8npnp9uLe9yaWhGc6sYcPWXzyO4raL4HomUzQOPzu3jLvkriJQ7BOrDM8vA==",
"dependencies": { "dependencies": {
"@tanstack/query-core": "4.29.7", "@tanstack/query-core": "4.29.11",
"use-sync-external-store": "^1.2.0" "use-sync-external-store": "^1.2.0"
}, },
"funding": { "funding": {
@ -2080,19 +2096,38 @@
} }
} }
}, },
"node_modules/@tanstack/react-query-persist-client": { "node_modules/@tanstack/react-query-devtools": {
"version": "4.29.7", "version": "4.29.12",
"resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-4.29.7.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.29.12.tgz",
"integrity": "sha512-KYUeESnthjjcfakpAei9Cz5gsIm1uDAVHrKcIAoARQwksk4j0KAo9ieExoIhL9v4mpTOlE9GsuZ/y06ANmaVaQ==", "integrity": "sha512-ug4YGQhMhh6QI8/sWJhjXxuvdeehxf1cyxpTifGMH5qreQ5ECHT6vzqG/aKvADQDzqLBGrF0q4wTDnRRYvvtrA==",
"dependencies": { "dependencies": {
"@tanstack/query-persist-client-core": "4.29.7" "@tanstack/match-sorter-utils": "^8.7.0",
"superjson": "^1.10.0",
"use-sync-external-store": "^1.2.0"
}, },
"funding": { "funding": {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/tannerlinsley" "url": "https://github.com/sponsors/tannerlinsley"
}, },
"peerDependencies": { "peerDependencies": {
"@tanstack/react-query": "4.29.7" "@tanstack/react-query": "4.29.12",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@tanstack/react-query-persist-client": {
"version": "4.29.12",
"resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-4.29.12.tgz",
"integrity": "sha512-rh6zZJB+3j8lr+YsEkVadnqmUELmqNFZQzGGsHS5col/YOjYsMe9ppqaUjIMJ2aXnFXye50sbe4KxHhSGoaNVw==",
"dependencies": {
"@tanstack/query-persist-client-core": "4.29.11"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"@tanstack/react-query": "4.29.12"
} }
}, },
"node_modules/@tlon/sigil-js": { "node_modules/@tlon/sigil-js": {
@ -3245,6 +3280,20 @@
"safe-buffer": "~5.1.1" "safe-buffer": "~5.1.1"
} }
}, },
"node_modules/copy-anything": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
"dependencies": {
"is-what": "^4.1.8"
},
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/core-js": { "node_modules/core-js": {
"version": "3.21.1", "version": "3.21.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz",
@ -5779,6 +5828,17 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/is-what": {
"version": "4.1.12",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.12.tgz",
"integrity": "sha512-w7JwFt3gIzbzpp+I//2Ov2UeTGgKM10PxJRD6yf7yGruT3415CdT8TDR6F9/mBAakZKsIaysQVVvxryctQUbnw==",
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/is-wsl": { "node_modules/is-wsl": {
"version": "2.2.0", "version": "2.2.0",
"dev": true, "dev": true,
@ -7488,6 +7548,11 @@
"url": "https://github.com/sponsors/mysticatea" "url": "https://github.com/sponsors/mysticatea"
} }
}, },
"node_modules/remove-accents": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA=="
},
"node_modules/rename-keys": { "node_modules/rename-keys": {
"version": "1.2.0", "version": "1.2.0",
"license": "MIT", "license": "MIT",
@ -8019,6 +8084,17 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/superjson": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/superjson/-/superjson-1.12.3.tgz",
"integrity": "sha512-0j+U70KUtP8+roVPbwfqkyQI7lBt7ETnuA7KXbTDX3mCKiD/4fXs2ldKSMdt0MCfpTwiMxo20yFU3vu6ewETpQ==",
"dependencies": {
"copy-anything": "^3.0.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "5.5.0", "version": "5.5.0",
"dev": true, "dev": true,
@ -10303,34 +10379,52 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"@tanstack/match-sorter-utils": {
"version": "8.8.4",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz",
"integrity": "sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==",
"requires": {
"remove-accents": "0.4.2"
}
},
"@tanstack/query-core": { "@tanstack/query-core": {
"version": "4.29.7", "version": "4.29.11",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.7.tgz", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.11.tgz",
"integrity": "sha512-GXG4b5hV2Loir+h2G+RXhJdoZhJLnrBWsuLB2r0qBRyhWuXq9w/dWxzvpP89H0UARlH6Mr9DiVj4SMtpkF/aUA==" "integrity": "sha512-8C+hF6SFAb/TlFZyS9FItgNwrw4PMa7YeX+KQYe2ZAiEz6uzg6yIr+QBzPkUwZ/L0bXvGd1sufTm3wotoz+GwQ=="
}, },
"@tanstack/query-persist-client-core": { "@tanstack/query-persist-client-core": {
"version": "4.29.7", "version": "4.29.11",
"resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-4.29.7.tgz", "resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-4.29.11.tgz",
"integrity": "sha512-/QahvSq9/f8hetCsCd9MaOy6fAoPn0YDGDcl6TTobqdr9kHMgrM9laP9yKJFg2hm5/jIsrCMDO/iCnxBiUhrqw==", "integrity": "sha512-CSmMZchr+446r79NJ/pjD2yfjqNqFV7k8BnqOq4yTZvXsaQLEIn3tsaU45IsPgs4N7g9OBfPUPDdapSQvck2WQ==",
"requires": { "requires": {
"@tanstack/query-core": "4.29.7" "@tanstack/query-core": "4.29.11"
} }
}, },
"@tanstack/react-query": { "@tanstack/react-query": {
"version": "4.29.7", "version": "4.29.12",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.29.7.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.29.12.tgz",
"integrity": "sha512-ijBWEzAIo09fB1yd22slRZzprrZ5zMdWYzBnCg5qiXuFbH78uGN1qtGz8+Ed4MuhaPaYSD+hykn+QEKtQviEtg==", "integrity": "sha512-zhcN6+zF6cxprxhTHQajHGlvxgK8npnp9uLe9yaWhGc6sYcPWXzyO4raL4HomUzQOPzu3jLvkriJQ7BOrDM8vA==",
"requires": { "requires": {
"@tanstack/query-core": "4.29.7", "@tanstack/query-core": "4.29.11",
"use-sync-external-store": "^1.2.0"
}
},
"@tanstack/react-query-devtools": {
"version": "4.29.12",
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.29.12.tgz",
"integrity": "sha512-ug4YGQhMhh6QI8/sWJhjXxuvdeehxf1cyxpTifGMH5qreQ5ECHT6vzqG/aKvADQDzqLBGrF0q4wTDnRRYvvtrA==",
"requires": {
"@tanstack/match-sorter-utils": "^8.7.0",
"superjson": "^1.10.0",
"use-sync-external-store": "^1.2.0" "use-sync-external-store": "^1.2.0"
} }
}, },
"@tanstack/react-query-persist-client": { "@tanstack/react-query-persist-client": {
"version": "4.29.7", "version": "4.29.12",
"resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-4.29.7.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-4.29.12.tgz",
"integrity": "sha512-KYUeESnthjjcfakpAei9Cz5gsIm1uDAVHrKcIAoARQwksk4j0KAo9ieExoIhL9v4mpTOlE9GsuZ/y06ANmaVaQ==", "integrity": "sha512-rh6zZJB+3j8lr+YsEkVadnqmUELmqNFZQzGGsHS5col/YOjYsMe9ppqaUjIMJ2aXnFXye50sbe4KxHhSGoaNVw==",
"requires": { "requires": {
"@tanstack/query-persist-client-core": "4.29.7" "@tanstack/query-persist-client-core": "4.29.11"
} }
}, },
"@tlon/sigil-js": { "@tlon/sigil-js": {
@ -11055,6 +11149,14 @@
"safe-buffer": "~5.1.1" "safe-buffer": "~5.1.1"
} }
}, },
"copy-anything": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
"requires": {
"is-what": "^4.1.8"
}
},
"core-js": { "core-js": {
"version": "3.21.1", "version": "3.21.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz",
@ -12692,6 +12794,11 @@
"version": "0.1.0", "version": "0.1.0",
"dev": true "dev": true
}, },
"is-what": {
"version": "4.1.12",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.12.tgz",
"integrity": "sha512-w7JwFt3gIzbzpp+I//2Ov2UeTGgKM10PxJRD6yf7yGruT3415CdT8TDR6F9/mBAakZKsIaysQVVvxryctQUbnw=="
},
"is-wsl": { "is-wsl": {
"version": "2.2.0", "version": "2.2.0",
"dev": true, "dev": true,
@ -13740,6 +13847,11 @@
"version": "3.2.0", "version": "3.2.0",
"dev": true "dev": true
}, },
"remove-accents": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA=="
},
"rename-keys": { "rename-keys": {
"version": "1.2.0" "version": "1.2.0"
}, },
@ -14069,6 +14181,14 @@
"version": "3.1.1", "version": "3.1.1",
"dev": true "dev": true
}, },
"superjson": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/superjson/-/superjson-1.12.3.tgz",
"integrity": "sha512-0j+U70KUtP8+roVPbwfqkyQI7lBt7ETnuA7KXbTDX3mCKiD/4fXs2ldKSMdt0MCfpTwiMxo20yFU3vu6ewETpQ==",
"requires": {
"copy-anything": "^3.0.2"
}
},
"supports-color": { "supports-color": {
"version": "5.5.0", "version": "5.5.0",
"dev": true, "dev": true,

View File

@ -28,8 +28,9 @@
"@radix-ui/react-portal": "^0.0.15", "@radix-ui/react-portal": "^0.0.15",
"@radix-ui/react-radio-group": "^0.1.5", "@radix-ui/react-radio-group": "^0.1.5",
"@radix-ui/react-toggle": "^0.0.10", "@radix-ui/react-toggle": "^0.0.10",
"@tanstack/react-query": "^4.29.5", "@tanstack/react-query": "^4.29.12",
"@tanstack/react-query-persist-client": "^4.29.5", "@tanstack/react-query-devtools": "^4.29.12",
"@tanstack/react-query-persist-client": "^4.29.12",
"@tlon/sigil-js": "^1.4.4", "@tlon/sigil-js": "^1.4.4",
"@tloncorp/mock-http-api": "^1.2.0", "@tloncorp/mock-http-api": "^1.2.0",
"@types/lodash": "^4.14.172", "@types/lodash": "^4.14.172",

View File

@ -1,5 +1,6 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { import {
BrowserRouter, BrowserRouter,
Switch, Switch,
@ -132,6 +133,7 @@ export function App() {
onReset={() => window.location.reload()} onReset={() => window.location.reload()}
> >
<BrowserRouter basename={base}> <BrowserRouter basename={base}>
<ReactQueryDevtools initialIsOpen={false} />
<AppRoutes /> <AppRoutes />
<Scheduler /> <Scheduler />
</BrowserRouter> </BrowserRouter>

View File

@ -95,3 +95,17 @@ export function useSawSeamMutation() {
}, },
}); });
} }
export function useHasInviteToGroup(): Skein | undefined {
const skeins = useSkeins();
if (!skeins.data) {
return undefined;
}
return skeins.data.find(
(skein) =>
skein.top.rope.desk === 'groups' &&
skein.top.con.some((con) => con === ' sent you an invite to ') &&
skein.unread
);
}

View File

@ -49,6 +49,12 @@ export interface SettingsState {
}; };
} }
interface GroupsSettingsState extends SettingsState {
groups: {
hasBeenUsed: boolean;
};
}
export const useSettings = () => { export const useSettings = () => {
const { data, ...rest } = useReactQuerySubscription< const { data, ...rest } = useReactQuerySubscription<
{ desk: SettingsState }, { desk: SettingsState },
@ -72,6 +78,29 @@ export const useSettings = () => {
}, [rest, data]); }, [rest, data]);
}; };
export const useGroupsSettings = () => {
const { data, ...rest } = useReactQuerySubscription<
{ desk: GroupsSettingsState },
SettingsEvent
>({
scry: `/desk/groups`,
scryApp: 'settings',
app: 'settings',
path: `/desk/groups`,
queryKey: ['settings', 'groups'],
});
return useMemo(() => {
if (!data) {
return { data: undefined, ...rest };
}
const { desk } = data;
return { data: desk, ...rest };
}, [rest, data]);
};
export function useDisplay(): SettingsState['display'] { export function useDisplay(): SettingsState['display'] {
const { data, isLoading } = useSettings(); const { data, isLoading } = useSettings();
@ -291,3 +320,16 @@ export function useBrowserNotifications(browserId: string): boolean {
const browserSetting = getBrowserSetting(settings, browserId); const browserSetting = getBrowserSetting(settings, browserId);
return browserSetting?.browserNotifications ?? false; return browserSetting?.browserNotifications ?? false;
} }
export function useGroupsHasBeenUsed() {
const { data, isLoading } = useGroupsSettings();
return useMemo(() => {
if (isLoading || data === undefined) {
return false;
}
const setting = data.groups.hasBeenUsed;
return setting;
}, [isLoading, data]);
}

View File

@ -1,6 +1,7 @@
import classNames from 'classnames'; import classNames from 'classnames';
import React, { FunctionComponent } from 'react'; import React, { FunctionComponent, useState } from 'react';
import { useDrag } from 'react-dnd'; import { useDrag } from 'react-dnd';
import * as Popover from '@radix-ui/react-popover';
import { chadIsRunning } from '@urbit/api'; import { chadIsRunning } from '@urbit/api';
import { TileMenu } from './TileMenu'; import { TileMenu } from './TileMenu';
import { Spinner } from '../components/Spinner'; import { Spinner } from '../components/Spinner';
@ -11,6 +12,8 @@ import { useTileColor } from './useTileColor';
import { usePike } from '../state/kiln'; import { usePike } from '../state/kiln';
import { Bullet } from '../components/icons/Bullet'; import { Bullet } from '../components/icons/Bullet';
import { dragTypes } from './TileGrid'; import { dragTypes } from './TileGrid';
import { useGroupsHasBeenUsed } from '@/state/settings';
import { useHasInviteToGroup } from '@/state/hark';
type TileProps = { type TileProps = {
charge: ChargeWithDesk; charge: ChargeWithDesk;
@ -23,6 +26,15 @@ export const Tile: FunctionComponent<TileProps> = ({
desk, desk,
disabled = false, disabled = false,
}) => { }) => {
const [showGroupsPopover, setShowGroupsPopover] = useState(false);
const hasOpenedGroups = useGroupsHasBeenUsed();
const invite = useHasInviteToGroup();
const inviteGroupName =
invite &&
typeof invite.top.con[2] === 'object' &&
'emph' in invite.top.con[2]
? invite.top.con[2].emph
: 'a group';
const addRecentApp = useRecentsStore((state) => state.addRecentApp); const addRecentApp = useRecentsStore((state) => state.addRecentApp);
const { title, image, color, chad, href } = charge; const { title, image, color, chad, href } = charge;
const pike = usePike(desk); const pike = usePike(desk);
@ -66,6 +78,45 @@ export const Tile: FunctionComponent<TileProps> = ({
onAuxClick={() => addRecentApp(desk)} onAuxClick={() => addRecentApp(desk)}
> >
<div> <div>
{desk === 'groups' && !hasOpenedGroups && (
<Popover.Root
open={showGroupsPopover}
onOpenChange={(o) => setShowGroupsPopover(o)}
>
<div
className="absolute top-4 right-4 z-10 sm:top-6 sm:right-6"
onMouseOver={() => setShowGroupsPopover(true)}
onMouseOut={() => setShowGroupsPopover(false)}
>
<Popover.Trigger>
<>
<div className="absolute h-[42px] w-[42px] animate-pulse rounded-full bg-indigo opacity-10 sm:top-0 sm:right-0" />
<Bullet className="h-[42px] w-[42px] text-indigo" />
</>
</Popover.Trigger>
<Popover.Portal>
<Popover.Content
side="right"
sideOffset={16}
className="z-40 w-[216px] rounded-lg bg-indigo p-4"
onOpenAutoFocus={(e) => e.preventDefault()}
onCloseAutoFocus={(e) => e.preventDefault()}
>
<p className="text-white">
{invite ? (
<>You have an invitation to join {inviteGroupName}.</>
) : (
<>
Open Groups to create, join, and accept invitations to
communities.
</>
)}
</p>
</Popover.Content>
</Popover.Portal>
</div>
</Popover.Root>
)}
<div className="absolute top-4 left-4 z-10 flex items-center sm:top-6 sm:left-6"> <div className="absolute top-4 left-4 z-10 flex items-center sm:top-6 sm:left-6">
{pike?.zest === 'held' && !disabled && ( {pike?.zest === 'held' && !disabled && (
<Bullet className="h-4 w-4 text-orange-500 dark:text-black" /> <Bullet className="h-4 w-4 text-orange-500 dark:text-black" />
@ -85,13 +136,15 @@ export const Tile: FunctionComponent<TileProps> = ({
</> </>
)} )}
</div> </div>
<TileMenu {desk === 'groups' && !hasOpenedGroups ? null : (
desk={desk} <TileMenu
chad={chad} desk={desk}
menuColor={active ? menuColor : suspendMenuColor} chad={chad}
lightText={lightText} menuColor={active ? menuColor : suspendMenuColor}
className="absolute top-3 right-3 z-10 opacity-0 focus:opacity-100 group-hover:opacity-100 pointer-coarse:opacity-100 hover-none:opacity-100 sm:top-5 sm:right-5" lightText={lightText}
/> className="absolute top-3 right-3 z-10 opacity-0 focus:opacity-100 group-hover:opacity-100 pointer-coarse:opacity-100 hover-none:opacity-100 sm:top-5 sm:right-5"
/>
)}
{title && ( {title && (
<div <div
className="h4 absolute bottom-[8%] left-[5%] z-10 rounded-lg py-1 px-3 sm:bottom-7 sm:left-5" className="h4 absolute bottom-[8%] left-[5%] z-10 rounded-lg py-1 px-3 sm:bottom-7 sm:left-5"

View File

@ -102,6 +102,9 @@ const base = new Theme().addColors({
800: '#641E00', 800: '#641E00',
900: '#3E1100', 900: '#3E1100',
}, },
indigo: {
DEFAULT: '#615FD3',
},
green: { green: {
100: '#E6F5F0', 100: '#E6F5F0',
200: '#B3E2D1', 200: '#B3E2D1',