diff --git a/assets/newspack-ui/index.js b/assets/newspack-ui/index.js
index 423b033ce7..72c8d03a0b 100644
--- a/assets/newspack-ui/index.js
+++ b/assets/newspack-ui/index.js
@@ -1 +1,2 @@
import './style.scss';
+import './js/index.js';
diff --git a/assets/newspack-ui/js/index.js b/assets/newspack-ui/js/index.js
new file mode 100644
index 0000000000..1075a5b952
--- /dev/null
+++ b/assets/newspack-ui/js/index.js
@@ -0,0 +1 @@
+import './segmented-control';
diff --git a/assets/newspack-ui/js/segmented-control/index.js b/assets/newspack-ui/js/segmented-control/index.js
new file mode 100644
index 0000000000..ef1d2103de
--- /dev/null
+++ b/assets/newspack-ui/js/segmented-control/index.js
@@ -0,0 +1,34 @@
+import { domReady } from '../utils'; // Global utils.
+
+domReady( function () {
+ function segmented_control( element ) {
+ const header = element.querySelector( '.newspack-ui__segmented-control__tabs' );
+ const tab_headers = [ ...header.children ];
+ const tab_body = element.querySelector( '.newspack-ui__segmented-control__content' );
+ let tab_contents = [];
+
+ if ( null !== tab_body ) {
+ tab_contents = [ ...tab_body.children ];
+ }
+
+ tab_headers.forEach( ( tab, i ) => {
+ if ( tab_contents.length !== 0 && tab.classList.contains( 'selected' ) ) {
+ tab_contents[ i ].classList.add( 'selected' );
+ }
+
+ tab.addEventListener( 'click', function () {
+ tab_headers.forEach( t => t.classList.remove( 'selected' ) );
+ this.classList.add( 'selected' );
+
+ if ( tab_contents.length !== 0 ) {
+ tab_contents.forEach( content => content.classList.remove( 'selected' ) );
+ tab_contents[ i ].classList.add( 'selected' );
+ }
+ } );
+ } );
+ }
+
+ [ ...document.querySelectorAll( '.newspack-ui__segmented-control' ) ].forEach( x =>
+ segmented_control( x )
+ );
+} );
diff --git a/assets/newspack-ui/js/utils/index.js b/assets/newspack-ui/js/utils/index.js
new file mode 100644
index 0000000000..17c2b92274
--- /dev/null
+++ b/assets/newspack-ui/js/utils/index.js
@@ -0,0 +1,25 @@
+/**
+ * Util functions.
+ */
+
+/**
+ * Specify a function to execute when the DOM is fully loaded.
+ *
+ * @see https://github.com/WordPress/gutenberg/blob/trunk/packages/dom-ready/
+ *
+ * @param {Function} callback A function to execute after the DOM is ready.
+ * @return {void}
+ */
+export const domReady = callback => {
+ if ( typeof document === 'undefined' ) {
+ return;
+ }
+ if (
+ document.readyState === 'complete' || // DOMContentLoaded + Images/Styles/etc loaded, so we call directly.
+ document.readyState === 'interactive' // DOMContentLoaded fires at this point, so we call directly.
+ ) {
+ return void callback();
+ }
+ // DOMContentLoaded has not fired yet, delay callback until then.
+ document.addEventListener( 'DOMContentLoaded', callback );
+};
diff --git a/assets/newspack-ui/scss/elements/_index.scss b/assets/newspack-ui/scss/elements/_index.scss
index 8135ecc6d4..77410cd29d 100644
--- a/assets/newspack-ui/scss/elements/_index.scss
+++ b/assets/newspack-ui/scss/elements/_index.scss
@@ -2,6 +2,7 @@
@use 'forms';
@use 'icons';
@use 'misc';
+@use 'segmented-control';
@use 'tables';
@use 'typography';
@use 'woocommerce';
diff --git a/assets/newspack-ui/scss/elements/_segmented-control.scss b/assets/newspack-ui/scss/elements/_segmented-control.scss
new file mode 100644
index 0000000000..92057dea6f
--- /dev/null
+++ b/assets/newspack-ui/scss/elements/_segmented-control.scss
@@ -0,0 +1,43 @@
+.newspack-ui {
+ &__segmented-control {
+ align-items: center;
+ display: flex;
+ gap: var( --newspack-ui-spacer-2 );
+ flex-direction: column;
+
+ &:not( :last-child ) {
+ margin-bottom: var( --newspack-ui-spacer-2 );
+ }
+
+ &__tabs {
+ background: var( --newspack-ui-color-neutral-10 );
+ border-radius: var( --newspack-ui-border-radius-m );
+ display: flex;
+ flex-wrap: wrap;
+ gap: calc( var( --newspack-ui-spacer-base ) / 2 );
+ justify-content: center;
+ padding: calc( var( --newspack-ui-spacer-base ) / 2 );
+
+ .newspack-ui__button {
+ background: transparent;
+ border: 1px solid transparent;
+ color: var( --newspack-ui-color-neutral-60 );
+ margin: 0;
+
+ &.selected {
+ background: var( --newspack-ui-color-neutral-0 );
+ border-color: var( --newspack-ui-color-neutral-30 );
+ color: var( --newspack-ui-color-neutral-90 );
+ }
+ }
+ }
+
+ &__content {
+ width: 100%;
+
+ > *:not( .selected ) {
+ display: none;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss
index 665f313b84..a16609dd9d 100644
--- a/assets/newspack-ui/scss/elements/forms/_buttons.scss
+++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss
@@ -8,10 +8,11 @@
font-family: var( --newspack-ui-font-family );
font-size: var( --newspack-ui-font-size-s );
font-weight: 600;
- gap: var( --newspack-ui-spacer-2 );
+ gap: calc( var( --newspack-ui-spacer-base ) / 2 );
justify-content: center;
line-height: var( --newspack-ui-line-height-s );
- padding: var( --newspack-ui-spacer-2 ) var( --newspack-ui-spacer-4 );
+ min-height: var( --newspack-ui-spacer-9 );
+ padding: var( --newspack-ui-spacer-2 ) var( --newspack-ui-spacer-5 );
transition: background-color 125ms ease-in-out, border-color 125ms ease-in-out, outline 125ms ease-in-out;
&:not( :last-child ) {
@@ -30,6 +31,26 @@
outline-offset: 1px;
}
+ // Sizes
+ &--x-small {
+ border-radius: var( --newspack-ui-border-radius-s );
+ font-size: var( --newspack-ui-font-size-xs );
+ line-height: var( --newspack-ui-line-height-xs );
+ min-height: var( --newspack-ui-spacer-6 );
+ padding: calc( var( --newspack-ui-spacer-base ) / 2 ) var( --newspack-ui-spacer-base );
+ }
+
+ &--small {
+ font-size: var( --newspack-ui-font-size-xs );
+ line-height: var( --newspack-ui-line-height-xs );
+ min-height: var( --newspack-ui-spacer-8 );
+ padding: var( --newspack-ui-spacer-base ) var( --newspack-ui-spacer-3 );
+ }
+
+ &--medium {
+ // is the default.
+ }
+
// Styles
&--primary {
background: var( --newspack-ui-color-button-bg );
@@ -139,13 +160,16 @@
&--icon {
display: grid;
height: var( --newspack-ui-spacer-7 ); // TODO: This is the XS size, we will need S, and M
+ min-height: unset;
padding: 0;
place-items: center;
width: var( --newspack-ui-spacer-7 );
- svg {
- fill: currentcolor;
- }
+
+ }
+
+ svg {
+ fill: currentcolor;
}
}
}
diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php
index 48a88b4ba2..afc09058aa 100644
--- a/includes/class-newspack-ui.php
+++ b/includes/class-newspack-ui.php
@@ -35,6 +35,14 @@ public static function enqueue_styles() {
[],
NEWSPACK_PLUGIN_VERSION
);
+
+ wp_enqueue_script(
+ 'newspack-ui',
+ Newspack::plugin_url() . '/dist/newspack-ui.js',
+ [],
+ NEWSPACK_PLUGIN_VERSION,
+ true
+ );
}
/**
@@ -269,17 +277,13 @@ public static function return_demo_content() {
Uses the same classes as the newspack-ui__button
but we add an extra class to it newspack-ui__button--icon