mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Modals: design update (#33368)
* Modals: Style update draft * Modal.ButtonRow to control spacing better in a centralised way * Remove header border if no tabs * Added border and made buttons right aligned and changed order of buttons * Updating the overlay * Tweaks to paddings * Updated share modals
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { sumBy } from 'lodash';
|
||||
import { Modal, ConfirmModal, HorizontalGroup, Button } from '@grafana/ui';
|
||||
import { Modal, ConfirmModal, Button } from '@grafana/ui';
|
||||
import { DashboardModel, PanelModel } from '../../state';
|
||||
import { useDashboardDelete } from './useDashboardDelete';
|
||||
import useAsyncFn from 'react-use/lib/useAsyncFn';
|
||||
@@ -88,10 +88,10 @@ const ProvisionedDeleteModal = ({ hideModal, provisionedId }: { hideModal(): voi
|
||||
<br />
|
||||
File path: {provisionedId}
|
||||
</p>
|
||||
<HorizontalGroup justify="center">
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={hideModal}>
|
||||
OK
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</Modal.ButtonRow>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { FC, useCallback, useState } from 'react';
|
||||
import { Button, Field, Form, HorizontalGroup, Input } from '@grafana/ui';
|
||||
import { Button, Field, Form, Modal, Input } from '@grafana/ui';
|
||||
|
||||
import { RepeatRowSelect } from '../RepeatRowSelect/RepeatRowSelect';
|
||||
|
||||
@@ -33,12 +33,12 @@ export const RowOptionsForm: FC<Props> = ({ repeat, title, onUpdate, onCancel })
|
||||
<RepeatRowSelect repeat={newRepeat} onChange={onChangeRepeat} />
|
||||
</Field>
|
||||
|
||||
<HorizontalGroup>
|
||||
<Modal.ButtonRow>
|
||||
<Button type="submit">Update</Button>
|
||||
<Button variant="secondary" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</Modal.ButtonRow>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { Button, ConfirmModal, HorizontalGroup, Modal, stylesFactory, useTheme } from '@grafana/ui';
|
||||
import { Button, ConfirmModal, Modal, stylesFactory, useTheme } from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { css } from '@emotion/css';
|
||||
import { DashboardModel } from 'app/features/dashboard/state';
|
||||
@@ -89,7 +89,7 @@ const ConfirmPluginDashboardSaveModal: React.FC<SaveDashboardModalProps> = ({ on
|
||||
Use <strong>Save As</strong> to create custom version.
|
||||
</small>
|
||||
</div>
|
||||
<HorizontalGroup justify="center">
|
||||
<Modal.ButtonRow>
|
||||
<SaveDashboardAsButton dashboard={dashboard} onSaveSuccess={onDismiss} />
|
||||
<Button
|
||||
variant="destructive"
|
||||
@@ -103,7 +103,7 @@ const ConfirmPluginDashboardSaveModal: React.FC<SaveDashboardModalProps> = ({ on
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</Modal.ButtonRow>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button, HorizontalGroup, Modal, VerticalGroup } from '@grafana/ui';
|
||||
import { Button, Modal } from '@grafana/ui';
|
||||
import { SaveDashboardButton } from './SaveDashboardButton';
|
||||
import { DashboardModel } from '../../state';
|
||||
import { css } from '@emotion/css';
|
||||
@@ -27,24 +27,22 @@ export const UnsavedChangesModal: React.FC<UnsavedChangesModalProps> = ({
|
||||
width: 500px;
|
||||
`}
|
||||
>
|
||||
<VerticalGroup align={'center'} spacing={'md'}>
|
||||
<h4>Do you want to save your changes?</h4>
|
||||
<HorizontalGroup justify="center">
|
||||
<SaveDashboardButton dashboard={dashboard} onSaveSuccess={onSaveSuccess} />
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={() => {
|
||||
onDiscard();
|
||||
onDismiss();
|
||||
}}
|
||||
>
|
||||
Discard
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
<h5>Do you want to save your changes?</h5>
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={() => {
|
||||
onDiscard();
|
||||
onDismiss();
|
||||
}}
|
||||
>
|
||||
Discard
|
||||
</Button>
|
||||
<SaveDashboardButton dashboard={dashboard} onSaveSuccess={onSaveSuccess} />
|
||||
</Modal.ButtonRow>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button, HorizontalGroup, Input, Switch, Form, Field, InputControl } from '@grafana/ui';
|
||||
import { Button, Input, Switch, Form, Field, InputControl, Modal } from '@grafana/ui';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
|
||||
import { SaveDashboardFormProps } from '../types';
|
||||
@@ -114,14 +114,14 @@ export const SaveDashboardAsForm: React.FC<SaveDashboardFormProps & { isNew?: bo
|
||||
<Field label="Copy tags">
|
||||
<Switch name="copyTags" ref={register} />
|
||||
</Field>
|
||||
<HorizontalGroup>
|
||||
<Button type="submit" aria-label="Save dashboard button">
|
||||
Save
|
||||
</Button>
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
<Button type="submit" aria-label="Save dashboard button">
|
||||
Save
|
||||
</Button>
|
||||
</Modal.ButtonRow>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import { Button, Checkbox, Form, HorizontalGroup, TextArea } from '@grafana/ui';
|
||||
import { Button, Checkbox, Form, Modal, TextArea } from '@grafana/ui';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
import { SaveDashboardFormProps } from '../types';
|
||||
@@ -36,7 +36,7 @@ export const SaveDashboardForm: React.FC<SaveDashboardFormProps> = ({ dashboard,
|
||||
>
|
||||
{({ register, errors }) => (
|
||||
<>
|
||||
<div className="gf-form-group">
|
||||
<div>
|
||||
{hasTimeChanged && (
|
||||
<Checkbox
|
||||
label="Save current time range as dashboard default"
|
||||
@@ -58,14 +58,14 @@ export const SaveDashboardForm: React.FC<SaveDashboardFormProps> = ({ dashboard,
|
||||
<TextArea name="message" ref={register} placeholder="Add a note to describe your changes." autoFocus />
|
||||
</div>
|
||||
|
||||
<HorizontalGroup>
|
||||
<Button type="submit" aria-label={selectors.pages.SaveDashboardModal.save}>
|
||||
Save
|
||||
</Button>
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
<Button type="submit" aria-label={selectors.pages.SaveDashboardModal.save}>
|
||||
Save
|
||||
</Button>
|
||||
</Modal.ButtonRow>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { Button, HorizontalGroup, stylesFactory, TextArea, useTheme, VerticalGroup } from '@grafana/ui';
|
||||
import { Button, Modal, stylesFactory, TextArea, useTheme } from '@grafana/ui';
|
||||
import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';
|
||||
import { SaveDashboardFormProps } from '../types';
|
||||
import { AppEvents, GrafanaTheme } from '@grafana/data';
|
||||
@@ -29,8 +29,8 @@ export const SaveProvisionedDashboardForm: React.FC<SaveDashboardFormProps> = ({
|
||||
const styles = getStyles(theme);
|
||||
return (
|
||||
<>
|
||||
<VerticalGroup spacing="lg">
|
||||
<small>
|
||||
<div>
|
||||
<div>
|
||||
This dashboard cannot be saved from the Grafana UI because it has been provisioned from another source. Copy
|
||||
the JSON or save it to a file below, then you can update your dashboard in the provisioning source.
|
||||
<br />
|
||||
@@ -46,8 +46,7 @@ export const SaveProvisionedDashboardForm: React.FC<SaveDashboardFormProps> = ({
|
||||
</a>{' '}
|
||||
for more information about provisioning.
|
||||
</i>
|
||||
</small>
|
||||
<div>
|
||||
<br /> <br />
|
||||
<strong>File path: </strong> {dashboard.meta.provisionedExternalId}
|
||||
</div>
|
||||
<TextArea
|
||||
@@ -58,16 +57,16 @@ export const SaveProvisionedDashboardForm: React.FC<SaveDashboardFormProps> = ({
|
||||
}}
|
||||
className={styles.json}
|
||||
/>
|
||||
<HorizontalGroup>
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<CopyToClipboard text={() => dashboardJSON} elType={Button} onSuccess={onCopyToClipboardSuccess}>
|
||||
Copy JSON to clipboard
|
||||
</CopyToClipboard>
|
||||
<Button onClick={saveToFile}>Save JSON to file</Button>
|
||||
<Button variant="secondary" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
</Modal.ButtonRow>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { FormEvent, PureComponent } from 'react';
|
||||
import { RadioButtonGroup, Switch, Field, TextArea, ClipboardButton } from '@grafana/ui';
|
||||
import { RadioButtonGroup, Switch, Field, TextArea, ClipboardButton, Modal } from '@grafana/ui';
|
||||
import { SelectableValue, AppEvents } from '@grafana/data';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { appEvents } from 'app/core/core';
|
||||
@@ -96,9 +96,11 @@ export class ShareEmbed extends PureComponent<Props, State> {
|
||||
>
|
||||
<TextArea rows={5} value={iframeHtml} onChange={this.onIframeHtmlChange}></TextArea>
|
||||
</Field>
|
||||
<ClipboardButton variant="primary" getText={this.getIframeHtml} onClipboardCopy={this.onIframeHtmlCopy}>
|
||||
Copy to clipboard
|
||||
</ClipboardButton>
|
||||
<Modal.ButtonRow>
|
||||
<ClipboardButton variant="primary" getText={this.getIframeHtml} onClipboardCopy={this.onIframeHtmlCopy}>
|
||||
Copy to clipboard
|
||||
</ClipboardButton>
|
||||
</Modal.ButtonRow>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { Button, Field, Switch } from '@grafana/ui';
|
||||
import { Button, Field, Modal, Switch } from '@grafana/ui';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { DashboardExporter } from 'app/features/dashboard/components/DashExportModal';
|
||||
import { appEvents } from 'app/core/core';
|
||||
@@ -95,17 +95,17 @@ export class ShareExport extends PureComponent<Props, State> {
|
||||
<Field label="Export for sharing externally">
|
||||
<Switch value={shareExternally} onChange={this.onShareExternallyChange} />
|
||||
</Field>
|
||||
<div className="gf-form-button-row">
|
||||
<Button variant="primary" onClick={this.onSaveAsFile}>
|
||||
Save to file
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={this.onViewJson}>
|
||||
View JSON
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
<Button variant="primary" onClick={this.onSaveAsFile}>
|
||||
Save to file
|
||||
</Button>
|
||||
</div>
|
||||
</Modal.ButtonRow>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Button, ClipboardButton, Icon, Spinner, Select, Input, LinkButton, Field } from '@grafana/ui';
|
||||
import { Button, ClipboardButton, Icon, Spinner, Select, Input, LinkButton, Field, Modal } from '@grafana/ui';
|
||||
import { AppEvents, SelectableValue } from '@grafana/data';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
@@ -233,19 +233,19 @@ export class ShareSnapshot extends PureComponent<Props, State> {
|
||||
<Input type="number" width={21} value={timeoutSeconds} onChange={this.onTimeoutChange} />
|
||||
</Field>
|
||||
|
||||
<div className="gf-form-button-row">
|
||||
<Button variant="primary" disabled={isLoading} onClick={this.createSnapshot()}>
|
||||
Local Snapshot
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
{externalEnabled && (
|
||||
<Button variant="secondary" disabled={isLoading} onClick={this.createSnapshot(true)}>
|
||||
{sharingButtonText}
|
||||
</Button>
|
||||
)}
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
<Button variant="primary" disabled={isLoading} onClick={this.createSnapshot()}>
|
||||
Local Snapshot
|
||||
</Button>
|
||||
</div>
|
||||
</Modal.ButtonRow>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Button, Field, Input, Modal, useStyles } from '@grafana/ui';
|
||||
import { Button, Field, Input, Modal } from '@grafana/ui';
|
||||
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
|
||||
import { PanelModel } from '../../../dashboard/state';
|
||||
import { css } from '@emotion/css';
|
||||
import { usePanelSave } from '../../utils/usePanelSave';
|
||||
interface AddLibraryPanelContentsProps {
|
||||
onDismiss: () => void;
|
||||
@@ -11,7 +10,6 @@ interface AddLibraryPanelContentsProps {
|
||||
}
|
||||
|
||||
export const AddLibraryPanelContents = ({ panel, initialFolderId, onDismiss }: AddLibraryPanelContentsProps) => {
|
||||
const styles = useStyles(getStyles);
|
||||
const [folderId, setFolderId] = useState(initialFolderId);
|
||||
const [panelTitle, setPanelTitle] = useState(panel.title);
|
||||
const { saveLibraryPanel } = usePanelSave();
|
||||
@@ -25,7 +23,7 @@ export const AddLibraryPanelContents = ({ panel, initialFolderId, onDismiss }: A
|
||||
<FolderPicker onChange={({ id }) => setFolderId(id)} initialFolderId={initialFolderId} />
|
||||
</Field>
|
||||
|
||||
<div className={styles.buttons}>
|
||||
<Modal.ButtonRow>
|
||||
<Button
|
||||
onClick={() => {
|
||||
panel.title = panelTitle;
|
||||
@@ -37,7 +35,7 @@ export const AddLibraryPanelContents = ({ panel, initialFolderId, onDismiss }: A
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</Modal.ButtonRow>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -53,10 +51,3 @@ export const AddLibraryPanelModal: React.FC<Props> = ({ isOpen = false, panel, i
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const getStyles = () => ({
|
||||
buttons: css`
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
`,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { FC, useEffect, useMemo, useReducer } from 'react';
|
||||
import { Button, HorizontalGroup, Modal, useStyles } from '@grafana/ui';
|
||||
import { Button, Modal, useStyles } from '@grafana/ui';
|
||||
import { LoadingState } from '@grafana/data';
|
||||
|
||||
import { LibraryPanelDTO } from '../../types';
|
||||
@@ -35,14 +35,14 @@ export const DeleteLibraryPanelModal: FC<Props> = ({ libraryPanel, onDismiss, on
|
||||
{connected ? <HasConnectedDashboards dashboardTitles={dashboardTitles} /> : null}
|
||||
{!connected ? <Confirm /> : null}
|
||||
|
||||
<HorizontalGroup>
|
||||
<Button variant="destructive" onClick={onConfirm} disabled={connected}>
|
||||
Delete
|
||||
</Button>
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
<Button variant="destructive" onClick={onConfirm} disabled={connected}>
|
||||
Delete
|
||||
</Button>
|
||||
</Modal.ButtonRow>
|
||||
</div>
|
||||
) : null}
|
||||
</Modal>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { Button, HorizontalGroup, Icon, Input, Modal, useStyles } from '@grafana/ui';
|
||||
import { Button, Icon, Input, Modal, useStyles } from '@grafana/ui';
|
||||
import { useAsync, useDebounce } from 'react-use';
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
import { usePanelSave } from '../../utils/usePanelSave';
|
||||
@@ -98,7 +98,13 @@ export const SaveLibraryPanelModal: React.FC<Props> = ({
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
<HorizontalGroup>
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={discardAndClose}>
|
||||
Discard
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
saveLibraryPanel(panel, folderId).then(() => {
|
||||
@@ -109,13 +115,7 @@ export const SaveLibraryPanelModal: React.FC<Props> = ({
|
||||
>
|
||||
Update all
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={discardAndClose}>
|
||||
Discard
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={onDismiss}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</Modal.ButtonRow>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@@ -132,11 +132,11 @@ export const StartModal: FC<StartModalProps> = ({ playlist, onDismiss }) => {
|
||||
onChange={(e) => setAutofit(e.currentTarget.checked)}
|
||||
/>
|
||||
</VerticalGroup>
|
||||
<div className="gf-form-button-row">
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="primary" onClick={onStart}>
|
||||
Start {playlist.name}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal.ButtonRow>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user