+
diff --git a/pkg/ui/src/views/dashboard/emailSubscription.styl b/pkg/ui/src/views/dashboard/emailSubscription.styl
new file mode 100644
index 000000000000..50c6edf8222d
--- /dev/null
+++ b/pkg/ui/src/views/dashboard/emailSubscription.styl
@@ -0,0 +1,79 @@
+// Copyright 2020 The Cockroach Authors.
+//
+// Use of this software is governed by the Business Source License
+// included in the file licenses/BSL.txt.
+//
+// As of the Change Date specified in that file, in accordance with
+// the Business Source License, use of this software will be governed
+// by the Apache License, Version 2.0, included in the file
+// licenses/APL.txt.
+
+@require '~src/components/core/index.styl'
+
+$text-width = 352px
+
+.crl-email-subscription
+ border-radius 5px
+ box-shadow: 0 0 1px 0 rgba(67, 90, 111, 0.41)
+ display flex
+ flex-direction row
+ align-items center
+ justify-content flex-end
+ height 90px
+ background-color $colors--white
+ background-image url("../../../assets/dashboard/email_signup_background.svg")
+ background-repeat no-repeat
+ background-position-x $text-width
+
+ &__text
+ font-size $font-size--large
+ font-family $font-family--base
+ line-height 1.6
+ letter-spacing -0.2px
+ color $colors--white
+ flex-grow 1
+ height inherit
+ border-radius inherit
+ & > div
+ max-width $text-width
+ background $colors--primary-green-3
+ padding-left $spacing-large
+ height inherit
+ border-bottom-left-radius: inherit;
+ border-top-left-radius: inherit;
+ display flex
+ align-items center
+
+
+ &__controls
+ flex-grow 0
+ margin-left $spacing-medium
+
+ &__close-button
+ flex-grow 0
+ color $colors--neutral-7
+ align-self flex-start
+ margin $spacing-smaller $spacing-small $spacing-small $spacing-medium
+ cursor pointer
+ font-size $font-size--large
+ line-height $spacing-smaller
+ font-weight $font-weight--extra-bold
+
+
+ @media (max-width: 1055px) {
+ background-position center
+
+ .crl-email-subscription__text {
+ font-size $font-size--tall
+ font-family $font-family--base
+ line-height 1.6
+ }
+ }
+
+ @media (max-width: 940px) {
+ background-position left
+
+ .crl-email-subscription__text {
+ display none
+ }
+ }
diff --git a/pkg/ui/src/views/dashboard/emailSubscription.tsx b/pkg/ui/src/views/dashboard/emailSubscription.tsx
new file mode 100644
index 000000000000..66db364e6bc5
--- /dev/null
+++ b/pkg/ui/src/views/dashboard/emailSubscription.tsx
@@ -0,0 +1,87 @@
+// Copyright 2020 The Cockroach Authors.
+//
+// Use of this software is governed by the Business Source License
+// included in the file licenses/BSL.txt.
+//
+// As of the Change Date specified in that file, in accordance with
+// the Business Source License, use of this software will be governed
+// by the Apache License, Version 2.0, included in the file
+// licenses/APL.txt.
+
+import React from "react";
+import { connect } from "react-redux";
+
+import { EmailSubscriptionForm } from "src/views/shared/components/emailSubscriptionForm";
+import { signUpForEmailSubscription } from "src/redux/customAnalytics";
+import { AdminUIState } from "src/redux/state";
+import { clusterIdSelector } from "src/redux/nodes";
+import { LocalSetting } from "src/redux/localsettings";
+
+import "./emailSubscription.styl";
+
+type EmailSubscriptionProps = MapDispatchToProps & MapStateToProps;
+
+class EmailSubscription extends React.Component
{
+ handleEmailSubscriptionSubmit = (email: string) => {
+ this.props.signUpForEmailSubscription(this.props.clusterId, email);
+ }
+
+ handlePanelHide = () => {
+ this.props.hidePanel();
+ }
+
+ render() {
+ const { isHiddenPanel } = this.props;
+
+ if (isHiddenPanel) {
+ return null;
+ }
+
+ return (
+
+
+
+
+ Keep up-to-date with CockroachDB
+ software releases and best practices.
+
+
+
+
+
+
+ ×
+
+
+
+ );
+ }
+}
+
+const hidePanelLocalSetting = new LocalSetting(
+ "dashboard/release_notes_signup/hide", (s) => s.localSettings, false,
+);
+
+interface MapDispatchToProps {
+ signUpForEmailSubscription: (clusterId: string, email: string) => void;
+ hidePanel: () => void;
+}
+
+const mapDispatchToProps = {
+ signUpForEmailSubscription,
+ hidePanel: () => hidePanelLocalSetting.set(true),
+};
+
+interface MapStateToProps {
+ isHiddenPanel: boolean;
+ clusterId: string;
+}
+const mapStateToProps = (state: AdminUIState) => ({
+ isHiddenPanel: hidePanelLocalSetting.selector(state),
+ clusterId: clusterIdSelector(state),
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(EmailSubscription);