Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "openstack-uicore-foundation",
"version": "5.0.6",
"version": "5.0.7-beta.3",
"description": "ui reactjs components for openstack marketing site",
"main": "lib/openstack-uicore-foundation.js",
"scripts": {
Expand All @@ -26,6 +26,10 @@
"@mui/material": "^6.4.3",
"@mui/x-date-pickers": "^7.26.0",
"@react-pdf/renderer": "^3.1.11",
"@sentry/react": "^8.54.0",
"@sentry/webpack-plugin": "^3.1.2",
"@stripe/react-stripe-js": "^5.4.1",
"@stripe/stripe-js": "^8.5.3",
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "12.1.5",
"@testing-library/user-event": "14.5.2",
Expand Down Expand Up @@ -114,6 +118,9 @@
"@mui/material": "^6.4.3",
"@mui/x-date-pickers": "^7.26.0",
"@react-pdf/renderer": "^3.1.11",
"@sentry/react": "^8.54.0",
"@stripe/react-stripe-js": "^5.4.1",
"@stripe/stripe-js": "^8.5.3",
"awesome-bootstrap-checkbox": "^1.0.1",
"browser-tabs-lock": "^1.2.15",
"crypto-js": "^4.1.1",
Expand All @@ -131,6 +138,7 @@
"lodash": "^4.17.14",
"moment": "^2.22.2",
"moment-timezone": "^0.5.21",
"prop-types": "^15.8.1",
"react": "^17.0.0",
"react-beautiful-dnd": "^13.1.1",
"react-bootstrap": "^0.31.5",
Expand Down
25 changes: 20 additions & 5 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export {default as MuiChipNotify} from './mui/chip-notify'
export {default as MuiChipSelectInput} from './mui/chip-select-input'
export {default as MuiConfirmDialog} from './mui/confirm-dialog'
export {default as MuiCustomAlert} from './mui/custom-alert'
export {default as MuiDndList} from './mui/dnd-list'
export {default as MuiDropdownCheckbox} from './mui/dropdown-checkbox'
export {default as MuiMenuButton} from './mui/menu-button'
export {default as MuiSearchInput} from './mui/search-input'
Expand All @@ -78,10 +77,8 @@ export {default as MuiNotesModal} from './mui/NotesModal'
export {default as MuiSnackbarNotification} from './mui/SnackbarNotification'
export {default as MuiInfiniteTable} from './mui/infinite-table'
export {default as MuiEditableTable} from './mui/editable-table/mui-table-editable'
export {default as MuiSortableTable} from './mui/sortable-table/mui-table-sortable'
export {default as MuiTable} from './mui/table/mui-table'
export {default as MuiAdditionalInput} from './mui/formik-inputs/additional-input/additional-input'
export {default as MuiAdditionalInputList} from './mui/formik-inputs/additional-input/additional-input-list'
export {TotalRow as MuiTotalRow, NotesRow as MuiNotesRow} from './mui/table/extra-rows'
export {default as MuiFormikAsyncSelect} from './mui/formik-inputs/mui-formik-async-select'
export {default as MuiFormikCheckboxGroup} from './mui/formik-inputs/mui-formik-checkbox-group'
export {default as MuiFormikCheckbox} from './mui/formik-inputs/mui-formik-checkbox'
Expand All @@ -105,13 +102,31 @@ export {default as MuiItemPriceTiers} from './mui/formik-inputs/item-price-tiers
export {default as MuiSponsorInput} from './mui/formik-inputs/mui-sponsor-input'
export {default as MuiSponsorshipInput} from './mui/formik-inputs/sponsorship-input-mui'
export {default as MuiSponsorshipSummitSelect} from './mui/formik-inputs/sponsorship-summit-select-mui'
export {default as MuiAlertButton} from './mui/AlertButton'
export {default as MuiAlertModal} from './mui/AlertModal'
export {default as MuiAuthButton} from './mui/AuthButton'
export {default as MuiCartButton} from './mui/CartButton'
export {default as MuiConfirmDeleteDialog} from './mui/ConfirmDeleteDialog'
export {default as MuiDashboardCard} from './mui/DashboardCard'
export {default as MuiDownloadBtn} from './mui/DownloadBtn'
export {default as MuiLoadingOverlay} from './mui/LoadingOverlay'
export {default as MuiNavBar} from './mui/NavBar'
export {default as MuiOrderSummary} from './mui/OrderSummary'
export {default as MuiStatusChip} from './mui/StatusChip'
export {default as MuiUploadBtn} from './mui/UploadBtn'
export {default as MuiUploadDialog} from './mui/UploadDialog'

// this 5 includes 3rd party deps
// these include 3rd party deps
// export {default as ExtraQuestionsForm } from './extra-questions/index.js';
// export {default as GMap} from './google-map';
// export {default as TextEditorV2} from './inputs/editor-input-v2'
// export {default as TextEditorV3} from './inputs/editor-input-v3'
// export {default as CompanyInputV2} from './inputs/company-input-v2.js'
// export {default as MuiDndList} from './mui/dnd-list' // react-beautiful-dnd
// export {default as MuiSortableTable} from './mui/sortable-table/mui-table-sortable' // react-beautiful-dnd
// export {default as MuiStripePayment} from './mui/StripePayment' // @stripe/react-stripe-js, @stripe/stripe-js
// export {default as MuiAdditionalInput} from './mui/formik-inputs/additional-input/additional-input' // react-beautiful-dnd (via dnd-list)
// export {default as MuiAdditionalInputList} from './mui/formik-inputs/additional-input/additional-input-list' // react-beautiful-dnd (via dnd-list)

let language = getCurrentUserLanguage();

Expand Down
31 changes: 31 additions & 0 deletions src/components/mui/AlertButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright 2026 OpenStack Foundation
* 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 React from "react";
import { Button } from "@mui/material";
import NotificationsIcon from "@mui/icons-material/Notifications";

const AlertButton = ({ label, onClick }) => (
<Button
endIcon={<NotificationsIcon sx={{ fontSize: 16 }} />}
onClick={onClick}
color="warning"
variant="outlined"
size="large"
sx={{ borderRadius: 92 }}
>
{label}
</Button>
);

export default AlertButton;
57 changes: 57 additions & 0 deletions src/components/mui/AlertModal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright 2026 OpenStack Foundation
* 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 React from "react";
import PropTypes from "prop-types";
import T from "i18n-react";
import { Divider, IconButton, Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";

const AlertModal = ({ title, message, open, onClose }) => {
return (
<Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
<DialogTitle>{title}</DialogTitle>
<IconButton
aria-label="close"
onClick={onClose}
sx={(theme) => ({
position: "absolute",
right: 8,
top: 8,
color: theme.palette.grey[500]
})}
>
<CloseIcon />
</IconButton>
<Divider />
<DialogContent>
<DialogContentText>{message}</DialogContentText>
</DialogContent>
<Divider />
<DialogActions>
<Button onClick={onClose} variant="contained" fullWidth>
{T.translate("general.ok")}
</Button>
</DialogActions>
</Dialog>
);
};

AlertModal.propTypes = {
title: PropTypes.string.isRequired,
message: PropTypes.string.isRequired,
open: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired
};

export default AlertModal;
66 changes: 66 additions & 0 deletions src/components/mui/AuthButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Copyright 2026 OpenStack Foundation
* 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 React, { useState } from "react";
import T from "i18n-react";
import {Button, Box} from '@mui/material';
import styles from "./styles.module.scss"

const AuthButton = ({ isLoggedUser, doLogin, initLogOut, picture }) => {
const [showLogOut, setShowLogOut] = useState(false);

const toggleLogOut = () => {
setShowLogOut(!showLogOut);
};

if (isLoggedUser) {
return (
<div className={styles.userMenu} onClick={toggleLogOut}>
<div
className={styles.profilePic}
style={{ backgroundImage: `url(${picture})` }}
/>
{showLogOut && (
<Button
className={styles.logout}
variant="contained"
size="small"
color="secondary"
onClick={() => {
initLogOut();
}}
>
{T.translate("buttons.sign_out")}
</Button>
)}
</div>
Comment thread
santipalenque marked this conversation as resolved.
Comment on lines +26 to +46

Copilot AI Apr 10, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logout UI uses a clickable <div> (onClick={toggleLogOut}) that also contains the Sign Out <Button>. Clicking the button will bubble to the parent and toggle the menu state too, which can lead to flaky UX (e.g., immediately hiding the button or toggling unexpectedly). Consider moving the toggle handler to a dedicated button/icon, or calling event.stopPropagation() in the Sign Out button handler. Also, a clickable <div> should have appropriate accessibility props (role, tabIndex, keyboard handlers) or be replaced with a semantic button.

Copilot uses AI. Check for mistakes.
);
}
return (
<Box className={styles.login}>
<Button
variant="contained"
size="small"
color="secondary"
onClick={() => {
doLogin();
}}
>
{T.translate("buttons.log_in")}
</Button>
</Box>
);

};

export default AuthButton;
28 changes: 28 additions & 0 deletions src/components/mui/AuthButton/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.userMenu {
position: absolute;
top: 12px;
right: 34px;
height: 40px;
width: 140px;
cursor: pointer;
}

.login {
width: 100%;
text-align: right;
}

.logout {
top: 4px;
right: 4px;
}

.profilePic {
height: 40px;
width: 40px;
border: 1px solid #afafaf;
border-radius: 20px;
overflow: hidden;
float: right;
background-size: cover;
}
53 changes: 53 additions & 0 deletions src/components/mui/CartButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Copyright 2026 OpenStack Foundation
* 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 React from "react";
import { Button, Box } from "@mui/material";
import T from "i18n-react";

const CartButton = ({ itemCount, onClick, sx, disabled }) => {
return (
<Button
endIcon={
!disabled && (
<Box
component="div"
sx={{
backgroundColor: "white",
color: "primary.main",
fontWeight: 700,
fontSize: "12px !important",
minWidth: "20px",
height: "20px",
borderRadius: "10px",
marginLeft: "4px",
marginRight: "2px"
}}
>
{itemCount}
</Box>
)
}
onClick={onClick}
color="primary"
variant="contained"
size="large"
sx={{ borderRadius: 92, ...sx }}
disabled={disabled}
>
{T.translate("buttons.my_cart")}
</Button>
);
};

export default CartButton;
58 changes: 58 additions & 0 deletions src/components/mui/ConfirmDeleteDialog/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright 2026 OpenStack Foundation
* 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 React from "react";
import PropTypes from "prop-types";
import {Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material";
import T from "i18n-react";

const ConfirmDeleteDialog = ({ open, onClose, onConfirm, message }) => {
return (
<Dialog
open={open}
onClose={onClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{T.translate("alerts.confirm_delete_title")}
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
{message || T.translate("alerts.confirm_delete")}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={onClose} color="primary">
{T.translate("general.cancel")}
</Button>
<Button onClick={onConfirm} color="error" autoFocus>
{T.translate("general.delete")}
</Button>
</DialogActions>
</Dialog>
);
};

ConfirmDeleteDialog.propTypes = {
open: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
onConfirm: PropTypes.func.isRequired,
message: PropTypes.string
};

ConfirmDeleteDialog.defaultProps = {
message: ""
};

export default ConfirmDeleteDialog;
Loading
Loading