Skip to content

Commit 7bda303

Browse files
authored
feat: web announcement banner (#50)
1 parent 70d30ae commit 7bda303

File tree

7 files changed

+159
-24
lines changed

7 files changed

+159
-24
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { cn } from '@onlook/ui/utils';
2+
import { observer } from 'mobx-react-lite';
3+
import { useEditorEngine } from '../Context';
4+
5+
enum Variant {
6+
INFO = 'info',
7+
WARNING = 'warning',
8+
SUCCESS = 'success',
9+
}
10+
11+
export const AnnouncementBanner = observer(({ variant = Variant.INFO }: { variant?: Variant }) => {
12+
const MESSAGE = 'Onlook is moving to the web';
13+
const editorEngine = useEditorEngine();
14+
15+
return (
16+
<div
17+
className={cn(
18+
'w-full h-full flex flex-row items-center justify-center transition-colors duration-300 ease-in-out',
19+
)}
20+
>
21+
<div className="flex flex-row items-center gap-2 text-sm">
22+
<span className="flex-1">{MESSAGE}</span>
23+
<span></span>
24+
<button
25+
onClick={() => {
26+
editorEngine.isAnnouncementOpen = true;
27+
}}
28+
className="no-drag underline hover:text-blue-300"
29+
>
30+
Learn more
31+
</button>
32+
</div>
33+
</div>
34+
);
35+
});

apps/studio/src/components/AppBar/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useRouteManager, useUpdateManager } from '@/components/Context';
22
import { Route } from '@/lib/routes';
33
import { cn } from '@onlook/ui/utils';
44
import { observer } from 'mobx-react-lite';
5+
import { AnnouncementBanner } from './AnnouncementBanner';
56
import { HelpButton } from './HelpButton';
67
import UpdateButton from './UpdateButton';
78
import { WindowsControls } from './WindowsControls';
@@ -13,13 +14,15 @@ export const AppBar = observer(() => {
1314
return (
1415
<div
1516
className={cn(
16-
'flex flex-row items-center pl-20 h-10 border-b bg-background dark:bg-background-active transition-colors duration-300 ease-in-out',
17+
'flex flex-row items-center pl-20 h-10 border-b bg-blue-600 dark:bg-blue-800 dark:text-blue-300 text-blue-400 transition-colors duration-300 ease-in-out',
1718
routeManager.route === Route.SIGN_IN && 'bg-transparent border-b-0',
1819
updateManager.updateAvailable &&
1920
'bg-red-950 dark:bg-red-950 dark:text-red-300 text-red-300 transition-opacity duration-300 ease-in-out',
2021
)}
2122
>
22-
<div className="appbar w-full h-full"></div>
23+
<div className="appbar w-full h-full">
24+
<AnnouncementBanner />
25+
</div>
2326
<div className="flex mr-2 gap-2">
2427
<UpdateButton />
2528
</div>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { useEditorEngine } from '@/components/Context';
2+
import { Button } from '@onlook/ui/button';
3+
import { Icons } from '@onlook/ui/icons';
4+
import { AnimatePresence, motion } from 'framer-motion';
5+
import { observer } from 'mobx-react-lite';
6+
7+
export const AnnouncementModal = observer(() => {
8+
const editorEngine = useEditorEngine();
9+
10+
return (
11+
<AnimatePresence>
12+
{editorEngine.isAnnouncementOpen && (
13+
<>
14+
{/* Backdrop */}
15+
<motion.div
16+
initial={{ opacity: 0 }}
17+
animate={{ opacity: 1 }}
18+
exit={{ opacity: 0 }}
19+
className="fixed inset-0 bg-background/80 backdrop-blur-sm z-50"
20+
onClick={() => (editorEngine.isAnnouncementOpen = false)}
21+
/>
22+
{/* Modal Content */}
23+
<motion.div
24+
initial={{ opacity: 0, scale: 0.95 }}
25+
animate={{ opacity: 1, scale: 1 }}
26+
exit={{ opacity: 0, scale: 0.95 }}
27+
transition={{ duration: 0.15 }}
28+
className="fixed font-light inset-0 z-50 flex items-center justify-center pointer-events-none"
29+
>
30+
<div className="flex flex-col bg-background border rounded-lg shadow-lg pointer-events-auto w-[580px] p-8 gap-1">
31+
<div className="flex flex-row items-center justify-between ">
32+
<h2 className="text-2xl font-light">Onlook has moved to the Web</h2>
33+
<Button
34+
variant="ghost"
35+
size="icon"
36+
className="hover:bg-background-active text-foreground-secondary"
37+
onClick={() => (editorEngine.isAnnouncementOpen = false)}
38+
>
39+
<Icons.CrossL className="h-3 w-3" />
40+
</Button>
41+
</div>
42+
<p className="text-sm text-foreground-secondary">
43+
{"It's faster, easier, and has more tools for designing in code."}
44+
</p>
45+
<div className="flex flex-col dark:bg-blue-800 bg-blue-200 dark:border-blue-300 border rounded-lg p-4 mt-5 gap-3">
46+
<h3 className="dark:text-blue-100 text-medium">Get 1 Month Free</h3>
47+
<p className="dark:text-blue-200 text-sm">
48+
If you already have Onlook Pro, you get 1 free month on the Tier
49+
1 plan. Just sign up for Onlook Web using the same email.
50+
</p>
51+
<Button
52+
size="sm"
53+
className="w-fit border-blue-200 border-[0.5px] bg-blue-600 rounded-[4px] hover:bg-blue-700 text-white"
54+
onClick={() => window.open('https://onlook.com', '_blank')}
55+
>
56+
Start designing in Onlook Web
57+
<Icons.ExternalLink className="ml-2 h-4 w-4" />
58+
</Button>
59+
</div>
60+
<p className="text-xs mt-4 text-foreground-secondary">
61+
The desktop app will be sunset after August 31. Thanks for all of
62+
your feedback!
63+
</p>
64+
</div>
65+
</motion.div>
66+
</>
67+
)}
68+
</AnimatePresence>
69+
);
70+
});

apps/studio/src/components/Modals/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { AnnouncementModal } from './Announcement';
12
import { QuittingModal } from './Quitting';
23
import { SettingsModal } from './Settings';
34
import { SubscriptionModal } from './Subscription/PricingPage';
@@ -8,6 +9,7 @@ export const Modals = () => {
89
<SettingsModal />
910
<QuittingModal />
1011
<SubscriptionModal />
12+
<AnnouncementModal />
1113
</>
1214
);
1315
};

apps/studio/src/index.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
-webkit-app-region: drag;
33
}
44

5+
.no-drag {
6+
-webkit-app-region: no-drag;
7+
}
8+
59
html body #root {
610
height: 100%;
711
width: 100%;

apps/studio/src/lib/editor/engine/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { CodeManager } from './code';
2121
import { CopyManager } from './copy';
2222
import { ElementManager } from './element';
2323
import { ErrorManager } from './error';
24+
import { FilesManager } from './files';
2425
import { FontManager } from './font';
2526
import { GroupManager } from './group';
2627
import { HistoryManager } from './history';
@@ -29,7 +30,6 @@ import { InsertManager } from './insert';
2930
import { MoveManager } from './move';
3031
import { OverlayManager } from './overlay';
3132
import { PagesManager } from './pages';
32-
import { FilesManager } from './files';
3333
import { ProjectInfoManager } from './projectinfo';
3434
import { StyleManager } from './style';
3535
import { TextEditingManager } from './text';
@@ -42,7 +42,7 @@ export class EditorEngine {
4242
private _hotkeysOpen: boolean = false;
4343
private _publishOpen: boolean = false;
4444
private _isLayersPanelLocked: boolean = false;
45-
45+
private _isAnnouncementOpen: boolean = false;
4646
private _editorMode: EditorMode = EditorMode.DESIGN;
4747
private _editorPanelTab: EditorTabValue = EditorTabValue.CHAT;
4848
private _settingsTab: SettingsTabValue | string = SettingsTabValue.PREFERENCES;
@@ -190,7 +190,9 @@ export class EditorEngine {
190190
get isLayersPanelLocked() {
191191
return this._isLayersPanelLocked;
192192
}
193-
193+
get isAnnouncementOpen() {
194+
return this._isAnnouncementOpen;
195+
}
194196
set isLayersPanelLocked(value: boolean) {
195197
this._isLayersPanelLocked = value;
196198
}
@@ -234,6 +236,10 @@ export class EditorEngine {
234236
this._brandTab = tab;
235237
}
236238

239+
set isAnnouncementOpen(open: boolean) {
240+
this._isAnnouncementOpen = open;
241+
}
242+
237243
dispose() {
238244
this.overlay.clear();
239245
this.elements.clear();

0 commit comments

Comments
 (0)