mirror of
https://github.com/anomalyco/opencode.git
synced 2026-02-01 22:48:16 +00:00
feat: animate accordion, user message
This commit is contained in:
@@ -36,7 +36,9 @@
|
||||
border-radius: var(--radius-md);
|
||||
overflow: clip;
|
||||
color: var(--text-strong);
|
||||
transition: background-color 0.15s ease;
|
||||
transition-property: background-color, border-color;
|
||||
transition-duration: var(--transition-duration);
|
||||
transition-timing-function: var(--transition-easing);
|
||||
|
||||
/* text-12-regular */
|
||||
font-family: var(--font-family-sans);
|
||||
@@ -58,6 +60,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="accordion-arrow"] {
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--text-weak);
|
||||
}
|
||||
|
||||
&[data-expanded] {
|
||||
[data-slot="accordion-trigger"] {
|
||||
border-bottom-left-radius: 0;
|
||||
@@ -69,30 +81,29 @@
|
||||
border-top: none;
|
||||
border-bottom-left-radius: var(--radius-md);
|
||||
border-bottom-right-radius: var(--radius-md);
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="accordion-content"] {
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
transition-property: grid-template-rows, opacity;
|
||||
transition-duration: var(--transition-duration);
|
||||
transition-timing-function: var(--transition-easing);
|
||||
width: 100%;
|
||||
|
||||
> * {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&[data-expanded] {
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
|
||||
&[data-closed] {
|
||||
grid-template-rows: 0fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
height: 0;
|
||||
}
|
||||
to {
|
||||
height: var(--kb-accordion-content-height);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
height: var(--kb-accordion-content-height);
|
||||
}
|
||||
to {
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Accordion as Kobalte } from "@kobalte/core/accordion"
|
||||
import { splitProps } from "solid-js"
|
||||
import { Accessor, createContext, splitProps, useContext } from "solid-js"
|
||||
import type { ComponentProps, ParentProps } from "solid-js"
|
||||
import { MorphChevron } from "./morph-chevron"
|
||||
|
||||
export interface AccordionProps extends ComponentProps<typeof Kobalte> {}
|
||||
export interface AccordionItemProps extends ComponentProps<typeof Kobalte.Item> {}
|
||||
@@ -8,6 +9,8 @@ export interface AccordionHeaderProps extends ComponentProps<typeof Kobalte.Head
|
||||
export interface AccordionTriggerProps extends ComponentProps<typeof Kobalte.Trigger> {}
|
||||
export interface AccordionContentProps extends ComponentProps<typeof Kobalte.Content> {}
|
||||
|
||||
const AccordionItemContext = createContext<Accessor<boolean>>()
|
||||
|
||||
function AccordionRoot(props: AccordionProps) {
|
||||
const [split, rest] = splitProps(props, ["class", "classList"])
|
||||
return (
|
||||
@@ -22,17 +25,19 @@ function AccordionRoot(props: AccordionProps) {
|
||||
)
|
||||
}
|
||||
|
||||
function AccordionItem(props: AccordionItemProps) {
|
||||
const [split, rest] = splitProps(props, ["class", "classList"])
|
||||
function AccordionItem(props: AccordionItemProps & { expanded?: boolean }) {
|
||||
const [split, rest] = splitProps(props, ["class", "classList", "expanded"])
|
||||
return (
|
||||
<Kobalte.Item
|
||||
{...rest}
|
||||
data-slot="accordion-item"
|
||||
classList={{
|
||||
...(split.classList ?? {}),
|
||||
[split.class ?? ""]: !!split.class,
|
||||
}}
|
||||
/>
|
||||
<AccordionItemContext.Provider value={() => split.expanded ?? false}>
|
||||
<Kobalte.Item
|
||||
{...rest}
|
||||
data-slot="accordion-item"
|
||||
classList={{
|
||||
...(split.classList ?? {}),
|
||||
[split.class ?? ""]: !!split.class,
|
||||
}}
|
||||
/>
|
||||
</AccordionItemContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -84,9 +89,25 @@ function AccordionContent(props: ParentProps<AccordionContentProps>) {
|
||||
)
|
||||
}
|
||||
|
||||
export interface AccordionArrowProps extends ComponentProps<"div"> {
|
||||
expanded?: boolean
|
||||
}
|
||||
|
||||
function AccordionArrow(props: AccordionArrowProps = {}) {
|
||||
const [local, rest] = splitProps(props, ["expanded"])
|
||||
const contextExpanded = useContext(AccordionItemContext)
|
||||
const isExpanded = () => local.expanded ?? contextExpanded?.() ?? false
|
||||
return (
|
||||
<div data-slot="accordion-arrow" {...rest}>
|
||||
<MorphChevron expanded={isExpanded()} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const Accordion = Object.assign(AccordionRoot, {
|
||||
Item: AccordionItem,
|
||||
Header: AccordionHeader,
|
||||
Trigger: AccordionTrigger,
|
||||
Content: AccordionContent,
|
||||
Arrow: AccordionArrow,
|
||||
})
|
||||
|
||||
@@ -106,10 +106,11 @@
|
||||
|
||||
[data-component="user-message"] [data-slot="user-message-text"] {
|
||||
max-height: var(--user-message-collapsed-height, 64px);
|
||||
transition: max-height 200ms cubic-bezier(0.25, 0, 0.5, 1);
|
||||
}
|
||||
|
||||
[data-component="user-message"][data-expanded="true"] [data-slot="user-message-text"] {
|
||||
max-height: none;
|
||||
max-height: 2000px;
|
||||
}
|
||||
|
||||
[data-component="user-message"][data-can-expand="true"] [data-slot="user-message-text"] {
|
||||
@@ -141,17 +142,6 @@
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
color: var(--text-weak);
|
||||
|
||||
[data-slot="icon-svg"] {
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="user-message"][data-expanded="true"]
|
||||
[data-slot="user-message-text"]
|
||||
[data-slot="user-message-expand"]
|
||||
[data-slot="icon-svg"] {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
[data-component="user-message"] [data-slot="user-message-text"] [data-slot="user-message-expand"]:hover {
|
||||
@@ -457,6 +447,7 @@
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
color: var(--icon-base);
|
||||
}
|
||||
|
||||
[data-slot="session-turn-accordion-content"] {
|
||||
|
||||
@@ -548,7 +548,7 @@ export function SessionTurn(
|
||||
data-slot="session-turn-collapsible-trigger-content"
|
||||
variant="ghost"
|
||||
size="small"
|
||||
onClick={props.onStepsExpandedToggle ?? (() => {})}
|
||||
onClick={props.onStepsExpandedToggle ?? (() => { })}
|
||||
aria-expanded={props.stepsExpanded}
|
||||
>
|
||||
<Switch>
|
||||
|
||||
@@ -33,8 +33,10 @@
|
||||
@import "../components/markdown.css" layer(components);
|
||||
@import "../components/message-part.css" layer(components);
|
||||
@import "../components/message-nav.css" layer(components);
|
||||
@import "../components/morph-chevron.css" layer(components);
|
||||
@import "../components/popover.css" layer(components);
|
||||
@import "../components/progress-circle.css" layer(components);
|
||||
@import "../components/reasoning-icon.css" layer(components);
|
||||
@import "../components/radio-group.css" layer(components);
|
||||
@import "../components/resize-handle.css" layer(components);
|
||||
@import "../components/select.css" layer(components);
|
||||
|
||||
Reference in New Issue
Block a user