Skip to content

Commit cbe999c

Browse files
Replace CDN Amplitude with proper npm package implementation
1 parent 2bced3a commit cbe999c

File tree

12 files changed

+410
-119
lines changed

12 files changed

+410
-119
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,4 @@ docs/instructions/Roadmap.md
4848
.qodo
4949
CLAUDE.md
5050
.roo
51-
!AGENTS.md
51+
AGENTS.md
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { useEffect } from 'react';
2+
import * as amplitude from '@amplitude/analytics-browser';
3+
import { sessionReplayPlugin } from '@amplitude/plugin-session-replay-browser';
4+
5+
export function AmplitudeProvider() {
6+
useEffect(() => {
7+
// Add Session Replay plugin
8+
amplitude.add(sessionReplayPlugin({ sampleRate: 1 }));
9+
10+
// Initialize Amplitude
11+
amplitude.init('7d559bd95c2dfb5a17653a383f8f2e21', {
12+
autocapture: {
13+
elementInteractions: true,
14+
},
15+
});
16+
}, []);
17+
18+
return null;
19+
}

app/components/ui/BuiltWithCodinitBadge.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* Do not remove/edit this file as it will cause the app to break
3+
*/
4+
15
export function BuiltWithCodinitBadge() {
26
return (
37
<a

app/components/ui/Command.tsx

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const Command = React.forwardRef<
1313
<CommandPrimitive
1414
ref={ref}
1515
className={cn(
16-
'flex h-full w-full flex-col overflow-hidden rounded-lg bg-popover text-popover-foreground',
16+
'flex h-full w-full flex-col overflow-hidden rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 border border-gray-200 dark:border-gray-700',
1717
className,
1818
)}
1919
{...props}
@@ -23,10 +23,10 @@ Command.displayName = CommandPrimitive.displayName;
2323

2424
const CommandDialog = ({ children, ...props }: DialogProps) => {
2525
return (
26-
<Dialog {...props}>
26+
<Dialog {...props} className="sm:max-w-lg">
2727
<DialogTitle></DialogTitle> {/* Temporary fix to silence console warning */}
2828
<DialogDescription></DialogDescription> {/* Temporary fix to silence console warning */}
29-
<div className="overflow-hidden p-0 sm:max-w-lg">
29+
<div className="overflow-hidden p-0">
3030
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-3 [&_[cmdk-item]]:py-2">
3131
{children}
3232
</Command>
@@ -39,12 +39,12 @@ const CommandInput = React.forwardRef<
3939
React.ElementRef<typeof CommandPrimitive.Input>,
4040
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
4141
>(({ className, ...props }, ref) => (
42-
<div className="flex items-center border-b border-input px-5" cmdk-input-wrapper="">
43-
<Search size={20} strokeWidth={2} className="me-3 text-muted-foreground/80" />
42+
<div className="flex items-center border-b border-gray-200 dark:border-gray-700 px-5" cmdk-input-wrapper="">
43+
<Search size={20} strokeWidth={2} className="me-3 text-gray-500 dark:text-gray-400" />
4444
<CommandPrimitive.Input
4545
ref={ref}
4646
className={cn(
47-
'flex h-10 w-full rounded-lg bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground/70 disabled:cursor-not-allowed disabled:opacity-50',
47+
'flex h-10 w-full rounded-lg bg-transparent py-3 text-sm outline-none placeholder:text-gray-500 dark:placeholder:text-gray-400 disabled:cursor-not-allowed disabled:opacity-50 text-gray-900 dark:text-gray-100',
4848
className,
4949
)}
5050
{...props}
@@ -66,7 +66,9 @@ CommandList.displayName = CommandPrimitive.List.displayName;
6666
const CommandEmpty = React.forwardRef<
6767
React.ElementRef<typeof CommandPrimitive.Empty>,
6868
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
69-
>((props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />);
69+
>((props, ref) => (
70+
<CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm text-gray-500 dark:text-gray-400" {...props} />
71+
));
7072

7173
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
7274

@@ -77,7 +79,7 @@ const CommandGroup = React.forwardRef<
7779
<CommandPrimitive.Group
7880
ref={ref}
7981
className={cn(
80-
'overflow-hidden p-2 text-foreground [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
82+
'overflow-hidden p-2 text-gray-900 dark:text-gray-100 [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-gray-500 dark:[&_[cmdk-group-heading]]:text-gray-400',
8183
className,
8284
)}
8385
{...props}
@@ -90,7 +92,11 @@ const CommandSeparator = React.forwardRef<
9092
React.ElementRef<typeof CommandPrimitive.Separator>,
9193
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
9294
>(({ className, ...props }, ref) => (
93-
<CommandPrimitive.Separator ref={ref} className={cn('-mx-1 h-px bg-border', className)} {...props} />
95+
<CommandPrimitive.Separator
96+
ref={ref}
97+
className={cn('-mx-1 h-px bg-gray-200 dark:bg-gray-700', className)}
98+
{...props}
99+
/>
94100
));
95101
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
96102

@@ -101,7 +107,7 @@ const CommandItem = React.forwardRef<
101107
<CommandPrimitive.Item
102108
ref={ref}
103109
className={cn(
104-
'relative flex cursor-default select-none items-center gap-3 rounded-md px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
110+
'relative flex cursor-default select-none items-center gap-3 rounded-md px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-gray-100 dark:data-[selected=true]:bg-gray-800 data-[selected=true]:text-gray-900 dark:data-[selected=true]:text-gray-100 data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
105111
className,
106112
)}
107113
{...props}
@@ -114,7 +120,7 @@ const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanE
114120
return (
115121
<kbd
116122
className={cn(
117-
'-me-1 ms-auto inline-flex h-5 max-h-full items-center rounded border border-border bg-background px-1 font-[inherit] text-[0.625rem] font-medium text-muted-foreground/70',
123+
'-me-1 ms-auto inline-flex h-5 max-h-full items-center rounded border border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-800 px-1 font-[inherit] text-[0.625rem] font-medium text-gray-500 dark:text-gray-400',
118124
className,
119125
)}
120126
{...props}

app/components/ui/Dialog.tsx

Lines changed: 18 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const Dialog = memo(({ children, className, showCloseButton = true, onClo
105105
<RadixDialog.Portal>
106106
<RadixDialog.Overlay asChild>
107107
<motion.div
108-
className={classNames('fixed inset-0 z-[9999] bg-black/70 dark:bg-black/80 backdrop-blur-sm')}
108+
className="fixed inset-0 z-[9999] bg-black/80 backdrop-blur-sm"
109109
initial="closed"
110110
animate="open"
111111
exit="closed"
@@ -116,7 +116,7 @@ export const Dialog = memo(({ children, className, showCloseButton = true, onClo
116116
<RadixDialog.Content asChild>
117117
<motion.div
118118
className={classNames(
119-
'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white dark:bg-gray-950 rounded-lg shadow-xl border border-codinit-elements-borderColor z-[9999] w-[520px] focus:outline-none',
119+
'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-2xl shadow-2xl z-[9999] w-[520px] focus:outline-none',
120120
className,
121121
)}
122122
initial="closed"
@@ -130,7 +130,7 @@ export const Dialog = memo(({ children, className, showCloseButton = true, onClo
130130
<RadixDialog.Close asChild onClick={onClose}>
131131
<IconButton
132132
icon="i-ph:x"
133-
className="absolute top-3 right-3 text-codinit-elements-textTertiary hover:text-codinit-elements-textSecondary"
133+
className="absolute top-3 right-3 text-muted-foreground hover:text-foreground"
134134
/>
135135
</RadixDialog.Close>
136136
)}
@@ -208,7 +208,7 @@ export function ConfirmationDialog({
208208
return (
209209
<RadixDialog.Root open={isOpen} onOpenChange={onClose}>
210210
<Dialog showCloseButton={false}>
211-
<div className="p-6 bg-white dark:bg-gray-950 relative z-10">
211+
<div className="p-6 relative z-10">
212212
<DialogTitle>{title}</DialogTitle>
213213
<DialogDescription className="mb-4">{description}</DialogDescription>
214214
<div className="flex justify-end space-x-2">
@@ -221,8 +221,8 @@ export function ConfirmationDialog({
221221
disabled={isLoading}
222222
className={
223223
variant === 'destructive'
224-
? 'bg-red-500 text-white hover:bg-red-600'
225-
: 'bg-codinit-elements-item-backgroundAccent text-codinit-elements-item-contentAccent hover:bg-codinit-elements-button-primary-backgroundHover'
224+
? 'bg-destructive text-destructive-foreground hover:bg-destructive/90'
225+
: 'bg-primary text-primary-foreground hover:bg-primary/90'
226226
}
227227
>
228228
{isLoading ? (
@@ -346,9 +346,7 @@ export function SelectionDialog({
346346
key={item.id}
347347
className={classNames(
348348
'flex items-start space-x-3 p-2 rounded-md transition-colors',
349-
selectedItems.includes(item.id)
350-
? 'bg-codinit-elements-item-backgroundAccent'
351-
: 'bg-codinit-elements-bg-depth-2 hover:bg-codinit-elements-item-backgroundActive',
349+
selectedItems.includes(item.id) ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/50',
352350
)}
353351
style={{
354352
...style,
@@ -362,18 +360,10 @@ export function SelectionDialog({
362360
onCheckedChange={() => handleToggleItem(item.id)}
363361
/>
364362
<div className="grid gap-1.5 leading-none">
365-
<Label
366-
htmlFor={`item-${item.id}`}
367-
className={classNames(
368-
'text-sm font-medium cursor-pointer',
369-
selectedItems.includes(item.id)
370-
? 'text-codinit-elements-item-contentAccent'
371-
: 'text-codinit-elements-textPrimary',
372-
)}
373-
>
363+
<Label htmlFor={`item-${item.id}`} className="text-sm font-medium cursor-pointer">
374364
{item.label}
375365
</Label>
376-
{item.description && <p className="text-xs text-codinit-elements-textSecondary">{item.description}</p>}
366+
{item.description && <p className="text-xs text-muted-foreground">{item.description}</p>}
377367
</div>
378368
</div>
379369
);
@@ -382,30 +372,25 @@ export function SelectionDialog({
382372
return (
383373
<RadixDialog.Root open={isOpen} onOpenChange={onClose}>
384374
<Dialog showCloseButton={false}>
385-
<div className="p-6 bg-white dark:bg-gray-950 relative z-10">
375+
<div className="p-6 relative z-10">
386376
<DialogTitle>{title}</DialogTitle>
387377
<DialogDescription className="mt-2 mb-4">
388378
Select the items you want to include and click{' '}
389-
<span className="text-codinit-elements-item-contentAccent font-medium">{confirmLabel}</span>.
379+
<span className="text-primary font-medium">{confirmLabel}</span>.
390380
</DialogDescription>
391381

392382
<div className="py-4">
393383
<div className="flex items-center justify-between mb-4">
394-
<span className="text-sm font-medium text-codinit-elements-textSecondary">
384+
<span className="text-sm font-medium text-muted-foreground">
395385
{selectedItems.length} of {items.length} selected
396386
</span>
397-
<Button
398-
variant="ghost"
399-
size="sm"
400-
onClick={handleSelectAll}
401-
className="text-xs h-8 px-2 text-codinit-elements-textPrimary hover:text-codinit-elements-item-contentAccent hover:bg-codinit-elements-item-backgroundAccent bg-codinit-elements-bg-depth-2 dark:bg-transparent"
402-
>
387+
<Button variant="ghost" size="sm" onClick={handleSelectAll} className="text-xs h-8 px-2">
403388
{selectAll ? 'Deselect All' : 'Select All'}
404389
</Button>
405390
</div>
406391

407392
<div
408-
className="pr-2 border rounded-md border-codinit-elements-borderColor bg-codinit-elements-bg-depth-2"
393+
className="pr-2 border rounded-md border-border bg-muted/50"
409394
style={{
410395
maxHeight,
411396
}}
@@ -416,28 +401,24 @@ export function SelectionDialog({
416401
width="100%"
417402
itemCount={items.length}
418403
itemSize={60}
419-
className="scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-codinit-elements-bg-depth-3"
404+
className="scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-muted-foreground/30"
420405
>
421406
{ItemRenderer}
422407
</FixedSizeList>
423408
) : (
424-
<div className="text-center py-4 text-sm text-codinit-elements-textTertiary">No items to display</div>
409+
<div className="text-center py-4 text-sm text-muted-foreground">No items to display</div>
425410
)}
426411
</div>
427412
</div>
428413

429414
<div className="flex justify-between mt-6">
430-
<Button
431-
variant="outline"
432-
onClick={onClose}
433-
className="border-codinit-elements-borderColor text-codinit-elements-textPrimary hover:bg-codinit-elements-item-backgroundActive"
434-
>
415+
<Button variant="outline" onClick={onClose}>
435416
Cancel
436417
</Button>
437418
<Button
438419
onClick={handleConfirm}
439420
disabled={selectedItems.length === 0}
440-
className="bg-accent-500 text-white hover:bg-accent-600 disabled:opacity-50 disabled:pointer-events-none"
421+
className="bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:pointer-events-none"
441422
>
442423
{confirmLabel}
443424
</Button>
@@ -447,61 +428,3 @@ export function SelectionDialog({
447428
</RadixDialog.Root>
448429
);
449430
}
450-
451-
const DialogTrigger = RadixDialog.Trigger;
452-
453-
const DialogPortal = RadixDialog.Portal;
454-
455-
const DialogOverlay = React.forwardRef<
456-
React.ElementRef<typeof RadixDialog.Overlay>,
457-
React.ComponentPropsWithoutRef<typeof RadixDialog.Overlay>
458-
>(({ className, ...props }, ref) => (
459-
<RadixDialog.Overlay
460-
ref={ref}
461-
className={classNames(
462-
'fixed inset-0 z-[101] bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
463-
className,
464-
)}
465-
{...props}
466-
/>
467-
));
468-
DialogOverlay.displayName = RadixDialog.Overlay.displayName;
469-
470-
const DialogContent = React.forwardRef<
471-
React.ElementRef<typeof RadixDialog.Content>,
472-
React.ComponentPropsWithoutRef<typeof RadixDialog.Content>
473-
>(({ className, children, ...props }, ref) => (
474-
<DialogPortal>
475-
<DialogOverlay />
476-
<RadixDialog.Content
477-
ref={ref}
478-
className={classNames(
479-
'fixed left-1/2 top-1/2 z-[101] grid max-h-[calc(100%-4rem)] w-full -translate-x-1/2 -translate-y-1/2 gap-4 overflow-y-auto border bg-background p-6 shadow-lg shadow-black/5 duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:max-w-[400px] sm:rounded-xl',
480-
className,
481-
)}
482-
{...props}
483-
>
484-
{children}
485-
<RadixDialog.Close className="group absolute right-3 top-3 flex size-7 items-center justify-center rounded-lg outline-offset-2 transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring/70 disabled:pointer-events-none">
486-
<div className="i-ph:x w-4 h-4 opacity-60 transition-opacity group-hover:opacity-100" />
487-
<span className="sr-only">Close</span>
488-
</RadixDialog.Close>
489-
</RadixDialog.Content>
490-
</DialogPortal>
491-
));
492-
DialogContent.displayName = RadixDialog.Content.displayName;
493-
494-
const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
495-
<div className={classNames('flex flex-col space-y-1.5 text-center sm:text-left', className)} {...props} />
496-
);
497-
DialogHeader.displayName = 'DialogHeader';
498-
499-
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
500-
<div
501-
className={classNames('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:gap-3', className)}
502-
{...props}
503-
/>
504-
);
505-
DialogFooter.displayName = 'DialogFooter';
506-
507-
export { DialogContent, DialogHeader, DialogFooter, DialogOverlay, DialogPortal, DialogTrigger };

app/root.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { HTML5Backend } from 'react-dnd-html5-backend';
1111
import { ClientOnly } from 'remix-utils/client-only';
1212
import { BuiltWithCodinitBadge } from './components/ui/BuiltWithCodinitBadge';
1313
import { ToastContainer } from 'react-toastify';
14+
import { AmplitudeProvider } from './components/AmplitudeProvider';
1415

1516
import reactToastifyStyles from 'react-toastify/dist/ReactToastify.css?url';
1617
import globalStyles from './styles/index.scss?url';
@@ -57,20 +58,12 @@ const inlineThemeCode = stripIndents`
5758
}
5859
`;
5960

60-
const amplitudeScript = stripIndents`
61-
!function(){var e=window.amplitude=window.amplitude||[];e._q=[];function t(t){e[t]=function(){e._q.push([t].concat(Array.prototype.slice.call(arguments,0)))}}var i=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties","setGroup","logRevenueV2","regenerateDeviceId","groupIdentify","onInit","logEventWithTimestamp","logEventWithGroups","setSessionId","resetSessionId"];for(var r=0;r<i.length;r++)t(i[r])}();
62-
window.amplitude.init('7d559bd95c2dfb5a17653a383f8f2e21', {"autocapture":{"elementInteractions":true}});
63-
`;
64-
6561
export const Head = createHead(() => (
6662
<>
6763
<meta charSet="utf-8" />
6864
<meta name="viewport" content="width=device-width, initial-scale=1" />
6965
<Meta />
7066
<Links />
71-
<script src="https://cdn.amplitude.com/libs/analytics-browser-2.11.1-min.js.gz"></script>
72-
<script src="https://cdn.amplitude.com/libs/plugin-session-replay-browser-1.23.2-min.js.gz"></script>
73-
<script dangerouslySetInnerHTML={{ __html: amplitudeScript }} />
7467
<script dangerouslySetInnerHTML={{ __html: inlineThemeCode }} />
7568
</>
7669
));
@@ -84,6 +77,7 @@ export function Layout({ children }: { children: React.ReactNode }) {
8477

8578
return (
8679
<>
80+
<ClientOnly>{() => <AmplitudeProvider />}</ClientOnly>
8781
<ClientOnly>{() => <DndProvider backend={HTML5Backend}>{children}</DndProvider>}</ClientOnly>
8882
<ClientOnly>{() => <BuiltWithCodinitBadge />}</ClientOnly>
8983
<ClientOnly>{() => <ToastContainer />}</ClientOnly>

app/styles/components/resize-handle.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@
2525

2626
&[data-resize-handle-state='hover']:after,
2727
&[data-resize-handle-state='drag']:after {
28-
background-color: #8882;
28+
background-color: rgba(136, 136, 136, 0.5);
2929
}
3030
}

0 commit comments

Comments
 (0)