diff --git a/web/components/status-indicator.css b/web/components/status-indicator.css new file mode 100644 --- /dev/null +++ b/web/components/status-indicator.css @@ -0,0 +1,30 @@ +.indicatorOuter { + border-radius: 50%; + height: 18px; + width: 18px; + display: flex; + justify-content: center; + align-items: center; +} + +.indicatorInner { + border-radius: 50%; + height: 8px; + width: 8px; +} + +.outerActive { + background-color: var(--statusIndicator-background-outer-active); +} + +.innerActive { + background-color: var(--statusIndicator-background-inner-active); +} + +.outerInactive { + background-color: var(--statusIndicator-background-outer-inactive); +} + +.innerInactive { + background-color: var(--statusIndicator-background-inner-inactive); +} diff --git a/web/components/status-indicator.react.js b/web/components/status-indicator.react.js new file mode 100644 --- /dev/null +++ b/web/components/status-indicator.react.js @@ -0,0 +1,38 @@ +// @flow + +import classNames from 'classnames'; +import * as React from 'react'; + +import type { ConnectionInfo } from 'lib/types/socket-types.js'; + +import css from './status-indicator.css'; + +type Props = { + +connectionInfo: ConnectionInfo, +}; + +function StatusIndicator(props: Props): React.Node { + const { connectionInfo } = props; + + const isConnected = connectionInfo.status === 'connected'; + + const outerClassName = classNames({ + [css.indicatorOuter]: true, + [css.outerActive]: isConnected, + [css.outerInactive]: !isConnected, + }); + + const innerClassName = classNames({ + [css.indicatorInner]: true, + [css.innerActive]: isConnected, + [css.innerInactive]: !isConnected, + }); + + return ( +
+
+
+ ); +} + +export default StatusIndicator; diff --git a/web/theme.css b/web/theme.css --- a/web/theme.css +++ b/web/theme.css @@ -294,6 +294,12 @@ --inputField-border-primary-default: var(--shades-black-75); --inputField-clearBackground-primary-default: var(--shades-black-60); --inputField-clearIcon-primary-default: var(--shades-white-100); + + /* Status Indicator */ + --statusIndicator-background-outer-active: var(--success-dark-90); + --statusIndicator-background-outer-inactive: var(--error-dark-90); + --statusIndicator-background-inner-active: var(--success-primary); + --statusIndicator-background-inner-inactive: var(--error-primary); } /* Light theme */ @@ -336,4 +342,10 @@ --inputField-border-primary-default: var(--shades-white-60); --inputField-clearBackground-primary-default: var(--shades-black-50); --inputField-clearIcon-primary-default: var(--shades-white-100); + + /* Status Indicator */ + --statusIndicator-background-outer-active: var(--success-dark-50); + --statusIndicator-background-outer-inactive: var(--error-dark-50); + --statusIndicator-background-inner-active: var(--success-primary); + --statusIndicator-background-inner-inactive: var(--error-primary); }