diff --git a/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.jsx b/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.jsx index 752b203b7c0d7ecc0032275dfa1810c3c255c97c..de39f2f1daeca754ea7e3d33d6ef1f09fb3cf718 100644 --- a/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.jsx +++ b/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.jsx @@ -8,11 +8,16 @@ import { SAVED_QUESTIONS_VIRTUAL_DB_ID } from "metabase/lib/saved-questions"; import Database from "metabase/entities/databases"; import EntityItem from "metabase/components/EntityItem"; import Icon from "metabase/components/Icon"; -import { Grid, GridItem } from "metabase/components/Grid"; +import { Grid } from "metabase/components/Grid"; -import { ANALYTICS_CONTEXT, ITEM_WIDTHS } from "../../constants"; +import { ANALYTICS_CONTEXT } from "../../constants"; import BrowseHeader from "../BrowseHeader"; -import { TableActionLink, TableCard, TableLink } from "./TableBrowser.styled"; +import { + TableActionLink, + TableCard, + TableGridItem, + TableLink, +} from "./TableBrowser.styled"; const propTypes = { tables: PropTypes.array.isRequired, @@ -44,7 +49,7 @@ const TableBrowser = ({ /> <Grid> {tables.map(table => ( - <GridItem key={table.id} width={ITEM_WIDTHS}> + <TableGridItem key={table.id}> <TableCard hoverable={isSyncCompleted(table)}> <TableLink to={isSyncCompleted(table) ? getTableUrl(table, metadata) : ""} @@ -57,7 +62,7 @@ const TableBrowser = ({ /> </TableLink> </TableCard> - </GridItem> + </TableGridItem> ))} </Grid> </div> diff --git a/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.styled.jsx b/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.styled.jsx index 1cda8e3c1ee79a598a4741b61ad310856e05cec6..4aa25dcbe3111d2cd5b9bf7ab8b955831aa18705 100644 --- a/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.styled.jsx +++ b/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.styled.jsx @@ -1,9 +1,26 @@ import styled from "styled-components"; -import { space } from "metabase/styled-components/theme"; +import { + breakpointMinMedium, + breakpointMinSmall, + space, +} from "metabase/styled-components/theme"; import Card from "metabase/components/Card"; import Link from "metabase/core/components/Link"; +import { GridItem } from "metabase/components/Grid"; import { forwardRefToInnerRef } from "metabase/styled-components/utils"; +export const TableGridItem = styled(GridItem)` + width: 100%; + + ${breakpointMinSmall} { + width: 50%; + } + + ${breakpointMinMedium} { + width: 33.33%; + } +`; + export const TableLink = styled(Link)` display: block; margin-left: ${space(1)}; diff --git a/frontend/src/metabase/browse/constants.js b/frontend/src/metabase/browse/constants.js index f01fa7a865fcdc2c6b7b9640728878e2b61b2cad..581b38dd68ff76c4bad4051c43e3e3cbd60582ea 100644 --- a/frontend/src/metabase/browse/constants.js +++ b/frontend/src/metabase/browse/constants.js @@ -1,3 +1,2 @@ -export const ITEM_WIDTHS = [1, 1 / 2, 1 / 3]; export const ANALYTICS_CONTEXT = "Data Browse"; export const RELOAD_INTERVAL = 2000; diff --git a/frontend/src/metabase/browse/containers/DatabaseBrowser.jsx b/frontend/src/metabase/browse/containers/DatabaseBrowser.jsx index 2cf3323229c94e3d881b35c31fac2e338db452ea..2817f44a08e18696c22d602e0807dafa60fbbb2f 100644 --- a/frontend/src/metabase/browse/containers/DatabaseBrowser.jsx +++ b/frontend/src/metabase/browse/containers/DatabaseBrowser.jsx @@ -8,13 +8,14 @@ import { color } from "metabase/lib/colors"; import * as Urls from "metabase/lib/urls"; import Card from "metabase/components/Card"; -import { Grid, GridItem } from "metabase/components/Grid"; +import { Grid } from "metabase/components/Grid"; import Icon from "metabase/components/Icon"; import Link from "metabase/core/components/Link"; import BrowseHeader from "metabase/browse/components/BrowseHeader"; -import { ANALYTICS_CONTEXT, ITEM_WIDTHS } from "metabase/browse/constants"; +import { ANALYTICS_CONTEXT } from "metabase/browse/constants"; +import { DatabaseGridItem } from "./DatabaseBrowser.styled"; function DatabaseBrowser({ databases }) { return ( @@ -23,7 +24,7 @@ function DatabaseBrowser({ databases }) { <Grid> {databases.map(database => ( - <GridItem width={ITEM_WIDTHS} key={database.id}> + <DatabaseGridItem key={database.id}> <Link to={Urls.browseDatabase(database)} data-metabase-event={`${ANALYTICS_CONTEXT};Database Click`} @@ -40,7 +41,7 @@ function DatabaseBrowser({ databases }) { <h3 className="text-wrap">{database.name}</h3> </Card> </Link> - </GridItem> + </DatabaseGridItem> ))} </Grid> </div> diff --git a/frontend/src/metabase/browse/containers/DatabaseBrowser.styled.tsx b/frontend/src/metabase/browse/containers/DatabaseBrowser.styled.tsx new file mode 100644 index 0000000000000000000000000000000000000000..7b7129b23de99140123a86e307de7bf9f1700eee --- /dev/null +++ b/frontend/src/metabase/browse/containers/DatabaseBrowser.styled.tsx @@ -0,0 +1,18 @@ +import styled from "styled-components"; +import { + breakpointMinMedium, + breakpointMinSmall, +} from "metabase/styled-components/theme"; +import { GridItem } from "metabase/components/Grid"; + +export const DatabaseGridItem = styled(GridItem)` + width: 100%; + + ${breakpointMinSmall} { + width: 50%; + } + + ${breakpointMinMedium} { + width: 33.33%; + } +`; diff --git a/frontend/src/metabase/browse/containers/SchemaBrowser.jsx b/frontend/src/metabase/browse/containers/SchemaBrowser.jsx index ba2f74a0d11af0c45bdf28436299e84c97b48afd..6f5a6516990ca6eb8c537091e8cc2406eeb41284 100644 --- a/frontend/src/metabase/browse/containers/SchemaBrowser.jsx +++ b/frontend/src/metabase/browse/containers/SchemaBrowser.jsx @@ -7,7 +7,7 @@ import Database from "metabase/entities/databases"; import Card from "metabase/components/Card"; import EntityItem from "metabase/components/EntityItem"; -import { Grid, GridItem } from "metabase/components/Grid"; +import { Grid } from "metabase/components/Grid"; import Icon from "metabase/components/Icon"; import Link from "metabase/core/components/Link"; import Tooltip from "metabase/components/Tooltip"; @@ -17,8 +17,12 @@ import * as Urls from "metabase/lib/urls"; import { color } from "metabase/lib/colors"; import BrowseHeader from "metabase/browse/components/BrowseHeader"; -import { ANALYTICS_CONTEXT, ITEM_WIDTHS } from "metabase/browse/constants"; -import { CardActions, CardContent } from "./SchemaBrowser.styled"; +import { ANALYTICS_CONTEXT } from "metabase/browse/constants"; +import { + SchemaCardActions, + SchemaCardContent, + SchemaGridItem, +} from "./SchemaBrowser.styled"; function SchemaBrowser(props) { const { schemas, params } = props; @@ -47,7 +51,7 @@ function SchemaBrowser(props) { ) : ( <Grid> {schemas.map(schema => ( - <GridItem width={ITEM_WIDTHS} key={schema.id}> + <SchemaGridItem key={schema.id}> <Link to={`/browse/${dbId}/schema/${schema.name}`} mb={1} @@ -56,23 +60,23 @@ function SchemaBrowser(props) { className="overflow-hidden" > <Card hoverable px={1}> - <CardContent> + <SchemaCardContent> <EntityItem name={schema.name} iconName="folder" iconColor={color("accent2")} item={schema} /> - <CardActions> + <SchemaCardActions> <Icon name="reference" /> <Tooltip tooltip={t`X-ray this schema`}> <Icon name="bolt" mx={1} /> </Tooltip> - </CardActions> - </CardContent> + </SchemaCardActions> + </SchemaCardContent> </Card> </Link> - </GridItem> + </SchemaGridItem> ))} </Grid> )} diff --git a/frontend/src/metabase/browse/containers/SchemaBrowser.styled.tsx b/frontend/src/metabase/browse/containers/SchemaBrowser.styled.tsx index f03874a1a9600c575832fd697b30e6191a42419f..7a3c284d990198a22cba0ab5e542835fe7d80257 100644 --- a/frontend/src/metabase/browse/containers/SchemaBrowser.styled.tsx +++ b/frontend/src/metabase/browse/containers/SchemaBrowser.styled.tsx @@ -1,10 +1,27 @@ import styled from "styled-components"; +import { + breakpointMinMedium, + breakpointMinSmall, +} from "metabase/styled-components/theme"; +import { GridItem } from "metabase/components/Grid"; -export const CardContent = styled.div` +export const SchemaGridItem = styled(GridItem)` + width: 100%; + + ${breakpointMinSmall} { + width: 50%; + } + + ${breakpointMinMedium} { + width: 33.33%; + } +`; + +export const SchemaCardContent = styled.div` display: flex; align-items: center; `; -export const CardActions = styled.div` +export const SchemaCardActions = styled.div` margin-left: auto; `; diff --git a/frontend/src/metabase/collections/components/BulkActions.jsx b/frontend/src/metabase/collections/components/BulkActions.jsx index 8113c427e0a5aa9ee23683427ca275b353ab906f..9919dbd365dd4be3614d52810164966111d56c92 100644 --- a/frontend/src/metabase/collections/components/BulkActions.jsx +++ b/frontend/src/metabase/collections/components/BulkActions.jsx @@ -3,7 +3,7 @@ import React from "react"; import { t, msgid, ngettext } from "ttag"; import _ from "underscore"; -import { Grid, GridItem } from "metabase/components/Grid"; +import { Grid } from "metabase/components/Grid"; import BulkActionBar from "metabase/components/BulkActionBar"; import Button from "metabase/core/components/Button"; import Modal from "metabase/components/Modal"; @@ -17,7 +17,9 @@ import { ActionBarContent, ActionBarText, ActionControlsRoot, - GridItemContent, + ActionGridItem, + ActionGridItemContent, + ActionGridPlaceholder, } from "./BulkActions.styled"; const BulkActionControls = ({ onArchive, onMove }) => ( @@ -71,9 +73,9 @@ function BulkActions(props) { to the main content above to ensure the bulk checkbox lines up */} <ActionBarContent> <Grid> - <GridItem width={[1, 1 / 3]} /> - <GridItem width={[1, 2 / 3]} px={[1, 2]}> - <GridItemContent> + <ActionGridPlaceholder /> + <ActionGridItem> + <ActionGridItemContent> <SelectionControls {...props} /> <BulkActionControls onArchive={ @@ -92,8 +94,8 @@ function BulkActions(props) { selected.length, )} </ActionBarText> - </GridItemContent> - </GridItem> + </ActionGridItemContent> + </ActionGridItem> </Grid> </ActionBarContent> {!_.isEmpty(selectedItems) && selectedAction === "copy" && ( diff --git a/frontend/src/metabase/collections/components/BulkActions.styled.tsx b/frontend/src/metabase/collections/components/BulkActions.styled.tsx index 4a3cb5ce56bec786dd02ab480a9bb24d2b989a81..4f9bd4b5a286e77ef2091e765204fb8803c2bc14 100644 --- a/frontend/src/metabase/collections/components/BulkActions.styled.tsx +++ b/frontend/src/metabase/collections/components/BulkActions.styled.tsx @@ -1,5 +1,6 @@ import styled from "styled-components"; import { breakpointMinSmall } from "metabase/styled-components/theme"; +import { GridItem } from "metabase/components/Grid"; export const ActionBarContent = styled.div` padding: 0.5rem 1rem; @@ -18,9 +19,29 @@ export const ActionControlsRoot = styled.div` margin-left: 0.5rem; `; -export const GridItemContent = styled.div` +export const ActionGridItem = styled(GridItem)` + width: 100%; + padding-left: 0.5rem; + padding-right: 0.5rem; + + ${breakpointMinSmall} { + width: 66.66%; + padding-left: 1rem; + padding-right: 1rem; + } +`; + +export const ActionGridItemContent = styled.div` display: flex; justify-content: center; align-items: center; padding: 0 1rem; `; + +export const ActionGridPlaceholder = styled.div` + width: 100%; + + ${breakpointMinSmall} { + width: 33.33%; + } +`; diff --git a/frontend/src/metabase/components/CollectionList.jsx b/frontend/src/metabase/components/CollectionList.jsx index b0406da76ca89da970a696d072031bf33a45c566..d6bf1259c71df45a1c90cbc631feda31949210f7 100644 --- a/frontend/src/metabase/components/CollectionList.jsx +++ b/frontend/src/metabase/components/CollectionList.jsx @@ -3,16 +3,16 @@ import PropTypes from "prop-types"; import { connect } from "react-redux"; import CollectionItem from "metabase/components/CollectionItem"; -import { Grid, GridItem } from "metabase/components/Grid"; +import { Grid } from "metabase/components/Grid"; import { getUser } from "metabase/selectors/user"; +import { CollectionGridItem } from "metabase/components/CollectionList.styled"; const propTypes = { collections: PropTypes.arrayOf(PropTypes.object).isRequired, currentUser: PropTypes.shape({ personal_collection_id: PropTypes.number, }), - w: PropTypes.arrayOf(PropTypes.number), analyticsContext: PropTypes.string, }; @@ -22,23 +22,18 @@ function mapStateToProps(state) { }; } -function CollectionList({ - collections, - currentUser, - w = [1, 1 / 2, 1 / 4], - analyticsContext, -}) { +function CollectionList({ collections, currentUser, analyticsContext }) { return ( <Grid> {collections .filter(c => c.id !== currentUser.personal_collection_id) .map(collection => ( - <GridItem width={w} key={collection.id}> + <CollectionGridItem key={collection.id}> <CollectionItem collection={collection} event={`${analyticsContext};Collection List;Collection click`} /> - </GridItem> + </CollectionGridItem> ))} </Grid> ); diff --git a/frontend/src/metabase/components/CollectionList.styled.tsx b/frontend/src/metabase/components/CollectionList.styled.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6b7326859862cb5571f4b4e61b6febe7c1f77536 --- /dev/null +++ b/frontend/src/metabase/components/CollectionList.styled.tsx @@ -0,0 +1,18 @@ +import styled from "styled-components"; +import { + breakpointMinSmall, + breakpointMinMedium, +} from "metabase/styled-components/theme"; +import { GridItem } from "metabase/components/Grid"; + +export const CollectionGridItem = styled(GridItem)` + width: 100%; + + ${breakpointMinSmall} { + width: 50%; + } + + ${breakpointMinMedium} { + width: 25%; + } +`; diff --git a/frontend/src/metabase/components/Grid.jsx b/frontend/src/metabase/components/Grid.jsx index aca62286afeb2b7445974c890ec55db4625e80e4..0155327686d08b6efd96e58dcf2737bf7c4828c8 100644 --- a/frontend/src/metabase/components/Grid.jsx +++ b/frontend/src/metabase/components/Grid.jsx @@ -1,21 +1,7 @@ /* eslint-disable react/prop-types */ import React from "react"; -import { Box, Flex } from "grid-styled"; +import { GridItemRoot, GridRoot } from "./Grid.styled"; -export const GridItem = ({ children, width, px, py, ...props }) => ( - <Box px={px} py={py} {...props} width={width}> - {children} - </Box> -); +export const Grid = props => <GridRoot {...props} />; -GridItem.defaultProps = { - width: 1 / 4, - px: 1, - py: 1, -}; - -export const Grid = ({ children }) => ( - <Flex mx={-1} style={{ flexWrap: "wrap" }}> - {children} - </Flex> -); +export const GridItem = props => <GridItemRoot {...props} />; diff --git a/frontend/src/metabase/components/Grid.styled.tsx b/frontend/src/metabase/components/Grid.styled.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b4d56f5c6ad3bb5c7cbdb664a2401d1eb15610a8 --- /dev/null +++ b/frontend/src/metabase/components/Grid.styled.tsx @@ -0,0 +1,13 @@ +import styled from "styled-components"; + +export const GridRoot = styled.div` + display: flex; + flex-wrap: wrap; + margin-left: -0.5rem; + margin-right: -0.5rem; +`; + +export const GridItemRoot = styled.div` + width: 25%; + padding: 0.5rem; +`; diff --git a/frontend/src/metabase/containers/UserCollectionList.jsx b/frontend/src/metabase/containers/UserCollectionList.jsx index a2490d4616f4bfa363550c8d46bf0e66ea4ccf74..6cc15074f7350f182eb9a45f4efd555038439ee7 100644 --- a/frontend/src/metabase/containers/UserCollectionList.jsx +++ b/frontend/src/metabase/containers/UserCollectionList.jsx @@ -7,7 +7,7 @@ import { color } from "metabase/lib/colors"; import Card from "metabase/components/Card"; import Icon from "metabase/components/Icon"; -import { Grid, GridItem } from "metabase/components/Grid"; +import { Grid } from "metabase/components/Grid"; import Link from "metabase/core/components/Link"; import BrowserCrumbs from "metabase/components/BrowserCrumbs"; @@ -16,7 +16,12 @@ import Collection, { ROOT_COLLECTION, PERSONAL_COLLECTIONS, } from "metabase/entities/collections"; -import { CardContent, ListHeader, ListRoot } from "./UserCollectionList.styled"; +import { + CardContent, + ListGridItem, + ListHeader, + ListRoot, +} from "./UserCollectionList.styled"; function mapStateToProps(state) { return { @@ -44,7 +49,7 @@ const UserCollectionList = ({ collectionsById }) => ( list.map( user => user.personal_collection_id && ( - <GridItem width={1 / 3} key={user.personal_collection_id}> + <ListGridItem key={user.personal_collection_id}> <Link to={Urls.collection( collectionsById[user.personal_collection_id], @@ -62,7 +67,7 @@ const UserCollectionList = ({ collectionsById }) => ( </CardContent> </Card> </Link> - </GridItem> + </ListGridItem> ), )} </Grid> diff --git a/frontend/src/metabase/containers/UserCollectionList.styled.tsx b/frontend/src/metabase/containers/UserCollectionList.styled.tsx index aa8433f47a57c51bee262e11d7c347888ad222c4..3e4c399a1b75619fae469a94c05263dd722a222a 100644 --- a/frontend/src/metabase/containers/UserCollectionList.styled.tsx +++ b/frontend/src/metabase/containers/UserCollectionList.styled.tsx @@ -1,4 +1,5 @@ import styled from "styled-components"; +import { GridItem } from "metabase/components/Grid"; export const ListRoot = styled.div` padding: 0 4rem; @@ -8,6 +9,10 @@ export const ListHeader = styled.div` padding: 1rem 0; `; +export const ListGridItem = styled(GridItem)` + width: 33.33%; +`; + export const CardContent = styled.div` display: flex; align-items: center; diff --git a/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx b/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx index a36074f20313720de376b792a42516a2c71f9747..98592bae93c2d4e1718660d852ced5a664589f21 100644 --- a/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx +++ b/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx @@ -8,7 +8,7 @@ import { t } from "ttag"; import fitViewport from "metabase/hoc/FitViewPort"; -import { Grid, GridItem } from "metabase/components/Grid"; +import { Grid } from "metabase/components/Grid"; import NewQueryOption from "metabase/new_query/components/NewQueryOption"; import NoDatabasesEmptyState from "metabase/reference/databases/NoDatabasesEmptyState"; @@ -19,7 +19,10 @@ import { getHasDataAccess, getHasNativeWrite, } from "metabase/new_query/selectors"; -import { QueryOptionsRoot } from "./NewQueryOptions.styled"; +import { + QueryOptionsGridItem, + QueryOptionsRoot, +} from "./NewQueryOptions.styled"; import Database from "metabase/entities/databases"; @@ -69,14 +72,13 @@ export default class NewQueryOptions extends Component { { /* Determine how many items will be shown based on permissions etc so we can make sure the layout adapts */ } - const NUM_ITEMS = (hasDataAccess ? 2 : 0) + (hasNativeWrite ? 1 : 0); - const ITEM_WIDTHS = [1, 1 / 2, 1 / NUM_ITEMS]; + const itemsCount = (hasDataAccess ? 2 : 0) + (hasNativeWrite ? 1 : 0); return ( <QueryOptionsRoot> <Grid className="justifyCenter"> {hasDataAccess && ( - <GridItem width={ITEM_WIDTHS}> + <QueryOptionsGridItem itemsCount={itemsCount}> <NewQueryOption image="app/img/simple_mode_illustration" title={t`Simple question`} @@ -85,10 +87,10 @@ export default class NewQueryOptions extends Component { to={Urls.newQuestion({ creationType: "simple_question" })} data-metabase-event={`New Question; Simple Question Start`} /> - </GridItem> + </QueryOptionsGridItem> )} {hasDataAccess && ( - <GridItem width={ITEM_WIDTHS}> + <QueryOptionsGridItem itemsCount={itemsCount}> <NewQueryOption image="app/img/notebook_mode_illustration" title={t`Custom question`} @@ -100,10 +102,10 @@ export default class NewQueryOptions extends Component { })} data-metabase-event={`New Question; Custom Question Start`} /> - </GridItem> + </QueryOptionsGridItem> )} {hasNativeWrite && ( - <GridItem width={ITEM_WIDTHS}> + <QueryOptionsGridItem itemsCount={itemsCount}> <NewQueryOption image="app/img/sql_illustration" title={t`Native query`} @@ -115,7 +117,7 @@ export default class NewQueryOptions extends Component { width={180} data-metabase-event={`New Question; Native Query Start`} /> - </GridItem> + </QueryOptionsGridItem> )} </Grid> </QueryOptionsRoot> diff --git a/frontend/src/metabase/new_query/containers/NewQueryOptions.styled.tsx b/frontend/src/metabase/new_query/containers/NewQueryOptions.styled.tsx index d165bf80d10e575a6a397f3ce9b1ed8e7d652f19..e47c77374f9b0e385c1da4233b98a494a63df5a5 100644 --- a/frontend/src/metabase/new_query/containers/NewQueryOptions.styled.tsx +++ b/frontend/src/metabase/new_query/containers/NewQueryOptions.styled.tsx @@ -1,5 +1,13 @@ import styled from "styled-components"; -import { breakpointMinSmall } from "metabase/styled-components/theme"; +import { + breakpointMinMedium, + breakpointMinSmall, +} from "metabase/styled-components/theme"; +import { GridItem } from "metabase/components/Grid"; + +const getPercentage = (number: number): string => { + return `${number * 100}%`; +}; export const QueryOptionsRoot = styled.div` margin: auto 0.5rem; @@ -9,3 +17,19 @@ export const QueryOptionsRoot = styled.div` margin-right: 4rem; } `; + +export interface QueryOptionsGridItemProps { + itemsCount: number; +} + +export const QueryOptionsGridItem = styled(GridItem)<QueryOptionsGridItemProps>` + width: 100%; + + ${breakpointMinSmall} { + width: 50%; + } + + ${breakpointMinMedium} { + width: ${props => getPercentage(1 / props.itemsCount)}; + } +`;