Compare commits

...

3 Commits

Author SHA1 Message Date
hsiegeln
4b873194c9 fix(ci): add --allow-same-version to npm version in publish workflow
All checks were successful
Build & Publish / publish (push) Successful in 51s
The tag push job fails with "Version not changed" when package.json
already has the correct version from the bump commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:05:08 +01:00
hsiegeln
5f1b039056 chore: bump version to 0.1.6
Some checks failed
Build & Publish / publish (push) Failing after 50s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:01:53 +01:00
hsiegeln
095abe1751 feat: self-portaling DetailPanel via AppShell portal target
Some checks failed
Build & Publish / publish (push) Failing after 50s
DetailPanel now uses createPortal to render itself into
#cameleer-detail-panel-root, a div that AppShell places as a
direct sibling of .main in the top-level flex row. This means
pages can render <DetailPanel> anywhere in their JSX and it
automatically appears at the correct layout position.

AppShell's detail prop is deprecated and ignored — the portal
handles positioning automatically.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:58:06 +01:00
5 changed files with 13 additions and 7 deletions

View File

@@ -28,7 +28,7 @@ jobs:
case "$GITHUB_REF" in case "$GITHUB_REF" in
refs/tags/v*) refs/tags/v*)
VERSION="${GITHUB_REF_NAME#v}" VERSION="${GITHUB_REF_NAME#v}"
npm version "$VERSION" --no-git-tag-version npm version "$VERSION" --no-git-tag-version --allow-same-version
TAG="latest" TAG="latest"
;; ;;
*) *)

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@cameleer/design-system", "name": "@cameleer/design-system",
"version": "0.1.3", "version": "0.1.6",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@cameleer/design-system", "name": "@cameleer/design-system",
"version": "0.1.3", "version": "0.1.6",
"dependencies": { "dependencies": {
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@cameleer/design-system", "name": "@cameleer/design-system",
"version": "0.1.3", "version": "0.1.6",
"type": "module", "type": "module",
"main": "./dist/index.es.js", "main": "./dist/index.es.js",
"module": "./dist/index.es.js", "module": "./dist/index.es.js",

View File

@@ -1,4 +1,5 @@
import { useState, type ReactNode } from 'react' import { useState, type ReactNode } from 'react'
import { createPortal } from 'react-dom'
import styles from './DetailPanel.module.css' import styles from './DetailPanel.module.css'
interface Tab { interface Tab {
@@ -22,7 +23,7 @@ export function DetailPanel({ open, onClose, title, tabs, children, actions, cla
const activeContent = tabs?.find((t) => t.value === activeTab)?.content const activeContent = tabs?.find((t) => t.value === activeTab)?.content
return ( const panel = (
<aside <aside
className={`${styles.panel} ${open ? styles.open : ''} ${className ?? ''}`} className={`${styles.panel} ${open ? styles.open : ''} ${className ?? ''}`}
aria-hidden={!open} aria-hidden={!open}
@@ -65,4 +66,8 @@ export function DetailPanel({ open, onClose, title, tabs, children, actions, cla
)} )}
</aside> </aside>
) )
// Portal to AppShell level if target exists, otherwise render in place
const portalTarget = document.getElementById('cameleer-detail-panel-root')
return portalTarget ? createPortal(panel, portalTarget) : panel
} }

View File

@@ -4,17 +4,18 @@ import type { ReactNode } from 'react'
interface AppShellProps { interface AppShellProps {
sidebar: ReactNode sidebar: ReactNode
children: ReactNode children: ReactNode
/** @deprecated DetailPanel now portals itself automatically. This prop is ignored. */
detail?: ReactNode detail?: ReactNode
} }
export function AppShell({ sidebar, children, detail }: AppShellProps) { export function AppShell({ sidebar, children }: AppShellProps) {
return ( return (
<div className={styles.app}> <div className={styles.app}>
{sidebar} {sidebar}
<div className={styles.main}> <div className={styles.main}>
{children} {children}
</div> </div>
{detail} <div id="cameleer-detail-panel-root" />
</div> </div>
) )
} }