From e88dfb9d80a67e7fbff7285d6046a4839d4e43c0 Mon Sep 17 00:00:00 2001 From: debsmita1 Date: Tue, 7 Jan 2025 17:10:13 +0530 Subject: [PATCH] feat(fab): update fab content --- .../.changeset/thick-wolves-attack.md | 5 + .../packages/app/src/components/Root/Root.tsx | 26 ++++- .../global-floating-action-button/README.md | 6 +- .../dev/ExampleComponent/ExampleComponent.tsx | 12 +- .../ExampleFetchComponent.tsx | 2 +- .../dev/index.tsx | 2 +- .../report.api.md | 4 +- .../src/components/FAB.test.tsx | 80 +++++++++++++ .../src/components/FAB.tsx | 110 +++++++++++++++--- .../src/components/FABWithSubmenu.test.tsx | 86 ++++++++++++++ .../src/components/FABWithSubmenu.tsx | 75 ++++++++---- .../src/components/FabIcon.tsx | 2 +- .../src/components/FloatingButton.test.tsx | 12 +- .../src/components/FloatingButton.tsx | 23 ++-- .../components/GlobalFloatingActionButton.tsx | 2 +- .../src/components/index.ts | 2 +- .../src/index.ts | 2 +- .../src/plugin.test.ts | 2 +- .../src/plugin.ts | 3 +- .../src/setupTests.ts | 2 +- .../src/types.ts | 6 +- .../src/utils.test.ts | 20 ++-- .../src/utils.ts | 15 ++- 23 files changed, 401 insertions(+), 98 deletions(-) create mode 100644 workspaces/global-floating-action-button/.changeset/thick-wolves-attack.md create mode 100644 workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FAB.test.tsx create mode 100644 workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FABWithSubmenu.test.tsx diff --git a/workspaces/global-floating-action-button/.changeset/thick-wolves-attack.md b/workspaces/global-floating-action-button/.changeset/thick-wolves-attack.md new file mode 100644 index 000000000..04f1a872b --- /dev/null +++ b/workspaces/global-floating-action-button/.changeset/thick-wolves-attack.md @@ -0,0 +1,5 @@ +--- +'@red-hat-developer-hub/backstage-plugin-global-floating-action-button': patch +--- + +update fab content diff --git a/workspaces/global-floating-action-button/packages/app/src/components/Root/Root.tsx b/workspaces/global-floating-action-button/packages/app/src/components/Root/Root.tsx index 989e08909..cba51d246 100644 --- a/workspaces/global-floating-action-button/packages/app/src/components/Root/Root.tsx +++ b/workspaces/global-floating-action-button/packages/app/src/components/Root/Root.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { GitHubIcon, Link, @@ -96,14 +97,21 @@ export const Root = ({ children }: PropsWithChildren<{}>) => { to: '/create', }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, icon: , + label: 'Api Docs', + toolTip: 'Api Docs', + to: '/api-docs', + }, + { + slot: Slot.BOTTOM_LEFT, + icon: , + showLabel: true, label: 'Docs', toolTip: 'Docs', to: '/docs', }, { - color: 'success', icon: , label: 'Search', toolTip: 'Search', @@ -111,13 +119,21 @@ export const Root = ({ children }: PropsWithChildren<{}>) => { }, { color: 'success', - showLabel: true, icon: , - label: 'RHDH plugins', + label: 'RHDH pluginsssssssssssssss', + showLabel: true, toolTip: 'RHDH plugins', to: 'https://github.com/redhat-developer/rhdh-plugins', visibleOnPaths: ['/catalog'], }, + { + color: 'success', + icon: , + label: 'RHDH pluginsssssssssssssss', + toolTip: 'External link', + to: 'https://github.com/redhat-developer/rhdh-plugins', + visibleOnPaths: ['/catalog'], + }, { color: 'success', icon: , diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/README.md b/workspaces/global-floating-action-button/plugins/global-floating-action-button/README.md index 9063d2a50..15d2acf12 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/README.md +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/README.md @@ -40,7 +40,7 @@ This plugin has been added to the example app in this workspace, meaning it can to: '/create', }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, icon: , label: 'Docs', toolTip: 'Docs', @@ -57,9 +57,9 @@ This plugin has been added to the example app in this workspace, meaning it can | Name | Type | Description | Notes | | ------------------ | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -| **slot** | `enum` | The position where the fab will be placed. Valid values: `PAGE_END`, `BOTTOM_CENTER`. | [optional] default to `PAGE_END`. | +| **slot** | `enum` | The position where the fab will be placed. Valid values: `PAGE_END`, `BOTTOM_LEFT`. | [optional] default to `PAGE_END`. | | **label** | `String` | A name for your action button. | required | -| **icon** | `String`
`React.ReactElement` | An icon for your floating button. | optional | +| **icon** | `String`
`React.ReactElement` | An icon for your floating button. Recommended to use **filled** icons from the [Material Design library](https://fonts.google.com/icons) | required | | **showLabel** | `Boolean` | To display the label next to your icon. | optional | | **size** | `'small'`
`'medium'`
`'large'` | A name for your action button. | [optional] default to `'medium'` | | **color** | `'default'`
`'error'`
`'info'`
`'inherit'`
`'primary'`
`'secondary'`
`'success'`
`'warning'` | The color of the component. It supports both default and custom theme colors, which can be added as shown in the [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors). | [optional] default to `'default'`. | diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/ExampleComponent/ExampleComponent.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/ExampleComponent/ExampleComponent.tsx index 1374666c6..6cb0da340 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/ExampleComponent/ExampleComponent.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/ExampleComponent/ExampleComponent.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import { ContentHeader, HeaderLabel, SupportButton, + GitHubIcon, } from '@backstage/core-components'; import { ExampleFetchComponent } from './ExampleFetchComponent'; import { GlobalFloatingActionButton, Slot } from '../../src'; @@ -77,7 +78,7 @@ export const ExampleComponent = () => ( icon: '', }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: , label: 'Add', @@ -86,10 +87,11 @@ export const ExampleComponent = () => ( priority: 100, }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', - label: 'Menu', - toolTip: 'Menu', + label: 'Github', + icon: , + toolTip: 'Github', to: 'https://github.com/xyz', priority: 200, visibleOnPaths: ['/test-global-floating-action'], diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/ExampleComponent/ExampleFetchComponent.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/ExampleComponent/ExampleFetchComponent.tsx index b9e1530c4..1b524a7ce 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/ExampleComponent/ExampleFetchComponent.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/ExampleComponent/ExampleFetchComponent.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/index.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/index.tsx index cbf157340..884299598 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/index.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/dev/index.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/report.api.md b/workspaces/global-floating-action-button/plugins/global-floating-action-button/report.api.md index cea8b54dc..dff798667 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/report.api.md +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/report.api.md @@ -13,7 +13,7 @@ export type FloatingActionButton = { slot?: Slot; label: string; showLabel?: boolean; - icon?: string | React.ReactElement; + icon: string | React.ReactElement; size?: 'small' | 'medium' | 'large'; color?: | 'default' @@ -50,7 +50,7 @@ export const globalFloatingActionButtonPlugin: BackstagePlugin<{}, {}, {}>; // @public export enum Slot { - BOTTOM_CENTER = 'bottom-center', + BOTTOM_LEFT = 'bottom-left', PAGE_END = 'page-end', } diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FAB.test.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FAB.test.tsx new file mode 100644 index 000000000..16ba8c6e8 --- /dev/null +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FAB.test.tsx @@ -0,0 +1,80 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { render, screen } from '@testing-library/react'; +import GitIcon from '@mui/icons-material/GitHub'; +import * as React from 'react'; +import { FAB } from './FAB'; + +jest.mock('react-router-dom', () => ({ + useNavigate: jest.fn(), + useLocation: jest.fn(() => ({ + pathname: '/test-path', + })), +})); + +jest.mock('@backstage/core-plugin-api', () => ({ + useApp: jest.fn(() => ({ + getSystemIcon: jest.fn(), + })), + usetheme: jest.fn(() => ({ + theme: { + transitions: { + easing: { + easeOut: 'eo', + sharp: 's', + }, + }, + }, + })), +})); + +describe('Floating Action Button', () => { + it('should render the floating action button with icon and label', () => { + render( + , + label: 'Git repo', + showLabel: true, + to: 'https://github.com/xyz', + toolTip: 'Git', + }} + />, + ); + expect(screen.getByTestId('git-repo')).toBeInTheDocument(); + expect(screen.getByTestId('GitHubIcon')).toBeInTheDocument(); + expect(screen.getByText('Git repo')).toBeInTheDocument(); + expect(screen.getByTestId('OpenInNewIcon')).toBeInTheDocument(); + }); + + it('should render the floating action button with icon', () => { + render( + , + label: 'Git repo', + to: 'https://github.com/xyz', + toolTip: 'Git', + }} + />, + ); + expect(screen.getByTestId('git-repo')).toBeInTheDocument(); + expect(screen.getByTestId('GitHubIcon')).toBeInTheDocument(); + expect(screen.queryByText('Git repo')).not.toBeInTheDocument(); + }); +}); diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FAB.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FAB.tsx index 9eb083db7..d2db131f3 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FAB.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FAB.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,50 +16,126 @@ import * as React from 'react'; import { useNavigate } from 'react-router-dom'; +import { makeStyles } from '@mui/styles'; import Fab from '@mui/material/Fab'; import Tooltip from '@mui/material/Tooltip'; import Typography from '@mui/material/Typography'; +import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import { FabIcon } from './FabIcon'; import { FloatingActionButton, Slot } from '../types'; +import { slotOptions } from '../utils'; + +const useStyles = makeStyles(() => ({ + openInNew: { paddingBottom: '5px', paddingTop: '3px' }, +})); + +const FABLabel = ({ + label, + slot, + showExternalIcon, + icon, + order, +}: { + label: string; + slot: Slot; + showExternalIcon: boolean; + icon: string | React.ReactElement; + order: { externalIcon?: number; icon?: number }; +}) => { + const styles = useStyles(); + const marginStyle = slotOptions[slot].margin; + return ( + + {showExternalIcon && ( + + )} + {label && ( + + {label} + + )} + + + + + ); +}; export const FAB = ({ actionButton, size, + className, }: { actionButton: FloatingActionButton; size?: 'small' | 'medium' | 'large'; + className?: string; }) => { const navigate = useNavigate(); const isExternalUri = (uri: string) => /^([a-z+.-]+):/.test(uri); - const external = isExternalUri(actionButton.to!); - const newWindow = external && !!/^https?:/.exec(actionButton.to!); + const isExternal = isExternalUri(actionButton.to!); + const newWindow = isExternal && !!/^https?:/.exec(actionButton.to!); const navigateTo = () => - actionButton.to && !external ? navigate(actionButton.to) : ''; + actionButton.to && !isExternal ? navigate(actionButton.to) : ''; + const labelText = + actionButton.label.length > 20 + ? `${actionButton.label.slice(0, actionButton.label.length)}...` + : actionButton.label; + const getColor = () => { + if (actionButton.color) { + return actionButton.color; + } + if (!className) { + return 'info'; + } + return undefined; + }; + + const displayOnRight = + actionButton.slot === Slot.PAGE_END || !actionButton.slot; + return ( -
+
- {actionButton.icon && } - {(actionButton.showLabel || !actionButton.icon) && ( - - {actionButton.label} - - )} +
diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FABWithSubmenu.test.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FABWithSubmenu.test.tsx new file mode 100644 index 000000000..67ef4f43c --- /dev/null +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FABWithSubmenu.test.tsx @@ -0,0 +1,86 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { fireEvent, render, screen } from '@testing-library/react'; +import GitIcon from '@mui/icons-material/GitHub'; +import SnowFlake from '@mui/icons-material/AcUnit'; +import * as React from 'react'; +import { Slot } from '../types'; +import { FABWithSubmenu } from './FABWithSubmenu'; + +jest.mock('react-router-dom', () => ({ + useNavigate: jest.fn(), + useLocation: jest.fn(() => ({ + pathname: '/test-path', + })), +})); + +jest.mock('@mui/styles', () => ({ + ...jest.requireActual('@mui/styles'), + makeStyles: () => () => { + return { + button: 'button', + }; + }, +})); + +jest.mock('@backstage/core-plugin-api', () => ({ + useApp: jest.fn(() => ({ + getSystemIcon: jest.fn(), + })), + usetheme: jest.fn(() => ({ + theme: { + transitions: { + easing: { + easeOut: 'eo', + sharp: 's', + }, + }, + }, + })), +})); + +describe('Floating Button with submenu', () => { + it('should render a floating button with submenu actions', () => { + render( + , + label: 'Git repo', + showLabel: true, + to: 'https://github.com/xyz', + toolTip: 'Git', + }, + { + color: 'success', + icon: , + label: 'Ac Unit', + to: 'https://github.com/xyz1', + toolTip: 'Ac Unit', + }, + ]} + />, + ); + expect(screen.getByTestId('fab-with-submenu')).toBeInTheDocument(); + expect(screen.getByTestId('MenuIcon')).toBeInTheDocument(); + const button = screen.getByTestId('MenuIcon'); + fireEvent.click(button); + expect(screen.getByText('Git repo')).toBeInTheDocument(); + expect(screen.getByTestId('AcUnitIcon')).toBeInTheDocument(); + }); +}); diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FABWithSubmenu.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FABWithSubmenu.tsx index 0b77195ba..a48256cf3 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FABWithSubmenu.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FABWithSubmenu.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,22 +16,35 @@ import * as React from 'react'; import { useLocation } from 'react-router-dom'; +import { makeStyles } from '@mui/styles'; import Fab from '@mui/material/Fab'; import Tooltip from '@mui/material/Tooltip'; import { useTheme } from '@mui/material/styles'; import CloseIcon from '@mui/icons-material/Close'; import MenuIcon from '@mui/icons-material/Menu'; -import Slide from '@mui/material/Slide'; -import { FloatingActionButton } from '../types'; +import Collapse from '@mui/material/Collapse'; import { FAB } from './FAB'; +import { slotOptions } from '../utils'; +import { FloatingActionButton, Slot } from '../types'; + +const useStyles = makeStyles(theme => ({ + button: { + paddingTop: '10px', + color: theme.palette.grey[500], + }, + menuButtonStyle: { + color: '#1f1f1f', + }, +})); export const FABWithSubmenu = ({ fabs, - ref, + slot, }: { fabs: FloatingActionButton[]; - ref: HTMLDivElement | null; + slot: Slot; }) => { + const styles = useStyles(); const theme = useTheme(); const { pathname } = useLocation(); const [isMenuOpen, setIsMenuOpen] = React.useState(false); @@ -43,36 +56,50 @@ export const FABWithSubmenu = ({ }, [pathname]); const handleClick = () => { - setIsMenuOpen(!isMenuOpen); + setIsMenuOpen(prev => !prev); }; return ( <> - + - {isMenuOpen ? : } + {isMenuOpen ? ( + + ) : ( + + )} - {isMenuOpen && ( - - <> - {fabs?.map(fb => { - return ; - })} - - - )} + + <> + {fabs?.map(fb => { + return ( + + ); + })} + + ); }; diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FabIcon.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FabIcon.tsx index dac805291..e504ac687 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FabIcon.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FabIcon.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FloatingButton.test.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FloatingButton.test.tsx index 884184773..df157b096 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FloatingButton.test.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FloatingButton.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,9 +38,9 @@ jest.mock('@mui/styles', () => ({ ...jest.requireActual('@mui/styles'), makeStyles: () => () => { return { - button: 'button', + fabContainer: 'fabContainer', 'page-end': 'page-end', - 'bottom-center': 'bottom-center', + 'bottom-left': 'bottom-left', }; }, })); @@ -57,7 +57,7 @@ describe('Floating Button', () => { toolTip: 'Main menu', }, ]} - slot={Slot.BOTTOM_CENTER} + slot={Slot.BOTTOM_LEFT} />, ); expect(screen.getByTestId('floating-button')).toBeInTheDocument(); @@ -76,7 +76,7 @@ describe('Floating Button', () => { toolTip: 'Git', }, ]} - slot={Slot.BOTTOM_CENTER} + slot={Slot.BOTTOM_LEFT} />, ); expect(screen.getByTestId('floating-button')).toBeInTheDocument(); @@ -104,7 +104,7 @@ describe('Floating Button', () => { toolTip: 'Ac Unit', }, ]} - slot={Slot.BOTTOM_CENTER} + slot={Slot.BOTTOM_LEFT} />, ); expect(screen.getByTestId('floating-button')).toBeInTheDocument(); diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FloatingButton.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FloatingButton.tsx index 790a12938..261800280 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FloatingButton.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/FloatingButton.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,22 +25,21 @@ import { FloatingActionButton, Slot } from '../types'; import { filterAndSortButtons } from '../utils'; const useStyles = makeStyles(theme => ({ - button: { + fabContainer: { zIndex: 200, display: 'flex', position: 'fixed', - maxWidth: '150px', gap: '10px', }, 'page-end': { - bottom: theme.spacing(4), - right: theme.spacing(4), + bottom: theme.spacing(2), + right: theme.spacing(2), alignItems: 'end', }, - 'bottom-center': { - bottom: theme.spacing(4), - left: '50%', - alignItems: 'center', + 'bottom-left': { + bottom: theme.spacing(2), + paddingLeft: theme.spacing(2), + alignItems: 'start', }, })); @@ -52,7 +51,6 @@ export const FloatingButton = ({ slot: Slot; }) => { const { pathname } = useLocation(); - const subMenuRef = React.useRef(null); const [subMenuDirection, setSubMenuDirection] = React.useState< 'column' | 'column-reverse' >('column'); @@ -81,16 +79,15 @@ export const FloatingButton = ({ } return (
{fabs.length > 1 ? ( - + ) : ( )} diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/GlobalFloatingActionButton.tsx b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/GlobalFloatingActionButton.tsx index 218f4037b..f5b5e1c70 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/GlobalFloatingActionButton.tsx +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/GlobalFloatingActionButton.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/index.ts b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/index.ts index 966b62c96..ab7450b12 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/index.ts +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/components/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/index.ts b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/index.ts index fd4367fbd..ad09eeaf8 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/index.ts +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/plugin.test.ts b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/plugin.test.ts index 85160ed81..954a9202f 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/plugin.test.ts +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/plugin.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/plugin.ts b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/plugin.ts index 2dc3789fb..231e9bf03 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/plugin.ts +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/plugin.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { createComponentExtension, createPlugin, diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/setupTests.ts b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/setupTests.ts index b57590b52..b529814c4 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/setupTests.ts +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/setupTests.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/types.ts b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/types.ts index b442ea348..bc4747a24 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/types.ts +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/types.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ export enum Slot { /** * Positions the floating action button at the bottom center of the page */ - BOTTOM_CENTER = 'bottom-center', + BOTTOM_LEFT = 'bottom-left', } /** @@ -39,7 +39,7 @@ export type FloatingActionButton = { slot?: Slot; label: string; showLabel?: boolean; - icon?: string | React.ReactElement; + icon: string | React.ReactElement; size?: 'small' | 'medium' | 'large'; color?: | 'default' diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/utils.test.ts b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/utils.test.ts index c838263b7..735dccd36 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/utils.test.ts +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/utils.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ const floatingButtons: FloatingActionButton[] = [ toolTip: 'Git', }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: 'GitIcon', label: 'Add', @@ -39,7 +39,7 @@ const floatingButtons: FloatingActionButton[] = [ priority: 100, }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: 'GitIcon', label: 'Menu', @@ -64,7 +64,7 @@ describe('Global floating action button utils', () => { const buttons = sortButtonsWithPriority(floatingButtons); expect(buttons).toEqual([ { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: 'GitIcon', label: 'Menu', @@ -84,7 +84,7 @@ describe('Global floating action button utils', () => { }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: 'GitIcon', label: 'Add', @@ -106,7 +106,7 @@ describe('Global floating action button utils', () => { const buttons = filterAndSortButtons(floatingButtons, '/test-pathname'); expect(buttons).toEqual([ { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: 'GitIcon', label: 'Menu', @@ -116,7 +116,7 @@ describe('Global floating action button utils', () => { visibleOnPaths: ['/test-pathname'], }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: 'GitIcon', label: 'Add', @@ -159,10 +159,10 @@ describe('Global floating action button utils', () => { ], }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, actions: [ { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: 'GitIcon', label: 'Add', @@ -171,7 +171,7 @@ describe('Global floating action button utils', () => { priority: 100, }, { - slot: Slot.BOTTOM_CENTER, + slot: Slot.BOTTOM_LEFT, color: 'success', icon: 'GitIcon', label: 'Menu', diff --git a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/utils.ts b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/utils.ts index 858646d4d..e44ecea4a 100644 --- a/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/utils.ts +++ b/workspaces/global-floating-action-button/plugins/global-floating-action-button/src/utils.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Backstage Authors + * Copyright Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,3 +73,16 @@ export const filterAndSortButtons = ( const sortedButtons = sortButtonsWithPriority(filteredButtons); return sortedButtons; }; + +export const slotOptions = { + [Slot.BOTTOM_LEFT]: { + tooltipDirection: 'right', + textAlign: 'left', + margin: { ml: 1 }, + }, + [Slot.PAGE_END]: { + tooltipDirection: 'left', + textAlign: 'right', + margin: { mr: 1 }, + }, +} as const;