mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Theme: Page styles move to emotion global styles and design tweaks (#33529)
* Theme: Page styles move to emotion global styles and design tweaks * More style tweaks * tweaks * Updating snapshots * Another fix * Another fix * minor fix * More style tweaks to page toolbar and alert rule page * minor polish
This commit is contained in:
parent
aaca022df6
commit
f6ecded86b
@ -135,7 +135,7 @@ const getStyles = (theme: GrafanaThemeV2) => {
|
||||
background: ${theme.colors.background.canvas};
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
padding: ${theme.spacing(0, 1, 1, 2)};
|
||||
padding: ${theme.spacing(1, 2, 0, 2)};
|
||||
`,
|
||||
toolbarLeft: css`
|
||||
display: flex;
|
||||
|
@ -4,10 +4,15 @@ import { useTheme2 } from '..';
|
||||
import { getElementStyles } from './elements';
|
||||
import { getCardStyles } from './card';
|
||||
import { getAgularPanelStyles } from './angularPanelStyles';
|
||||
import { getPageStyles } from './page';
|
||||
|
||||
/** @internal */
|
||||
export function GlobalStyles() {
|
||||
const theme = useTheme2();
|
||||
|
||||
return <Global styles={[getElementStyles(theme), getCardStyles(theme), getAgularPanelStyles(theme)]} />;
|
||||
return (
|
||||
<Global
|
||||
styles={[getElementStyles(theme), getPageStyles(theme), getCardStyles(theme), getAgularPanelStyles(theme)]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
114
packages/grafana-ui/src/themes/GlobalStyles/page.ts
Normal file
114
packages/grafana-ui/src/themes/GlobalStyles/page.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import { css } from '@emotion/react';
|
||||
import { GrafanaThemeV2 } from '@grafana/data';
|
||||
|
||||
export function getPageStyles(theme: GrafanaThemeV2) {
|
||||
return css`
|
||||
.grafana-app {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.main-view {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.page-scrollbar-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-scrollbar-content {
|
||||
display: flex;
|
||||
min-height: 100%;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
flex-grow: 1;
|
||||
flex-basis: 100%;
|
||||
padding-left: ${theme.spacing(2)};
|
||||
padding-right: ${theme.spacing(2)};
|
||||
|
||||
${theme.breakpoints.up('sm')} {
|
||||
margin: ${theme.spacing(0, 1)};
|
||||
}
|
||||
|
||||
${theme.breakpoints.up('md')} {
|
||||
margin: ${theme.spacing(0, 2)};
|
||||
}
|
||||
|
||||
@media (min-width: ${theme.breakpoints.values.xxl + theme.spacing.gridSize * 2}px) {
|
||||
max-width: ${theme.breakpoints.values.xxl}px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.page-full {
|
||||
margin-left: ${theme.spacing(2)};
|
||||
padding-left: ${theme.spacing(2)};
|
||||
padding-right: ${theme.spacing(2)};
|
||||
}
|
||||
|
||||
.page-body {
|
||||
padding: ${theme.spacing(1)};
|
||||
background: ${theme.components.panel.background};
|
||||
border: 1px solid ${theme.components.panel.borderColor};
|
||||
margin-bottom: 32px;
|
||||
|
||||
${theme.breakpoints.up('md')} {
|
||||
padding: ${theme.spacing(2)};
|
||||
}
|
||||
|
||||
${theme.breakpoints.up('lg')} {
|
||||
padding: ${theme.spacing(3)};
|
||||
}
|
||||
}
|
||||
|
||||
.page-heading {
|
||||
font-size: ${theme.typography.h4.fontSize};
|
||||
margin-top: 0;
|
||||
margin-bottom: ${theme.spacing(2)};
|
||||
}
|
||||
|
||||
.page-action-bar {
|
||||
margin-bottom: ${theme.spacing(2)};
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
> a,
|
||||
> button {
|
||||
margin-left: ${theme.spacing(2)};
|
||||
}
|
||||
}
|
||||
|
||||
.page-action-bar--narrow {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.page-action-bar__spacer {
|
||||
width: ${theme.spacing(2)};
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.page-sub-heading {
|
||||
margin-bottom: ${theme.spacing(2)};
|
||||
}
|
||||
|
||||
.page-sub-heading-icon {
|
||||
margin-left: ${theme.spacing(1)};
|
||||
margin-top: ${theme.spacing(0.5)};
|
||||
}
|
||||
`;
|
||||
}
|
@ -372,7 +372,7 @@ $panel-editor-viz-item-shadow: 0 0 4px $gray-3;
|
||||
$panel-editor-viz-item-border: 1px solid $gray-3;
|
||||
$panel-editor-viz-item-shadow-hover: 0 0 4px $blue-light;
|
||||
$panel-editor-viz-item-border-hover: 1px solid $blue-light;
|
||||
$panel-editor-viz-item-bg: $white;
|
||||
$panel-editor-viz-item-bg: $card-background;
|
||||
$panel-editor-tabs-line-color: $dark-2;
|
||||
|
||||
$panel-editor-viz-item-bg-hover: lighten($blue-base, 45%);
|
||||
|
@ -23,7 +23,7 @@ export const FilterInput: FC<Props> = ({ value, placeholder, width, onChange, au
|
||||
autoFocus={autoFocus ?? false}
|
||||
prefix={<Icon name="search" />}
|
||||
suffix={suffix}
|
||||
width={width ?? 40}
|
||||
width={width}
|
||||
type="text"
|
||||
value={value ? unEscapeStringFromRegex(value) : ''}
|
||||
onChange={(event) => onChange(escapeStringForRegex(event.currentTarget.value))}
|
||||
|
@ -7,14 +7,13 @@ import PageHeader from '../PageHeader/PageHeader';
|
||||
import { Footer } from '../Footer/Footer';
|
||||
import { PageContents } from './PageContents';
|
||||
import { CustomScrollbar, useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaThemeV2, NavModel, ThemeBreakpointsKey } from '@grafana/data';
|
||||
import { GrafanaThemeV2, NavModel } from '@grafana/data';
|
||||
import { Branding } from '../Branding/Branding';
|
||||
import { css, cx } from '@emotion/css';
|
||||
|
||||
interface Props extends HTMLAttributes<HTMLDivElement> {
|
||||
children: React.ReactNode;
|
||||
navModel: NavModel;
|
||||
contentWidth?: ThemeBreakpointsKey;
|
||||
}
|
||||
|
||||
export interface PageType extends FC<Props> {
|
||||
@ -22,7 +21,7 @@ export interface PageType extends FC<Props> {
|
||||
Contents: typeof PageContents;
|
||||
}
|
||||
|
||||
export const Page: PageType = ({ navModel, children, className, contentWidth, ...otherProps }) => {
|
||||
export const Page: PageType = ({ navModel, children, className, ...otherProps }) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
useEffect(() => {
|
||||
@ -31,10 +30,7 @@ export const Page: PageType = ({ navModel, children, className, contentWidth, ..
|
||||
}, [navModel]);
|
||||
|
||||
return (
|
||||
<div
|
||||
{...otherProps}
|
||||
className={cx(styles.wrapper, className, contentWidth ? styles.contentWidth(contentWidth) : undefined)}
|
||||
>
|
||||
<div {...otherProps} className={cx(styles.wrapper, className)}>
|
||||
<CustomScrollbar autoHeightMin={'100%'}>
|
||||
<div className="page-scrollbar-content">
|
||||
<PageHeader model={navModel} />
|
||||
@ -53,15 +49,9 @@ export default Page;
|
||||
|
||||
const getStyles = (theme: GrafanaThemeV2) => ({
|
||||
wrapper: css`
|
||||
background: ${theme.colors.background.primary};
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
`,
|
||||
contentWidth: (size: ThemeBreakpointsKey) => css`
|
||||
.page-container {
|
||||
max-width: ${theme.breakpoints.values[size]}px;
|
||||
}
|
||||
`,
|
||||
});
|
||||
|
@ -24,7 +24,6 @@ export default class PageActionBar extends PureComponent<Props> {
|
||||
<div className="gf-form gf-form--grow">
|
||||
<FilterInput value={searchQuery} onChange={setSearchQuery} placeholder={placeholder} />
|
||||
</div>
|
||||
<div className="page-action-bar__spacer" />
|
||||
{linkButton && <LinkButton {...linkProps}>{linkButton.title}</LinkButton>}
|
||||
</div>
|
||||
);
|
||||
|
@ -13,9 +13,6 @@ exports[`Render should render component 1`] = `
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
<LinkButton
|
||||
href="some/url"
|
||||
target="_blank"
|
||||
|
@ -140,7 +140,6 @@ function renderTitle(title: string, breadcrumbs: NavModelBreadcrumb[]) {
|
||||
const getStyles = (theme: GrafanaThemeV2) => ({
|
||||
headerCanvas: css`
|
||||
background: ${theme.colors.background.canvas};
|
||||
border-bottom: 1px solid ${theme.colors.border.weak};
|
||||
`,
|
||||
});
|
||||
|
||||
|
@ -3,13 +3,14 @@ import { css, cx } from '@emotion/css';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { Pagination, Tooltip, HorizontalGroup, stylesFactory, LinkButton, Input, Icon } from '@grafana/ui';
|
||||
import { Pagination, Tooltip, stylesFactory, LinkButton, Icon } from '@grafana/ui';
|
||||
import { AccessControlAction, StoreState, UserDTO } from '../../types';
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { getNavModel } from '../../core/selectors/navModel';
|
||||
import { fetchUsers, changeQuery, changePage } from './state/actions';
|
||||
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
import { FilterInput } from 'app/core/components/FilterInput/FilterInput';
|
||||
|
||||
interface OwnProps {}
|
||||
|
||||
@ -42,27 +43,21 @@ const UserListAdminPageUnConnected: React.FC<Props> = (props) => {
|
||||
<Page navModel={navModel}>
|
||||
<Page.Contents>
|
||||
<>
|
||||
<div>
|
||||
<HorizontalGroup justify="space-between">
|
||||
<Input
|
||||
width={40}
|
||||
type="text"
|
||||
<div className="page-action-bar">
|
||||
<div className="gf-form gf-form--grow">
|
||||
<FilterInput
|
||||
placeholder="Search user by login, email, or name."
|
||||
tabIndex={1}
|
||||
autoFocus={true}
|
||||
value={query}
|
||||
spellCheck={false}
|
||||
onChange={(event) => changeQuery(event.currentTarget.value)}
|
||||
prefix={<Icon name="search" />}
|
||||
onChange={(value) => changeQuery(value)}
|
||||
/>
|
||||
{contextSrv.hasPermission(AccessControlAction.UsersCreate) && (
|
||||
<LinkButton href="admin/users/create" variant="primary">
|
||||
New user
|
||||
</LinkButton>
|
||||
)}
|
||||
</HorizontalGroup>
|
||||
</div>
|
||||
{contextSrv.hasPermission(AccessControlAction.UsersCreate) && (
|
||||
<LinkButton href="admin/users/create" variant="primary">
|
||||
New user
|
||||
</LinkButton>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={cx(styles.table, 'admin-list-table')}>
|
||||
<table className="filter-table form-inline filter-table--hover">
|
||||
<thead>
|
||||
|
@ -16,7 +16,7 @@ export const AlertingPageWrapper: FC<Props> = ({ children, pageId, isLoading })
|
||||
);
|
||||
|
||||
return (
|
||||
<Page navModel={navModel} contentWidth="xxl">
|
||||
<Page navModel={navModel}>
|
||||
<Page.Contents isLoading={isLoading}>{children}</Page.Contents>
|
||||
</Page>
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { FC, useMemo } from 'react';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { PageToolbar, ToolbarButton, useStyles, CustomScrollbar, Spinner, Alert } from '@grafana/ui';
|
||||
import { GrafanaThemeV2 } from '@grafana/data';
|
||||
import { PageToolbar, Button, useStyles2, CustomScrollbar, Spinner, Alert } from '@grafana/ui';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import { AlertTypeStep } from './AlertTypeStep';
|
||||
@ -24,7 +24,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const AlertRuleForm: FC<Props> = ({ existing }) => {
|
||||
const styles = useStyles(getStyles);
|
||||
const styles = useStyles2(getStyles);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const defaultValues: RuleFormValues = useMemo(() => {
|
||||
@ -73,22 +73,22 @@ export const AlertRuleForm: FC<Props> = ({ existing }) => {
|
||||
return (
|
||||
<FormProvider {...formAPI}>
|
||||
<form onSubmit={handleSubmit((values) => submit(values, false))} className={styles.form}>
|
||||
<PageToolbar title="Create alert rule" pageIcon="bell" className={styles.toolbar}>
|
||||
<PageToolbar title="Create alert rule" pageIcon="bell">
|
||||
<Link to="/alerting/list">
|
||||
<ToolbarButton variant="default" disabled={submitState.loading} type="button">
|
||||
<Button variant="secondary" disabled={submitState.loading} type="button" fill="outline">
|
||||
Cancel
|
||||
</ToolbarButton>
|
||||
</Button>
|
||||
</Link>
|
||||
<ToolbarButton
|
||||
variant="primary"
|
||||
<Button
|
||||
variant="secondary"
|
||||
type="button"
|
||||
onClick={handleSubmit((values) => submit(values, false))}
|
||||
disabled={submitState.loading}
|
||||
>
|
||||
{submitState.loading && <Spinner className={styles.buttonSpinner} inline={true} />}
|
||||
Save
|
||||
</ToolbarButton>
|
||||
<ToolbarButton
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
type="button"
|
||||
onClick={handleSubmit((values) => submit(values, true))}
|
||||
@ -96,7 +96,7 @@ export const AlertRuleForm: FC<Props> = ({ existing }) => {
|
||||
>
|
||||
{submitState.loading && <Spinner className={styles.buttonSpinner} inline={true} />}
|
||||
Save and exit
|
||||
</ToolbarButton>
|
||||
</Button>
|
||||
</PageToolbar>
|
||||
<div className={styles.contentOuter}>
|
||||
<CustomScrollbar autoHeightMin="100%" hideHorizontalTrack={true}>
|
||||
@ -128,15 +128,10 @@ export const AlertRuleForm: FC<Props> = ({ existing }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const getStyles = (theme: GrafanaTheme) => {
|
||||
const getStyles = (theme: GrafanaThemeV2) => {
|
||||
return {
|
||||
buttonSpinner: css`
|
||||
margin-right: ${theme.spacing.sm};
|
||||
`,
|
||||
toolbar: css`
|
||||
padding-top: ${theme.spacing.sm};
|
||||
padding-bottom: ${theme.spacing.md};
|
||||
border-bottom: solid 1px ${theme.colors.border2};
|
||||
margin-right: ${theme.spacing(1)};
|
||||
`,
|
||||
form: css`
|
||||
width: 100%;
|
||||
@ -146,19 +141,16 @@ const getStyles = (theme: GrafanaTheme) => {
|
||||
`,
|
||||
contentInner: css`
|
||||
flex: 1;
|
||||
padding: ${theme.spacing.md};
|
||||
padding: ${theme.spacing(2)};
|
||||
`,
|
||||
contentOuter: css`
|
||||
background: ${theme.colors.panelBg};
|
||||
background: ${theme.colors.background.primary};
|
||||
border: 1px solid ${theme.colors.border.weak};
|
||||
border-radius: ${theme.shape.borderRadius()};
|
||||
margin: ${theme.spacing(2)};
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
`,
|
||||
formInput: css`
|
||||
width: 400px;
|
||||
& + & {
|
||||
margin-left: ${theme.spacing.sm};
|
||||
}
|
||||
`,
|
||||
flexRow: css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -15,8 +15,6 @@ export const ApiKeysActionBar: FC<Props> = ({ searchQuery, disabled, onAddClick,
|
||||
<div className="gf-form gf-form--grow">
|
||||
<FilterInput placeholder="Search keys" value={searchQuery} onChange={onSearchChange} />
|
||||
</div>
|
||||
|
||||
<div className="page-action-bar__spacer" />
|
||||
<Button className="pull-right" onClick={onAddClick} disabled={disabled}>
|
||||
Add API key
|
||||
</Button>
|
||||
|
@ -11,7 +11,7 @@ import { ApiKeysAddedModal } from './ApiKeysAddedModal';
|
||||
import config from 'app/core/config';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||
import { InlineField, InlineSwitch } from '@grafana/ui';
|
||||
import { InlineField, InlineSwitch, VerticalGroup } from '@grafana/ui';
|
||||
import { rangeUtil } from '@grafana/data';
|
||||
import { getTimeZone } from 'app/features/profile/state/selectors';
|
||||
import { setSearchQuery } from './state/reducers';
|
||||
@ -150,13 +150,12 @@ export class ApiKeysPageUnconnected extends PureComponent<Props, State> {
|
||||
) : null}
|
||||
<ApiKeysForm show={isAdding} onClose={toggleIsAdding} onKeyAdded={this.onAddApiKey} />
|
||||
{showTable ? (
|
||||
<>
|
||||
<h3 className="page-heading">Existing API keys</h3>
|
||||
<VerticalGroup>
|
||||
<InlineField label="Show expired">
|
||||
<InlineSwitch id="showExpired" value={includeExpired} onChange={this.onIncludeExpiredChange} />
|
||||
</InlineField>
|
||||
<ApiKeysTable apiKeys={apiKeys} timeZone={timeZone} onDelete={this.onDeleteApiKey} />
|
||||
</>
|
||||
</VerticalGroup>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
|
@ -74,7 +74,7 @@ const getStyles = (theme: GrafanaTheme) => {
|
||||
min-height: 0;
|
||||
`,
|
||||
vizButtonWrapper: css`
|
||||
padding: 0 ${theme.spacing.sm} ${theme.spacing.md} 0;
|
||||
padding: 0 ${theme.spacing.md} ${theme.spacing.md} 0;
|
||||
`,
|
||||
legacyOptions: css`
|
||||
label: legacy-options;
|
||||
|
@ -40,7 +40,7 @@ export const SnapshotListTable: FC = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="page-container page-body">
|
||||
<div>
|
||||
<table className="filter-table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -38,7 +38,7 @@ export class OrgDetailsPage extends PureComponent<Props> {
|
||||
<Page navModel={navModel}>
|
||||
<Page.Contents isLoading={isLoading}>
|
||||
{!isLoading && (
|
||||
<VerticalGroup>
|
||||
<VerticalGroup spacing="lg">
|
||||
<OrgProfile onSubmit={this.onUpdateOrganization} orgName={organization.name} />
|
||||
<SharedPreferences resourceUri="org" />
|
||||
</VerticalGroup>
|
||||
|
@ -35,7 +35,9 @@ exports[`Render should render organization and preferences 1`] = `
|
||||
<PageContents
|
||||
isLoading={false}
|
||||
>
|
||||
<VerticalGroup>
|
||||
<VerticalGroup
|
||||
spacing="lg"
|
||||
>
|
||||
<OrgProfile
|
||||
onSubmit={[Function]}
|
||||
orgName="Cool org"
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
UrlQueryMap,
|
||||
} from '@grafana/data';
|
||||
import { AppNotificationSeverity } from 'app/types';
|
||||
import { Alert, InfoBox, LinkButton, PluginSignatureBadge, Tooltip } from '@grafana/ui';
|
||||
import { Alert, LinkButton, PluginSignatureBadge, Tooltip } from '@grafana/ui';
|
||||
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { getPluginSettings } from './PluginSettingsCache';
|
||||
@ -170,9 +170,6 @@ class PluginPage extends PureComponent<Props, State> {
|
||||
<LinkButton fill="text" onClick={this.showUpdateInfo}>
|
||||
Update Available!
|
||||
</LinkButton>
|
||||
{/*<a href="#" onClick={this.showUpdateInfo}>*/}
|
||||
{/* Update Available!*/}
|
||||
{/*</a>*/}
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
@ -283,11 +280,10 @@ class PluginPage extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
return (
|
||||
<InfoBox
|
||||
<Alert
|
||||
aria-label={selectors.pages.PluginPage.signatureInfo}
|
||||
severity={plugin.meta.signature !== PluginSignatureStatus.valid ? 'warning' : 'info'}
|
||||
urlTitle="Read more about plugins signing"
|
||||
url="https://grafana.com/docs/grafana/latest/plugins/plugin-signatures/"
|
||||
title="Plugin signature"
|
||||
>
|
||||
<PluginSignatureBadge
|
||||
status={plugin.meta.signature}
|
||||
@ -303,7 +299,15 @@ class PluginPage extends PureComponent<Props, State> {
|
||||
{plugin.meta.signature !== PluginSignatureStatus.valid &&
|
||||
'Grafana Labs can’t guarantee the integrity of this unsigned plugin. Ask the plugin author to request it to be signed.'}
|
||||
</p>
|
||||
</InfoBox>
|
||||
<a
|
||||
href="https://grafana.com/docs/grafana/latest/plugins/plugin-signatures/"
|
||||
className="external-link"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Read more about plugins signing.
|
||||
</a>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ export const ChangePasswordForm: FC<Props> = ({ user, onChangePassword, isSaving
|
||||
<Button variant="primary" disabled={isSaving}>
|
||||
Change Password
|
||||
</Button>
|
||||
<LinkButton variant="secondary" href={`${config.appSubUrl}/profile`}>
|
||||
<LinkButton variant="secondary" href={`${config.appSubUrl}/profile`} fill="outline">
|
||||
Cancel
|
||||
</LinkButton>
|
||||
</HorizontalGroup>
|
||||
|
@ -27,7 +27,7 @@ export const ChangePasswordPage: FC<Props> = ({ navModel }) => (
|
||||
) => {
|
||||
return (
|
||||
<Page.Contents>
|
||||
<h3 className="page-sub-heading">Change Your Password</h3>
|
||||
<h3 className="page-heading">Change Your Password</h3>
|
||||
{states.loadUser ? (
|
||||
<LoadingPlaceholder text="Loading user profile..." />
|
||||
) : (
|
||||
|
@ -22,52 +22,52 @@ export class UserOrganizations extends PureComponent<Props> {
|
||||
return <LoadingPlaceholder text="Loading organizations..." />;
|
||||
}
|
||||
|
||||
if (orgs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{orgs.length > 0 && (
|
||||
<>
|
||||
<h3 className="page-sub-heading">Organizations</h3>
|
||||
<div className="gf-form-group">
|
||||
<table className="filter-table form-inline">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Role</th>
|
||||
<th />
|
||||
<div>
|
||||
<h3 className="page-sub-heading">Organizations</h3>
|
||||
<div className="gf-form-group">
|
||||
<table className="filter-table form-inline">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Role</th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{orgs.map((org: UserOrg, index) => {
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td>{org.name}</td>
|
||||
<td>{org.role}</td>
|
||||
<td className="text-right">
|
||||
{org.orgId === user.orgId ? (
|
||||
<Button variant="secondary" size="sm" disabled>
|
||||
Current
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
this.props.setUserOrg(org);
|
||||
}}
|
||||
>
|
||||
Select
|
||||
</Button>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{orgs.map((org: UserOrg, index) => {
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td>{org.name}</td>
|
||||
<td>{org.role}</td>
|
||||
<td className="text-right">
|
||||
{org.orgId === user.orgId ? (
|
||||
<Button variant="secondary" size="sm" disabled>
|
||||
Current
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
this.props.setUserOrg(org);
|
||||
}}
|
||||
>
|
||||
Select
|
||||
</Button>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { FC } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { LoadingPlaceholder } from '@grafana/ui';
|
||||
import { LoadingPlaceholder, VerticalGroup } from '@grafana/ui';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { UserProvider, UserAPI, LoadingStates } from 'app/core/utils/UserProvider';
|
||||
@ -34,16 +34,15 @@ export const UserProfileEdit: FC<Props> = ({ navModel }) => (
|
||||
{states.loadUser ? (
|
||||
<LoadingPlaceholder text="Loading user profile..." />
|
||||
) : (
|
||||
<UserProfileEditForm
|
||||
updateProfile={api.updateUserProfile}
|
||||
isSavingUser={states.updateUserProfile}
|
||||
user={user!}
|
||||
/>
|
||||
)}
|
||||
<SharedPreferences resourceUri="user" />
|
||||
<UserTeams isLoading={states.loadTeams} loadTeams={api.loadTeams} teams={teams} />
|
||||
{!states.loadUser && (
|
||||
<>
|
||||
<VerticalGroup spacing="md">
|
||||
<UserProfileEditForm
|
||||
updateProfile={api.updateUserProfile}
|
||||
isSavingUser={states.updateUserProfile}
|
||||
user={user!}
|
||||
/>
|
||||
|
||||
<SharedPreferences resourceUri="user" />
|
||||
<UserTeams isLoading={states.loadTeams} loadTeams={api.loadTeams} teams={teams} />
|
||||
<UserOrganizations
|
||||
isLoading={states.loadOrgs}
|
||||
setUserOrg={api.setUserOrg}
|
||||
@ -58,7 +57,7 @@ export const UserProfileEdit: FC<Props> = ({ navModel }) => (
|
||||
sessions={sessions}
|
||||
user={user!}
|
||||
/>
|
||||
</>
|
||||
</VerticalGroup>
|
||||
)}
|
||||
</Page.Contents>
|
||||
);
|
||||
|
@ -23,7 +23,7 @@ export class UserSessions extends PureComponent<Props> {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{sessions.length > 0 && (
|
||||
<>
|
||||
<h3 className="page-sub-heading">Sessions</h3>
|
||||
@ -59,7 +59,7 @@ export class UserSessions extends PureComponent<Props> {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -20,40 +20,40 @@ export class UserTeams extends PureComponent<Props> {
|
||||
return <LoadingPlaceholder text="Loading teams..." />;
|
||||
}
|
||||
|
||||
if (teams.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{teams.length > 0 && (
|
||||
<>
|
||||
<h3 className="page-sub-heading">Teams</h3>
|
||||
<div className="gf-form-group">
|
||||
<table className="filter-table form-inline">
|
||||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>Members</th>
|
||||
<div>
|
||||
<h3 className="page-sub-heading">Teams</h3>
|
||||
<div className="gf-form-group">
|
||||
<table className="filter-table form-inline">
|
||||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>Members</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{teams.map((team: Team, index) => {
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td className="width-4 text-center">
|
||||
<img className="filter-table__avatar" src={team.avatarUrl} />
|
||||
</td>
|
||||
<td>{team.name}</td>
|
||||
<td>{team.email}</td>
|
||||
<td>{team.memberCount}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{teams.map((team: Team, index) => {
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td className="width-4 text-center">
|
||||
<img className="filter-table__avatar" src={team.avatarUrl} />
|
||||
</td>
|
||||
<td>{team.name}</td>
|
||||
<td>{team.email}</td>
|
||||
<td>{team.memberCount}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,12 @@ export const DashboardActions: FC<Props> = ({ folderId, isEditor, canEdit }) =>
|
||||
};
|
||||
|
||||
return (
|
||||
<HorizontalGroup spacing="md" align="center">
|
||||
{canEdit && <LinkButton href={actionUrl('new')}>New Dashboard</LinkButton>}
|
||||
{!folderId && isEditor && <LinkButton href="dashboards/folder/new">New Folder</LinkButton>}
|
||||
{canEdit && <LinkButton href={actionUrl('import')}>Import</LinkButton>}
|
||||
</HorizontalGroup>
|
||||
<div>
|
||||
<HorizontalGroup spacing="md" align="center">
|
||||
{canEdit && <LinkButton href={actionUrl('new')}>New Dashboard</LinkButton>}
|
||||
{!folderId && isEditor && <LinkButton href="dashboards/folder/new">New Folder</LinkButton>}
|
||||
{canEdit && <LinkButton href={actionUrl('import')}>Import</LinkButton>}
|
||||
</HorizontalGroup>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { FC, memo, useState } from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { HorizontalGroup, stylesFactory, useTheme, Spinner } from '@grafana/ui';
|
||||
import { stylesFactory, useTheme, Spinner } from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||
@ -93,11 +93,11 @@ export const ManageDashboards: FC<Props> = memo(({ folder }) => {
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div>
|
||||
<HorizontalGroup justify="space-between">
|
||||
<div className="page-action-bar">
|
||||
<div className="gf-form gf-form--grow m-r-2">
|
||||
<FilterInput value={query.query} onChange={onQueryChange} placeholder={'Search dashboards by name'} />
|
||||
<DashboardActions isEditor={isEditor} canEdit={hasEditPermissionInFolders || canSave} folderId={folderId} />
|
||||
</HorizontalGroup>
|
||||
</div>
|
||||
<DashboardActions isEditor={isEditor} canEdit={hasEditPermissionInFolders || canSave} folderId={folderId} />
|
||||
</div>
|
||||
|
||||
<div className={styles.results}>
|
||||
|
@ -101,8 +101,6 @@ export class TeamList extends PureComponent<Props, any> {
|
||||
<FilterInput placeholder="Search teams" value={searchQuery} onChange={this.onSearchQueryChange} />
|
||||
</div>
|
||||
|
||||
<div className="page-action-bar__spacer" />
|
||||
|
||||
<LinkButton className={disabledClass} href={newTeamHref}>
|
||||
New Team
|
||||
</LinkButton>
|
||||
|
@ -78,8 +78,6 @@ export class TeamMembers extends PureComponent<Props, State> {
|
||||
<div className="gf-form gf-form--grow">
|
||||
<FilterInput placeholder="Search members" value={searchMemberQuery} onChange={this.onSearchQueryChange} />
|
||||
</div>
|
||||
|
||||
<div className="page-action-bar__spacer" />
|
||||
<Button className="pull-right" onClick={this.onToggleAdding} disabled={isAdding || !isTeamAdmin}>
|
||||
Add member
|
||||
</Button>
|
||||
|
@ -47,9 +47,6 @@ exports[`Render should render teams table 1`] = `
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
<LinkButton
|
||||
className=""
|
||||
href="org/teams/new"
|
||||
@ -380,9 +377,6 @@ exports[`Render when feature toggle editorsCanAdmin is turned on and signedin us
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
<LinkButton
|
||||
className=" disabled"
|
||||
href="#"
|
||||
@ -505,9 +499,6 @@ exports[`Render when feature toggle editorsCanAdmin is turned on and signedin us
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
<LinkButton
|
||||
className=""
|
||||
href="org/teams/new"
|
||||
|
@ -14,9 +14,6 @@ exports[`Render should render component 1`] = `
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
<Button
|
||||
className="pull-right"
|
||||
disabled={false}
|
||||
@ -101,9 +98,6 @@ exports[`Render should render team members 1`] = `
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
<Button
|
||||
className="pull-right"
|
||||
disabled={false}
|
||||
|
@ -44,19 +44,18 @@ export class UsersActionBar extends PureComponent<Props> {
|
||||
onChange={setUsersSearchQuery}
|
||||
placeholder="Search user by login, email or name"
|
||||
/>
|
||||
{pendingInvitesCount > 0 && (
|
||||
<div style={{ marginLeft: '1rem' }}>
|
||||
<RadioButtonGroup value={showInvites ? 'invites' : 'users'} options={options} onChange={onShowInvites} />
|
||||
</div>
|
||||
)}
|
||||
<div className="page-action-bar__spacer" />
|
||||
{canInvite && canAddToOrg && <LinkButton href="org/users/invite">Invite</LinkButton>}
|
||||
{externalUserMngLinkUrl && (
|
||||
<LinkButton href={externalUserMngLinkUrl} target="_blank" rel="noopener">
|
||||
{externalUserMngLinkName}
|
||||
</LinkButton>
|
||||
)}
|
||||
</div>
|
||||
{pendingInvitesCount > 0 && (
|
||||
<div style={{ marginLeft: '1rem' }}>
|
||||
<RadioButtonGroup value={showInvites ? 'invites' : 'users'} options={options} onChange={onShowInvites} />
|
||||
</div>
|
||||
)}
|
||||
{canInvite && canAddToOrg && <LinkButton href="org/users/invite">Invite</LinkButton>}
|
||||
{externalUserMngLinkUrl && (
|
||||
<LinkButton href={externalUserMngLinkUrl} target="_blank" rel="noopener">
|
||||
{externalUserMngLinkName}
|
||||
</LinkButton>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -12,9 +12,6 @@ exports[`Render should render component 1`] = `
|
||||
placeholder="Search user by login, email or name"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -31,32 +28,29 @@ exports[`Render should render pending invites button 1`] = `
|
||||
placeholder="Search user by login, email or name"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"marginLeft": "1rem",
|
||||
}
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"marginLeft": "1rem",
|
||||
}
|
||||
>
|
||||
<RadioButtonGroup
|
||||
onChange={[MockFunction]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"label": "Users",
|
||||
"value": "users",
|
||||
},
|
||||
Object {
|
||||
"label": "Pending Invites (5)",
|
||||
"value": "invites",
|
||||
},
|
||||
]
|
||||
}
|
||||
value="users"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
}
|
||||
>
|
||||
<RadioButtonGroup
|
||||
onChange={[MockFunction]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"label": "Users",
|
||||
"value": "users",
|
||||
},
|
||||
Object {
|
||||
"label": "Pending Invites (5)",
|
||||
"value": "invites",
|
||||
},
|
||||
]
|
||||
}
|
||||
value="users"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -74,15 +68,12 @@ exports[`Render should show external user management button 1`] = `
|
||||
placeholder="Search user by login, email or name"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
<LinkButton
|
||||
href="some/url"
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
/>
|
||||
</div>
|
||||
<LinkButton
|
||||
href="some/url"
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -98,14 +89,11 @@ exports[`Render should show invite button 1`] = `
|
||||
placeholder="Search user by login, email or name"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
<LinkButton
|
||||
href="org/users/invite"
|
||||
>
|
||||
Invite
|
||||
</LinkButton>
|
||||
</div>
|
||||
<LinkButton
|
||||
href="org/users/invite"
|
||||
>
|
||||
Invite
|
||||
</LinkButton>
|
||||
</div>
|
||||
`;
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
// LAYOUTS
|
||||
@import 'layout/lists';
|
||||
@import 'layout/page';
|
||||
|
||||
// COMPONENTS
|
||||
@import '../app/features/dashboard/components/AddPanelWidget/AddPanelWidget';
|
||||
|
@ -374,7 +374,7 @@ $panel-editor-viz-item-shadow: 0 0 4px $gray-3;
|
||||
$panel-editor-viz-item-border: 1px solid $gray-3;
|
||||
$panel-editor-viz-item-shadow-hover: 0 0 4px $blue-light;
|
||||
$panel-editor-viz-item-border-hover: 1px solid $blue-light;
|
||||
$panel-editor-viz-item-bg: $white;
|
||||
$panel-editor-viz-item-bg: $card-background;
|
||||
$panel-editor-tabs-line-color: $dark-2;
|
||||
|
||||
$panel-editor-viz-item-bg-hover: lighten($blue-base, 45%);
|
||||
|
@ -32,6 +32,15 @@ mark,
|
||||
background: $alert-warning-bg;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// Lists
|
||||
// --------------------------------------------------
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
.page-header {
|
||||
padding: $space-xl 0 0 0;
|
||||
|
||||
.btn {
|
||||
float: right;
|
||||
margin-left: $space-md;
|
||||
@ -11,12 +9,18 @@
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
margin-top: $space-md;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.page-header__inner {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
margin-bottom: $space-xl;
|
||||
padding: $space-lg 0;
|
||||
}
|
||||
|
||||
.page-header__title {
|
||||
@ -36,6 +40,7 @@
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: relative;
|
||||
color: $text-color-weak;
|
||||
|
||||
&.fa {
|
||||
top: 10px;
|
||||
@ -51,7 +56,8 @@
|
||||
}
|
||||
|
||||
.page-header__logo {
|
||||
margin: -1px $spacer;
|
||||
margin: -1px $spacer -1px 0;
|
||||
color: $text-color-weak;
|
||||
}
|
||||
|
||||
.page-header__sub-title {
|
||||
|
@ -23,7 +23,6 @@ $mobile-menu-breakpoint: md;
|
||||
@include media-breakpoint-up($mobile-menu-breakpoint) {
|
||||
background: $side-menu-bg;
|
||||
height: auto;
|
||||
box-shadow: $side-menu-shadow;
|
||||
position: relative;
|
||||
z-index: $zindex-sidemenu;
|
||||
}
|
||||
|
@ -1,165 +0,0 @@
|
||||
.grafana-app {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.main-view {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
background: $page-bg;
|
||||
}
|
||||
|
||||
.page-alerting,
|
||||
.page-explore,
|
||||
.page-dashboard {
|
||||
.main-view {
|
||||
background: $dashboard-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.page-scrollbar-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-scrollbar-content {
|
||||
display: flex;
|
||||
min-height: 100%;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
flex-basis: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: $spacer * 2;
|
||||
padding-right: $spacer * 2;
|
||||
max-width: 980px;
|
||||
@include clearfix();
|
||||
}
|
||||
|
||||
.page-full {
|
||||
margin-left: $page-sidebar-margin;
|
||||
padding-left: $spacer;
|
||||
padding-right: $spacer;
|
||||
@include clearfix();
|
||||
}
|
||||
|
||||
.scroll-canvas {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&--dashboard {
|
||||
height: calc(100% - 56px);
|
||||
}
|
||||
|
||||
> div {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
> .footer {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
// Render in correct position even ng-view div is not rendered yet
|
||||
> .footer:first-child {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
|
||||
> * {
|
||||
width: 100%;
|
||||
align-self: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-body {
|
||||
padding-top: $spacer * 2;
|
||||
padding-bottom: $spacer * 4;
|
||||
}
|
||||
|
||||
.page-heading {
|
||||
font-size: $font-size-h4;
|
||||
margin-top: 0;
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
|
||||
.page-action-bar {
|
||||
margin-bottom: $spacer * 2;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
> a,
|
||||
> button {
|
||||
margin-left: $spacer;
|
||||
}
|
||||
}
|
||||
|
||||
.page-action-bar--narrow {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.page-action-bar__spacer {
|
||||
width: $spacer * 2;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
width: calc(100% - #{$page-sidebar-width + $page-sidebar-margin}); // sidebar width + margin
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
@include media-breakpoint-up(md) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.page-sidebar {
|
||||
@include media-breakpoint-up(md) {
|
||||
width: $page-sidebar-width;
|
||||
margin-left: $page-sidebar-margin;
|
||||
}
|
||||
}
|
||||
|
||||
.page-sub-heading {
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
|
||||
.page-sub-heading-icon {
|
||||
margin-left: $spacer;
|
||||
margin-top: $space-xs;
|
||||
}
|
||||
|
||||
.page-sidebar {
|
||||
color: $text-color-weak;
|
||||
h4 {
|
||||
font-size: $font-size-base;
|
||||
font-weight: $font-weight-semi-bold;
|
||||
}
|
||||
h5 {
|
||||
font-size: $font-size-base;
|
||||
font-weight: $font-weight-semi-bold;
|
||||
}
|
||||
}
|
||||
|
||||
.page-sidebar-section {
|
||||
margin-bottom: $spacer * 2;
|
||||
}
|
@ -1,3 +1,26 @@
|
||||
.sidebar-content {
|
||||
width: calc(100% - #{$page-sidebar-width + $page-sidebar-margin}); // sidebar width + margin
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
@include media-breakpoint-up(md) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.page-sidebar {
|
||||
@include media-breakpoint-up(md) {
|
||||
width: $page-sidebar-width;
|
||||
margin-left: $page-sidebar-margin;
|
||||
}
|
||||
}
|
||||
|
||||
.page-sidebar-section {
|
||||
margin-bottom: $spacer * 2;
|
||||
}
|
||||
|
||||
.get-more-plugins-link {
|
||||
color: $gray-3;
|
||||
font-size: $font-size-sm;
|
||||
|
Loading…
Reference in New Issue
Block a user