From 75e5454b926f1945f1c6477a60c4e8e1d88722bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Ramos?= Date: Tue, 31 Oct 2017 10:29:15 +0000 Subject: [PATCH] implement table components and integrate them (#822) * feat: implement table components and integrate them * fix(ui-toolkit): styleguide css * fix(ui-toolkit): merge --- packages/cloudapi-gql/package.json | 1 + packages/my-joy-beta/package.json | 6 +- .../src/components/instances/firewall-rule.js | 30 +- .../src/components/instances/index.js | 2 - .../src/components/instances/list.js | 170 +++++- .../src/components/instances/network.js | 25 +- .../src/components/instances/snapshot.js | 56 -- .../src/components/instances/snapshots.js | 61 ++- .../src/containers/instances/firewall.js | 43 +- .../src/containers/instances/networks.js | 46 +- packages/ui-toolkit/package.json | 1 + packages/ui-toolkit/src/card/demo.md | 46 +- packages/ui-toolkit/src/card/index.js | 2 +- packages/ui-toolkit/src/card/test.md | 26 +- packages/ui-toolkit/src/card/usage.md | 486 ------------------ packages/ui-toolkit/src/icons/dot.js | 12 + packages/ui-toolkit/src/icons/index.js | 1 + packages/ui-toolkit/src/index.js | 10 + packages/ui-toolkit/src/popover/item.js | 1 + packages/ui-toolkit/src/table/index.js | 262 ++++++++++ packages/ui-toolkit/src/table/usage.md | 40 ++ packages/ui-toolkit/styleguide.config.js | 1 + yarn.lock | 4 + 23 files changed, 656 insertions(+), 676 deletions(-) delete mode 100644 packages/my-joy-beta/src/components/instances/snapshot.js delete mode 100644 packages/ui-toolkit/src/card/usage.md create mode 100644 packages/ui-toolkit/src/icons/dot.js create mode 100644 packages/ui-toolkit/src/table/index.js create mode 100644 packages/ui-toolkit/src/table/usage.md diff --git a/packages/cloudapi-gql/package.json b/packages/cloudapi-gql/package.json index f1ea3962..642c2b2d 100644 --- a/packages/cloudapi-gql/package.json +++ b/packages/cloudapi-gql/package.json @@ -41,6 +41,7 @@ "triton": "^5.4.0" }, "devDependencies": { + "graphql-faker": "^1.5.0", "eslint": "^4.9.0", "eslint-config-joyent-portal": "^3.2.0", "eslint-plugin-graphql": "^1.4.0-1", diff --git a/packages/my-joy-beta/package.json b/packages/my-joy-beta/package.json index ac37f14e..aa69d37a 100644 --- a/packages/my-joy-beta/package.json +++ b/packages/my-joy-beta/package.json @@ -9,8 +9,10 @@ "dev": "REACT_APP_GQL_PORT=4000 PORT=3069 REACT_APP_GQL_PROTOCOL=http joyent-react-scripts start", "start": "PORT=3069 joyent-react-scripts start", "build": "NODE_ENV=production joyent-react-scripts build", - "lint-ci": "eslint . --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`", - "lint": "eslint . --fix --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`", + "lint-ci": + "eslint . --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`", + "lint": + "eslint . --fix --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`", "test-ci": "echo 0 `# NODE_ENV=test ./test/run --env=jsdom --coverage`", "test": "NODE_ENV=test ./test/run --env=jsdom", "prepublish": "echo 0" diff --git a/packages/my-joy-beta/src/components/instances/firewall-rule.js b/packages/my-joy-beta/src/components/instances/firewall-rule.js index 5e70e0ad..168246d7 100644 --- a/packages/my-joy-beta/src/components/instances/firewall-rule.js +++ b/packages/my-joy-beta/src/components/instances/firewall-rule.js @@ -1,27 +1,15 @@ import React from 'react'; +import forceArray from 'force-array'; import { - Card, - CardMeta, - CardTitle, - CardLabel, - CardView + TableTr, + TableTd } from 'joyent-ui-toolkit'; -export default ({ - rule = '', - global = false, - enabled = false, - first, - last -}) => ( - - - - {rule} - - - - - +export default ({ rule = '', global = false, enabled = false }) => ( + + {rule} + {JSON.stringify(global)} + {JSON.stringify(enabled)} + ); diff --git a/packages/my-joy-beta/src/components/instances/index.js b/packages/my-joy-beta/src/components/instances/index.js index 115137b4..1de93acc 100644 --- a/packages/my-joy-beta/src/components/instances/index.js +++ b/packages/my-joy-beta/src/components/instances/index.js @@ -1,4 +1,3 @@ -export { default as Item } from './item'; export { default as List } from './list'; export { default as KeyValue } from './key-value'; export { default as Network } from './network'; @@ -6,4 +5,3 @@ export { default as FirewallRule } from './firewall-rule'; export { default as Resize } from './resize'; export { default as CreateSnapshot } from './create-snapshot'; export { default as Snapshots } from './snapshots'; -export { default as Snapshot } from './snapshot'; diff --git a/packages/my-joy-beta/src/components/instances/list.js b/packages/my-joy-beta/src/components/instances/list.js index cb5a3ebe..0cb45fd1 100644 --- a/packages/my-joy-beta/src/components/instances/list.js +++ b/packages/my-joy-beta/src/components/instances/list.js @@ -2,6 +2,8 @@ import React from 'react'; import { Row, Col } from 'react-styled-flexboxgrid'; import forceArray from 'force-array'; import find from 'lodash.find'; +import remcalc from 'remcalc'; +import titleCase from 'title-case'; import { FormGroup, @@ -14,12 +16,105 @@ import { MessageTitle, MessageDescription, Button, - QueryBreakpoints + QueryBreakpoints, + Table, + TableThead, + TableTr, + TableTh, + TableTbody, + TableTd, + Checkbox, + P, + DotIcon, + IconActions, + PopoverContainer, + PopoverTarget, + Popover, + PopoverItem, + PopoverDivider, + Anchor } from 'joyent-ui-toolkit'; -import Item from './item'; +const { SmallOnly, Small, Medium } = QueryBreakpoints; -const { SmallOnly, Medium } = QueryBreakpoints; +const stateColor = { + PROVISIONING: 'primary', + RUNNING: 'green', + STOPPING: 'grey', + STOPPED: 'grey', + DELETED: 'secondaryActive', + FAILED: 'red' +}; + +const Item = ({ + id, + name, + state, + allowedActions, + onStop, + onStart, + onReboot, + onResize, + onEnableFw, + onDisableFw, + onCreateSnap, + onStartSnap +}) => ( + + + + + + + + {id.substring(0, 7)} + + + {name} + + + {titleCase(state)} + + + + + + + + {!allowedActions.stop ? null : ( + Stop + )} + {!allowedActions.start ? null : ( + Start + )} + {!allowedActions.reboot ? null : ( + Reboot + )} + {!allowedActions.enableFw ? null : ( + Enable Firewall + )} + {!allowedActions.disableFw ? null : ( + Disable Firewall + )} + {!allowedActions.disableFw ? null : ( + Disable Firewall + )} + + {!allowedActions.resize ? null : ( + Resize + )} + {!allowedActions.createSnap ? null : ( + Create Snapshot + )} + {!allowedActions.startSnap ? null : ( + Start from Snapshot + )} + Delete + + + + +); export default ({ instances = [], @@ -59,23 +154,39 @@ export default ({ }); }; - const _instances = forceArray(instances); - - const items = _instances.map((instance, i, all) => { - const { id } = instance; - + const items = forceArray(instances).map(instance => { + // eslint-disable-next-line camelcase + const { id, name, state, firewall_enabled, snapshots, brand } = instance; const isSelected = Boolean(find(selected, ['id', id])); const isSubmitting = isSelected && submitting; - return ( - - ); + const allowedActions = { + stop: state === 'RUNNING', + start: state !== 'RUNNING', + reboot: true, + resize: brand === 'KVM', + // eslint-disable-next-line camelcase + enableFw: !firewall_enabled, + // eslint-disable-next-line camelcase + disableFw: firewall_enabled, + createSnap: true, + startSnap: Boolean(snapshots.length) + }; + + return { + ...instance, + isSubmitting, + isSelected, + allowedActions, + onStop: () => onAction({ name: 'stop', items: [instance] }), + onStart: () => onAction({ name: 'start', items: [instance] }), + onReboot: () => onAction({ name: 'reboot', items: [instance] }), + onResize: () => onAction({ name: 'resize', items: [instance] }), + onEnableFw: () => onAction({ name: 'enableFw', items: [instance] }), + onDisableFw: () => onAction({ name: 'disableFw', items: [instance] }), + onCreateSnap: () => onAction({ name: 'createSnap', items: [instance] }), + onStartSnap: () => onAction({ name: 'startSnap', items: [instance] }) + }; }); const _loading = @@ -93,6 +204,27 @@ export default ({ ); + const _table = !items.length ? null : ( + + + + + +

Id

+
+ +

Name

+
+ +

Status

+
+ +
+
+ {items.map(instance => )} +
+ ); + return (
@@ -196,9 +328,9 @@ export default ({ - {_loading} {_error} - {items} + {_loading} + {_table}
); }; diff --git a/packages/my-joy-beta/src/components/instances/network.js b/packages/my-joy-beta/src/components/instances/network.js index 01f12e69..ab88e88d 100644 --- a/packages/my-joy-beta/src/components/instances/network.js +++ b/packages/my-joy-beta/src/components/instances/network.js @@ -2,22 +2,15 @@ import React from 'react'; import forceArray from 'force-array'; import { - Card, - CardMeta, - CardTitle, - CardLabel, - CardView + TableTr, + TableTd } from 'joyent-ui-toolkit'; -export default ({ name, gateway, subnet, resolvers = [], first, last }) => ( - - - - {name} - {gateway} - {subnet} - {forceArray(resolvers).join('\u00B7')} - - - +export default ({ name, gateway, subnet, resolvers = [] }) => ( + + {name} + {gateway} + {subnet} + {forceArray(resolvers).join('\u00B7')} + ); diff --git a/packages/my-joy-beta/src/components/instances/snapshot.js b/packages/my-joy-beta/src/components/instances/snapshot.js deleted file mode 100644 index d11dbad8..00000000 --- a/packages/my-joy-beta/src/components/instances/snapshot.js +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react'; -import titleCase from 'title-case'; -import moment from 'moment'; - -import { - Card, - CardMeta, - CardAction, - CardTitle, - CardLabel, - CardView, - Checkbox, - FormGroup, - QueryBreakpoints, - StatusLoader -} from 'joyent-ui-toolkit'; - -const { SmallOnly, Small } = QueryBreakpoints; - -const stateColor = { - QUEUED: 'blue', - CANCELED: 'grey', - FAILED: 'red', - CREATED: 'green' -}; - -export default ({ name, state, created, loading, last, first }) => ( - - - - - - - - - {name} - {moment.unix(created).fromNow()} - {loading && ( - - - - )} - {!loading && ( - - {titleCase(state)} - - )} - {!loading && ( - - - - )} - - - -); diff --git a/packages/my-joy-beta/src/components/instances/snapshots.js b/packages/my-joy-beta/src/components/instances/snapshots.js index 3788d9f0..2a226ce7 100644 --- a/packages/my-joy-beta/src/components/instances/snapshots.js +++ b/packages/my-joy-beta/src/components/instances/snapshots.js @@ -2,6 +2,7 @@ import React from 'react'; import { Row, Col } from 'react-styled-flexboxgrid'; import forceArray from 'force-array'; import find from 'lodash.find'; +import moment from 'moment'; import { FormGroup, @@ -14,13 +15,31 @@ import { MessageTitle, MessageDescription, Button, - QueryBreakpoints + QueryBreakpoints, + Table, + TableThead, + TableTr, + TableTh, + TableTbody, + TableTd, + Checkbox, + P } from 'joyent-ui-toolkit'; -import Item from './snapshot'; - const { SmallOnly, Medium } = QueryBreakpoints; +const Item = ({ name, state, created }) => ( + + + + + + + {name} + {moment.unix(created).fromNow()} + +); + export default ({ snapshots = [], selected = [], @@ -57,21 +76,16 @@ export default ({ ); - const items = _snapshots.map((snapshot, i, all) => { + const items = _snapshots.map(snapshot => { const { name } = snapshot; - const isSelected = Boolean(find(selected, ['name', name])); const isSubmitting = isSelected && submitting; - return ( - - ); + return { + ...snapshot, + isSubmitting, + isSelected + }; }); const _error = error && @@ -82,6 +96,23 @@ export default ({ ); + const _table = !items.length ? null : ( + + + + + +

Name

+
+ +

Created

+
+
+
+ {items.map(snapshot => )} +
+ ); + return (
handleSubmit(ctx => handleChange(ctx))} @@ -156,7 +187,7 @@ export default ({ {_loading} {_error} - {items} + {_table}
); }; diff --git a/packages/my-joy-beta/src/containers/instances/firewall.js b/packages/my-joy-beta/src/containers/instances/firewall.js index eab2013f..e50c96ff 100644 --- a/packages/my-joy-beta/src/containers/instances/firewall.js +++ b/packages/my-joy-beta/src/containers/instances/firewall.js @@ -11,7 +11,13 @@ import { StatusLoader, Message, MessageDescription, - MessageTitle + MessageTitle, + Table, + TableThead, + TableTr, + TableTh, + TableTbody, + P } from 'joyent-ui-toolkit'; import GetFirewallRules from '@graphql/list-firewall-rules.gql'; @@ -28,16 +34,31 @@ const Firewall = ({ const _title = Firewall; const _loading = !(loading && !values.length) ? null : ; - const _firewall = - !_loading && - values.map((rule, i, all) => ( - - )); + const _firewall = (_loading && !values.length) ? null : ( + + + + +

Rule

+
+ +

Global

+
+ +

Enabled

+
+
+
+ { + values.map((network) => ( + + ))} + +
+ ); const _error = error && !values.length && !_loading ? ( diff --git a/packages/my-joy-beta/src/containers/instances/networks.js b/packages/my-joy-beta/src/containers/instances/networks.js index 4eb9ce99..91f3ef2b 100644 --- a/packages/my-joy-beta/src/containers/instances/networks.js +++ b/packages/my-joy-beta/src/containers/instances/networks.js @@ -11,7 +11,13 @@ import { StatusLoader, Message, MessageDescription, - MessageTitle + MessageTitle, + Table, + TableThead, + TableTr, + TableTh, + TableTbody, + P } from 'joyent-ui-toolkit'; import GetNetworks from '@graphql/list-networks.gql'; @@ -22,16 +28,34 @@ const Networks = ({ networks = [], loading, error }) => { const _title = Networks; const _loading = !(loading && !values.length) ? null : ; - const _networks = - !_loading && - values.map((network, i, all) => ( - - )); + const _networks = (_loading && !values.length) ? null : ( + + + + +

Name

+
+ +

Gateway

+
+ +

Subnet

+
+ +

Resolvers

+
+
+
+ { + values.map((network) => ( + + ))} + +
+ ); const _error = error && !values.length && !_loading ? ( diff --git a/packages/ui-toolkit/package.json b/packages/ui-toolkit/package.json index ad0d2f16..adc4ea94 100644 --- a/packages/ui-toolkit/package.json +++ b/packages/ui-toolkit/package.json @@ -75,6 +75,7 @@ "jest-snapshot": "^21.2.1", "jest-styled-components": "^4.9.0", "joyent-react-scripts": "^2.6.0", + "lodash.isboolean": "^3.0.3", "navalia": "^1.2.0", "react": "^16.0.0", "react-docgen": "^3.0.0-beta8", diff --git a/packages/ui-toolkit/src/card/demo.md b/packages/ui-toolkit/src/card/demo.md index f8f3dd70..7b6d4adb 100644 --- a/packages/ui-toolkit/src/card/demo.md +++ b/packages/ui-toolkit/src/card/demo.md @@ -1,6 +1,6 @@ ```jsx const React = require('react'); -const { Card } = require('.'); +const { default: Card } = require('.'); ; ``` @@ -9,7 +9,7 @@ const { Card } = require('.'); ```jsx const React = require('react'); -const { Card } = require('.'); +const { default: Card } = require('.'); ; ``` @@ -18,7 +18,7 @@ const { Card } = require('.'); ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); const { H4, P } = require('../text'); @@ -31,10 +31,10 @@ const {
- +

Nginx

- +

4 of 4 instances

@@ -52,7 +52,7 @@ const { ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); const { H4, P } = require('../text'); @@ -66,10 +66,10 @@ const {
- +

Nginx

- +

4 of 4 instances

@@ -104,7 +104,7 @@ const { ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); const { H4, P, Small } = require('../text'); @@ -117,10 +117,10 @@ const {
- +

Nginx

- +

4 of 4 instances

@@ -143,7 +143,7 @@ const { ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); const { H4, P } = require('../text'); const { default: StatusLoader } = require('../status-loader'); @@ -184,10 +184,10 @@ const {
- +

Nginx

- +

4 of 4 instances

@@ -233,7 +233,7 @@ const { ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); const { H4, P } = require('../text'); const { IconActions } = require('../icons'); @@ -245,7 +245,7 @@ const { IconActions } = require('../icons');

Nginx

- +

1 Instance

@@ -262,7 +262,7 @@ const { IconActions } = require('../icons'); ```jsx const React = require('react'); -const { Card, Outlet } = require('.'); +const { default: Card, Outlet } = require('.'); const { H4, P } = require('../text'); const { HealthyIcon } = require('../icons'); @@ -294,7 +294,7 @@ const { HealthyIcon } = require('../icons'); ```jsx const React = require('react'); -const { Card, Outlet } = require('.'); +const { default: Card, Outlet } = require('.'); const { H4, P } = require('../text'); const { HealthyIcon } = require('../icons'); @@ -326,7 +326,7 @@ const { HealthyIcon } = require('../icons'); ```jsx const React = require('react'); -const { Card, Outlet } = require('.'); +const { default: Card, Outlet } = require('.'); const { H4, P } = require('../text'); const { HealthyIcon } = require('../icons'); @@ -404,7 +404,7 @@ const { HealthyIcon } = require('../icons'); ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); const { H4, P } = require('../text'); const { HealthyIcon, IconActions, DataCenterIcon } = require('../icons'); @@ -414,15 +414,15 @@ const { HealthyIcon, IconActions, DataCenterIcon } = require('../icons');
- +

Nginx

- +

Healthy

- +

eu-ams-1

diff --git a/packages/ui-toolkit/src/card/index.js b/packages/ui-toolkit/src/card/index.js index dc8a7d26..c48854ba 100644 --- a/packages/ui-toolkit/src/card/index.js +++ b/packages/ui-toolkit/src/card/index.js @@ -1,4 +1,4 @@ -export { default as Card } from './card'; +export { default } from './card'; export { default as Outlet } from './outlet'; export { diff --git a/packages/ui-toolkit/src/card/test.md b/packages/ui-toolkit/src/card/test.md index f3a2b3ea..4524d4f3 100644 --- a/packages/ui-toolkit/src/card/test.md +++ b/packages/ui-toolkit/src/card/test.md @@ -2,7 +2,7 @@ ```jsx const React = require('react'); -const { Card } = require('.'); +const { default: Card } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -36,7 +36,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card } = require('.'); +const { default: Card } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -70,7 +70,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card } = require('.'); +const { default: Card } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -128,7 +128,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card } = require('.'); +const { default: Card } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -186,7 +186,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card } = require('.'); +const { default: Card } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -244,7 +244,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card, Header } = require('.'); +const { default: Card, Header } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -317,7 +317,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card, Header } = require('.'); +const { default: Card, Header } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -390,7 +390,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card, Header } = require('.'); +const { default: Card, Header } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -463,7 +463,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -590,7 +590,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -729,7 +729,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -889,7 +889,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ @@ -1094,7 +1094,7 @@ const { Row, Col } = require('react-styled-flexboxgrid'); ```jsx const React = require('react'); -const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); +const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.'); const { Row, Col } = require('react-styled-flexboxgrid'); [ diff --git a/packages/ui-toolkit/src/card/usage.md b/packages/ui-toolkit/src/card/usage.md deleted file mode 100644 index 1c2abeac..00000000 --- a/packages/ui-toolkit/src/card/usage.md +++ /dev/null @@ -1,486 +0,0 @@ -#### Card > Headed > Collapsed - -```jsx -const { - CardDescription, - CardHeader, - CardMeta, - CardOptions, - CardOutlet, - CardSubTitle, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const { InstancesIconLight } = require('../icons'); - - - - - Nginx - - - - - - - 4 of 4 instances - - - - - - -; -``` - -#### Card > Headed - -```jsx -const { - CardDescription, - CardHeader, - CardMeta, - CardOptions, - CardOutlet, - CardSubTitle, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const { InstancesIconLight, HealthyIcon } = require('../icons'); - - - - - Nginx - - - - - - - 4 of 4 instances - - - - - - - - - } - iconPosition="left" - label="Healthy" - color="dark" - /> - - -; -``` - -#### Card > Single state - -```jsx -const { - CardDescription, - CardHeader, - CardMeta, - CardOptions, - CardOutlet, - CardSubTitle, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const { InstancesIconLight, HealthyIcon } = require('../icons'); - - - - - Nginx - - - - - - - 4 of 4 instances - - - - - - - - - 1 instance paused
- 1 instances stopped
- 1 instance not responding
-
-
-
; -``` - -#### Card > Provisioning - -```jsx -const { - CardDescription, - CardHeader, - CardMeta, - CardOptions, - CardOutlet, - CardSubTitle, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const StatusLoader = require('../status-loader').default; -const { InstancesIconLight, HealthyIcon } = require('../icons'); - - - - - - Nginx - - - - - -; -``` - -```jsx -const { - CardDescription, - CardHeader, - CardMeta, - CardOptions, - CardOutlet, - CardSubTitle, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const StatusLoader = require('../status-loader').default; -const { InstancesIconLight, HealthyIcon } = require('../icons'); - - - - - Nginx - - - - - - - 4 of 4 instances - - - - - - - - - -
-
-
- - - - - Healthy - -
-
-
; -``` - -#### Card > Disabled - -```jsx -const { - CardDescription, - CardHeader, - CardMeta, - CardOptions, - CardOutlet, - CardSubTitle, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const { InstancesIcon, HealthyIcon } = require('../icons'); -const StatusLoader = require('../status-loader').default; - - - - - Nginx - - - - - - 4 of 4 instances - - - - - - - - - - -; -``` - -#### Card > Instance - -```jsx -const { - CardDescription, - CardOutlet, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const { Row } = require('react-styled-flexboxgrid'); -const { InstancesIconLight, HealthyIcon } = require('../icons'); - - - - - percona_primary - - - - - Healthy - - - -; -``` - -#### Card > Instance > Stacked - -```jsx -const { - CardDescription, - CardOutlet, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const { Row } = require('react-styled-flexboxgrid'); -const { InstancesIconLight, HealthyIcon } = require('../icons'); - - - - - percona_primary - 4 instances - - - - - Healthy - - - -; -``` - -#### Card > Instance > Group - -```jsx -const { - CardDescription, - CardOutlet, - CardTitle, - CardView, - CardInfo, - CardInfoLabel, - CardInfoIconContainer -} = require('./'); - -const { Row } = require('react-styled-flexboxgrid'); -const { InstancesIconLight, HealthyIcon } = require('../icons'); - -
- - - - percona_primary - - - - - Healthy - - - - - - - - percona_primary - - - - - Healthy - - - - - - - - percona_primary - 4 instances - - - - - Healthy - - - - -
; -``` - -#### Card > Instance > List - -```jsx -const { - Card, - CardInfo, - CardInfoLabel, - CardInfoIconContainer, - CardView, - CardTitle, - CardDescription, - CardOptions -} = require('./'); - -const { HealthyIcon, DataCenterIcon } = require('../icons'); - - - - WordPress_01 - - - - - - Healthy - - - - - - - - Healthy - - - - -; -``` - -#### Card > Secondary - -```jsx -const { - CardDescription, - CardHeader, - CardMeta, - CardOptions, - CardOutlet, - CardSubTitle, - CardTitle, - CardView, - CardGroupView, - CardFooter -} = require('./'); - - - - - $0.016 per hour - 0.256 GB RAM - 0.25 vCPUs - 0.01 TB disk - SSD - - Compute Optimise - - -; -``` - -#### Card > Secondary > Active - -```jsx -const { - CardDescription, - CardHeader, - CardMeta, - CardOptions, - CardOutlet, - CardSubTitle, - CardTitle, - CardView, - CardGroupView, - CardFooter -} = require('./'); - - - - - $0.016 per hour - 0.256 GB RAM - 0.25 vCPUs - 0.01 TB disk - SSD - - Compute Optimise - - -; -``` diff --git a/packages/ui-toolkit/src/icons/dot.js b/packages/ui-toolkit/src/icons/dot.js new file mode 100644 index 00000000..71a04586 --- /dev/null +++ b/packages/ui-toolkit/src/icons/dot.js @@ -0,0 +1,12 @@ +import remcalc from 'remcalc'; +import styled from 'styled-components'; + +import Baseline from '../baseline'; + +export default Baseline(styled.span` + width: ${remcalc(6)}; + height: ${remcalc(6)}; + border-radius: ${remcalc(3)}; + background-color: ${props => props.theme[props.color]}; + display: inline-block; +`); diff --git a/packages/ui-toolkit/src/icons/index.js b/packages/ui-toolkit/src/icons/index.js index 6e82337c..0f683781 100644 --- a/packages/ui-toolkit/src/icons/index.js +++ b/packages/ui-toolkit/src/icons/index.js @@ -15,6 +15,7 @@ export { default as UserIcon } from './user'; export { default as UserIconLight } from './user-light'; export { default as DataCenterIcon } from './data-center'; export { default as DataCenterIconLight } from './data-center-light'; +export { default as DotIcon } from './dot'; export { default as ChevronIcon } from './chevron'; export { default as TritonIcon } from './triton'; export { default as TritonBetaIcon } from './triton-beta' diff --git a/packages/ui-toolkit/src/index.js b/packages/ui-toolkit/src/index.js index cab45194..ed6ed07c 100644 --- a/packages/ui-toolkit/src/index.js +++ b/packages/ui-toolkit/src/index.js @@ -114,6 +114,7 @@ export { UserIcon, DataCenterIcon, DataCenterIconLight, + DotIcon, ChevronIcon, TritonIcon, UserIconLight, @@ -138,3 +139,12 @@ export { Divider as PopoverDivider, default as Popover } from './popover'; + +export { + default as Table, + Thead as TableThead, + Tr as TableTr, + Th as TableTh, + Tbody as TableTbody, + Td as TableTd +} from './table'; diff --git a/packages/ui-toolkit/src/popover/item.js b/packages/ui-toolkit/src/popover/item.js index 101c16f3..66f6c458 100644 --- a/packages/ui-toolkit/src/popover/item.js +++ b/packages/ui-toolkit/src/popover/item.js @@ -1,4 +1,5 @@ import remcalc from 'remcalc'; + import { H4 } from '../text/headings'; export default H4.extend` diff --git a/packages/ui-toolkit/src/table/index.js b/packages/ui-toolkit/src/table/index.js new file mode 100644 index 00000000..b923022a --- /dev/null +++ b/packages/ui-toolkit/src/table/index.js @@ -0,0 +1,262 @@ +import React from 'react'; +import { Broadcast, Subscriber } from 'joy-react-broadcast'; +import isBoolean from 'lodash.isboolean'; +import styled, { css } from 'styled-components'; +import is from 'styled-is'; +import remcalc from 'remcalc'; + +import Baseline from '../baseline'; +import { bottomShadow } from '../boxes'; +import * as breakpoints from '../breakpoints'; + +const { styled: query } = breakpoints; + +const handleBreakpoint = bp => props => { + const hidden = + (isBoolean(props[bp]) && !props[bp]) || Number(props[bp]) === 0; + const width = remcalc(props[bp]); + + return ` + width: ${width}; + + ${hidden && + ` + display: none; + `}; + `; +}; + +const ColumnBorder = css` + ${is('border')` + border-${props => props.border}-width: ${remcalc(1)}; + `}; +`; + +const Column = css` + border-width: ${remcalc(1)}; + border-style: solid; + border-color: ${props => props.theme.grey}; + border-spacing: 0; + + ${is('disabled')` + border-color: ${props => props.theme.grey}; + `}; + + white-space: nowrap; + + box-sizing: border-box; + padding: 0 ${remcalc(8)} 0 ${remcalc(8)}; + height: ${remcalc(48)}; + + ${handleBreakpoint('xs')}; + + ${query.small` + ${handleBreakpoint('sm')}; + `}; + + ${query.medium` + ${handleBreakpoint('md')}; + `}; + + ${query.xlargeUp` + ${handleBreakpoint('lg')}; + `}; + + ${is('actionable')` + cursor: pointer; + + &:hover { + background-color: ${props => props.theme.whiteHover}; + } + + &:active { + background-color: ${props => props.theme.whiteActive}; + } + `}; + + ${is('baseline')` + vertical-align: baseline; + `}; + + ${is('sub')` + vertical-align: sub; + `}; + + ${is('text-top')` + vertical-align: text-top; + `}; + + ${is('text-bottom')` + vertical-align: text-bottom; + `}; + + ${is('middle')` + vertical-align: middle; + `}; + + ${is('top')` + vertical-align: top; + `}; + + ${is('bottom')` + vertical-align: bottom; + `}; + + ${is('center')` + text-align: center; + `}; + + ${is('left')` + text-align: left; + `}; + + ${is('right')` + text-align: right; + `}; +`; + +const BaseTable = styled.table` + border-collapse: collapse; + table-layout: fixed; + width: 100%; +`; + +const BaseThead = styled.thead` + width: 100%; +`; + +const BaseTbody = styled.tbody` + width: 100%; + + border-width: ${remcalc(1)}; + border-style: solid; + border-color: ${props => props.theme.grey}; + + ${is('shadow')` + box-shadow: ${bottomShadow}; + `}; + + ${is('actionable')` + cursor: pointer; + `}; + + ${is('disabled')` + border-color: ${props => props.theme.grey}; + `}; +`; + +const BaseTh = styled.th` + ${Column}; + + border-left-width: 0; + border-right-width: 0; + border-top-width: 0; + padding-top: 0; + padding-bottom: ${remcalc(5)}; + + ${ColumnBorder}; +`; + +const BaseTd = styled.td` + ${Column}; + + border-left-width: 0; + border-right-width: 0; + + ${ColumnBorder}; +`; + +const BaseTr = styled.tr` + display: table-row; + + color: ${props => props.theme.text}; + background-color: ${props => props.theme.white}; + + ${is('actionable')` + cursor: pointer; + `}; + + ${is('disabled')` + background-color: ${props => props.theme.disabled}; + color: ${props => props.theme.text}; + cursor: default; + `}; + + /* override background when thead > tr */ + ${is('header')` + color: ${props => props.theme.text}; + background-color: transparent; + `}; +`; + +/** + * @example ./usage.md + */ +export default Baseline(({ children, ...rest }) => ( + + {children} + +)); + +const Propagate = ({ children, ...rest }) => ( + + {({ disabled, header }) => ( + + {children({ disabled, header, ...rest })} + + )} + +); + +export const Thead = Baseline(({ children, ...rest }) => ( + + {value => ( + + {children} + + )} + +)); + +export const Tr = Baseline(({ children, ...rest }) => ( + + {value => ( + + {children} + + )} + +)); + +export const Th = Baseline(({ children, ...rest }) => ( + + {value => ( + + {children} + + )} + +)); + +export const Tbody = Baseline(({ children, ...rest }) => ( + + {value => ( + + {children} + + )} + +)); + +export const Td = Baseline(({ children, ...rest }) => ( + + {value => ( + + {children} + + )} + +)); diff --git a/packages/ui-toolkit/src/table/usage.md b/packages/ui-toolkit/src/table/usage.md new file mode 100644 index 00000000..f090e0be --- /dev/null +++ b/packages/ui-toolkit/src/table/usage.md @@ -0,0 +1,40 @@ +```jsx +const React = require('react'); +const { default: Table, Thead, Tr, Th, Tbody, Td } = require('./'); +const { H4, P } = require('../text'); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ NameStatusShort ID +
HB

percona_high-ram-32_1

Provisioning2252839aHB
HBpercona_high-ram-32_2Provisioning2252839bHB
HBpercona_high-ram-32_3Provisioning2252839bHB
+``` diff --git a/packages/ui-toolkit/styleguide.config.js b/packages/ui-toolkit/styleguide.config.js index 0d25bd14..ebd4874a 100644 --- a/packages/ui-toolkit/styleguide.config.js +++ b/packages/ui-toolkit/styleguide.config.js @@ -61,6 +61,7 @@ module.exports = { name: 'Components', components: () => [ 'src/card/card.js', + 'src/table/index.js', 'src/breadcrumb/index.js', 'src/button/index.js', 'src/form/checkbox.js', diff --git a/yarn.lock b/yarn.lock index 9c22d5e3..83a13696 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7466,6 +7466,10 @@ lodash.isarraylike@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.isarraylike/-/lodash.isarraylike-4.2.0.tgz#4623310ab318804b667ddc3619058137559400c4" +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + lodash.isempty@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e"