Conversation
📝 WalkthroughWalkthroughAdds a client-side Agent page with a streaming AI reply UI, Emotion-based styling modules, new Chat/Search UI components, an Emotion cache registry integrated into the app layout, and a new dependency entry for Emotion cache. Changes
Sequence DiagramsequenceDiagram
participant User
participant AgentPage as Agent Page
participant StreamTimer as Stream Timer
participant UI as Chat/Search UI
User->>AgentPage: Load page / type input
AgentPage->>UI: Render logo or input UI
User->>AgentPage: Press Enter / Click Send
AgentPage->>AgentPage: set isChat=true, push user message
AgentPage->>UI: Render user message
AgentPage->>StreamTimer: start 50ms interval
loop every 50ms
StreamTimer->>AgentPage: tick
AgentPage->>AgentPage: append next AI char to streamedText
AgentPage->>UI: update AI message fragment
end
StreamTimer->>AgentPage: finished streaming
AgentPage->>AgentPage: clear input
AgentPage->>UI: render final AI message
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@src/app/agent/page.tsx`:
- Around line 88-108: The send control (S.IconCircle with className
"send-button") is not keyboard-accessible; replace it with a semantic <button>
(or if keeping the styled S.IconCircle wrapper, render it as a button element)
or add role="button", tabIndex={0}, aria-label="Send" and an onKeyDown that
invokes handleSearch for Enter/Space; ensure the element is focusable and uses
keyboard handlers consistent with handleKeyDown/handleSearch so keyboard and
screen-reader users can activate the send action.
- Around line 32-44: handleSearch currently allows empty/whitespace submissions
and handleKeyDown triggers submit even during IME composition; update
handleSearch to trim and early-return when inputValue is empty/whitespace (keep
setting isChatStarted only when actually submitting) and update handleKeyDown to
skip calling handleSearch while composition is active by checking
e.nativeEvent.isComposing (or e.isComposing) before invoking handleSearch;
reference functions: handleSearch, handleKeyDown, setInputValue,
setIsChatStarted, and the inputValue state to apply these guards.
- Around line 61-86: The user message is currently hardcoded using USER_MESSAGE
inside the UI (rendered in S.UserMessageCard) so typed inputValue is never
shown; update the submit flow to capture the inputValue into a state/local
variable (e.g., userMessage) before you clear inputValue in the submit handler,
then render that state (userMessage) in S.UserMessageCard instead of
USER_MESSAGE; ensure the change is applied where isChatStarted controls
rendering so the submitted text is preserved for the chat view.
In `@src/app/agent/style.ts`:
- Around line 131-143: The message card components UserMessageCard and
AIMessageCard use a fixed width (width: 800px) which causes overflow on narrow
viewports; change their styling to use a responsive constraint such as
max-width: 800px and make the card grow/shrink (e.g., width: 100% or remove
fixed width) while keeping box-sizing: border-box and existing padding so cards
stay within parent containers on small screens. Locate UserMessageCard and
AIMessageCard in this file and replace the fixed width with a max-width-based
responsive approach.
🧹 Nitpick comments (3)
src/app/agent/style.ts (2)
24-31:LogoTitlebypasses the centralized typography system.Other components use
typography.*tokens, butLogoTitlehardcodesfont-family,font-weight, andfont-sizedirectly. Consider using a typography token (or creating one if an 80px variant doesn't exist) to keep styling consistent.
12-12: Multiple hardcoded color values bypass the design token system.Colors like
#ffffff,#e2e8f0, and#1b2559are scattered across components while acolorstoken object is imported and used elsewhere. For maintainability and theme consistency, consider centralizing these into the color palette.Also applies to: 41-41, 118-118, 128-128, 132-132, 137-137, 146-146, 152-152
src/app/agent/page.tsx (1)
16-30: Streaming effect only fires once; subsequent sends are silently ignored.Since
isChatStartedis never reset tofalse, theuseEffectdependency[isChatStarted]won't trigger again on additional messages. The PR description acknowledges this is placeholder behavior, but worth noting: when integrating real server responses, this will need to be restructured (e.g., keyed off a message list length or a dedicated streaming trigger).Also,
streamedTextis never reset before a new stream — if you later allow multiple exchanges, stale text from the previous response will persist until overwritten.
| {isChatStarted && ( | ||
| <S.ChatArea> | ||
| <S.MessageRow> | ||
| <S.Avatar color={colors.primary.default}> | ||
| N | ||
| </S.Avatar> | ||
| <S.UserMessageCard> | ||
| {USER_MESSAGE} | ||
| </S.UserMessageCard> | ||
| </S.MessageRow> | ||
|
|
||
| <S.MessageRow> | ||
| <S.Avatar> | ||
| <Image | ||
| src="/assets/logo.svg" | ||
| alt="AI Avatar" | ||
| width={24} | ||
| height={24} | ||
| /> | ||
| </S.Avatar> | ||
| <S.AIMessageCard> | ||
| {streamedText} | ||
| </S.AIMessageCard> | ||
| </S.MessageRow> | ||
| </S.ChatArea> | ||
| )} |
There was a problem hiding this comment.
Chat always displays the same hardcoded user message regardless of actual input.
When chat starts, USER_MESSAGE (the hardcoded constant) is rendered rather than inputValue at the time of submission. The user's actual typed text is discarded. If this is intentional for the demo, consider adding a brief comment; otherwise, capture the input before clearing it:
+const [userMessage, setUserMessage] = useState("");
...
const handleSearch = (e?: React.FormEvent) => {
e?.preventDefault();
+ if (!inputValue.trim()) return;
+ setUserMessage(inputValue);
if (!isChatStarted) {
setIsChatStarted(true);
}
setInputValue("");
};Then render {userMessage} instead of {USER_MESSAGE} in the UserMessageCard.
🤖 Prompt for AI Agents
In `@src/app/agent/page.tsx` around lines 61 - 86, The user message is currently
hardcoded using USER_MESSAGE inside the UI (rendered in S.UserMessageCard) so
typed inputValue is never shown; update the submit flow to capture the
inputValue into a state/local variable (e.g., userMessage) before you clear
inputValue in the submit handler, then render that state (userMessage) in
S.UserMessageCard instead of USER_MESSAGE; ensure the change is applied where
isChatStarted controls rendering so the submitted text is preserved for the chat
view.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/app/agent/style.ts`:
- Around line 77-92: The SearchInput styled component currently uses the same
color for the input text and the ::placeholder (both colors.black[75]); change
the placeholder to a lighter shade so users can distinguish empty state from
typed text — update the ::placeholder color in the SearchInput definition to a
lighter token (e.g., colors.black[50]) or alternatively make the main input
color darker, ensuring the placeholder uses a different color than the input
text.
🧹 Nitpick comments (3)
src/app/agent/style.ts (3)
24-31: Inconsistent use of typography tokens.Every other text-bearing component in this file references
typography.*for font properties, butLogoTitlehard-codesfont-family,font-weight, andfont-size. If a dedicated token doesn't exist for this heading size, consider adding one rather than inlining values, to keep a single source of truth for typography.
60-75: Consider a prop-based variant instead of a magic class name.The
.send-buttonclass works, but it's invisible to TypeScript and easy to misspell. An Emotion-idiomatic approach would be a typed prop:Suggested refactor
-export const IconCircle = styled.div` +export const IconCircle = styled.div<{ variant?: 'send' }>` display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; overflow: hidden; flex-shrink: 0; - - &.send-button { - background: ${colors.primary.default}; - cursor: pointer; - border: 1px solid ${colors.primary.default}; - } + + ${({ variant }) => + variant === 'send' && + ` + background: ${colors.primary.default}; + cursor: pointer; + border: 1px solid ${colors.primary.default}; + `} `;
131-161: Hard-coded hex colours bypass the design-token system.
#e2e8f0,#1b2559,#ffffff, and the box-shadow RGBA are sprinkled acrossUserMessageCard,AIMessageCard,Avatar, and others, while thecolorsimport is already available and used elsewhere. This makes future theming or global colour tweaks error-prone. Consider mapping these values to existing (or new) tokens in@/styles/colors.
src/app/agent/style.ts
Outdated
| export const SearchInput = styled.input` | ||
| border: none; | ||
| background: transparent; | ||
| width: 100%; | ||
| padding: 0; | ||
| font-family: ${typography.text16Medium.fontFamily}; | ||
| font-size: ${typography.text16Medium.fontSize}; | ||
| font-weight: ${typography.text16Medium.fontWeight}; | ||
| line-height: ${typography.text16Medium.lineHeight}; | ||
| color: ${colors.black[75]}; | ||
| outline: none; | ||
|
|
||
| &::placeholder { | ||
| color: ${colors.black[75]}; | ||
| } | ||
| `; |
There was a problem hiding this comment.
Placeholder and input text share the same color — users can't tell them apart.
Both the input value (line 86) and ::placeholder (line 90) resolve to colors.black[75]. There's no visual cue to indicate whether the field is empty or already has typed content. Use a lighter shade (e.g., colors.black[50]) for the placeholder, or a darker shade for the input text.
Proposed fix
&::placeholder {
- color: ${colors.black[75]};
+ color: ${colors.black[50]};
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const SearchInput = styled.input` | |
| border: none; | |
| background: transparent; | |
| width: 100%; | |
| padding: 0; | |
| font-family: ${typography.text16Medium.fontFamily}; | |
| font-size: ${typography.text16Medium.fontSize}; | |
| font-weight: ${typography.text16Medium.fontWeight}; | |
| line-height: ${typography.text16Medium.lineHeight}; | |
| color: ${colors.black[75]}; | |
| outline: none; | |
| &::placeholder { | |
| color: ${colors.black[75]}; | |
| } | |
| `; | |
| export const SearchInput = styled.input` | |
| border: none; | |
| background: transparent; | |
| width: 100%; | |
| padding: 0; | |
| font-family: ${typography.text16Medium.fontFamily}; | |
| font-size: ${typography.text16Medium.fontSize}; | |
| font-weight: ${typography.text16Medium.fontWeight}; | |
| line-height: ${typography.text16Medium.lineHeight}; | |
| color: ${colors.black[75]}; | |
| outline: none; | |
| &::placeholder { | |
| color: ${colors.black[50]}; | |
| } | |
| `; |
🤖 Prompt for AI Agents
In `@src/app/agent/style.ts` around lines 77 - 92, The SearchInput styled
component currently uses the same color for the input text and the ::placeholder
(both colors.black[75]); change the placeholder to a lighter shade so users can
distinguish empty state from typed text — update the ::placeholder color in the
SearchInput definition to a lighter token (e.g., colors.black[50]) or
alternatively make the main input color darker, ensuring the placeholder uses a
different color than the input text.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/app/agent/style.ts`:
- Around line 4-14: Change the styled Container to use a transient prop so the
boolean does not get forwarded to the DOM: update the generic prop name from
isChat to $isChat (e.g., Container = styled.div<{ $isChat?: boolean }>`...`) and
update the template usages to reference ${({ $isChat }) => ...} for
justify-content and padding; then update the usage in src/app/agent/page.tsx to
pass $isChat instead of isChat when rendering <Container>.
In `@src/app/registry.tsx`:
- Around line 15-24: The current useServerInsertedHTML block keeps re-emitting
previously extracted CSS because cache.inserted isn't cleared; after you build
the style string from Object.values(cache.inserted).join(' ') (and use cache.key
for data-emotion), flush the inserted entries so they aren't re-injected on
subsequent calls (e.g., clear or delete entries on cache.inserted after
extraction). Update the useServerInsertedHTML callback that references cache.key
and cache.inserted to extract the styles, then purge cache.inserted entries
immediately after creating the __html content.
In `@src/components/ui/Agent/SearchSection/ui.tsx`:
- Around line 27-31: The send control uses S.IconCircle as a non-focusable div
with only onClick (handleSearch) — replace it with an actual button element (or
update S.IconCircle in style.ts to render as a <button> / support as="button")
and ensure it has type="button" and onClick={handleSearch}; if you cannot
convert it to a real button, add role="button", tabIndex={0} and an onKeyDown
handler that triggers handleSearch on Enter/Space to make S.IconCircle
keyboard-accessible. Ensure the change references the existing S.IconCircle
component and the handleSearch handler so keyboard users can activate the send
action.
🧹 Nitpick comments (3)
src/components/ui/Agent/SearchSection/style.ts (1)
42-46: Prefer a prop-based variant over className for Emotion styled components.Using
.send-buttonclassName is not idiomatic for Emotion. A boolean prop (e.g.,$isSend) would be more type-safe and consistent with Emotion patterns.♻️ Proposed refactor
-export const IconCircle = styled.div` +export const IconCircle = styled.div<{ $isSend?: boolean }>` display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; overflow: hidden; flex-shrink: 0; - - &.send-button { - background: ${colors.primary.default}; - cursor: pointer; - border: 1px solid ${colors.primary.default}; - } + ${({ $isSend }) => + $isSend && + `background: ${colors.primary.default}; + cursor: pointer; + border: 1px solid ${colors.primary.default};`} `;src/components/ui/Agent/ChatSection/style.ts (1)
42-71: Multiple hard-coded color values — consider using design tokens for consistency.Several colors are hard-coded (
#e2e8f0,#ffffff,#1b2559) acrossUserMessageCardandAIMessageCardinstead of using the centralizedcolorstoken system. This makes future theming or dark-mode support harder.Not blocking, but worth aligning with the rest of the codebase's approach.
src/app/agent/page.tsx (1)
18-32: Subsequent sends after the first are silently ignored.Once
isChatStartedistrue, theuseEffectdependency doesn't change on further submissions, so additional messages have no visible effect — input is cleared but nothing renders. This is acceptable for a static-data demo, but worth noting for the server-integration phase: you'll need a message-list model (e.g.,messages[]state) to support multi-turn conversation.
| export const Container = styled.div<{ isChat?: boolean }>` | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: center; | ||
| justify-content: ${({ isChat }) => (isChat ? 'space-between' : 'center')}; | ||
| width: 100%; | ||
| height: 100%; | ||
| background-color: #ffffff; | ||
| padding: ${({ isChat }) => (isChat ? '40px 0' : '0')}; | ||
| box-sizing: border-box; | ||
| `; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's check the current state of style.ts
cat -n src/app/agent/style.tsRepository: M-ADP/M-ADP-CLIENT
Length of output: 1065
🏁 Script executed:
# Check how Container is used in page.tsx
rg -n 'isChat' --type=ts --type=tsx -C 3Repository: M-ADP/M-ADP-CLIENT
Length of output: 89
🏁 Script executed:
# Also check for any imports or usage of Container component
rg -n 'Container' src/app/agent/ --type=ts --type=tsx -C 2Repository: M-ADP/M-ADP-CLIENT
Length of output: 89
🏁 Script executed:
# Search for isChat usage more broadly
rg 'isChat' --type-add 'typescripts:*.ts' --type-add 'typescripts:*.tsx'Repository: M-ADP/M-ADP-CLIENT
Length of output: 713
🏁 Script executed:
# Look at the agent page.tsx file directly
find . -name 'page.tsx' -path '*/agent/*' -type fRepository: M-ADP/M-ADP-CLIENT
Length of output: 86
🏁 Script executed:
# Search for Container usage in agent directory
rg 'Container' src/app/agent/ -A 2 -B 2Repository: M-ADP/M-ADP-CLIENT
Length of output: 734
Use transient prop syntax for isChat to prevent React warnings about unknown DOM attributes.
Emotion's styled passes non-transient props to underlying DOM elements. Since isChat is not a valid HTML attribute, prefix it with $ to mark it as transient (consumed only by the styled component, not forwarded to the DOM).
Required changes
-export const Container = styled.div<{ isChat?: boolean }>`
+export const Container = styled.div<{ $isChat?: boolean }>`
display: flex;
flex-direction: column;
align-items: center;
- justify-content: ${({ isChat }) => (isChat ? 'space-between' : 'center')};
+ justify-content: ${({ $isChat }) => ($isChat ? 'space-between' : 'center')};
width: 100%;
height: 100%;
background-color: `#ffffff`;
- padding: ${({ isChat }) => (isChat ? '40px 0' : '0')};
+ padding: ${({ $isChat }) => ($isChat ? '40px 0' : '0')};
box-sizing: border-box;
`;Also update src/app/agent/page.tsx to pass $isChat instead of isChat:
-<S.Container isChat={isChatStarted}>
+<S.Container $isChat={isChatStarted}>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const Container = styled.div<{ isChat?: boolean }>` | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: ${({ isChat }) => (isChat ? 'space-between' : 'center')}; | |
| width: 100%; | |
| height: 100%; | |
| background-color: #ffffff; | |
| padding: ${({ isChat }) => (isChat ? '40px 0' : '0')}; | |
| box-sizing: border-box; | |
| `; | |
| export const Container = styled.div<{ $isChat?: boolean }>` | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: ${({ $isChat }) => ($isChat ? 'space-between' : 'center')}; | |
| width: 100%; | |
| height: 100%; | |
| background-color: `#ffffff`; | |
| padding: ${({ $isChat }) => ($isChat ? '40px 0' : '0')}; | |
| box-sizing: border-box; | |
| `; |
🤖 Prompt for AI Agents
In `@src/app/agent/style.ts` around lines 4 - 14, Change the styled Container to
use a transient prop so the boolean does not get forwarded to the DOM: update
the generic prop name from isChat to $isChat (e.g., Container = styled.div<{
$isChat?: boolean }>`...`) and update the template usages to reference ${({
$isChat }) => ...} for justify-content and padding; then update the usage in
src/app/agent/page.tsx to pass $isChat instead of isChat when rendering
<Container>.
| useServerInsertedHTML(() => { | ||
| return ( | ||
| <style | ||
| data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`} | ||
| dangerouslySetInnerHTML={{ | ||
| __html: Object.values(cache.inserted).join(' '), | ||
| }} | ||
| /> | ||
| ); | ||
| }); |
There was a problem hiding this comment.
Styles accumulate and get re-injected on every useServerInsertedHTML call — flush after extraction.
cache.inserted is never cleared after extracting styles, so previously inserted CSS rules are re-emitted in subsequent calls. The standard pattern clears the entries after extraction to avoid duplicate <style> tags.
Proposed fix — flush inserted cache entries
useServerInsertedHTML(() => {
+ const entries = { ...cache.inserted };
+ // Flush inserted entries to avoid re-injecting on the next call
+ Object.keys(entries).forEach((key) => {
+ delete cache.inserted[key];
+ });
+ if (Object.keys(entries).length === 0) {
+ return null;
+ }
return (
<style
- data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`}
+ data-emotion={`${cache.key} ${Object.keys(entries).join(' ')}`}
dangerouslySetInnerHTML={{
- __html: Object.values(cache.inserted).join(' '),
+ __html: Object.values(entries).join(' '),
}}
/>
);
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| useServerInsertedHTML(() => { | |
| return ( | |
| <style | |
| data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`} | |
| dangerouslySetInnerHTML={{ | |
| __html: Object.values(cache.inserted).join(' '), | |
| }} | |
| /> | |
| ); | |
| }); | |
| useServerInsertedHTML(() => { | |
| const entries = { ...cache.inserted }; | |
| // Flush inserted entries to avoid re-injecting on the next call | |
| Object.keys(entries).forEach((key) => { | |
| delete cache.inserted[key]; | |
| }); | |
| if (Object.keys(entries).length === 0) { | |
| return null; | |
| } | |
| return ( | |
| <style | |
| data-emotion={`${cache.key} ${Object.keys(entries).join(' ')}`} | |
| dangerouslySetInnerHTML={{ | |
| __html: Object.values(entries).join(' '), | |
| }} | |
| /> | |
| ); | |
| }); |
🧰 Tools
🪛 ast-grep (0.40.5)
[warning] 18-18: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html
(react-unsafe-html-injection)
🪛 Biome (2.3.14)
[error] 19-19: Avoid passing content using the dangerouslySetInnerHTML prop.
Setting content using code can expose users to cross-site scripting (XSS) attacks
(lint/security/noDangerouslySetInnerHtml)
🤖 Prompt for AI Agents
In `@src/app/registry.tsx` around lines 15 - 24, The current useServerInsertedHTML
block keeps re-emitting previously extracted CSS because cache.inserted isn't
cleared; after you build the style string from
Object.values(cache.inserted).join(' ') (and use cache.key for data-emotion),
flush the inserted entries so they aren't re-injected on subsequent calls (e.g.,
clear or delete entries on cache.inserted after extraction). Update the
useServerInsertedHTML callback that references cache.key and cache.inserted to
extract the styles, then purge cache.inserted entries immediately after creating
the __html content.
| <S.IconCircle className="send-button" onClick={handleSearch}> | ||
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
| <path d="M12 19V5M12 5L5 12M12 5L19 12" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /> | ||
| </svg> | ||
| </S.IconCircle> |
There was a problem hiding this comment.
Send button div is not keyboard-accessible.
The send button is a div with only an onClick handler — it's not focusable and cannot be activated via keyboard. Use a <button> (or at minimum add role="button", tabIndex={0}, and onKeyDown for Enter/Space). This is an accessibility gap that prevents keyboard-only users from submitting.
Proposed fix — use a styled button instead
In style.ts, change IconCircle to support rendering as a button:
- <S.IconCircle className="send-button" onClick={handleSearch}>
+ <S.IconCircle as="button" className="send-button" type="button" onClick={handleSearch} aria-label="Send">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <S.IconCircle className="send-button" onClick={handleSearch}> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M12 19V5M12 5L5 12M12 5L19 12" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /> | |
| </svg> | |
| </S.IconCircle> | |
| <S.IconCircle as="button" className="send-button" type="button" onClick={handleSearch} aria-label="Send"> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
| <path d="M12 19V5M12 5L5 12M12 5L19 12" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /> | |
| </svg> | |
| </S.IconCircle> |
🤖 Prompt for AI Agents
In `@src/components/ui/Agent/SearchSection/ui.tsx` around lines 27 - 31, The send
control uses S.IconCircle as a non-focusable div with only onClick
(handleSearch) — replace it with an actual button element (or update
S.IconCircle in style.ts to render as a <button> / support as="button") and
ensure it has type="button" and onClick={handleSearch}; if you cannot convert it
to a real button, add role="button", tabIndex={0} and an onKeyDown handler that
triggers handleSearch on Enter/Space to make S.IconCircle keyboard-accessible.
Ensure the change references the existing S.IconCircle component and the
handleSearch handler so keyboard users can activate the send action.
🎫 관련 이슈
close #
📄 개요
AI agent chatOps 페이지 퍼블리싱 완료했습니다.
🔨 작업 내용
🏁 확인 사항
🙋🏻 덧붙일 말
현재 텍스트가 표시되는 방식은 정적인 데이터이므로 slice -> append 방식으로 되어있지만 실제로 서버와 연결할때는 prev + chunk 방식으로 변경하거나 백엔드에 맞춰 변경할 예정입니다.
Summary by CodeRabbit
New Features
Style