patternfly-react
patternfly-react copied to clipboard
Page, tabs, topology enhancements
Is this a new component or an extension of an existing one? Page, tabs, typology
Describe the feature To
Paste this snippet in code editor
- Shouldn't need to add various wrappers here
- Need access to
page-mainin React
import * as React from 'react';
// eslint-disable-next-line patternfly-react/import-tokens-icons
import { RegionsIcon as Icon1 } from '@patternfly/react-icons';
// eslint-disable-next-line patternfly-react/import-tokens-icons
import { FolderOpenIcon as Icon2 } from '@patternfly/react-icons';
import { Tabs, Tab, TabTitleText, Page, PageSection, Stack, StackItem } from '@patternfly/react-core';
import {
ColaLayout,
DefaultEdge,
DefaultGroup,
DefaultNode,
EdgeStyle,
GraphComponent,
ModelKind,
NodeModel,
NodeShape,
SELECTION_EVENT,
TopologySideBar,
TopologyView,
Visualization,
VisualizationProvider,
VisualizationSurface,
withSelection,
WithSelectionProps
} from '@patternfly/react-topology';
import { ComponentFactory, Graph, Layout, LayoutFactory, Model, Node, NodeStatus } from '@patternfly/react-topology';
interface CustomNodeProps {
element: Node;
}
const BadgeColors = [
{
name: 'A',
badgeColor: '#ace12e',
badgeTextColor: '#0f280d',
badgeBorderColor: '#486b00'
},
{
name: 'B',
badgeColor: '#F2F0FC',
badgeTextColor: '#5752d1',
badgeBorderColor: '#CBC1FF'
}
];
const CustomNode: React.FC<CustomNodeProps & WithSelectionProps> = ({ element, onSelect, selected }) => {
const data = element.getData();
const Icon = data.isAlternate ? Icon2 : Icon1;
const badgeColors = BadgeColors.find(badgeColor => badgeColor.name === data.badge);
return (
<DefaultNode
element={element}
showStatusDecorator
badge={data.badge}
badgeColor={badgeColors?.badgeColor}
badgeTextColor={badgeColors?.badgeTextColor}
badgeBorderColor={badgeColors?.badgeBorderColor}
onSelect={onSelect}
selected={selected}
>
<g transform={`translate(25, 25)`}>
<Icon style={{ color: '#393F44' }} width={25} height={25} />
</g>
</DefaultNode>
);
};
const customLayoutFactory: LayoutFactory = (type: string, graph: Graph): Layout | undefined => {
switch (type) {
case 'Cola':
return new ColaLayout(graph);
default:
return new ColaLayout(graph, { layoutOnDrag: false });
}
};
const customComponentFactory: ComponentFactory = (kind: ModelKind, type: string) => {
switch (type) {
case 'group':
return DefaultGroup;
default:
switch (kind) {
case ModelKind.graph:
return GraphComponent;
case ModelKind.node:
return withSelection()(CustomNode);
case ModelKind.edge:
return withSelection()(DefaultEdge);
default:
return undefined;
}
}
};
const NODE_DIAMETER = 75;
const NODES: NodeModel[] = [
{
id: 'node-0',
type: 'node',
label: 'Node 0',
width: NODE_DIAMETER,
height: NODE_DIAMETER,
shape: NodeShape.ellipse,
status: NodeStatus.danger,
data: {
badge: 'B',
isAlternate: false
}
},
{
id: 'node-1',
type: 'node',
label: 'Node 1',
width: NODE_DIAMETER,
height: NODE_DIAMETER,
shape: NodeShape.hexagon,
status: NodeStatus.warning,
data: {
badge: 'B',
isAlternate: false
}
},
{
id: 'node-2',
type: 'node',
label: 'Node 2',
width: NODE_DIAMETER,
height: NODE_DIAMETER,
shape: NodeShape.octagon,
status: NodeStatus.success,
data: {
badge: 'A',
isAlternate: true
}
},
{
id: 'node-3',
type: 'node',
label: 'Node 3',
width: NODE_DIAMETER,
height: NODE_DIAMETER,
shape: NodeShape.rhombus,
status: NodeStatus.info,
data: {
badge: 'A',
isAlternate: false
}
},
{
id: 'node-4',
type: 'node',
label: 'Node 4',
width: NODE_DIAMETER,
height: NODE_DIAMETER,
shape: NodeShape.hexagon,
status: NodeStatus.default,
data: {
badge: 'C',
isAlternate: false
}
},
{
id: 'node-5',
type: 'node',
label: 'Node 5',
width: NODE_DIAMETER,
height: NODE_DIAMETER,
shape: NodeShape.rect,
data: {
badge: 'C',
isAlternate: true
}
},
{
id: 'Group-1',
children: ['node-0', 'node-1', 'node-2'],
type: 'group',
group: true,
label: 'Group-1',
style: {
padding: 40
}
}
];
const EDGES = [
{
id: 'edge-node-4-node-5',
type: 'edge',
source: 'node-4',
target: 'node-5',
edgeStyle: EdgeStyle.default
},
{
id: 'edge-node-0-node-2',
type: 'edge',
source: 'node-0',
target: 'node-2',
edgeStyle: EdgeStyle.default
}
];
export const TopologySidebarDemo: React.FC = () => {
const [activeTabKey, setActiveTabKey] = React.useState<string | number>(0);
const [selectedIds, setSelectedIds] = React.useState<string[]>([]);
// Toggle currently active tab
const handleTabClick = (
event: React.MouseEvent<any> | React.KeyboardEvent | MouseEvent,
tabIndex: string | number
) => {
setActiveTabKey(tabIndex);
};
const controller = React.useMemo(() => {
const model: Model = {
nodes: NODES,
edges: EDGES,
graph: {
id: 'g1',
type: 'graph',
layout: 'Cola'
}
};
const newController = new Visualization();
newController.registerLayoutFactory(customLayoutFactory);
newController.registerComponentFactory(customComponentFactory);
newController.addEventListener(SELECTION_EVENT, setSelectedIds);
newController.fromModel(model, false);
return newController;
}, []);
const topologySideBar = (
<TopologySideBar
className="topology-example-sidebar"
show={selectedIds.length > 0}
onClose={() => setSelectedIds([])}
>
<div style={{ marginTop: 27, marginLeft: 20, height: '800px' }}>{selectedIds[0]}</div>
</TopologySideBar>
);
return (
<Page>
<PageSection variant={PageSectionVariants.light}>
<Stack>
<PageSection type="tabs">
<Tabs
activeKey={activeTabKey}
onSelect={handleTabClick}
aria-label="Tabs in the default example"
role="region"
>
<Tab eventKey={0} title={<TabTitleText>Users</TabTitleText>} aria-label="Default content - users"></Tab>
<Tab eventKey={1} title={<TabTitleText>Containers</TabTitleText>}>Containers</Tab>
</Tabs>
</PageSection>
<PageSection padding={{ default: 'noPadding' }}>
<TabContent key={0} eventKey={0} id={`tabContent${0}`} activeKey={activeTabKey} hidden={0 !== activeTabKey} style={{height: "100%"}}>
<TopologyView sideBar={topologySideBar}>
<VisualizationProvider controller={controller}>
<VisualizationSurface state={{ selectedIds }} />
</VisualizationProvider>
</TopologyView>
</TabContent>
</PageSection>
</Stack>
</PageSection>
</Page>
);
};
cc @nicolethoen
Are there visuals for this feature? If applicable, please include examples for each state and for varying widths Include screenshots or links to Marvel or other mockups.
Any other information?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.