= {
+ /**
+ * The default (initial) state to use if `value` is undefined.
+ */
+ defaultValue?: V;
+ /**
+ * Determines if element is disabled.
+ */
+ disabled?: boolean;
+ /**
+ * Label for the form element.
+ */
+ label?: string;
+};
+
+export type PopperPlacement =
+ | 'auto'
+ | 'auto-start'
+ | 'auto-end'
+ | 'top'
+ | 'top-start'
+ | 'top-end'
+ | 'right'
+ | 'right-start'
+ | 'right-end'
+ | 'bottom'
+ | 'bottom-start'
+ | 'bottom-end'
+ | 'left'
+ | 'left-start'
+ | 'left-end';
+
+export type PopperProps = {
+ /**
+ * Position of the popover element.
+ *
+ * @default 'auto'
+ *
+ * @see https://popper.js.org/docs/v1/#popperplacements--codeenumcode
+ */
+ placement?: PopperPlacement;
+};
diff --git a/packages/components/src/view/README.md b/packages/components/src/view/README.md
new file mode 100644
index 00000000000000..ec265056ca4081
--- /dev/null
+++ b/packages/components/src/view/README.md
@@ -0,0 +1,62 @@
+# View
+
+`View` is a core component that renders everything in the library. It is the principle component in the entire library. Note that `View` is not exported from components, it's fully internal.
+
+**Everything** is a `View`, and a `View` is **everything**.
+
+## Usage
+
+```jsx live
+import { Text, View } from '@wp-g2/components';
+
+function Example() {
+ return (
+
+ Into The Unknown
+
+ );
+}
+```
+
+## Props
+
+##### as
+
+**Type**: `string`,`E`
+
+Render the component as another React Component or HTML Element.
+
+##### css
+
+**Type**: `InterpolatedCSS`
+
+Render custom CSS using the style system.
+
+## Styling
+
+### Presets
+
+The Style system provides a bunch of style presets, which come from `@wp-g2/styles`. These presets are namespaced under `ui`.
+
+Presets can style a `View` by passing an `Array` of them into the `css` prop.
+
+```jsx live
+import { Text, View } from '@wp-g2/components';
+import { ui } from '@wp-g2/styles';
+
+function Example() {
+ return (
+
+ Into The Unknown
+
+ );
+}
+```
diff --git a/packages/components/src/view/index.js b/packages/components/src/view/index.js
new file mode 100644
index 00000000000000..64c032291ab979
--- /dev/null
+++ b/packages/components/src/view/index.js
@@ -0,0 +1 @@
+export { default as View } from './view';
diff --git a/packages/components/src/view/test/__snapshots__/view.js.snap b/packages/components/src/view/test/__snapshots__/view.js.snap
new file mode 100644
index 00000000000000..273ac93c27caa0
--- /dev/null
+++ b/packages/components/src/view/test/__snapshots__/view.js.snap
@@ -0,0 +1,180 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`props should render as another element 1`] = `
+.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ box-sizing: border-box;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ font-family: Inter,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
+ font-family: var(--wp-g2-font-family);
+ font-size: 13px;
+ font-size: var(--wp-g2-font-size);
+ font-weight: normal;
+ font-weight: var(--wp-g2-font-weight);
+ margin: 0;
+}
+
+@media (prefers-reduced-motion) {
+ .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+ }
+}
+
+[data-system-ui-reduced-motion-mode="true"] .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+}
+
+
+
+ Some people are worth melting for.
+
+
+`;
+
+exports[`props should render correctly 1`] = `
+.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ box-sizing: border-box;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ font-family: Inter,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
+ font-family: var(--wp-g2-font-family);
+ font-size: 13px;
+ font-size: var(--wp-g2-font-size);
+ font-weight: normal;
+ font-weight: var(--wp-g2-font-weight);
+ margin: 0;
+}
+
+@media (prefers-reduced-motion) {
+ .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+ }
+}
+
+[data-system-ui-reduced-motion-mode="true"] .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+}
+
+
+
+ Some people are worth melting for.
+
+
+`;
+
+exports[`props should render with custom styles (Array) 1`] = `
+.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ box-sizing: border-box;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ font-family: Inter,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
+ font-family: var(--wp-g2-font-family);
+ font-size: 13px;
+ font-size: var(--wp-g2-font-size);
+ font-weight: normal;
+ font-weight: var(--wp-g2-font-weight);
+ margin: 0;
+ background: pink;
+ font-weight: bold;
+}
+
+@media (prefers-reduced-motion) {
+ .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+ }
+}
+
+[data-system-ui-reduced-motion-mode="true"] .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+}
+
+
+
+ Some people are worth melting for.
+
+
+`;
+
+exports[`props should render with custom styles (object) 1`] = `
+.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ box-sizing: border-box;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ font-family: Inter,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
+ font-family: var(--wp-g2-font-family);
+ font-size: 13px;
+ font-size: var(--wp-g2-font-size);
+ font-weight: normal;
+ font-weight: var(--wp-g2-font-weight);
+ margin: 0;
+ background: pink;
+}
+
+@media (prefers-reduced-motion) {
+ .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+ }
+}
+
+[data-system-ui-reduced-motion-mode="true"] .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+}
+
+
+
+ Some people are worth melting for.
+
+
+`;
+
+exports[`props should render with custom styles (string) 1`] = `
+.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ box-sizing: border-box;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ font-family: Inter,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
+ font-family: var(--wp-g2-font-family);
+ font-size: 13px;
+ font-size: var(--wp-g2-font-size);
+ font-weight: normal;
+ font-weight: var(--wp-g2-font-weight);
+ margin: 0;
+ background: pink;
+}
+
+@media (prefers-reduced-motion) {
+ .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+ }
+}
+
+[data-system-ui-reduced-motion-mode="true"] .emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0.emotion-0 {
+ -webkit-transition: none !important;
+ transition: none !important;
+}
+
+
+
+ Some people are worth melting for.
+
+
+`;
diff --git a/packages/components/src/view/test/view.js b/packages/components/src/view/test/view.js
new file mode 100644
index 00000000000000..a9524e88101871
--- /dev/null
+++ b/packages/components/src/view/test/view.js
@@ -0,0 +1,74 @@
+/**
+ * External dependencies
+ */
+import { render } from '@testing-library/react';
+
+/**
+ * Internal dependencies
+ */
+import { View } from '../index';
+
+describe( 'props', () => {
+ test( 'should render correctly', () => {
+ const { container } = render(
+
+ Some people are worth melting for.
+
+ );
+ expect( container.firstChild ).toMatchSnapshot();
+ } );
+
+ test( 'should render as another element', () => {
+ const { container } = render(
+
+ Some people are worth melting for.
+
+ );
+ expect( container.firstChild ).toMatchSnapshot();
+ } );
+
+ test( 'should render with custom styles (string)', () => {
+ const { container } = render(
+
+ Some people are worth melting for.
+
+ );
+ expect( container.firstChild ).toMatchSnapshot();
+ } );
+
+ test( 'should render with custom styles (object)', () => {
+ const { container } = render(
+
+ Some people are worth melting for.
+
+ );
+ expect( container.firstChild ).toMatchSnapshot();
+ } );
+
+ test( 'should render with custom styles (Array)', () => {
+ const { container } = render(
+
+ Some people are worth melting for.
+
+ );
+ expect( container.firstChild ).toMatchSnapshot();
+ } );
+} );
diff --git a/packages/components/src/view/view.js b/packages/components/src/view/view.js
new file mode 100644
index 00000000000000..968b0ad42c225d
--- /dev/null
+++ b/packages/components/src/view/view.js
@@ -0,0 +1,9 @@
+/**
+ * External dependencies
+ */
+import { BaseView } from '@wp-g2/styles';
+
+const View = BaseView;
+View.displayName = 'View';
+
+export default View;
diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json
index c697cb71d98c17..7d6a733e557940 100644
--- a/packages/components/tsconfig.json
+++ b/packages/components/tsconfig.json
@@ -15,7 +15,9 @@
"src/base-control/**/*",
"src/dashicon/**/*",
"src/tip/**/*",
+ "src/truncate/**/*",
"src/utils/**/*",
+ "src/view/**/*",
"src/visually-hidden/**/*"
],
"exclude": [