Skip to content

Commit

Permalink
feat(styling): added rey effects for the UI as decorative elements
Browse files Browse the repository at this point in the history
  • Loading branch information
thecodacus committed Nov 14, 2024
1 parent a081f8b commit 7984a07
Show file tree
Hide file tree
Showing 6 changed files with 305 additions and 14 deletions.
5 changes: 1 addition & 4 deletions app/components/chat/BaseChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
return (
<div
ref={ref}
className={classNames(
styles.BaseChat,
'relative flex h-full w-full overflow-hidden bg-bolt-elements-background-depth-1',
)}
className={classNames(styles.BaseChat, 'relative flex h-full w-full overflow-hidden')}
data-chat-visible={showChat}
>
<ClientOnly>{() => <Menu />}</ClientOnly>
Expand Down
6 changes: 3 additions & 3 deletions app/components/chat/Chat.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
const { messages, isLoading, input, handleInputChange, setInput, stop, append } = useChat({
api: '/api/chat',
body: {
apiKeys
apiKeys,
},
onError: (error) => {
logger.error('Request failed\n\n', error);
Expand Down Expand Up @@ -263,14 +263,14 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
})}
enhancePrompt={() => {
enhancePrompt(
input,
input,
(input) => {
setInput(input);
scrollTextArea();
},
model,
provider,
apiKeys
apiKeys,
);
}}
/>
Expand Down
11 changes: 4 additions & 7 deletions app/components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@ export function Header() {

return (
<header
className={classNames(
'flex items-center bg-bolt-elements-background-depth-1 p-5 border-b h-[var(--header-height)]',
{
'border-transparent': !chat.started,
'border-bolt-elements-borderColor': chat.started,
},
)}
className={classNames('flex items-center p-5 border-b h-[var(--header-height)]', {
'border-transparent': !chat.started,
'border-bolt-elements-borderColor': chat.started,
})}
>
<div className="flex items-center gap-2 z-logo text-bolt-elements-textPrimary cursor-pointer">
<div className="i-ph:sidebar-simple-duotone text-xl" />
Expand Down
44 changes: 44 additions & 0 deletions app/components/ui/BackgroundRays/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// PurpleRays.jsx
import React, { useEffect, useState } from 'react';
import styles from './styles.module.scss';

const BackgroundRays = () => {
const [theme, setTheme] = useState('dark');

useEffect(() => {
// Initial theme
const currentTheme = document.documentElement.getAttribute('data-theme');
setTheme(currentTheme || 'dark');

// Optional: Watch for theme changes
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === 'data-theme') {
const newTheme = document.documentElement.getAttribute('data-theme');
setTheme((existingTheme) => newTheme || existingTheme);
}
});
});

observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-theme'],
});

return () => observer.disconnect();
}, []);
return (
<div className={`${styles.rayContainer} bg-bolt-elements-background-depth-1`}>
<div className={`${styles.lightRay} ${styles.ray1}`}></div>
<div className={`${styles.lightRay} ${styles.ray2}`}></div>
<div className={`${styles.lightRay} ${styles.ray3}`}></div>
<div className={`${styles.lightRay} ${styles.ray4}`}></div>
<div className={`${styles.lightRay} ${styles.ray5}`}></div>
<div className={`${styles.lightRay} ${styles.ray6}`}></div>
<div className={`${styles.lightRay} ${styles.ray7}`}></div>
<div className={`${styles.lightRay} ${styles.ray8}`}></div>
</div>
);
};

export default BackgroundRays;
251 changes: 251 additions & 0 deletions app/components/ui/BackgroundRays/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
.rayContainer {
--gradient-opacity: 0.8;
--primary-color: rgba(147, 112, 219, var(--gradient-opacity));
--secondary-color: rgba(138, 43, 226, var(--gradient-opacity));
--accent-color: rgba(180, 170, 220, var(--gradient-opacity));

// Theme-specific colors
--ray-color-primary: color-mix(in srgb, var(--primary-color), transparent 30%);
--ray-color-secondary: color-mix(in srgb, var(--secondary-color), transparent 30%);
--ray-color-accent: color-mix(in srgb, var(--accent-color), transparent 30%);

// Theme-specific gradients
--ray-gradient-primary: radial-gradient(var(--ray-color-primary) 0%, transparent 70%);
--ray-gradient-secondary: radial-gradient(var(--ray-color-secondary) 0%, transparent 70%);
--ray-gradient-accent: radial-gradient(var(--ray-color-accent) 0%, transparent 70%);

position: fixed;
inset: 0;
overflow: hidden;
animation: fadeIn 1.5s ease-out;
pointer-events: none;
z-index: 0;
// background-color: transparent;

:global(html[data-theme='dark']) & {
mix-blend-mode: screen;
}

:global(html[data-theme='light']) & {
mix-blend-mode: multiply;
}
}

