sh-ui-cli 0.82.2 → 0.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/changelog/versions.json +22 -0
- package/data/registry/react/components/sidebar/index.tailwind.tsx +24 -0
- package/data/registry/react/components/sidebar/styles.css +30 -0
- package/data/registry/react/components/sidebar/styles.module.css +16 -0
- package/package.json +1 -1
- package/templates/nextjs-app/package.json +1 -2
- package/templates/nextjs-standalone/package.json +1 -2
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$description": "sh-ui 릴리즈 노트 단일 소스. docs(React)와 showcase(Flutter)가 함께 읽는다. 새 릴리즈마다 맨 앞에 추가.",
|
|
4
4
|
"versions": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.83.0",
|
|
7
|
+
"date": "2026-05-13",
|
|
8
|
+
"title": "Sidebar — data-when-collapsed 컨벤션 (custom JSX 의 collapsed/icon 자동 적응)",
|
|
9
|
+
"type": "minor",
|
|
10
|
+
"highlights": [
|
|
11
|
+
"**`<SidebarHeader>` / `<SidebarFooter>` 안 사용자 custom JSX 가 `collapsible=\"icon\"` 모드 전환 시 `useSidebar()` 훅 + 조건부 렌더 ceremony 없이 attribute 한 줄로 자동 적응** — 새 export 0개, 발견성 좋은 plain CSS 컨벤션. 값 (공백 구분 다중 토큰, `~=` 매처): `hide` (display:none) · `center` (가운데 정렬 + 좌우 padding 제거) · `strip-chrome` (border / background 투명). 워크스페이스 스위처 · 브랜드 카드 · 유저 프로필 등 admin/dashboard sidebar 의 흔한 패턴에 매번 박던 수동 처리 일소.",
|
|
12
|
+
"예시 — `<button data-when-collapsed=\"center strip-chrome\"> <Avatar /> <div data-when-collapsed=\"hide\">{name}</div> <ChevronsUpDown data-when-collapsed=\"hide\" /></button>` — collapsed 모드에선 Avatar 만 가운데 정렬돼 보이고 카드 chrome 사라짐.",
|
|
13
|
+
"**3 변종 모두 지원** — plain `styles.css` / module `styles.module.css` 에 직접 룰. tailwind 변종은 CSS import 없어 `SidebarProvider` mount 시 1회 head 에 `<style id=\"sh-ui-sidebar-helpers\">` inject (모듈 레벨 dedup). 사용자 코드는 변종 무관 동일 attribute 만 박으면 됨."
|
|
14
|
+
],
|
|
15
|
+
"url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.83.0"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"version": "0.82.3",
|
|
19
|
+
"date": "2026-05-13",
|
|
20
|
+
"title": "스캐폴드 dependencies 에서 미사용 zustand 제거",
|
|
21
|
+
"type": "patch",
|
|
22
|
+
"highlights": [
|
|
23
|
+
"**`nextjs-app` / `nextjs-standalone` 템플릿의 `dependencies` 에서 `zustand@^5.0.11` 제거** — 두 템플릿에 박혀 있었지만 어디서도 import / store 정의 없이 dep 만 설치되던 노이즈. 필요할 때 사용자가 `pnpm add zustand` 한 줄로 추가. 번들 영향은 처음부터 없었지만 (tree-shaken) `pnpm install` 시간 / lockfile / dep 표면적이 줄어듦."
|
|
24
|
+
],
|
|
25
|
+
"url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.82.3"
|
|
26
|
+
},
|
|
5
27
|
{
|
|
6
28
|
"version": "0.82.2",
|
|
7
29
|
"date": "2026-05-13",
|
|
@@ -10,6 +10,29 @@ const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
|
10
10
|
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
11
11
|
const MOBILE_BREAKPOINT = 768;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* v0.83.0+ — `data-when-collapsed` 컨벤션을 위한 CSS 룰 inject.
|
|
15
|
+
*
|
|
16
|
+
* plain/module 변종은 styles.css/.module.css 가 import 되며 자동으로 룰이 깔리는데,
|
|
17
|
+
* tailwind 변종은 별도 CSS import 가 없으므로 SidebarProvider mount 시 한 번만 head
|
|
18
|
+
* 에 <style> 박는다. id="sh-ui-sidebar-helpers" 로 중복 inject 방지.
|
|
19
|
+
*
|
|
20
|
+
* 토큰: hide(display:none) · center(가운데 정렬 + 좌우 padding 0) · strip-chrome
|
|
21
|
+
* (border/bg 투명). `~=` 매처로 공백 구분 다중 토큰 지원.
|
|
22
|
+
*/
|
|
23
|
+
const SIDEBAR_HELPER_STYLE_ID = "sh-ui-sidebar-helpers";
|
|
24
|
+
const SIDEBAR_HELPER_CSS = `[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="hide"]{display:none}[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="center"]{justify-content:center;padding-left:0;padding-right:0}[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="strip-chrome"]{border-color:transparent;background-color:transparent}`;
|
|
25
|
+
function useSidebarHelperStyles() {
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
if (typeof document === "undefined") return;
|
|
28
|
+
if (document.getElementById(SIDEBAR_HELPER_STYLE_ID)) return;
|
|
29
|
+
const style = document.createElement("style");
|
|
30
|
+
style.id = SIDEBAR_HELPER_STYLE_ID;
|
|
31
|
+
style.textContent = SIDEBAR_HELPER_CSS;
|
|
32
|
+
document.head.appendChild(style);
|
|
33
|
+
}, []);
|
|
34
|
+
}
|
|
35
|
+
|
|
13
36
|
const FOCUSABLE_SELECTOR =
|
|
14
37
|
'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
15
38
|
|
|
@@ -77,6 +100,7 @@ export interface SidebarProviderProps extends React.HTMLAttributes<HTMLDivElemen
|
|
|
77
100
|
export function SidebarProvider({
|
|
78
101
|
defaultOpen = true, open: openProp, onOpenChange: setOpenProp, className, style, children, embedded, ...props
|
|
79
102
|
}: SidebarProviderProps) {
|
|
103
|
+
useSidebarHelperStyles();
|
|
80
104
|
const isMobile = useIsMobile();
|
|
81
105
|
const [openMobile, setOpenMobile] = React.useState(false);
|
|
82
106
|
const [_open, _setOpen] = React.useState(defaultOpen);
|
|
@@ -288,6 +288,36 @@
|
|
|
288
288
|
border-bottom: 1px solid var(--sidebar-border);
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
/* ───────────── data-when-collapsed 컨벤션 (v0.83.0+) ─────────────
|
|
292
|
+
* SidebarHeader / SidebarFooter 안의 사용자 custom JSX (WorkspaceSwitcher,
|
|
293
|
+
* 브랜드 카드, 유저 프로필 등) 가 collapsible="icon" 모드 전환 시 자동
|
|
294
|
+
* 적응하도록 일반 attribute 컨벤션 제공. 사용자가 useSidebar() 훅 + 조건부
|
|
295
|
+
* 렌더 ceremony 없이 attribute 한 줄로 처리.
|
|
296
|
+
*
|
|
297
|
+
* 사용:
|
|
298
|
+
* <button data-when-collapsed="center strip-chrome">
|
|
299
|
+
* <Avatar />
|
|
300
|
+
* <div data-when-collapsed="hide">{name}</div>
|
|
301
|
+
* <ChevronsUpDown data-when-collapsed="hide" />
|
|
302
|
+
* </button>
|
|
303
|
+
*
|
|
304
|
+
* 값(공백 구분 토큰 — `~=` 매처):
|
|
305
|
+
* hide — collapsed/icon 모드에서 display:none
|
|
306
|
+
* center — 가로 가운데 정렬 + 좌우 padding 제거
|
|
307
|
+
* strip-chrome — border / background 투명화 (카드 chrome 제거) */
|
|
308
|
+
.sh-ui-sidebar[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="hide"] {
|
|
309
|
+
display: none;
|
|
310
|
+
}
|
|
311
|
+
.sh-ui-sidebar[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="center"] {
|
|
312
|
+
justify-content: center;
|
|
313
|
+
padding-left: 0;
|
|
314
|
+
padding-right: 0;
|
|
315
|
+
}
|
|
316
|
+
.sh-ui-sidebar[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="strip-chrome"] {
|
|
317
|
+
border-color: transparent;
|
|
318
|
+
background-color: transparent;
|
|
319
|
+
}
|
|
320
|
+
|
|
291
321
|
.sh-ui-sidebar__content {
|
|
292
322
|
display: flex;
|
|
293
323
|
flex-direction: column;
|
|
@@ -285,6 +285,22 @@
|
|
|
285
285
|
border-bottom: 1px solid var(--sidebar-border);
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
/* data-when-collapsed 컨벤션 (v0.83.0+) — 사용자 custom JSX (WorkspaceSwitcher 등) 가
|
|
289
|
+
* collapsible="icon" 모드 전환 시 자동 적응. 값: hide / center / strip-chrome.
|
|
290
|
+
* 자세한 설명은 plain 변종 styles.css 참고. */
|
|
291
|
+
.sidebar[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="hide"] {
|
|
292
|
+
display: none;
|
|
293
|
+
}
|
|
294
|
+
.sidebar[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="center"] {
|
|
295
|
+
justify-content: center;
|
|
296
|
+
padding-left: 0;
|
|
297
|
+
padding-right: 0;
|
|
298
|
+
}
|
|
299
|
+
.sidebar[data-state="collapsed"][data-collapsible="icon"] [data-when-collapsed~="strip-chrome"] {
|
|
300
|
+
border-color: transparent;
|
|
301
|
+
background-color: transparent;
|
|
302
|
+
}
|
|
303
|
+
|
|
288
304
|
.sidebar__content {
|
|
289
305
|
display: flex;
|
|
290
306
|
flex-direction: column;
|
package/package.json
CHANGED