fix(app): accordion styles
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 8px;
|
gap: 0px;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
|
|
||||||
[data-slot="accordion-item"] {
|
[data-slot="accordion-item"] {
|
||||||
@@ -11,7 +11,11 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
overflow: clip;
|
overflow: visible;
|
||||||
|
|
||||||
|
& + [data-slot="accordion-item"] {
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
[data-slot="accordion-header"] {
|
[data-slot="accordion-header"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -31,9 +35,10 @@
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
background-color: var(--surface-base);
|
background-color: var(--background-stronger);
|
||||||
border: 1px solid var(--border-weak-base);
|
border: 1px solid var(--border-weak-base);
|
||||||
border-radius: var(--radius-md);
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
overflow: clip;
|
overflow: clip;
|
||||||
color: var(--text-strong);
|
color: var(--text-strong);
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
@@ -47,7 +52,10 @@
|
|||||||
letter-spacing: var(--letter-spacing-normal);
|
letter-spacing: var(--letter-spacing-normal);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--surface-base);
|
background-color: var(--surface-base-hover);
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
background-color: var(--surface-base-active);
|
||||||
}
|
}
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -58,23 +66,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-expanded] {
|
&:first-child {
|
||||||
[data-slot="accordion-trigger"] {
|
[data-slot="accordion-header"] [data-slot="accordion-trigger"] {
|
||||||
border-bottom-left-radius: 0;
|
border-top-left-radius: var(--radius-lg);
|
||||||
border-bottom-right-radius: 0;
|
border-top-right-radius: var(--radius-lg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child:not([data-expanded]) {
|
||||||
|
[data-slot="accordion-header"] [data-slot="accordion-trigger"] {
|
||||||
|
border-bottom-left-radius: var(--radius-lg);
|
||||||
|
border-bottom-right-radius: var(--radius-lg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-expanded] {
|
||||||
[data-slot="accordion-content"] {
|
[data-slot="accordion-content"] {
|
||||||
border: 1px solid var(--border-weak-base);
|
border: 1px solid var(--border-weak-base);
|
||||||
border-top: none;
|
border-top: 0;
|
||||||
border-bottom-left-radius: var(--radius-md);
|
background-color: var(--background-stronger);
|
||||||
border-bottom-right-radius: var(--radius-md);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child[data-expanded] {
|
||||||
|
[data-slot="accordion-content"] {
|
||||||
|
border-bottom-left-radius: var(--radius-lg);
|
||||||
|
border-bottom-right-radius: var(--radius-lg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-slot="accordion-content"] {
|
[data-slot="accordion-content"] {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1288,7 +1288,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-component="apply-patch-file-diff"] {
|
[data-component="apply-patch-file-diff"] {
|
||||||
border-top: 1px solid var(--border-weaker-base);
|
|
||||||
max-height: 420px;
|
max-height: 420px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[data-component="session-review"] {
|
[data-component="session-review"] {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 0px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
@@ -19,7 +19,8 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
background-color: var(--background-stronger);
|
background-color: var(--background-stronger);
|
||||||
height: 32px;
|
height: 40px;
|
||||||
|
padding-bottom: 8px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -57,70 +58,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-component="sticky-accordion-header"] {
|
[data-component="sticky-accordion-header"] {
|
||||||
top: 40px;
|
--sticky-accordion-top: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="sticky-accordion-header"][data-expanded]::before,
|
[data-slot="session-review-accordion-item"][data-selected]
|
||||||
[data-slot="accordion-item"][data-expanded] [data-component="sticky-accordion-header"]::before {
|
[data-slot="accordion-header"]
|
||||||
top: -40px;
|
[data-slot="accordion-trigger"] {
|
||||||
}
|
background-color: var(--surface-base-active);
|
||||||
|
|
||||||
[data-slot="session-review-diffs-group"] {
|
|
||||||
background-color: var(--background-stronger);
|
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
border: 1px solid var(--border-weak-base);
|
|
||||||
overflow: clip;
|
|
||||||
|
|
||||||
[data-component="accordion"] {
|
|
||||||
gap: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="accordion"] [data-slot="accordion-item"] {
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="accordion"]
|
|
||||||
[data-slot="accordion-item"]
|
|
||||||
[data-slot="accordion-header"]
|
|
||||||
[data-slot="accordion-trigger"] {
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--surface-base-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: var(--surface-base-active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="accordion"]
|
|
||||||
[data-slot="accordion-item"]
|
|
||||||
+ [data-slot="accordion-item"]
|
|
||||||
[data-slot="accordion-header"]
|
|
||||||
[data-slot="accordion-trigger"] {
|
|
||||||
border-top: 1px solid var(--border-weak-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="accordion"] [data-slot="accordion-item"][data-expanded] [data-slot="accordion-content"] {
|
|
||||||
border: 0;
|
|
||||||
border-top: 1px solid var(--border-weak-base);
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="sticky-accordion-header"][data-expanded]::before,
|
|
||||||
[data-slot="accordion-item"][data-expanded] [data-component="sticky-accordion-header"]::before {
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-slot="session-review-accordion-item"][data-selected]
|
|
||||||
[data-slot="accordion-header"]
|
|
||||||
[data-slot="accordion-trigger"] {
|
|
||||||
background-color: var(--surface-base-active);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-slot="accordion-item"] {
|
[data-slot="accordion-item"] {
|
||||||
|
|||||||
@@ -320,395 +320,393 @@ export const SessionReview = (props: SessionReviewProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div data-slot="session-review-container" class={props.classes?.container}>
|
<div data-slot="session-review-container" class={props.classes?.container}>
|
||||||
<Show when={hasDiffs()} fallback={props.empty}>
|
<Show when={hasDiffs()} fallback={props.empty}>
|
||||||
<div data-slot="session-review-diffs-group">
|
<Accordion multiple value={open()} onChange={handleChange}>
|
||||||
<Accordion multiple value={open()} onChange={handleChange}>
|
<For each={props.diffs}>
|
||||||
<For each={props.diffs}>
|
{(diff) => {
|
||||||
{(diff) => {
|
let wrapper: HTMLDivElement | undefined
|
||||||
let wrapper: HTMLDivElement | undefined
|
|
||||||
|
|
||||||
const expanded = createMemo(() => open().includes(diff.file))
|
const expanded = createMemo(() => open().includes(diff.file))
|
||||||
const [force, setForce] = createSignal(false)
|
const [force, setForce] = createSignal(false)
|
||||||
|
|
||||||
const comments = createMemo(() => (props.comments ?? []).filter((c) => c.file === diff.file))
|
const comments = createMemo(() => (props.comments ?? []).filter((c) => c.file === diff.file))
|
||||||
const commentedLines = createMemo(() => comments().map((c) => c.selection))
|
const commentedLines = createMemo(() => comments().map((c) => c.selection))
|
||||||
|
|
||||||
const beforeText = () => (typeof diff.before === "string" ? diff.before : "")
|
const beforeText = () => (typeof diff.before === "string" ? diff.before : "")
|
||||||
const afterText = () => (typeof diff.after === "string" ? diff.after : "")
|
const afterText = () => (typeof diff.after === "string" ? diff.after : "")
|
||||||
const changedLines = () => diff.additions + diff.deletions
|
const changedLines = () => diff.additions + diff.deletions
|
||||||
|
|
||||||
const tooLarge = createMemo(() => {
|
const tooLarge = createMemo(() => {
|
||||||
if (!expanded()) return false
|
if (!expanded()) return false
|
||||||
if (force()) return false
|
if (force()) return false
|
||||||
if (isImageFile(diff.file)) return false
|
if (isImageFile(diff.file)) return false
|
||||||
return changedLines() > MAX_DIFF_CHANGED_LINES
|
return changedLines() > MAX_DIFF_CHANGED_LINES
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAdded = () => diff.status === "added" || (beforeText().length === 0 && afterText().length > 0)
|
const isAdded = () => diff.status === "added" || (beforeText().length === 0 && afterText().length > 0)
|
||||||
const isDeleted = () =>
|
const isDeleted = () =>
|
||||||
diff.status === "deleted" || (afterText().length === 0 && beforeText().length > 0)
|
diff.status === "deleted" || (afterText().length === 0 && beforeText().length > 0)
|
||||||
const isImage = () => isImageFile(diff.file)
|
const isImage = () => isImageFile(diff.file)
|
||||||
const isAudio = () => isAudioFile(diff.file)
|
const isAudio = () => isAudioFile(diff.file)
|
||||||
|
|
||||||
const diffImageSrc = dataUrlFromValue(diff.after) ?? dataUrlFromValue(diff.before)
|
const diffImageSrc = dataUrlFromValue(diff.after) ?? dataUrlFromValue(diff.before)
|
||||||
const [imageSrc, setImageSrc] = createSignal<string | undefined>(diffImageSrc)
|
const [imageSrc, setImageSrc] = createSignal<string | undefined>(diffImageSrc)
|
||||||
const [imageStatus, setImageStatus] = createSignal<"idle" | "loading" | "error">("idle")
|
const [imageStatus, setImageStatus] = createSignal<"idle" | "loading" | "error">("idle")
|
||||||
|
|
||||||
const diffAudioSrc = dataUrlFromValue(diff.after) ?? dataUrlFromValue(diff.before)
|
const diffAudioSrc = dataUrlFromValue(diff.after) ?? dataUrlFromValue(diff.before)
|
||||||
const [audioSrc, setAudioSrc] = createSignal<string | undefined>(diffAudioSrc)
|
const [audioSrc, setAudioSrc] = createSignal<string | undefined>(diffAudioSrc)
|
||||||
const [audioStatus, setAudioStatus] = createSignal<"idle" | "loading" | "error">("idle")
|
const [audioStatus, setAudioStatus] = createSignal<"idle" | "loading" | "error">("idle")
|
||||||
const [audioMime, setAudioMime] = createSignal<string | undefined>(undefined)
|
const [audioMime, setAudioMime] = createSignal<string | undefined>(undefined)
|
||||||
|
|
||||||
const selectedLines = createMemo(() => {
|
const selectedLines = createMemo(() => {
|
||||||
const current = selection()
|
const current = selection()
|
||||||
if (!current || current.file !== diff.file) return null
|
if (!current || current.file !== diff.file) return null
|
||||||
return current.range
|
return current.range
|
||||||
})
|
})
|
||||||
|
|
||||||
const draftRange = createMemo(() => {
|
const draftRange = createMemo(() => {
|
||||||
const current = commenting()
|
const current = commenting()
|
||||||
if (!current || current.file !== diff.file) return null
|
if (!current || current.file !== diff.file) return null
|
||||||
return current.range
|
return current.range
|
||||||
})
|
})
|
||||||
|
|
||||||
const [draft, setDraft] = createSignal("")
|
const [draft, setDraft] = createSignal("")
|
||||||
const [positions, setPositions] = createSignal<Record<string, number>>({})
|
const [positions, setPositions] = createSignal<Record<string, number>>({})
|
||||||
const [draftTop, setDraftTop] = createSignal<number | undefined>(undefined)
|
const [draftTop, setDraftTop] = createSignal<number | undefined>(undefined)
|
||||||
|
|
||||||
const getRoot = () => {
|
const getRoot = () => {
|
||||||
const el = wrapper
|
const el = wrapper
|
||||||
if (!el) return
|
if (!el) return
|
||||||
|
|
||||||
const host = el.querySelector("diffs-container")
|
const host = el.querySelector("diffs-container")
|
||||||
if (!(host instanceof HTMLElement)) return
|
if (!(host instanceof HTMLElement)) return
|
||||||
return host.shadowRoot ?? undefined
|
return host.shadowRoot ?? undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateAnchors = () => {
|
||||||
|
const el = wrapper
|
||||||
|
if (!el) return
|
||||||
|
|
||||||
|
const root = getRoot()
|
||||||
|
if (!root) return
|
||||||
|
|
||||||
|
const next: Record<string, number> = {}
|
||||||
|
for (const item of comments()) {
|
||||||
|
const marker = findMarker(root, item.selection)
|
||||||
|
if (!marker) continue
|
||||||
|
next[item.id] = markerTop(el, marker)
|
||||||
|
}
|
||||||
|
setPositions(next)
|
||||||
|
|
||||||
|
const range = draftRange()
|
||||||
|
if (!range) {
|
||||||
|
setDraftTop(undefined)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateAnchors = () => {
|
const marker = findMarker(root, range)
|
||||||
const el = wrapper
|
if (!marker) {
|
||||||
if (!el) return
|
setDraftTop(undefined)
|
||||||
|
return
|
||||||
const root = getRoot()
|
|
||||||
if (!root) return
|
|
||||||
|
|
||||||
const next: Record<string, number> = {}
|
|
||||||
for (const item of comments()) {
|
|
||||||
const marker = findMarker(root, item.selection)
|
|
||||||
if (!marker) continue
|
|
||||||
next[item.id] = markerTop(el, marker)
|
|
||||||
}
|
|
||||||
setPositions(next)
|
|
||||||
|
|
||||||
const range = draftRange()
|
|
||||||
if (!range) {
|
|
||||||
setDraftTop(undefined)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const marker = findMarker(root, range)
|
|
||||||
if (!marker) {
|
|
||||||
setDraftTop(undefined)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setDraftTop(markerTop(el, marker))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const scheduleAnchors = () => {
|
setDraftTop(markerTop(el, marker))
|
||||||
requestAnimationFrame(updateAnchors)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
createEffect(() => {
|
const scheduleAnchors = () => {
|
||||||
comments()
|
requestAnimationFrame(updateAnchors)
|
||||||
scheduleAnchors()
|
}
|
||||||
})
|
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const range = draftRange()
|
comments()
|
||||||
if (!range) return
|
scheduleAnchors()
|
||||||
setDraft("")
|
})
|
||||||
scheduleAnchors()
|
|
||||||
})
|
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (!open().includes(diff.file)) return
|
const range = draftRange()
|
||||||
if (!isImage()) return
|
if (!range) return
|
||||||
if (imageSrc()) return
|
setDraft("")
|
||||||
if (imageStatus() !== "idle") return
|
scheduleAnchors()
|
||||||
if (isDeleted()) return
|
})
|
||||||
|
|
||||||
const reader = props.readFile
|
createEffect(() => {
|
||||||
if (!reader) return
|
if (!open().includes(diff.file)) return
|
||||||
|
if (!isImage()) return
|
||||||
|
if (imageSrc()) return
|
||||||
|
if (imageStatus() !== "idle") return
|
||||||
|
if (isDeleted()) return
|
||||||
|
|
||||||
setImageStatus("loading")
|
const reader = props.readFile
|
||||||
reader(diff.file)
|
if (!reader) return
|
||||||
.then((result) => {
|
|
||||||
const src = dataUrl(result)
|
setImageStatus("loading")
|
||||||
if (!src) {
|
reader(diff.file)
|
||||||
setImageStatus("error")
|
.then((result) => {
|
||||||
return
|
const src = dataUrl(result)
|
||||||
}
|
if (!src) {
|
||||||
setImageSrc(src)
|
|
||||||
setImageStatus("idle")
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setImageStatus("error")
|
setImageStatus("error")
|
||||||
})
|
return
|
||||||
})
|
}
|
||||||
|
setImageSrc(src)
|
||||||
|
setImageStatus("idle")
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setImageStatus("error")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (!open().includes(diff.file)) return
|
if (!open().includes(diff.file)) return
|
||||||
if (!isAudio()) return
|
if (!isAudio()) return
|
||||||
if (audioSrc()) return
|
if (audioSrc()) return
|
||||||
if (audioStatus() !== "idle") return
|
if (audioStatus() !== "idle") return
|
||||||
|
|
||||||
const reader = props.readFile
|
const reader = props.readFile
|
||||||
if (!reader) return
|
if (!reader) return
|
||||||
|
|
||||||
setAudioStatus("loading")
|
setAudioStatus("loading")
|
||||||
reader(diff.file)
|
reader(diff.file)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
const src = dataUrl(result)
|
const src = dataUrl(result)
|
||||||
if (!src) {
|
if (!src) {
|
||||||
setAudioStatus("error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setAudioMime(normalizeMimeType(result?.mimeType))
|
|
||||||
setAudioSrc(src)
|
|
||||||
setAudioStatus("idle")
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setAudioStatus("error")
|
setAudioStatus("error")
|
||||||
})
|
return
|
||||||
})
|
}
|
||||||
|
setAudioMime(normalizeMimeType(result?.mimeType))
|
||||||
|
setAudioSrc(src)
|
||||||
|
setAudioStatus("idle")
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setAudioStatus("error")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const handleLineSelected = (range: SelectedLineRange | null) => {
|
const handleLineSelected = (range: SelectedLineRange | null) => {
|
||||||
if (!props.onLineComment) return
|
if (!props.onLineComment) return
|
||||||
|
|
||||||
if (!range) {
|
if (!range) {
|
||||||
setSelection(null)
|
setSelection(null)
|
||||||
return
|
return
|
||||||
}
|
|
||||||
|
|
||||||
setSelection({ file: diff.file, range })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLineSelectionEnd = (range: SelectedLineRange | null) => {
|
setSelection({ file: diff.file, range })
|
||||||
if (!props.onLineComment) return
|
}
|
||||||
|
|
||||||
if (!range) {
|
const handleLineSelectionEnd = (range: SelectedLineRange | null) => {
|
||||||
setCommenting(null)
|
if (!props.onLineComment) return
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setSelection({ file: diff.file, range })
|
if (!range) {
|
||||||
setCommenting({ file: diff.file, range })
|
setCommenting(null)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const openComment = (comment: SessionReviewComment) => {
|
setSelection({ file: diff.file, range })
|
||||||
setOpened({ file: comment.file, id: comment.id })
|
setCommenting({ file: diff.file, range })
|
||||||
setSelection({ file: comment.file, range: comment.selection })
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const isCommentOpen = (comment: SessionReviewComment) => {
|
const openComment = (comment: SessionReviewComment) => {
|
||||||
const current = opened()
|
setOpened({ file: comment.file, id: comment.id })
|
||||||
if (!current) return false
|
setSelection({ file: comment.file, range: comment.selection })
|
||||||
return current.file === comment.file && current.id === comment.id
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
const isCommentOpen = (comment: SessionReviewComment) => {
|
||||||
<Accordion.Item
|
const current = opened()
|
||||||
value={diff.file}
|
if (!current) return false
|
||||||
id={diffId(diff.file)}
|
return current.file === comment.file && current.id === comment.id
|
||||||
data-file={diff.file}
|
}
|
||||||
data-slot="session-review-accordion-item"
|
|
||||||
data-selected={props.focusedFile === diff.file ? "" : undefined}
|
return (
|
||||||
>
|
<Accordion.Item
|
||||||
<StickyAccordionHeader>
|
value={diff.file}
|
||||||
<Accordion.Trigger>
|
id={diffId(diff.file)}
|
||||||
<div data-slot="session-review-trigger-content">
|
data-file={diff.file}
|
||||||
<div data-slot="session-review-file-info">
|
data-slot="session-review-accordion-item"
|
||||||
<FileIcon node={{ path: diff.file, type: "file" }} />
|
data-selected={props.focusedFile === diff.file ? "" : undefined}
|
||||||
<div data-slot="session-review-file-name-container">
|
>
|
||||||
<Show when={diff.file.includes("/")}>
|
<StickyAccordionHeader>
|
||||||
<span data-slot="session-review-directory">{`\u202A${getDirectory(diff.file)}\u202C`}</span>
|
<Accordion.Trigger>
|
||||||
</Show>
|
<div data-slot="session-review-trigger-content">
|
||||||
<span data-slot="session-review-filename">{getFilename(diff.file)}</span>
|
<div data-slot="session-review-file-info">
|
||||||
<Show when={props.onViewFile}>
|
<FileIcon node={{ path: diff.file, type: "file" }} />
|
||||||
<Tooltip value="Open file" placement="top" gutter={4}>
|
<div data-slot="session-review-file-name-container">
|
||||||
<button
|
<Show when={diff.file.includes("/")}>
|
||||||
data-slot="session-review-view-button"
|
<span data-slot="session-review-directory">{`\u202A${getDirectory(diff.file)}\u202C`}</span>
|
||||||
type="button"
|
</Show>
|
||||||
aria-label="Open file"
|
<span data-slot="session-review-filename">{getFilename(diff.file)}</span>
|
||||||
onClick={(e) => {
|
<Show when={props.onViewFile}>
|
||||||
e.stopPropagation()
|
<Tooltip value="Open file" placement="top" gutter={4}>
|
||||||
props.onViewFile?.(diff.file)
|
<button
|
||||||
}}
|
data-slot="session-review-view-button"
|
||||||
>
|
type="button"
|
||||||
<Icon name="open-file" size="small" />
|
aria-label="Open file"
|
||||||
</button>
|
onClick={(e) => {
|
||||||
</Tooltip>
|
e.stopPropagation()
|
||||||
</Show>
|
props.onViewFile?.(diff.file)
|
||||||
</div>
|
}}
|
||||||
</div>
|
>
|
||||||
<div data-slot="session-review-trigger-actions">
|
<Icon name="open-file" size="small" />
|
||||||
<Switch>
|
</button>
|
||||||
<Match when={isAdded()}>
|
</Tooltip>
|
||||||
<div data-slot="session-review-change-group" data-type="added">
|
</Show>
|
||||||
<span data-slot="session-review-change" data-type="added">
|
|
||||||
{i18n.t("ui.sessionReview.change.added")}
|
|
||||||
</span>
|
|
||||||
<DiffChanges changes={diff} />
|
|
||||||
</div>
|
|
||||||
</Match>
|
|
||||||
<Match when={isDeleted()}>
|
|
||||||
<span data-slot="session-review-change" data-type="removed">
|
|
||||||
{i18n.t("ui.sessionReview.change.removed")}
|
|
||||||
</span>
|
|
||||||
</Match>
|
|
||||||
<Match when={isImage()}>
|
|
||||||
<span data-slot="session-review-change" data-type="modified">
|
|
||||||
{i18n.t("ui.sessionReview.change.modified")}
|
|
||||||
</span>
|
|
||||||
</Match>
|
|
||||||
<Match when={true}>
|
|
||||||
<DiffChanges changes={diff} />
|
|
||||||
</Match>
|
|
||||||
</Switch>
|
|
||||||
<span data-slot="session-review-diff-chevron">
|
|
||||||
<Icon name="chevron-down" size="small" />
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Accordion.Trigger>
|
<div data-slot="session-review-trigger-actions">
|
||||||
</StickyAccordionHeader>
|
|
||||||
<Accordion.Content data-slot="session-review-accordion-content">
|
|
||||||
<div
|
|
||||||
data-slot="session-review-diff-wrapper"
|
|
||||||
ref={(el) => {
|
|
||||||
wrapper = el
|
|
||||||
anchors.set(diff.file, el)
|
|
||||||
scheduleAnchors()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Show when={expanded()}>
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={isImage() && imageSrc()}>
|
<Match when={isAdded()}>
|
||||||
<div data-slot="session-review-image-container">
|
<div data-slot="session-review-change-group" data-type="added">
|
||||||
<img data-slot="session-review-image" src={imageSrc()} alt={diff.file} />
|
<span data-slot="session-review-change" data-type="added">
|
||||||
</div>
|
{i18n.t("ui.sessionReview.change.added")}
|
||||||
</Match>
|
|
||||||
<Match when={isImage() && isDeleted()}>
|
|
||||||
<div data-slot="session-review-image-container" data-removed>
|
|
||||||
<span data-slot="session-review-image-placeholder">
|
|
||||||
{i18n.t("ui.sessionReview.change.removed")}
|
|
||||||
</span>
|
</span>
|
||||||
|
<DiffChanges changes={diff} />
|
||||||
</div>
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={isImage() && !imageSrc()}>
|
<Match when={isDeleted()}>
|
||||||
<div data-slot="session-review-image-container">
|
<span data-slot="session-review-change" data-type="removed">
|
||||||
<span data-slot="session-review-image-placeholder">
|
{i18n.t("ui.sessionReview.change.removed")}
|
||||||
{imageStatus() === "loading"
|
</span>
|
||||||
? i18n.t("ui.sessionReview.image.loading")
|
|
||||||
: i18n.t("ui.sessionReview.image.placeholder")}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={!isImage() && tooLarge()}>
|
<Match when={isImage()}>
|
||||||
<div data-slot="session-review-large-diff">
|
<span data-slot="session-review-change" data-type="modified">
|
||||||
<div data-slot="session-review-large-diff-title">
|
{i18n.t("ui.sessionReview.change.modified")}
|
||||||
{i18n.t("ui.sessionReview.largeDiff.title")}
|
</span>
|
||||||
</div>
|
|
||||||
<div data-slot="session-review-large-diff-meta">
|
|
||||||
{i18n.t("ui.sessionReview.largeDiff.meta", {
|
|
||||||
limit: MAX_DIFF_CHANGED_LINES.toLocaleString(),
|
|
||||||
current: changedLines().toLocaleString(),
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div data-slot="session-review-large-diff-actions">
|
|
||||||
<Button size="normal" variant="secondary" onClick={() => setForce(true)}>
|
|
||||||
{i18n.t("ui.sessionReview.largeDiff.renderAnyway")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={!isImage()}>
|
<Match when={true}>
|
||||||
<Dynamic
|
<DiffChanges changes={diff} />
|
||||||
component={diffComponent}
|
|
||||||
preloadedDiff={diff.preloaded}
|
|
||||||
diffStyle={diffStyle()}
|
|
||||||
onRendered={() => {
|
|
||||||
props.onDiffRendered?.()
|
|
||||||
scheduleAnchors()
|
|
||||||
}}
|
|
||||||
enableLineSelection={props.onLineComment != null}
|
|
||||||
onLineSelected={handleLineSelected}
|
|
||||||
onLineSelectionEnd={handleLineSelectionEnd}
|
|
||||||
selectedLines={selectedLines()}
|
|
||||||
commentedLines={commentedLines()}
|
|
||||||
before={{
|
|
||||||
name: diff.file!,
|
|
||||||
contents: typeof diff.before === "string" ? diff.before : "",
|
|
||||||
}}
|
|
||||||
after={{
|
|
||||||
name: diff.file!,
|
|
||||||
contents: typeof diff.after === "string" ? diff.after : "",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
<span data-slot="session-review-diff-chevron">
|
||||||
<For each={comments()}>
|
<Icon name="chevron-down" size="small" />
|
||||||
{(comment) => (
|
</span>
|
||||||
<LineComment
|
</div>
|
||||||
id={comment.id}
|
|
||||||
top={positions()[comment.id]}
|
|
||||||
onMouseEnter={() => setSelection({ file: comment.file, range: comment.selection })}
|
|
||||||
onClick={() => {
|
|
||||||
if (isCommentOpen(comment)) {
|
|
||||||
setOpened(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
openComment(comment)
|
|
||||||
}}
|
|
||||||
open={isCommentOpen(comment)}
|
|
||||||
comment={comment.comment}
|
|
||||||
selection={selectionLabel(comment.selection)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
|
|
||||||
<Show when={draftRange()}>
|
|
||||||
{(range) => (
|
|
||||||
<Show when={draftTop() !== undefined}>
|
|
||||||
<LineCommentEditor
|
|
||||||
top={draftTop()}
|
|
||||||
value={draft()}
|
|
||||||
selection={selectionLabel(range())}
|
|
||||||
onInput={setDraft}
|
|
||||||
onCancel={() => setCommenting(null)}
|
|
||||||
onSubmit={(comment) => {
|
|
||||||
props.onLineComment?.({
|
|
||||||
file: diff.file,
|
|
||||||
selection: range(),
|
|
||||||
comment,
|
|
||||||
preview: selectionPreview(diff, range()),
|
|
||||||
})
|
|
||||||
setCommenting(null)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Show>
|
|
||||||
)}
|
|
||||||
</Show>
|
|
||||||
</Show>
|
|
||||||
</div>
|
</div>
|
||||||
</Accordion.Content>
|
</Accordion.Trigger>
|
||||||
</Accordion.Item>
|
</StickyAccordionHeader>
|
||||||
)
|
<Accordion.Content data-slot="session-review-accordion-content">
|
||||||
}}
|
<div
|
||||||
</For>
|
data-slot="session-review-diff-wrapper"
|
||||||
</Accordion>
|
ref={(el) => {
|
||||||
</div>
|
wrapper = el
|
||||||
|
anchors.set(diff.file, el)
|
||||||
|
scheduleAnchors()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Show when={expanded()}>
|
||||||
|
<Switch>
|
||||||
|
<Match when={isImage() && imageSrc()}>
|
||||||
|
<div data-slot="session-review-image-container">
|
||||||
|
<img data-slot="session-review-image" src={imageSrc()} alt={diff.file} />
|
||||||
|
</div>
|
||||||
|
</Match>
|
||||||
|
<Match when={isImage() && isDeleted()}>
|
||||||
|
<div data-slot="session-review-image-container" data-removed>
|
||||||
|
<span data-slot="session-review-image-placeholder">
|
||||||
|
{i18n.t("ui.sessionReview.change.removed")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Match>
|
||||||
|
<Match when={isImage() && !imageSrc()}>
|
||||||
|
<div data-slot="session-review-image-container">
|
||||||
|
<span data-slot="session-review-image-placeholder">
|
||||||
|
{imageStatus() === "loading"
|
||||||
|
? i18n.t("ui.sessionReview.image.loading")
|
||||||
|
: i18n.t("ui.sessionReview.image.placeholder")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Match>
|
||||||
|
<Match when={!isImage() && tooLarge()}>
|
||||||
|
<div data-slot="session-review-large-diff">
|
||||||
|
<div data-slot="session-review-large-diff-title">
|
||||||
|
{i18n.t("ui.sessionReview.largeDiff.title")}
|
||||||
|
</div>
|
||||||
|
<div data-slot="session-review-large-diff-meta">
|
||||||
|
{i18n.t("ui.sessionReview.largeDiff.meta", {
|
||||||
|
limit: MAX_DIFF_CHANGED_LINES.toLocaleString(),
|
||||||
|
current: changedLines().toLocaleString(),
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div data-slot="session-review-large-diff-actions">
|
||||||
|
<Button size="normal" variant="secondary" onClick={() => setForce(true)}>
|
||||||
|
{i18n.t("ui.sessionReview.largeDiff.renderAnyway")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Match>
|
||||||
|
<Match when={!isImage()}>
|
||||||
|
<Dynamic
|
||||||
|
component={diffComponent}
|
||||||
|
preloadedDiff={diff.preloaded}
|
||||||
|
diffStyle={diffStyle()}
|
||||||
|
onRendered={() => {
|
||||||
|
props.onDiffRendered?.()
|
||||||
|
scheduleAnchors()
|
||||||
|
}}
|
||||||
|
enableLineSelection={props.onLineComment != null}
|
||||||
|
onLineSelected={handleLineSelected}
|
||||||
|
onLineSelectionEnd={handleLineSelectionEnd}
|
||||||
|
selectedLines={selectedLines()}
|
||||||
|
commentedLines={commentedLines()}
|
||||||
|
before={{
|
||||||
|
name: diff.file!,
|
||||||
|
contents: typeof diff.before === "string" ? diff.before : "",
|
||||||
|
}}
|
||||||
|
after={{
|
||||||
|
name: diff.file!,
|
||||||
|
contents: typeof diff.after === "string" ? diff.after : "",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
|
|
||||||
|
<For each={comments()}>
|
||||||
|
{(comment) => (
|
||||||
|
<LineComment
|
||||||
|
id={comment.id}
|
||||||
|
top={positions()[comment.id]}
|
||||||
|
onMouseEnter={() => setSelection({ file: comment.file, range: comment.selection })}
|
||||||
|
onClick={() => {
|
||||||
|
if (isCommentOpen(comment)) {
|
||||||
|
setOpened(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
openComment(comment)
|
||||||
|
}}
|
||||||
|
open={isCommentOpen(comment)}
|
||||||
|
comment={comment.comment}
|
||||||
|
selection={selectionLabel(comment.selection)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
|
||||||
|
<Show when={draftRange()}>
|
||||||
|
{(range) => (
|
||||||
|
<Show when={draftTop() !== undefined}>
|
||||||
|
<LineCommentEditor
|
||||||
|
top={draftTop()}
|
||||||
|
value={draft()}
|
||||||
|
selection={selectionLabel(range())}
|
||||||
|
onInput={setDraft}
|
||||||
|
onCancel={() => setCommenting(null)}
|
||||||
|
onSubmit={(comment) => {
|
||||||
|
props.onLineComment?.({
|
||||||
|
file: diff.file,
|
||||||
|
selection: range(),
|
||||||
|
comment,
|
||||||
|
preview: selectionPreview(diff, range()),
|
||||||
|
})
|
||||||
|
setCommenting(null)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Show>
|
||||||
|
)}
|
||||||
|
</Show>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
</Accordion.Content>
|
||||||
|
</Accordion.Item>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</For>
|
||||||
|
</Accordion>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -129,49 +129,6 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-slot="session-turn-diffs-group"] {
|
|
||||||
background-color: var(--background-stronger);
|
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
border: 1px solid var(--border-weak-base);
|
|
||||||
overflow: clip;
|
|
||||||
|
|
||||||
[data-component="accordion"] {
|
|
||||||
gap: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="accordion"]
|
|
||||||
[data-slot="accordion-item"]
|
|
||||||
[data-slot="accordion-header"]
|
|
||||||
[data-slot="accordion-trigger"] {
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--surface-base-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: var(--surface-base-active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="accordion"]
|
|
||||||
[data-slot="accordion-item"]
|
|
||||||
+ [data-slot="accordion-item"]
|
|
||||||
[data-slot="accordion-header"]
|
|
||||||
[data-slot="accordion-trigger"] {
|
|
||||||
border-top: 1px solid var(--border-weak-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-component="accordion"] [data-slot="accordion-item"][data-expanded] [data-slot="accordion-content"] {
|
|
||||||
border: 0;
|
|
||||||
border-top: 1px solid var(--border-weak-base);
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-slot="session-turn-diff-trigger"] {
|
[data-slot="session-turn-diff-trigger"] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -315,78 +315,76 @@ export function SessionTurn(
|
|||||||
<Collapsible.Content>
|
<Collapsible.Content>
|
||||||
<Show when={open()}>
|
<Show when={open()}>
|
||||||
<div data-component="session-turn-diffs-content">
|
<div data-component="session-turn-diffs-content">
|
||||||
<div data-slot="session-turn-diffs-group">
|
<Accordion
|
||||||
<Accordion
|
multiple
|
||||||
multiple
|
value={expanded()}
|
||||||
value={expanded()}
|
onChange={(value) => setExpanded(Array.isArray(value) ? value : value ? [value] : [])}
|
||||||
onChange={(value) => setExpanded(Array.isArray(value) ? value : value ? [value] : [])}
|
>
|
||||||
>
|
<For each={diffs()}>
|
||||||
<For each={diffs()}>
|
{(diff) => {
|
||||||
{(diff) => {
|
const active = createMemo(() => expanded().includes(diff.file))
|
||||||
const active = createMemo(() => expanded().includes(diff.file))
|
const [visible, setVisible] = createSignal(false)
|
||||||
const [visible, setVisible] = createSignal(false)
|
|
||||||
|
|
||||||
createEffect(
|
createEffect(
|
||||||
on(
|
on(
|
||||||
active,
|
active,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
setVisible(false)
|
setVisible(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
if (!active()) return
|
if (!active()) return
|
||||||
setVisible(true)
|
setVisible(true)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{ defer: true },
|
{ defer: true },
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Accordion.Item value={diff.file}>
|
<Accordion.Item value={diff.file}>
|
||||||
<Accordion.Header>
|
<Accordion.Header>
|
||||||
<Accordion.Trigger>
|
<Accordion.Trigger>
|
||||||
<div data-slot="session-turn-diff-trigger">
|
<div data-slot="session-turn-diff-trigger">
|
||||||
<span data-slot="session-turn-diff-path">
|
<span data-slot="session-turn-diff-path">
|
||||||
<Show when={diff.file.includes("/")}>
|
<Show when={diff.file.includes("/")}>
|
||||||
<span data-slot="session-turn-diff-directory">
|
<span data-slot="session-turn-diff-directory">
|
||||||
{`\u202A${getDirectory(diff.file)}\u202C`}
|
{`\u202A${getDirectory(diff.file)}\u202C`}
|
||||||
</span>
|
|
||||||
</Show>
|
|
||||||
<span data-slot="session-turn-diff-filename">
|
|
||||||
{getFilename(diff.file)}
|
|
||||||
</span>
|
</span>
|
||||||
|
</Show>
|
||||||
|
<span data-slot="session-turn-diff-filename">
|
||||||
|
{getFilename(diff.file)}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div data-slot="session-turn-diff-meta">
|
||||||
|
<span data-slot="session-turn-diff-changes">
|
||||||
|
<DiffChanges changes={diff} />
|
||||||
|
</span>
|
||||||
|
<span data-slot="session-turn-diff-chevron">
|
||||||
|
<Icon name="chevron-down" size="small" />
|
||||||
</span>
|
</span>
|
||||||
<div data-slot="session-turn-diff-meta">
|
|
||||||
<span data-slot="session-turn-diff-changes">
|
|
||||||
<DiffChanges changes={diff} />
|
|
||||||
</span>
|
|
||||||
<span data-slot="session-turn-diff-chevron">
|
|
||||||
<Icon name="chevron-down" size="small" />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Accordion.Trigger>
|
</div>
|
||||||
</Accordion.Header>
|
</Accordion.Trigger>
|
||||||
<Accordion.Content>
|
</Accordion.Header>
|
||||||
<Show when={visible()}>
|
<Accordion.Content>
|
||||||
<div data-slot="session-turn-diff-view" data-scrollable>
|
<Show when={visible()}>
|
||||||
<Dynamic
|
<div data-slot="session-turn-diff-view" data-scrollable>
|
||||||
component={diffComponent}
|
<Dynamic
|
||||||
before={{ name: diff.file, contents: diff.before }}
|
component={diffComponent}
|
||||||
after={{ name: diff.file, contents: diff.after }}
|
before={{ name: diff.file, contents: diff.before }}
|
||||||
/>
|
after={{ name: diff.file, contents: diff.after }}
|
||||||
</div>
|
/>
|
||||||
</Show>
|
</div>
|
||||||
</Accordion.Content>
|
</Show>
|
||||||
</Accordion.Item>
|
</Accordion.Content>
|
||||||
)
|
</Accordion.Item>
|
||||||
}}
|
)
|
||||||
</For>
|
}}
|
||||||
</Accordion>
|
</For>
|
||||||
</div>
|
</Accordion>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
</Collapsible.Content>
|
</Collapsible.Content>
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
[data-component="sticky-accordion-header"] {
|
[data-component="sticky-accordion-header"] {
|
||||||
|
--sticky-accordion-top: 0px;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0px;
|
top: var(--sticky-accordion-top);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="accordion-item"]:first-child [data-component="sticky-accordion-header"] {
|
||||||
|
background-color: var(--background-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="sticky-accordion-header"][data-expanded],
|
[data-component="sticky-accordion-header"][data-expanded],
|
||||||
[data-slot="accordion-item"][data-expanded] [data-component="sticky-accordion-header"] {
|
[data-slot="accordion-item"][data-expanded] [data-component="sticky-accordion-header"] {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="sticky-accordion-header"][data-expanded]::before,
|
|
||||||
[data-slot="accordion-item"][data-expanded] [data-component="sticky-accordion-header"]::before {
|
|
||||||
content: "";
|
|
||||||
z-index: -10;
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background-color: var(--background-stronger);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user