panel fixes 4
All checks were successful
Deploy Nyla Frontend to Integration / deploy (push) Successful in 1m26s
All checks were successful
Deploy Nyla Frontend to Integration / deploy (push) Successful in 1m26s
This commit is contained in:
parent
0ad9006b94
commit
27abfde833
10 changed files with 90 additions and 20 deletions
|
|
@ -5,6 +5,18 @@
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: var(--bg-primary, #fff);
|
background: var(--bg-primary, #fff);
|
||||||
overflow: clip;
|
overflow: clip;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card regions in bounded flex hosts (sidebar, PanelLayout pane): body fills and scrolls. */
|
||||||
|
.panel[data-variant="card"] .body:not(.bodyHidden) {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Variant: table — fills available height, bounded scroll --- */
|
/* --- Variant: table — fills available height, bounded scroll --- */
|
||||||
|
|
@ -94,11 +106,14 @@
|
||||||
background: var(--bg-secondary, rgba(0, 0, 0, 0.02));
|
background: var(--bg-secondary, rgba(0, 0, 0, 0.02));
|
||||||
border-bottom: 1px solid var(--border-color, rgba(0, 0, 0, 0.08));
|
border-bottom: 1px solid var(--border-color, rgba(0, 0, 0, 0.08));
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.headerCollapsible {
|
.headerCollapsible {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
/* Reserve space so action icons never overlap the collapse chevron */
|
||||||
|
padding-right: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.headerCollapsible:hover {
|
.headerCollapsible:hover {
|
||||||
|
|
@ -128,15 +143,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
flex-shrink: 0;
|
flex-shrink: 1;
|
||||||
|
min-width: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stable chevron position: fixed at the right edge of the header, same spot
|
/* Collapse chevron: always rightmost, above action icons (never covered). */
|
||||||
whether collapsed or expanded. Icon swaps (down = open, right = collapsed). */
|
|
||||||
.chevron {
|
.chevron {
|
||||||
|
position: absolute;
|
||||||
|
right: 14px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -145,6 +165,8 @@
|
||||||
height: 16px;
|
height: 16px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--text-tertiary, #888);
|
color: var(--text-tertiary, #888);
|
||||||
|
z-index: 2;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
|
|
|
||||||
|
|
@ -75,12 +75,12 @@ export const Panel: FC<PanelProps> = ({
|
||||||
<span className={styles.title}>{title}</span>
|
<span className={styles.title}>{title}</span>
|
||||||
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
||||||
</div>
|
</div>
|
||||||
{actions && <div className={styles.actions} onClick={(e) => e.stopPropagation()}>{actions}</div>}
|
|
||||||
{collapsible && (
|
{collapsible && (
|
||||||
<span className={styles.chevron} aria-hidden>
|
<span className={styles.chevron} aria-hidden>
|
||||||
{collapsed ? <FaChevronRight /> : <FaChevronDown />}
|
{collapsed ? <FaChevronRight /> : <FaChevronDown />}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
{actions && <div className={styles.actions} onClick={(e) => e.stopPropagation()}>{actions}</div>}
|
||||||
</div>
|
</div>
|
||||||
<div className={`${styles.body} ${collapsed ? styles.bodyHidden : ''}`}>
|
<div className={`${styles.body} ${collapsed ? styles.bodyHidden : ''}`}>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,6 +102,9 @@
|
||||||
.tree {
|
.tree {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chatItem {
|
.chatItem {
|
||||||
|
|
|
||||||
22
src/components/UnifiedDataBar/SourcesTab.module.css
Normal file
22
src/components/UnifiedDataBar/SourcesTab.module.css
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
.sourcesTab {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.treeHost {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ import { createUdbSourcesProvider } from './UdbSourcesProvider';
|
||||||
import type { UdbBackendNode } from './UdbSourcesProvider';
|
import type { UdbBackendNode } from './UdbSourcesProvider';
|
||||||
import { DataSourceSettingsModal } from './DataSourceSettingsModal';
|
import { DataSourceSettingsModal } from './DataSourceSettingsModal';
|
||||||
import { useLanguage } from '../../providers/language/LanguageContext';
|
import { useLanguage } from '../../providers/language/LanguageContext';
|
||||||
|
import styles from './SourcesTab.module.css';
|
||||||
|
|
||||||
interface SourcesTabProps {
|
interface SourcesTabProps {
|
||||||
context: UdbContext;
|
context: UdbContext;
|
||||||
|
|
@ -84,15 +85,15 @@ const SourcesTab: React.FC<SourcesTabProps> = ({
|
||||||
|
|
||||||
if (!instanceId || !provider) {
|
if (!instanceId || !provider) {
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: 12, fontSize: 12, color: '#888' }}>
|
<div className={styles.empty}>
|
||||||
{t('Keine Workspace-Instanz aktiv.')}
|
{t('Keine Workspace-Instanz aktiv.')}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ height: '100%', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
|
<div className={styles.sourcesTab}>
|
||||||
<div style={{ flex: 1, overflow: 'auto', minHeight: 0 }}>
|
<div className={styles.treeHost}>
|
||||||
<FormGeneratorTree
|
<FormGeneratorTree
|
||||||
provider={provider}
|
provider={provider}
|
||||||
ownership="own"
|
ownership="own"
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@
|
||||||
.tabContent {
|
.tabContent {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow-y: auto;
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,7 @@ export const CommcoachSessionView: React.FC = () => {
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
collapseKey: 'commcoach-session-udb',
|
collapseKey: 'commcoach-session-udb',
|
||||||
content: (
|
content: (
|
||||||
<Panel variant="card" title={t('Datenquellen')} id="commcoach-session-data-sources">
|
<Panel variant="card" title={t('Datenquellen')} id="commcoach-session-data-sources" fill>
|
||||||
<UnifiedDataBar
|
<UnifiedDataBar
|
||||||
context={_udbContext}
|
context={_udbContext}
|
||||||
activeTab={udbTab}
|
activeTab={udbTab}
|
||||||
|
|
|
||||||
|
|
@ -1006,7 +1006,7 @@ export const TeamsbotSessionView: React.FC = () => {
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
collapseKey: 'teamsbot-session-udb',
|
collapseKey: 'teamsbot-session-udb',
|
||||||
content: (
|
content: (
|
||||||
<Panel variant="card" title={t('Datenquellen')} id="teamsbot-session-datasources">
|
<Panel variant="card" title={t('Datenquellen')} id="teamsbot-session-datasources" fill>
|
||||||
<UnifiedDataBar
|
<UnifiedDataBar
|
||||||
context={_udbContext}
|
context={_udbContext}
|
||||||
activeTab={udbTab}
|
activeTab={udbTab}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,19 @@ export const WorkspaceContextSidebar: React.FC<WorkspaceContextSidebarProps> = (
|
||||||
aria-label="Kontext"
|
aria-label="Kontext"
|
||||||
>
|
>
|
||||||
<div className={styles.contextToolbar}>
|
<div className={styles.contextToolbar}>
|
||||||
|
{allowCollapse && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.contextCollapseBtn}
|
||||||
|
onClick={onToggleCollapsed}
|
||||||
|
title={isCollapsed ? 'Kontext ausklappen' : 'Kontext einklappen'}
|
||||||
|
aria-expanded={!isCollapsed}
|
||||||
|
>
|
||||||
|
{isCollapsed ? <FaChevronRight aria-hidden /> : <FaChevronLeft aria-hidden />}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{!isCollapsed && (
|
||||||
|
<>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`${styles.contextToolBtn} ${activeTab === 'files' ? styles.contextToolBtnActive : ''}`}
|
className={`${styles.contextToolBtn} ${activeTab === 'files' ? styles.contextToolBtnActive : ''}`}
|
||||||
|
|
@ -104,16 +117,7 @@ export const WorkspaceContextSidebar: React.FC<WorkspaceContextSidebarProps> = (
|
||||||
<FaEye aria-hidden />
|
<FaEye aria-hidden />
|
||||||
</button>
|
</button>
|
||||||
<span className={styles.contextToolbarGrow} />
|
<span className={styles.contextToolbarGrow} />
|
||||||
{allowCollapse && (
|
</>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={styles.contextCollapseBtn}
|
|
||||||
onClick={onToggleCollapsed}
|
|
||||||
title={isCollapsed ? 'Kontext ausklappen' : 'Kontext einklappen'}
|
|
||||||
aria-expanded={!isCollapsed}
|
|
||||||
>
|
|
||||||
{isCollapsed ? <FaChevronRight aria-hidden /> : <FaChevronLeft aria-hidden />}
|
|
||||||
</button>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!isCollapsed && (
|
{!isCollapsed && (
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,20 @@
|
||||||
width: 44px;
|
width: 44px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.contextSidebarCollapsed .contextToolbar {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 6px 4px;
|
||||||
|
gap: 6px;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contextSidebarCollapsed .contextCollapseBtn {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
/* When hosted inside a PanelLayout pane, the sidebar fills the pane width so
|
/* When hosted inside a PanelLayout pane, the sidebar fills the pane width so
|
||||||
the divider controls its size (instead of the fixed 320px). */
|
the divider controls its size (instead of the fixed 320px). */
|
||||||
.contextSidebarFill {
|
.contextSidebarFill {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue