Sidebar: peek & control gaps (transparent inset peek, reduced-motion, external control, peek state, backdrop)
Maintainer thường phản hồi trong vòng 2 ngày
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- react, typescript
- Lĩnh vực
- accessibility, design, frontend
Hướng nghiên cứu
Bắt đầu từ phần định kiểu root của Sidebar và các entry point Sidebar, Sidebar.Trigger và useSidebar. So sánh các quy tắc inset peek với các biến thể floating và plain, sau đó kiểm tra các guard hiện có cho reduced motion và trạng thái context hiện tại. Công việc được xem là hoàn tất khi lỗi hiển thị và hành vi chuyển động đã được xử lý, đồng thời các quyết định API về external control, peek callback và backdrop được triển khai nhất quán.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
This issue collects several related Sidebar gaps found while building an
inset sidebar with peekOnHover. The first is a concrete visual bug; the rest
are behaviour/API gaps that force consumers to reach around the component.
1. Peek overlay is transparent under variant="inset"
Summary
When a Sidebar uses variant="inset" together with peekOnHover, the peek
overlay renders with a transparent background. Because peek lifts the sidebar
above the page content (shadow + z-index), the content behind it shows
straight through, making the nav unreadable.
The same feature works correctly on variant="floating" and variant="plain",
where the sidebar keeps an opaque background — so this looks like the inset
case was missed in the peek path.
Reproduction
<Sidebar variant="inset" collapsible="hidden" peekOnHover defaultOpen>
<Sidebar.Header>…</Sidebar.Header>
<Sidebar.Main>
<Sidebar.Item leadingIcon={<Home />}>Home</Sidebar.Item>
{/* …more items… */}
</Sidebar.Main>
</Sidebar>
- Collapse the sidebar (it hides).
- Hover the collapsed edge to trigger the peek.
- The revealed sidebar is transparent — page content is visible through it.
Happens with collapsible="icon" too; inset is the deciding factor.
Root cause
In the compiled sidebar CSS:
- Base rule sets an opaque background:
[data-slot="sidebar"] { background: var(--rs-color-background-base-primary) } insetoverrides it to transparent (correct while docked):
[data-variant="inset"] { background: transparent }- The peek rule adds elevation but never restores a background:
[data-peeking] { box-shadow: var(--rs-shadow-lifted); z-index: …; width: … }
floating never zeroes the background, so its peek stays opaque — hence the
inconsistency.
Suggested fix
Give the peeking overlay an opaque background in the peek rule, independent of
variant:
[data-peeking] {
background: var(--rs-color-background-base-primary);
}
2. prefers-reduced-motion not honored for the sidebar's own transitions
Apsara already gates dialog, accordion, and announcement-bar transitions behind
@media (prefers-reduced-motion: no-preference), but the sidebar's
width / margin peek & collapse transition on the root is unconditional:
[data-slot="sidebar"] {
transition: width var(--rs-duration-normal) var(--rs-ease-out),
margin var(--rs-duration-normal) var(--rs-ease-out);
}
Users who request reduced motion still get the animated peek/collapse.
Suggested fix: wrap the root's transition in the same
prefers-reduced-motion: no-preference guard already used elsewhere in the
library, so it's consistent.
3. Cannot control the sidebar from outside its subtree
Sidebar.Trigger reads the internal useSidebar() context, so it only works
inside <Sidebar>. There's no supported way to toggle the sidebar from
elsewhere in the app — e.g. a top bar, breadcrumb row, or header rendered
outside the sidebar tree.
Consumers who want an external toggle must lift open / onOpenChange into
their own state and re-implement the control, duplicating what the sidebar
already manages.
Suggested options (any one):
- An imperative handle via
ref(sidebarRef.current.toggle()/open()/
close()). - A standalone trigger that targets a sidebar by
id. - Documenting
open/onOpenChangeas the supported pattern for external
control (if that's the intended answer).
4. Peek state (isPeeking) is not exposed to the parent
isPeeking is available on the context via useSidebar(), but only to
descendants inside the sidebar. A parent can't react to a peek starting or
ending — e.g. to render a backdrop, coordinate other UI, or fire analytics.
Today the only way to observe a peek from outside is a CSS
:has([data-peeking]) hack.
Suggested fix: add an onPeekChange(isPeeking: boolean) callback prop,
mirroring onOpenChange.
5. No backdrop option for peekOnHover
When peeking, the sidebar floats above the content with only a shadow. There's
no built-in way to dim or scrim the app behind the peek — a common pattern for
hover-drawers, and it helps the floating panel read as a distinct layer.
Suggested fix: an opt-in peekBackdrop (boolean, or a slot) that renders a
backdrop behind the peeking sidebar. Consumers style the look (color/blur);
Apsara owns the show/hide wiring, which it's uniquely able to tie to the
internal peek state.
- Ngôn ngữ chính
- TypeScript
- Star
- 69
- Fork
- 13
- Merge trung bình
- 3 ngày 15 giờ
- Pull request đã merge (30 ngày)
- 24
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của raystack/apsara
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 2 ngày
-
DataView: don't offer select/multiselect filters with empty filterOptionsCó thể đã có người làm @rohanchkrabrty đã nhận 5 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 2 ngày
Tất cả issue của raystack/apsara
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
cockpit-project/cockpit-machines#2835 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
cloudflare/kumo#866 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area:connector bug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày
-
environment: OPENCODE_API_KEY is described as a Console service account key, but a Go subscription key worksCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
tester-army/e2e#1015 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Maintainer thường phản hồi trong vòng 1 ngày