-
Notifications
You must be signed in to change notification settings - Fork 27
Design update for shell and conversion starter #248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
a9fb37d
Add CrayonChat styles and enhance BottomTray animations
ankit-thesys 9403fbf
Enhance BottomTray component with ConversationStarter integration
ankit-thesys 1a3c5ad
Refactor ConversationStarter component for cleaner syntax and update …
ankit-thesys fc859a0
Integrate ConversationStarter component into CopilotShell and enhance…
ankit-thesys 0fbcb00
Integrate ConversationStarter component into Shell and enhance stories
ankit-thesys 949cf81
format fix
ankit-thesys bf6abee
Merge branch 'main' of https://github.com/thesysdev/crayon into shell…
ankit-thesys 9d903d6
update shell stories and conversation starter styles
ankit-thesys 1ca9be9
styling and conversation starter type
ankit-thesys 85fc3ce
long variant style and story book mode, types export
ankit-thesys f01eb4b
Update BottomTray styles and stories for conversation starters
ankit-thesys 00d0e35
Enhance ConversationStarter component with variant support and stylin…
ankit-thesys 444fa57
Update BottomTray and CopilotShell styles for ConversationStarter com…
ankit-thesys 8129e49
Add WelcomeScreen component to BottomTray and enhance stories
ankit-thesys 7a52300
Add WelcomeScreen integration to CopilotShell
ankit-thesys 4ab5426
Refactor WelcomeScreen component and enhance integration in BottomTra…
ankit-thesys c8bf9a3
Enhance ConversationStarter component with improved variant support a…
ankit-thesys d24485f
Refactor ConversationStarter component imports and enhance WelcomeScr…
ankit-thesys a9fac45
format fix
ankit-thesys 4ee1764
build fix
ankit-thesys ea2489a
Refactor ConversationStarter and WelcomeScreen components for improve…
ankit-thesys 8836815
Update typography and add center alignment for ConversationStarter co…
ankit-thesys 6e35d0a
Enhance WelcomeScreen layout with new composer starters container
ankit-thesys 2d8c6a7
Update spacing and border radius in conversation starter styles
ankit-thesys b57787e
Refactor BottomTray and CopilotShell components for improved icon usa…
ankit-thesys 27bf277
Refactor conversation starter styles in BottomTray, CopilotShell, and…
ankit-thesys a7b8870
Refactor lastMessage retrieval in ScrollArea component for improved r…
ankit-thesys 71218cf
Refactor BottomTray component styles and structure for consistency
ankit-thesys 3a2318a
Refactor lastMessage retrieval in ScrollArea component for improved c…
ankit-thesys 93ea494
Refactor icon handling in ConversationStarter components for clarity
ankit-thesys 61f64e4
format fix
ankit-thesys ba17946
Refactor WelcomeScreen component to unify image handling
ankit-thesys 5bdf5da
Add welcome message and conversation starters support to CrayonChat c…
ankit-thesys 2f88b11
Enhance CrayonChat types and utilities for welcome messages
ankit-thesys 1ff4093
Refactor CrayonChat components to utilize thread list state and enhan…
ankit-thesys de1634e
Update loading state in useThreadManager to reflect message loading s…
ankit-thesys ee8e46e
Update package versions for react-core and react-ui to 0.7.7 and 0.9.…
ankit-thesys 4bc2241
Implement thread manager initialization and loading state updates
ankit-thesys ae73afd
State Sync
ankit-thesys b3f1339
Integrate thread state management into WelcomeScreen components
ankit-thesys 00308aa
Refactor CrayonChat components to streamline thread state usage
ankit-thesys e254ea6
Enhance CrayonChat components with loading state checks
ankit-thesys File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
js/packages/react-ui/src/components/BottomTray/ConversationStarter.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| import { useThreadActions, useThreadState } from "@crayonai/react-core"; | ||
| import clsx from "clsx"; | ||
| import { ArrowUp, Lightbulb } from "lucide-react"; | ||
| import { Fragment, ReactNode } from "react"; | ||
| import { ConversationStarterIcon, ConversationStarterProps } from "../../types/ConversationStarter"; | ||
| import { Separator } from "../Separator"; | ||
|
|
||
| export type ConversationStarterVariant = "short" | "long"; | ||
|
|
||
| interface ConversationStarterItemProps extends ConversationStarterProps { | ||
| onClick: (prompt: string) => void; | ||
| variant: ConversationStarterVariant; | ||
| } | ||
|
|
||
| /** | ||
| * Renders the appropriate icon based on the icon prop value | ||
| * - undefined: Show default lightbulb icon | ||
| * - ReactNode: Show the provided icon (use <></> or React.Fragment for no icon) | ||
| */ | ||
| const renderIcon = (icon: ConversationStarterIcon | undefined): ReactNode => { | ||
| if (icon === undefined) { | ||
| return <Lightbulb size={16} />; | ||
| } | ||
| return icon; | ||
| }; | ||
|
|
||
| const ConversationStarterItem = ({ | ||
| displayText, | ||
| prompt, | ||
| onClick, | ||
| variant, | ||
| icon, | ||
| }: ConversationStarterItemProps) => { | ||
| const renderedIcon = renderIcon(icon); | ||
|
|
||
| if (variant === "short") { | ||
| return ( | ||
| <button | ||
| type="button" | ||
| className="crayon-bottom-tray-conversation-starter-item-short" | ||
| onClick={() => onClick(prompt)} | ||
| > | ||
| {renderedIcon && ( | ||
| <span className="crayon-bottom-tray-conversation-starter-item-short__icon"> | ||
| {renderedIcon} | ||
| </span> | ||
| )} | ||
| <span className="crayon-bottom-tray-conversation-starter-item-short__text"> | ||
| {displayText} | ||
| </span> | ||
| </button> | ||
| ); | ||
| } | ||
|
|
||
| // Long variant (detailed list style) | ||
| return ( | ||
| <button | ||
| type="button" | ||
| className="crayon-bottom-tray-conversation-starter-item-long" | ||
| onClick={() => onClick(prompt)} | ||
| > | ||
| <div className="crayon-bottom-tray-conversation-starter-item-long__content"> | ||
| {renderedIcon && ( | ||
| <span className="crayon-bottom-tray-conversation-starter-item-long__icon"> | ||
| {renderedIcon} | ||
| </span> | ||
| )} | ||
| <span className="crayon-bottom-tray-conversation-starter-item-long__text"> | ||
| {displayText} | ||
| </span> | ||
| </div> | ||
| <span className="crayon-bottom-tray-conversation-starter-item-long__arrow"> | ||
| <ArrowUp size={16} /> | ||
| </span> | ||
| </button> | ||
| ); | ||
| }; | ||
|
|
||
| export interface ConversationStarterContainerProps { | ||
| starters: ConversationStarterProps[]; | ||
| className?: string; | ||
| /** | ||
| * Variant of the conversation starter | ||
| * - "short": Pill-style horizontal buttons (default) | ||
| * - "long": List items with icons and hover arrow | ||
| */ | ||
| variant?: ConversationStarterVariant; | ||
| } | ||
|
|
||
| export const ConversationStarter = ({ | ||
| starters, | ||
| className, | ||
| variant = "short", | ||
| }: ConversationStarterContainerProps) => { | ||
| const { processMessage } = useThreadActions(); | ||
| const { isRunning, messages } = useThreadState(); | ||
|
|
||
| const handleClick = (prompt: string) => { | ||
| if (isRunning) return; | ||
| processMessage({ | ||
| type: "prompt", | ||
| role: "user", | ||
| message: prompt, | ||
| }); | ||
| }; | ||
|
|
||
| // Only show when there are no messages | ||
| if (messages.length > 0) { | ||
| return null; | ||
| } | ||
|
|
||
| if (starters.length === 0) { | ||
| return null; | ||
| } | ||
|
|
||
| return ( | ||
| <div | ||
| className={clsx( | ||
| "crayon-bottom-tray-conversation-starter", | ||
| `crayon-bottom-tray-conversation-starter--${variant}`, | ||
| className, | ||
| )} | ||
| > | ||
| {starters.map((item, index) => ( | ||
| <Fragment key={`${item.displayText}-${index}`}> | ||
| <ConversationStarterItem | ||
| displayText={item.displayText} | ||
| prompt={item.prompt} | ||
| icon={item.icon} | ||
| onClick={handleClick} | ||
| variant={variant} | ||
| /> | ||
| {/* Add separator between items in long variant */} | ||
| {variant === "long" && index < starters.length - 1 && ( | ||
| <div className="crayon-bottom-tray-conversation-starter__separator"> | ||
| <Separator /> | ||
| </div> | ||
| )} | ||
| </Fragment> | ||
| ))} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default ConversationStarter; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
js/packages/react-ui/src/components/BottomTray/WelcomeScreen.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| import { useThreadState } from "@crayonai/react-core"; | ||
| import clsx from "clsx"; | ||
| import { ReactNode } from "react"; | ||
|
|
||
| interface WelcomeScreenBaseProps { | ||
| /** | ||
| * Additional CSS class name | ||
| */ | ||
| className?: string; | ||
| } | ||
|
|
||
| interface WelcomeScreenWithContentProps extends WelcomeScreenBaseProps { | ||
| /** | ||
| * The greeting/title text to display | ||
| */ | ||
| title?: string; | ||
| /** | ||
| * Optional description text to add more context | ||
| */ | ||
| description?: string; | ||
| /** | ||
| * Image to display - can be a URL object or a ReactNode | ||
| * - { url: string }: Renders an <img> tag with default styling (64x64, object-fit: cover, rounded) | ||
| * - ReactNode: Renders the provided element directly (for custom icons, styled images, etc.) | ||
| */ | ||
| image?: { url: string } | ReactNode; | ||
| /** | ||
| * Children are not allowed when using props-based content | ||
| */ | ||
| children?: never; | ||
| } | ||
|
|
||
| interface WelcomeScreenWithChildrenProps extends WelcomeScreenBaseProps { | ||
| /** | ||
| * Custom content to render inside the welcome screen | ||
| * When children are provided, title, description, and image are ignored | ||
| */ | ||
| children: ReactNode; | ||
| title?: never; | ||
| description?: never; | ||
| image?: never; | ||
| } | ||
|
|
||
| export type WelcomeScreenProps = WelcomeScreenWithContentProps | WelcomeScreenWithChildrenProps; | ||
|
|
||
| /** | ||
| * Type guard to check if image is a URL object | ||
| */ | ||
| const isImageUrl = (image: { url: string } | ReactNode): image is { url: string } => { | ||
| return typeof image === "object" && image !== null && "url" in image; | ||
| }; | ||
|
|
||
| export const WelcomeScreen = (props: WelcomeScreenProps) => { | ||
| const { className } = props; | ||
|
|
||
| const { messages } = useThreadState(); | ||
|
|
||
| // Only show when there are no messages | ||
| if (messages.length > 0) { | ||
| return null; | ||
| } | ||
|
|
||
| // Check if children are provided | ||
| if ("children" in props && props.children) { | ||
| return ( | ||
| <div className={clsx("crayon-bottom-tray-welcome-screen", className)}>{props.children}</div> | ||
| ); | ||
| } | ||
|
|
||
| // Props-based content | ||
| const { title, description, image } = props as WelcomeScreenWithContentProps; | ||
|
|
||
| const renderImage = () => { | ||
| if (!image) return null; | ||
|
|
||
| if (isImageUrl(image)) { | ||
| return ( | ||
| <img | ||
| src={image.url} | ||
| alt={title || ""} | ||
| className="crayon-bottom-tray-welcome-screen__image" | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| return image; | ||
| }; | ||
|
|
||
| return ( | ||
| <div className={clsx("crayon-bottom-tray-welcome-screen", className)}> | ||
| {image && ( | ||
| <div className="crayon-bottom-tray-welcome-screen__image-container">{renderImage()}</div> | ||
| )} | ||
| {(title || description) && ( | ||
| <div className="crayon-bottom-tray-welcome-screen__content"> | ||
| {title && <h2 className="crayon-bottom-tray-welcome-screen__title">{title}</h2>} | ||
| {description && ( | ||
| <p className="crayon-bottom-tray-welcome-screen__description">{description}</p> | ||
| )} | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default WelcomeScreen; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test with C1Chat persistence, on switch thread + on new thread.
when switching thread and loading started/or not donot show
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually remove this case from here and add in crayonchat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testing, I have changed the condition so that we dont see flashes of the welcome screen.