.lightRay {
position: absolute;
border-radius: 100%;

:global(html[data-theme='dark']) & {
mix-blend-mode: screen;
}

:global(html[data-theme='light']) & {
mix-blend-mode: multiply;
opacity: 0.4;
}
}

.ray1 {
width: 600px;
height: 800px;
background: var(--ray-gradient-primary);
transform: rotate(65deg);
top: -500px;
left: -100px;
filter: blur(80px);
opacity: 0.6;
animation: float1 15s infinite ease-in-out;
}

.ray2 {
width: 400px;
height: 600px;
background: var(--ray-gradient-secondary);
transform: rotate(-30deg);
top: -300px;
left: 200px;
filter: blur(60px);
opacity: 0.6;
animation: float2 18s infinite ease-in-out;
}

.ray3 {
width: 500px;
height: 400px;
background: var(--ray-gradient-accent);
top: -320px;
left: 500px;
filter: blur(65px);
opacity: 0.5;
animation: float3 20s infinite ease-in-out;
}

.ray4 {
width: 400px;
height: 450px;
background: var(--ray-gradient-secondary);
top: -350px;
left: 800px;
filter: blur(55px);
opacity: 0.55;
animation: float4 17s infinite ease-in-out;
}

.ray5 {
width: 350px;
height: 500px;
background: var(--ray-gradient-primary);
transform: rotate(-45deg);
top: -250px;
left: 1000px;
filter: blur(45px);
opacity: 0.6;
animation: float5 16s infinite ease-in-out;
}

.ray6 {
width: 300px;
height: 700px;
background: var(--ray-gradient-accent);
transform: rotate(75deg);
top: -400px;
left: 600px;
filter: blur(75px);
opacity: 0.45;
animation: float6 19s infinite ease-in-out;
}

.ray7 {
width: 450px;
height: 600px;
background: var(--ray-gradient-primary);
transform: rotate(45deg);
top: -450px;
left: 350px;
filter: blur(65px);
opacity: 0.55;
animation: float7 21s infinite ease-in-out;
}

.ray8 {
width: 380px;
height: 550px;
background: var(--ray-gradient-secondary);
transform: rotate(-60deg);
top: -380px;
left: 750px;
filter: blur(58px);
opacity: 0.6;
animation: float8 14s infinite ease-in-out;
}

@keyframes float1 {
0%,
100% {
transform: rotate(65deg) translate(0, 0);
}
25% {
transform: rotate(70deg) translate(30px, 20px);
}
50% {
transform: rotate(60deg) translate(-20px, 40px);
}
75% {
transform: rotate(68deg) translate(-40px, 10px);
}
}

@keyframes float2 {
0%,
100% {
transform: rotate(-30deg) scale(1);
}
33% {
transform: rotate(-25deg) scale(1.1);
}
66% {
transform: rotate(-35deg) scale(0.95);
}
}

@keyframes float3 {
0%,
100% {
transform: translate(0, 0) rotate(0deg);
}
25% {
transform: translate(40px, 20px) rotate(5deg);
}
75% {
transform: translate(-30px, 40px) rotate(-5deg);
}
}

@keyframes float4 {
0%,
100% {
transform: scale(1) rotate(0deg);
}
50% {
transform: scale(1.15) rotate(10deg);
}
}

@keyframes float5 {
0%,
100% {
transform: rotate(-45deg) translate(0, 0);
}
33% {
transform: rotate(-40deg) translate(25px, -20px);
}
66% {
transform: rotate(-50deg) translate(-25px, 20px);
}
}

@keyframes float6 {
0%,
100% {
transform: rotate(75deg) scale(1);
filter: blur(75px);
}
50% {
transform: rotate(85deg) scale(1.1);
filter: blur(65px);
}
}

@keyframes float7 {
0%,
100% {
transform: rotate(45deg) translate(0, 0);
opacity: 0.55;
}
50% {
transform: rotate(40deg) translate(-30px, 30px);
opacity: 0.65;
}
}

@keyframes float8 {
0%,
100% {
transform: rotate(-60deg) scale(1);
}
25% {
transform: rotate(-55deg) scale(1.05);
}
75% {
transform: rotate(-65deg) scale(0.95);
}
}

@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
2 changes: 2 additions & 0 deletions app/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ClientOnly } from 'remix-utils/client-only';
import { BaseChat } from '~/components/chat/BaseChat';
import { Chat } from '~/components/chat/Chat.client';
import { Header } from '~/components/header/Header';
import BackgroundRays from '~/components/ui/BackgroundRays';

export const meta: MetaFunction = () => {
return [{ title: 'Bolt' }, { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }];
Expand All @@ -13,6 +14,7 @@ export const loader = () => json({});
export default function Index() {
return (
<div className="flex flex-col h-full w-full">
<BackgroundRays />
<Header />
<ClientOnly fallback={<BaseChat />}>{() => <Chat />}</ClientOnly>
</div>
Expand Down

0 comments on commit 7984a07

Please sign in to comment.