diff --git a/.storybook/main.ts b/.storybook/main.ts
index 4d3d1b925..7d72cd85d 100644
--- a/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -58,8 +58,33 @@ const storybookConfig: StorybookConfig = {
})
].filter(Boolean);
+ // Modify the css-loader options to simplify the class names
+ // By default, with the config, the classnames are like this: GETEs8cGi4WwwvV1ooFy MUs8LC8twKwy5uAnhOWJ PafTkO4uwI6M3m4HX7JI
+ // With this new config, the classnames are like this: hop-Button___GETEs hop-Button--primary___MUs8L hop-Button--md___PafTk
+ for (const rule of config.module?.rules || []) {
+ if (typeof rule === "object" && rule?.use && Array.isArray(rule.use)) {
+ for (const loader of rule.use) {
+ if (typeof loader === "object" && loader?.loader?.includes("css-loader")) {
+ const cssLoader = loader;
+ if (cssLoader && typeof cssLoader === "object") {
+ const previousOptions = typeof cssLoader.options === "string" ? { } : cssLoader.options;
+ cssLoader.options = {
+ ...previousOptions,
+ modules: {
+ ...((typeof previousOptions?.modules === "string" ? { mode: previousOptions?.modules } : previousOptions?.modules)),
+ auto: true,
+ localIdentName: "[local]___[hash:base64:5]"
+ }
+ };
+ }
+ }
+ }
+ }
+ }
+
return config;
}
};
+
export default storybookConfig;
diff --git a/apps/docs/.eslintrc.json b/apps/docs/.eslintrc.json
index c632ceb3b..82295d8eb 100644
--- a/apps/docs/.eslintrc.json
+++ b/apps/docs/.eslintrc.json
@@ -22,7 +22,9 @@
"Switcher": true,
"IconSpecTable": true,
"PreviewComponent": true,
- "MigrateGuide": true
+ "MigrateGuide": true,
+ "PackageInstallation": true,
+ "PropTable": true
},
"overrides": [
{
diff --git a/apps/docs/app/globals.css b/apps/docs/app/globals.css
index 00ecf5523..93f4f8360 100644
--- a/apps/docs/app/globals.css
+++ b/apps/docs/app/globals.css
@@ -58,14 +58,6 @@ a {
display: flex;
}
-.hd-home {
- display: flex;
- flex-direction: column;
- gap: 3rem;
- min-height: 40vh;
- justify-content: center;
-}
-
.hd-display {
font-size: var(--hd-step-5);
font-weight: 500;
diff --git a/apps/docs/app/home.css b/apps/docs/app/home.css
new file mode 100644
index 000000000..ceca49135
--- /dev/null
+++ b/apps/docs/app/home.css
@@ -0,0 +1,594 @@
+.hd-home__heading {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ text-align: center;
+ margin: 0 auto;
+ max-width: 43rem;
+}
+
+.hd-home__header {
+ font-size: 2.25rem;
+ line-height: 1.3333;
+}
+
+.hd-home__tagline {
+ color: var(--hd-color-neutral-text-weak);
+ font-size: 1rem;
+ line-height: 1.5;
+ margin-top: var(--hd-space-1);
+ max-width: 60ch;
+}
+
+.hd-home__ctas {
+ display: flex;
+ gap: var(--hd-space-3);
+ justify-content: center;
+ margin-top: var(--hd-space-4);
+}
+
+.hd-home__features {
+ display: grid;
+ gap: var(--hd-space-4);
+ grid-template-columns: repeat(1, 1fr);
+ margin-top: var(--hd-space-10);
+ text-align: center;
+}
+
+.hd-home__feature-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.hd-home__feature-title {
+ justify-content: center;
+ display: flex;
+ font-size: 1.125rem;
+ gap: var(--hd-space-1);
+ line-height: 1.3333;
+}
+
+.hd-home-feature-title__icon path {
+ height: var(--hd-space-3);
+ aspect-ratio: 1/1;
+ stroke: var(--hd-color-neutral-icon);
+}
+
+@media screen and (width >= 37.5rem) {
+ .hd-home__features {
+ grid-template-columns: repeat(2, 1fr);
+ text-align: left;
+ }
+
+ .hd-home__feature-item {
+ align-items: start;
+ }
+}
+
+@media screen and (width >= 48rem) {
+ .hd-home__features {
+ grid-template-columns: repeat(4, 1fr);
+ }
+}
+
+.hd-icon-fill {
+ fill: var(--hd-color-neutral-icon);
+ stroke: transparent;
+}
+
+.hd-icon-fill path {
+ stroke: transparent;
+}
+
+.hd-home__feature-copy {
+ color: var(--hd-color-neutral-text-weak);
+ font-size: 0.875rem;
+ line-height: 1.4285;
+ margin-top: var(--hd-space-1);
+ max-width: 50ch;
+}
+
+/* Samples Section */
+.hd-home-samples {
+ display: grid;
+ gap: var(--hd-space-3);
+ grid-template-columns: 1fr;
+ margin-top: var(--hd-space-10);
+}
+
+@media screen and (width >= 78.75rem) {
+ .hd-home-samples {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+.hd-home-sample__item {
+ --background: var(--hd-white);
+ --color: var(--hd-neutral-50);
+
+ background: linear-gradient(90deg, var(--background) 0.625rem, transparent 1%) 50%, linear-gradient(var(--background) 0.625rem, transparent 1%) 50%, var(--color);
+ background-size: 0.75rem 0.75rem;
+ border: var(--hd-border-size) solid var(--hd-color-neutral-border);
+ border-radius: var(--hd-space-2);
+ padding: var(--hd-space-3);
+ position: relative;
+}
+
+[data-theme="dark"] .hd-home-sample__item {
+ --background: var(--hd-neutral-900);
+ --color: var(--hd-neutral-800);
+}
+
+a.hd-home-sample__item:hover {
+ box-shadow: 0 0.625rem 0.625rem calc(-1 * 0.0313rem) rgba(0 0 0 / 6%), 0 0.1875rem 0.1875rem calc(-1 * 0.0938rem) rgba(0 0 0 / 6%), 0 0.375rem 0.375rem calc(-1 * 0.0938rem) rgba(0 0 0 / 6%), 0 0.75rem 0.75rem calc(-1 * 0.375rem) rgba(0 0 0 / 6%), 0 1.5rem 1.5rem calc(-1 * 0.75rem) rgba(0 0 0 / 6%);
+ transform: translate(-0.125rem, -0.125rem);
+ transition: box-shadow 0.3s ease, transform 0.2s ease-in;
+}
+
+a.hd-home-sample__item:hover .hd-home-sample__title-icon {
+ opacity: 1;
+ transform: translateX(0);
+}
+
+a.hd-home-sample__item:hover::after {
+ bottom: -0.25rem;
+ content: "";
+ display: block;
+ height: 0.25rem;
+ left: 0;
+ position: absolute;
+ width: 100%;
+}
+
+.hd-home-sample__title {
+ align-items: center;
+ align-self: flex-start;
+ color: var(--hd-color-neutral-text);
+ display: flex;
+ font-size: 1.25rem;
+ gap: 0.25rem;
+ line-height: 1.2;
+}
+
+.hd-home-sample__title-wrap {
+ align-items: center;
+ display: flex;
+ gap: 0.5rem;
+}
+
+.hd-home-sample__title-icon {
+ fill: var(--hd-color-neutral-icon);
+ opacity: 0;
+ transform: translateX(-1rem);
+ transition: opacity 0.2s ease, transform 0.1s ease-in;
+}
+
+.hd-home-sample__tagline {
+ color: var(--hd-color-neutral-text-weak);
+ font-size: 1rem;
+ line-height: 1.5;
+ margin-top: var(--hd-space-05);
+ margin-bottom: var(--hd-space-3);
+}
+
+.hd-home-samples__row {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 1.5rem;
+}
+
+@media screen and (width >= 37.5rem) {
+ .hd-home-samples__row {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+.hd-home-samples__col {
+ display: grid;
+ gap: 1.5rem;
+}
+
+.hd-home-samples__main-wrapper {
+ grid-template-columns: 1fr;
+}
+
+@media screen and (width >= 62rem) {
+ .hd-home-samples__main-wrapper {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media screen and (width >= 78.75rem) {
+ .hd-home-samples__main-wrapper {
+ grid-template-columns: 1fr;
+ }
+}
+
+/* colors sample */
+.hd-home-sample__colors {
+ align-self: start;
+ display: grid;
+ justify-content: flex-end;
+ gap: var(--hd-space-1);
+ margin-block: calc(-1 * var(--hd-space-1));
+}
+
+.hd-home-sample__colors-row {
+ display: flex;
+ gap: var(--hd-space-1);
+}
+
+.hd-home-sample__color {
+ border-radius: var(--hd-space-1);
+ display: flex;
+ height: 1.875rem;
+ width: 1.875rem;
+}
+
+.hd-home-sample__item-colors {
+ display: flex;
+ gap: var(--hd-space-1);
+ justify-content: space-between;
+}
+
+/* Rock Color */
+.hd-home-sample__color-rock-200 {
+ background-color: #B3B3B1;
+}
+
+.hd-home-sample__color-rock-300 {
+ background-color: #959593;
+}
+
+.hd-home-sample__color-rock-400 {
+ background-color: #777775;
+}
+
+.hd-home-sample__color-rock-500 {
+ background-color: #6C6C6B;
+}
+
+/* Sapphire Color */
+.hd-home-sample__color-sapphire-200 {
+ background-color: #95B1FF;
+}
+
+.hd-home-sample__color-sapphire-300 {
+ background-color: #6C8FFD;
+}
+
+.hd-home-sample__color-sapphire-400 {
+ background-color: #4767FE;
+}
+
+.hd-home-sample__color-sapphire-500 {
+ background-color: #3B57FF;
+}
+
+/* Sizes */
+.hd-home-sample__sizes {
+ display: flex;
+ gap: var(--hd-space-1);
+ margin-block: calc(-1 * var(--hd-space-1));
+}
+
+.hd-home-sample__item-sizes {
+ display: flex;
+ justify-content: space-between;
+ gap: var(--hd-space-1);
+ flex-wrap: wrap;
+}
+
+.hd-home-sample__size {
+ display: flex;
+ flex-direction: column;
+ gap: var(--hd-space-05);
+}
+
+.hd-home-sample__size-text {
+ color: var(--hd-color-accent-text);
+ font-size: 0.625rem;
+ text-align: right;
+}
+
+.hd-home-sample__size-bar {
+ background-color: var(--hd-color-accent-surface);
+ min-height: 3.5rem;
+ height: 100%;
+}
+
+.hd-home-sample__size-16 .hd-home-sample__size-bar {
+ width: 1rem;
+}
+
+.hd-home-sample__size-24 .hd-home-sample__size-bar {
+ width: 1.5rem;
+}
+
+.hd-home-sample__size-32 .hd-home-sample__size-bar {
+ width: 2rem;
+}
+
+.hd-home-sample__size-40 .hd-home-sample__size-bar {
+ width: 2.5rem;
+}
+
+/* Icons */
+.hd-home-sample__icons {
+ display: flex;
+ gap: var(--hd-space-2);
+ flex-direction: column;
+ flex-grow: 1;
+ justify-content: space-between
+}
+
+.hd-home-sample__item-icons {
+ display: flex;
+ flex-direction: column;
+}
+
+.hd-home-sample__icons-row.hd-home-sample__icons-extra-row {
+ display: none;
+}
+
+@media screen and (width >= 62rem) {
+ .hd-home-sample__icons {
+ gap: var(--hd-space-3);
+ }
+
+ .hd-home-sample__icons-row.hd-home-sample__icons-extra-row {
+ display: flex;
+ }
+}
+
+@media screen and (width >= 78.75rem) {
+ .hd-home-sample__icons {
+ gap: var(--hd-space-2);
+ }
+
+ .hd-home-sample__icons-row.hd-home-sample__icons-extra-row {
+ display: none;
+ }
+}
+
+.hd-home-sample__icons-row {
+ display: flex;
+ justify-content: space-between;
+}
+
+.hd-home-samples .hd-home-sample__icons-icon {
+ color: var(--hop-neutral-icon-weak);
+}
+
+.hd-home-samples .hd-home-sample__icons-icon--active {
+ color: var(--hop-primary-icon);
+}
+
+.hd-home-samples .hd-home-sample__icons-icon--strong {
+ color: var(--hop-neutral-icon);
+}
+
+/* Text Styles */
+.hd-home-sample__item-text-styles {
+ display: flex;
+ flex-direction: column;
+}
+
+.hd-home-sample__text-styles {
+ border-bottom: 0;
+ border-image: linear-gradient(90deg,rgba(0 0 0 / 0%),rgb(186 188 192)) 1;
+ border-top: 0;
+ border-style: solid;
+ border-right: 0;
+ border-top-width: var(--hd-border-size);
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: var(--hd-space-3);
+ margin-top: var(--hd-space-3);
+}
+
+@media screen and (width >= 37.5rem) {
+ .hd-home-sample__text-styles {
+ grid-template-columns: 1fr;
+ gap: var(--hd-space-1);
+ }
+}
+
+@media screen and (width >= 44rem) {
+ .hd-home-sample__text-styles {
+ grid-template-columns: repeat(2, 1fr);
+ gap: var(--hd-space-3);
+ }
+}
+
+.hd-home-sample__text {
+ font-family: Inter, sans-serif;
+ font-size: 5.25rem;
+ font-weight: 700;
+}
+
+.hd-home-sample__text-lowercase {
+ color: transparent;
+ -webkit-text-stroke: 0.125rem var(--hd-color-neutral-text);
+}
+
+.hd-home-sample__text-styles-col {
+ display: flex;
+ align-items: center;
+}
+
+.hd-home-sample__text-styles-controls {
+ --background: var(--hd-white);
+
+ align-items: start;
+ background-image: linear-gradient(180deg, var(--background) 0%, var(--background) 75%, rgba(255 255 255 / 0%) 100%);
+ border-bottom: 0;
+ border-image: linear-gradient(0deg, rgba(0 0 0 / 0%), rgb(186 188 192)) 1;
+ border-style: solid;
+ border-right: 0;
+ border-top: 0;
+ border-left-width: var(--hd-border-size);
+ display: grid;
+ flex-direction: column;
+ flex-grow: 1;
+ gap: 0.75rem;
+ padding: var(--hd-space-2);
+}
+
+@media screen and (width >= 37.5rem) {
+ .hd-home-sample__text-styles-controls {
+ grid-template-columns: repeat(2, 1fr);
+ border-image: linear-gradient(90deg, rgba(0 0 0 / 0%), rgb(186 188 192)) 1;
+ border-style: solid;
+ border-top-width: var(--hd-border-size);
+ }
+}
+
+@media screen and (width >= 44rem) {
+ .hd-home-sample__text-styles-controls {
+ grid-template-columns: 1fr;
+ border-image: linear-gradient(0deg, rgba(0 0 0 / 0%), rgb(186 188 192)) 1;
+ border-top: 0;
+ }
+}
+
+[data-theme="dark"] .hd-home-sample__text-styles-controls {
+ --background: var(--hd-neutral-900);
+}
+
+.hd-home-sample__control-knob {
+ align-items: center;
+ display: flex;
+ gap: 0.75rem;
+}
+
+.hd-home-sample__control-knob-title {
+ align-items: center;
+ display: flex;
+ gap: 0.25rem;
+}
+
+.hd-home-sample__control-knob-value {
+ color: var(--hd-color-neutral-text);
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 0.75rem;
+ line-height: 1;
+}
+
+/* Text Styles - Control Text */
+.hd-home-sample__control-title {
+ font-family: Inter, sans-serif;
+ font-size: 0.75rem;
+ font-weight: 500;
+ line-height: 1.3333;
+}
+
+/* Components */
+.hd-home-sample__item-components {
+ display: grid;
+ grid-template-rows: min-content min-content 1fr;
+}
+
+.hd-home-sample-components {
+ display: grid;
+ grid-template-columns: 1fr;
+}
+
+@media screen and (width >= 37.5rem) {
+ .hd-home-sample-components {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media screen and (width >= 62rem) {
+ .hd-home-sample-components {
+ grid-template-columns: repeat(4, 1fr);
+ }
+}
+
+@media screen and (width >= 78.75rem) {
+ .hd-home-sample-components {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+.hd-home-sample-components__item-wrapper {
+ display: flex;
+}
+
+.hd-home-sample-components__item {
+ --background: rgba(255 255 255 / 70%);
+
+ align-items: center;
+ display: flex;;
+ flex-grow: 1;
+ justify-content: center;
+ padding: 1rem;
+}
+
+@media screen and (width >= 78.75rem) {
+ .hd-home-sample-components__item-wrapper:nth-child(odd) {
+ background: linear-gradient(-90deg, var(--background) 0%, var(--background) 85%, rgba(0 212 255 / 0%) 100%);
+ border-bottom: 0;
+ border-image: linear-gradient(90deg,rgba(0 0 0 / 0%),rgb(186 188 192)) 1;
+ border-style: solid;
+ border-right: 0;
+ border-left: 0;
+ border-top-width: var(--hd-border-size);
+ }
+
+ .hd-home-sample-components__item-wrapper:nth-child(even) {
+ background: linear-gradient(90deg, var(--background) 0%, var(--background) 85%, rgba(255 255 255 / 0%) 100%);
+ border-bottom: 0;
+ border-image: linear-gradient(-90deg,rgba(0 0 0 / 0%), rgb(186 188 192)) 1;
+ border-style: solid;
+ border-right: 0;
+ border-left: 0;
+ border-top-width: var(--hd-border-size);
+ }
+
+ .hd-home-sample-components__item-wrapper:nth-child(2) .hd-home-sample-components__item {
+ border-bottom: 0;
+ border-image: linear-gradient(-90deg,rgba(0 0 0 / 0%), rgb(186 188 192)) 1;
+ border-style: solid;
+ border-right: 0;
+ border-left-width: var(--hd-border-size);
+ border-top: 0;
+ }
+
+ .hd-home-sample-components__item-wrapper:nth-child(4) .hd-home-sample-components__item {
+ border-bottom: 0;
+ border-image: linear-gradient(0deg,rgba(0 0 0 / 0%) 0%, rgba(0 0 0 / 0%) 25%, rgb(186 188 192)) 1;
+ border-style: solid;
+ border-right: 0;
+ border-left-width: var(--hd-border-size);
+ border-top: 0;
+ }
+}
+
+[data-theme="dark"] .hd-home-sample-components__item {
+ --background: rgba(41 41 41 / 70%);
+}
+
+/* Components - Fake */
+.hd-home-sample-components__buttons {
+ display: flex;
+ gap: var(--hd-space-2);
+}
+
+/* Upcoming */
+.hd-home-sample__item-upcoming {
+ background-image: linear-gradient(0deg, rgba(202 79 79 / 20%) 0%, rgba(60 60 60 / 50%) 75%);
+ border-radius: inherit;
+ display: flex;
+ inset: 0;
+ opacity: 0.1;
+ position: absolute;
+ z-index: 10;
+}
+
+[data-theme="dark"] .hd-home-sample__item-upcoming {
+ background: linear-gradient(0deg, rgba(80 80 80 / 20%) 0%, rgba(80 80 80 / 60%) 75%);
+ opacity: 0.6;
+}
diff --git a/apps/docs/app/layout.css b/apps/docs/app/layout.css
index 39952a4e7..ccc7c99b3 100644
--- a/apps/docs/app/layout.css
+++ b/apps/docs/app/layout.css
@@ -23,18 +23,12 @@ html {
}
main {
- padding-block: var(--hd-space-4) var(--hd-space-8);
+ padding-block: var(--hd-space-8);
flex: 1 1 auto;
min-width: 0;
order: 1;
}
-@media screen and (width >= 48rem) {
- main {
- padding-block-start: 0;
- }
-}
-
@media screen and (width >= 62rem) {
.hd-container {
flex-direction: row;
@@ -42,7 +36,6 @@ main {
main {
order: 1;
- padding-block-start: var(--hd-space-8);
}
}
@@ -51,6 +44,10 @@ p {
line-height: 1.5;
}
+.hd-content ul {
+ list-style-position: inside;
+}
+
.hd-content p:not(:last-child) {
margin-block-end: 1.25rem;
}
diff --git a/apps/docs/app/lib/contentConfig.ts b/apps/docs/app/lib/contentConfig.ts
new file mode 100644
index 000000000..6def6e9ed
--- /dev/null
+++ b/apps/docs/app/lib/contentConfig.ts
@@ -0,0 +1,5 @@
+/* `compileMDX` accepts a scope prop, which makes all of the values available for use in your MDX.
+ * Each key/value pair in the scope argument will be exposed as a javascript variable.
+ * So, for example, you could imagine if you had a scope like { foo: 'bar' }, it would be interpreted as const foo = 'bar'.
+ */
+export const data = {};
diff --git a/apps/docs/app/lib/getComponentCode.ts b/apps/docs/app/lib/getComponentCode.ts
index 955604097..f0c8346e4 100644
--- a/apps/docs/app/lib/getComponentCode.ts
+++ b/apps/docs/app/lib/getComponentCode.ts
@@ -1,10 +1,6 @@
import path from "path";
import { promises as fs } from "fs";
-import { type Plugin, unified } from "unified";
-import remarkParse from "remark-parse";
-import remarkRehype from "remark-rehype";
-import rehypeStringify from "rehype-stringify";
-import { rehypePluginOptions } from "@/app/lib/rehypeConfig";
+import { highlightCode } from "@/components/highlightCode";
function formatComponentExamplePath(uri: string) {
return path.join(process.cwd(), "..", "..", "packages", "components", "src", uri);
@@ -22,17 +18,6 @@ ${code}
`);
}
-async function highlightCode(code: string) {
- const file = await unified()
- .use(remarkParse as unknown as Plugin)
- .use(remarkRehype as unknown as Plugin)
- .use(rehypePluginOptions as unknown as Plugin)
- .use(rehypeStringify as unknown as Plugin)
- .process(code);
-
- return String(file);
-}
-
export async function getComponentCode(filePath: string) {
const examplePath = formatComponentExamplePath(filePath);
const fileContent = await getFileContent(`${examplePath}.tsx`);
diff --git a/apps/docs/app/lib/getComponentDetails.ts b/apps/docs/app/lib/getComponentDetails.ts
index 5c74769b5..a99db4158 100644
--- a/apps/docs/app/lib/getComponentDetails.ts
+++ b/apps/docs/app/lib/getComponentDetails.ts
@@ -3,6 +3,7 @@ import fs from "fs";
import { compileMDX } from "next-mdx-remote/rsc";
import { components } from "@/components/mdx/components.tsx";
import { rehypePluginOptions } from "@/app/lib/rehypeConfig";
+import { data } from "@/app/lib/contentConfig.ts";
export const COMPONENT_PATH = path.join(process.cwd(), "content", "components");
@@ -15,6 +16,7 @@ async function parseFrontMatter(fileContent: string) {
}>({
source: fileContent,
options: {
+ scope: data,
parseFrontmatter: true,
mdxOptions: { remarkPlugins: [], rehypePlugins: rehypePluginOptions as unknown as [] }
},
@@ -41,6 +43,7 @@ function getMDXData(dir: string) {
const { frontmatter, content } = await readMDXFile(path.join(dir, file));
const slug = path.basename(file, path.extname(file));
+
return {
slug,
frontmatter,
diff --git a/apps/docs/app/pages/landing/page.tsx b/apps/docs/app/pages/landing/page.tsx
new file mode 100644
index 000000000..bb0db0314
--- /dev/null
+++ b/apps/docs/app/pages/landing/page.tsx
@@ -0,0 +1,211 @@
+"use client";
+
+import { Button as HopperButton, HopperProvider } from "@hopper-ui/components";
+import Image from "next/image";
+import { AccessibleIcon, ArrowIcon, DarkModeIcon, FontSizeIcon, InternationalIcon, LineHeightIcon, MarginIcon, SelectArrowIcon, TypescriptIcon } from "../../../components/icon/index";
+import { type ColorScheme, ThemeContext } from "@/context/theme/ThemeProvider.tsx";
+import { useContext } from "react";
+import Button from "@/components/button/Button";
+import Tag from "@/components/tag/Tag";
+import { ExternalLinkIcon, Icon } from "@/components/icon";
+
+// eslint-disable-next-line max-len
+import { CalendarIcon, ChartBarIcon, CheckmarkIcon, DeleteIcon, EyeVisibleIcon, FilterIcon, FocusIcon, ItalicIcon, LightbulbIcon, LockIcon, MailIcon, NotebookIcon, PinIcon, ProfileIcon, ReactionIcon, RecurringIcon, RewindIcon, SearchIcon, ShareIcon, StarIcon, StickyIcon, SyncIcon, TeamIcon, ThumbsUpIcon, UnarchiveIcon, WarningIcon } from "@hopper-ui/icons";
+
+import "@hopper-ui/tokens/fonts.css";
+import "../../home.css";
+
+export default function Home() {
+ const { colorMode } = useContext(ThemeContext);
+
+ const theme = colorMode as ColorScheme;
+
+ return (
+
+
+
+
Leap into creativity
+
Explore our Design System, where icons, tokens, and components are handpicked for ultimate simplicity and accessibility.
+
+
+ Get Started
+ Github
+
+
+
+
Accessible
+
+ Built with accessibility in mind Hopper is based on React Aria Components
+
+
+
+
International
+
+ Experience is pushed further with internationalization.
+
+
+
+
Typescript
+
+ Typescript based for reduced learning curve and error detection.
+
+
+
+
Dark mode
+
+ Switching from light to dark mode couldn't be easier.
+
+
+
+
+
+
+
+
+
Components
+ upcoming
+
+
An accessible suite of components powered by react-aria.
+
+
+
+
+
+
+
+ Confirm
+ I need help
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/docs/app/tokens.css b/apps/docs/app/tokens.css
index 6b7d4f2e3..415ae193a 100644
--- a/apps/docs/app/tokens.css
+++ b/apps/docs/app/tokens.css
@@ -89,7 +89,7 @@
[data-theme="dark"] {
--hd-color-white-surface: var(--hd-neutral-800);
--hd-color-neutral-surface: var(--hd-neutral-900);
- --hd-color-neutral-surface-weak: var(--hd-neutral-800);
+ --hd-color-neutral-surface-weak: var(--hd-neutral-900);
--hd-color-surface-neutral-selection: var(--hd-neutral-300);
--hd-color-neutral-text: var(--hd-neutral-0);
--hd-color-neutral-text-strong: var(--hd-neutral-900);
diff --git a/apps/docs/app/ui/components/previewComponent/CodeWrapper.tsx b/apps/docs/app/ui/components/previewComponent/CodeWrapper.tsx
index 67c4e33cd..b371d50cf 100644
--- a/apps/docs/app/ui/components/previewComponent/CodeWrapper.tsx
+++ b/apps/docs/app/ui/components/previewComponent/CodeWrapper.tsx
@@ -1,5 +1,5 @@
import { getComponentCode } from "@/app/lib/getComponentCode.ts";
-import CodeBlock from "@/app/ui/components/codeBlock/CodeBlock.tsx";
+import HighlightCode from "@/components/highlightCode/HighlightCode.tsx";
interface CodeWrapperProps {
src: string;
@@ -9,7 +9,7 @@ async function CodeWrapper({ src }: CodeWrapperProps) {
const code = await getComponentCode(src);
return (
-
+
);
}
diff --git a/apps/docs/app/ui/components/previewComponent/previewComponent.css b/apps/docs/app/ui/components/previewComponent/previewComponent.css
index b8661bbb3..73b5c28b8 100644
--- a/apps/docs/app/ui/components/previewComponent/previewComponent.css
+++ b/apps/docs/app/ui/components/previewComponent/previewComponent.css
@@ -26,7 +26,7 @@
.hd-component-wrapper__action {
position: absolute;
- inset: 1rem 1rem 0 auto;
+ inset: 1rem 1rem auto auto;
z-index: 100;
}
diff --git a/apps/docs/app/ui/components/propTable/PropTable.tsx b/apps/docs/app/ui/components/propTable/PropTable.tsx
new file mode 100644
index 000000000..ae885064a
--- /dev/null
+++ b/apps/docs/app/ui/components/propTable/PropTable.tsx
@@ -0,0 +1,93 @@
+import { promises as fs } from "fs";
+import path from "path";
+import type { PropItem } from "react-docgen-typescript/lib/parser";
+import type { ComponentDocWithGroups } from "@/scripts/generateComponentData.mjs";
+import Collapsible from "@/components/collapsible/Collapsible.tsx";
+import Title from "@/components/title/Title.tsx";
+
+import "./propTable.css";
+
+export interface PropTableProps {
+ component: string;
+}
+
+interface PropItemTypeValue {
+ name: string;
+ value?: Array<{ value: string; name: string }>;
+ raw?: string;
+}
+
+const filePath = path.join(process.cwd(), "datas", "components");
+
+const getType = (type: PropItemTypeValue) => {
+ const handler: {
+ [key: string]: (type: PropItemTypeValue) => string;
+ } = {
+ enum: t =>
+ t.value ? t.value.map(item => item.value.replace(/'/g, "")).join(" \\| ") : "",
+ union: t => t.value ? t.value.map(item => item.name).join(" \\| ") : ""
+ };
+ if (typeof handler[type.name] === "function") {
+ return handler[type.name](type).replace(/\|/g, "");
+ }
+
+ return type.name;
+};
+
+const renderRow = (key: string, prop: PropItem) => {
+ const { name, type, defaultValue, required, description } = prop;
+
+ return (
+
+ {name}
+ {getType(type)}
+ {defaultValue?.value}
+ {required ? "✓" : "✗"}
+ {description}
+
+ );
+};
+
+export default async function PropTable({ component }: PropTableProps) {
+ const file = await fs.readFile(filePath + `/${component}.json`, "utf8");
+ const data = JSON.parse(file);
+
+ return data.map((item: ComponentDocWithGroups) => {
+ const { description, displayName, groups } = item;
+
+ return (
+ <>
+ {displayName}
+ {description}
+ {Object.keys(groups).map(group => {
+ return (
+
+ {group}
+
+ }
+ className="props__section"
+ >
+
+
+
+ Property
+ Type
+ Default
+ Required
+ Description
+
+
+
+ {Object.keys(groups[group]).map(key => renderRow(key, groups[group][key]))}
+
+
+
+ );
+ })}
+ >
+ );
+ });
+}
diff --git a/apps/docs/app/ui/components/propTable/propTable.css b/apps/docs/app/ui/components/propTable/propTable.css
new file mode 100644
index 000000000..578471498
--- /dev/null
+++ b/apps/docs/app/ui/components/propTable/propTable.css
@@ -0,0 +1,7 @@
+.props__section {
+ margin-top: var(--hd-space-1);
+}
+
+.props__section .hd-collapsible__content {
+ margin-top: var(--hd-space-1);
+}
diff --git a/apps/docs/app/ui/layout/aside/aside.css b/apps/docs/app/ui/layout/aside/aside.css
index 53d5f6607..0bf3b13c2 100644
--- a/apps/docs/app/ui/layout/aside/aside.css
+++ b/apps/docs/app/ui/layout/aside/aside.css
@@ -11,6 +11,10 @@
display: flex;
padding-block-start: var(--hd-space-8);
}
+
+ .hd-aside + main {
+ padding-block-start: 0;
+ }
}
@media screen and (width >= 62rem) {
@@ -23,6 +27,10 @@
top: var(--hd-space-8);
height: calc(100vh - var(--hd-space-8));
}
+
+ .hd-aside + main {
+ padding-block-start: var(--hd-space-8);
+ }
}
.hd-aside__list {
@@ -50,7 +58,7 @@
/* making sure that if a user toggles the list and resize his browser the list is still visible */
/* We could do this in JS but I think that fixes the issue */
- display: flex!important;
+ display: flex !important;
}
.hd-aside__list--closed {
@@ -109,7 +117,7 @@
left: 0;
z-index: 1;
border-radius: var(--hd-space-1);
- transition: top .25s cubic-bezier(0,1,.5,1);
+ transition: top .25s cubic-bezier(0, 1, .5, 1);
display: none;
}
diff --git a/apps/docs/app/ui/layout/header/header.css b/apps/docs/app/ui/layout/header/header.css
index b07815403..3ebfe5f22 100644
--- a/apps/docs/app/ui/layout/header/header.css
+++ b/apps/docs/app/ui/layout/header/header.css
@@ -3,10 +3,22 @@
--hd-header-background-color: rgb(252 251 251 / 50%);
--hd-header-border-color: var(--hd-color-neutral-border-weak);
--hd-header-height: var(--hd-space-8);
+ --hd-header-shadow-1-block-color: rgba(175 182 225 / 80%);
+ --hd-header-shadow-2-block-color: #FECD94;
+ --hd-header-shadow-3-block-color: #A9F1D6;
+ --hd-header-shadow-1-top-position: -2.75rem;
+ --hd-header-shadow-2-top-position: -21.25rem;
+ --hd-header-shadow-3-top-position: -10.5rem;
}
[data-theme="dark"] {
--hd-header-background-color: rgb(41 40 41 / 80%);
+ --hd-header-shadow-1-block-color: rgba(175 182 225 / 70%);
+ --hd-header-shadow-2-block-color: #FECD94;
+ --hd-header-shadow-3-block-color: #A9F1D6;
+ --hd-header-shadow-1-top-position: -18.75rem;
+ --hd-header-shadow-2-top-position: -31.25rem;
+ --hd-header-shadow-3-top-position: -19.5rem;
}
.hd-header {
@@ -17,9 +29,18 @@
background-color: var(--hd-header-background-color);
backdrop-filter: blur(1rem);
border-block-end: var(--hd-border-size) solid var(--hd-header-border-color);
+ border-radius: 0 0 0.5rem 0.5rem;
z-index: 999;
}
+@media screen and (width >= 37.5rem) {
+ .hd-header {
+ border-radius: 0.5rem;
+ margin: 1.5rem auto 0;
+ width: min(100% - 3rem, 75rem);
+ }
+}
+
@media screen and (width >= 48rem) {
.hd-header {
position: sticky;
@@ -85,25 +106,25 @@
}
.hd-header-shadow-block-1 {
- background-color: #AFB6E1;
+ background-color: var(--hd-header-shadow-1-block-color);
width: 32rem;
height: 32rem;
- top: -18.75rem;
+ top: var(--hd-header-shadow-1-top-position);
right: 6rem;
}
.hd-header-shadow-block-2 {
width: 40rem;
height: 40rem;
- background-color: #FECD94;
+ background-color: var(--hd-header-shadow-2-block-color);
filter: blur(12.5rem);
- top: -31.25rem;
+ top: var(--hd-header-shadow-2-top-position);
}
.hd-header-shadow-block-3 {
- background-color: #A9F1D6;
+ background-color: var(--hd-header-shadow-3-block-color);
width: 32rem;
height: 32rem;
- top: -24rem;
+ top: var(--hd-header-shadow-3-top-position);
left: -10.5rem;
}
diff --git a/apps/docs/app/ui/layout/nav/nav.css b/apps/docs/app/ui/layout/nav/nav.css
index eb26c3e25..f93652df7 100644
--- a/apps/docs/app/ui/layout/nav/nav.css
+++ b/apps/docs/app/ui/layout/nav/nav.css
@@ -6,9 +6,9 @@
}
.hd-nav {
+ display: none;
font-size: var(--hd-nav-font-size);
line-height: var(--hd-nav-line-height);
- display: none;
}
@media screen and (width >= 37.5rem) {
diff --git a/apps/docs/app/ui/tokens/preview/preview.css b/apps/docs/app/ui/tokens/preview/preview.css
index 5d5fbcddf..cde6d319c 100644
--- a/apps/docs/app/ui/tokens/preview/preview.css
+++ b/apps/docs/app/ui/tokens/preview/preview.css
@@ -3,7 +3,9 @@
width: var(--hd-space-5);
height: var(--hd-space-3);
border-radius: 0;
- float: right;
+
+ /* float: right; */
+ display: inline-block;
background-color: var(--hd-color-primary-surface);
}
@@ -18,7 +20,7 @@
.hd-preview--font {
align-items: center;
background-color: transparent;
- display: flex;
+ display: inline-flex;
font-size: 1.5rem;
height: auto;
justify-content: flex-end;
diff --git a/apps/docs/app/ui/tokens/table/IconSpecTable.tsx b/apps/docs/app/ui/tokens/table/IconSpecTable.tsx
index e4b1368de..45042d04d 100644
--- a/apps/docs/app/ui/tokens/table/IconSpecTable.tsx
+++ b/apps/docs/app/ui/tokens/table/IconSpecTable.tsx
@@ -1,8 +1,6 @@
-"use client";
+import Table from "@/components/table/Table";
-import { Cell, Column, Row, Table as TableRA, TableBody, TableHeader } from "react-aria-components";
-
-import "./table.css";
+import "./tokenTable.css";
interface IconSpecTableProps {
data: {
@@ -15,34 +13,11 @@ interface IconSpecTableProps {
}
const IconSpecTable = ({ data }: IconSpecTableProps) => {
- const sizes = ["sm", "md", "lg"];
-
- const listItems = data?.map(row => {
- return (
-
- {row.name} |
- {sizes.map(size => (
-
- {row[size]}
- |
- ))}
-
- );
- });
-
- return (
-
-
- Anatomy
- Small
- Medium
- Large
-
-
- {listItems}
-
-
- );
+ return ;
};
export default IconSpecTable;
diff --git a/apps/docs/app/ui/tokens/table/Table.tsx b/apps/docs/app/ui/tokens/table/Table.tsx
deleted file mode 100644
index d4ebe9621..000000000
--- a/apps/docs/app/ui/tokens/table/Table.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-"use client";
-
-import { Cell, Column, Row, Table as TableRA, TableBody, TableHeader } from "react-aria-components";
-
-import Preview from "@/app/ui/tokens/preview/Preview";
-import Code from "@/components/code/Code";
-
-import "./table.css";
-
-interface TableProps {
- category: string;
- noPreview?: boolean;
- data: {
- name: string;
- value: string;
- }[];
-}
-
-const Table = ({ category, data, noPreview }: TableProps) => {
- const listItems = data?.map(token => {
- const { name, value } = token;
-
- return (
-
-
- {`--${name}`}
- |
- {value} |
- {!noPreview &&
-
- | }
-
- );
- });
-
- return (
-
-
- Name
- Value
- {!noPreview && Preview }
-
-
- {listItems}
-
-
- );
-};
-
-export default Table;
diff --git a/apps/docs/app/ui/tokens/table/Table.stories.tsx b/apps/docs/app/ui/tokens/table/TokenTable.stories.tsx
similarity index 80%
rename from apps/docs/app/ui/tokens/table/Table.stories.tsx
rename to apps/docs/app/ui/tokens/table/TokenTable.stories.tsx
index 2aa8f577b..cd080f86c 100644
--- a/apps/docs/app/ui/tokens/table/Table.stories.tsx
+++ b/apps/docs/app/ui/tokens/table/TokenTable.stories.tsx
@@ -1,11 +1,11 @@
import type { Meta, StoryObj } from "@storybook/react";
-import Table from "./Table";
+import TokenTable from "./TokenTable.tsx";
const meta = {
- title: "app/tokens/Table",
- component: Table
-} satisfies Meta;
+ title: "app/tokens/TokenTable",
+ component: TokenTable
+} satisfies Meta;
export default meta;
type Story = StoryObj;
diff --git a/apps/docs/app/ui/tokens/table/TokenTable.tsx b/apps/docs/app/ui/tokens/table/TokenTable.tsx
new file mode 100644
index 000000000..8276385e3
--- /dev/null
+++ b/apps/docs/app/ui/tokens/table/TokenTable.tsx
@@ -0,0 +1,36 @@
+import Table from "@/components/table/Table";
+
+import Preview from "@/app/ui/tokens/preview/Preview";
+import Code from "@/components/code/Code";
+
+import "./tokenTable.css";
+
+interface TableProps {
+ category: string;
+ noPreview?: boolean;
+ data: {
+ name: string;
+ value: string;
+ }[];
+}
+
+const TokenTable = ({ category, data, noPreview }: TableProps) => {
+ const formattedData = data.map(token => {
+ const { name, value } = token;
+
+ return {
+ name: {`--${name}`}
,
+ value: value,
+ preview: !noPreview &&
+ };
+ });
+
+
+ return ;
+};
+
+export default TokenTable;
diff --git a/apps/docs/app/ui/tokens/table/TypographyTable.tsx b/apps/docs/app/ui/tokens/table/TypographyTable.tsx
index cbc5618ef..c9a2e68f6 100644
--- a/apps/docs/app/ui/tokens/table/TypographyTable.tsx
+++ b/apps/docs/app/ui/tokens/table/TypographyTable.tsx
@@ -1,11 +1,15 @@
-"use client";
-
-import React from "react";
import clsx from "clsx";
-import { groupItemsByProperties, groupItemsByPropertiesAndSizes, type Size, type TokenData } from "@/app/lib/getTypographyTokens";
-import { TypographyTableRow } from "./TypographyTableRow";
+import Table from "@/components/table/Table";
+
+import {
+ groupItemsByProperties,
+ groupItemsByPropertiesAndSizes,
+ type Size,
+ type TokenData
+} from "@/app/lib/getTypographyTokens";
+import { typographyTableRow } from "./TypographyTableRow";
-import "./table.css";
+import "./tokenTable.css";
// maps the raw token list of a list filtered by property
function transformDataToTokenData(inputData: Record): TokenData {
@@ -31,36 +35,36 @@ const TypographyTable = ({ type, data }: TypographyTableProps) => {
const hasNoSizes = type === "overline";
const tokenData = transformDataToTokenData(data);
- const listItems = hasNoSizes ? generateSizelessRows(tokenData, type) : generateSizeRows(tokenData, type);
+ const listItems = hasNoSizes ? [generateSizelessRows(tokenData, type)] : generateSizeRows(tokenData, type);
- return (
-
-
-
- {!hasNoSizes && Size }
- Values
- Preview
-
-
-
- {listItems}
-
-
- );
+ return ();
};
function generateSizeRows(tokenData: TokenData, type: string) {
const filteredData = groupItemsByPropertiesAndSizes(tokenData, type);
return Object.keys(filteredData).map(size => {
- return ;
+ return typographyTableRow(
+ type,
+ filteredData[size as keyof typeof filteredData]!,
+ size as Size
+ );
});
}
function generateSizelessRows(tokenData: TokenData, type: string) {
const properties = groupItemsByProperties(tokenData, type);
- return ;
+ return typographyTableRow(type, properties!);
}
export default TypographyTable;
diff --git a/apps/docs/app/ui/tokens/table/TypographyTableRow.tsx b/apps/docs/app/ui/tokens/table/TypographyTableRow.tsx
index d8547b7d3..3e7fd31f6 100644
--- a/apps/docs/app/ui/tokens/table/TypographyTableRow.tsx
+++ b/apps/docs/app/ui/tokens/table/TypographyTableRow.tsx
@@ -2,15 +2,10 @@ import type { ComponentProps, ReactNode } from "react";
import TypographyPreview from "../preview/TypographyPreview";
import Code from "@/components/code/Code";
import type { FontProperties, Size } from "@/app/lib/getTypographyTokens";
-import "./table.css";
-interface TypographyTableRowProps {
- type: string;
- properties: FontProperties;
- size?: Size;
-}
+import "./tokenTable.css";
-export function TypographyTableRow({ type, properties, size }: TypographyTableRowProps) {
+export function typographyTableRow(type: string, properties: FontProperties, size?: Size) {
const {
fontFamily,
fontSize,
@@ -29,101 +24,97 @@ export function TypographyTableRow({ type, properties, size }: TypographyTableRo
};
}
- return (
-
- {size && {size} }
-
-
-
-
-
- );
+ return ({
+ name: size,
+ value: ,
+ preview:
+ });
}
interface PropertiesCellProps {
properties: FontProperties;
}
-function PropertiesCell({ properties } : PropertiesCellProps) {
+function PropertiesCell({ properties }: PropertiesCellProps) {
return (
-
-
-
- {properties.fontSize && (
-
- )}
- {properties.fontWeight && (
-
- )}
- {properties.lineHeight && (
-
- )}
- {properties.fontFamily && (
-
- )}
- {properties.topOffset && (
- Top Offset1 >}
- value={properties.topOffset.value}
- />
- )}
- {properties.bottomOffset && (
- Bottom Offset1 >}
- value={properties.bottomOffset.value}
- />
- )}
-
-
-
+
+
+ {properties.fontSize && (
+
+ )}
+ {properties.fontWeight && (
+
+ )}
+ {properties.lineHeight && (
+
+ )}
+ {properties.fontFamily && (
+
+ )}
+ {properties.topOffset && (
+ Top Offset1 >}
+ value={properties.topOffset.value}
+ />
+ )}
+ {properties.bottomOffset && (
+ Bottom Offset1 >}
+ value={properties.bottomOffset.value}
+ />
+ )}
+
+
);
}
-interface PropertyRowProps extends Omit, "children">{
+interface PropertyRowProps extends Omit, "children"> {
tokenName: string;
displayName: ReactNode;
value: string;
}
function PropertyRow({ tokenName, displayName, value, ...rest }: PropertyRowProps) {
- const tokenValue = value;
-
return (
@@ -133,7 +124,7 @@ function PropertyRow({ tokenName, displayName, value, ...rest }: PropertyRowProp
{tokenName}
- {tokenValue}
+ {value}
);
diff --git a/apps/docs/app/ui/tokens/table/TypographyVariantTable.tsx b/apps/docs/app/ui/tokens/table/TypographyVariantTable.tsx
index 0f9088dae..87f55ce1e 100644
--- a/apps/docs/app/ui/tokens/table/TypographyVariantTable.tsx
+++ b/apps/docs/app/ui/tokens/table/TypographyVariantTable.tsx
@@ -1,10 +1,8 @@
-"use client";
-
-import React from "react";
import TypographyPreview from "@/app/ui/tokens/preview/TypographyPreview";
import Code from "@/components/code/Code";
+import Table from "@/components/table/Table";
-import "./table.css";
+import "./tokenTable.css";
interface TypographyVariantTableProps {
data: Record;
@@ -27,37 +25,20 @@ const TypographyVariantTable = ({ type, data }: TypographyVariantTableProps) =>
const listItems = filteredDataByWeightVariation.map(item => {
const fontWeight = item.value;
- return (
-
-
- {item.name}
-
- {`--${item.name}`}
-
-
- {item.value}
-
-
-
-
-
-
- );
+ return {
+ name: {`--${item.name}`}
,
+ value: fontWeight,
+ preview:
+ };
});
return (
-
-
-
- Name
- Value
- Preview
-
-
-
- {listItems}
-
-
+
);
};
diff --git a/apps/docs/app/ui/tokens/table/table.css b/apps/docs/app/ui/tokens/table/tokenTable.css
similarity index 60%
rename from apps/docs/app/ui/tokens/table/table.css
rename to apps/docs/app/ui/tokens/table/tokenTable.css
index cd275e8f4..56f42626e 100644
--- a/apps/docs/app/ui/tokens/table/table.css
+++ b/apps/docs/app/ui/tokens/table/tokenTable.css
@@ -1,44 +1,3 @@
-.hd-table {
- width: 100%;
- outline: none;
- border-spacing: 0;
- align-self: start;
-}
-
-.hd-table__column {
- padding: var(--hd-space-2) var(--hd-space-1);
- text-align: left;
- color: var(--hd-color-neutral-text-weakest);
- font-size: 0.8125rem;
- font-style: normal;
- font-weight: 400;
- line-height: 0.8125rem;
-}
-
-.hd-table__column:first-child {
- padding-left: 0;
-}
-
-.hd-table__column:last-child,
-.hd-table__cell:last-child {
- text-align: right;
-}
-
-.hd-table__column--size {
- min-width: 3rem;
-}
-
-.hd-table__cell {
- font-family: var(--hd-mono-font-family);
- font-size: 0.8125rem;
- padding: var(--hd-space-1);
- border-bottom: var(--hd-border-size) solid var(--hd-color-neutral-border);
-}
-
-.hd-table__row > .hd-table__cell:first-child {
- padding-left: 0;
-}
-
/* TypoTable */
.hd-table__cell.hd-typo__cell {
text-align: left;
@@ -72,7 +31,7 @@
}
/* Has No Sizes */
-.hd-typo-table--has-no-sizes .hd-typo__cell{
+.hd-typo-table--has-no-sizes .hd-typo__cell {
padding: 0;
}
diff --git a/apps/docs/app/ui/tokens/tableSection/TableSection.tsx b/apps/docs/app/ui/tokens/tableSection/TableSection.tsx
index 7ed27b1d0..b5d44607c 100644
--- a/apps/docs/app/ui/tokens/tableSection/TableSection.tsx
+++ b/apps/docs/app/ui/tokens/tableSection/TableSection.tsx
@@ -1,7 +1,7 @@
"use client";
import React from "react";
-import Table from "@/app/ui/tokens/table/Table";
+import TokenTable from "@/app/ui/tokens/table/TokenTable.tsx";
import "@hopper-ui/tokens/fonts.css";
@@ -25,7 +25,7 @@ const TableSection = ({ tokens, categories, excludedCategories, categoryKey }: T
});
return ;
};
diff --git a/apps/docs/components/button/Button.stories.tsx b/apps/docs/components/button/Button.stories.tsx
index 6dafae8ea..229c921dd 100644
--- a/apps/docs/components/button/Button.stories.tsx
+++ b/apps/docs/components/button/Button.stories.tsx
@@ -49,7 +49,6 @@ export const AsLink: Story = {
as: "a",
href: "https://www.npmjs.com/package/@hopper-ui/components",
target: "_blank"
-
},
render: args => (
diff --git a/apps/docs/components/button/button.css b/apps/docs/components/button/button.css
index 7a06b9555..9ad25469a 100644
--- a/apps/docs/components/button/button.css
+++ b/apps/docs/components/button/button.css
@@ -32,7 +32,8 @@
flex-direction: row-reverse;
}
-.hd-btn[data-focus-visible="true"] {
+.hd-btn[data-focus-visible="true"],
+a.hd-btn:focus-visible {
box-shadow: var(--hd-focus-ring);
}
diff --git a/apps/docs/components/collapsible/Collapsible.stories.tsx b/apps/docs/components/collapsible/Collapsible.stories.tsx
new file mode 100644
index 000000000..5f3d09385
--- /dev/null
+++ b/apps/docs/components/collapsible/Collapsible.stories.tsx
@@ -0,0 +1,19 @@
+import type { Meta, StoryObj } from "@storybook/react";
+
+import Collasible from "./Collapsible.tsx";
+
+
+const meta = {
+ title: "components/Collasible",
+ component: Collasible
+} satisfies Meta
;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ title: "Label",
+ children: "Conent of the collapsible"
+ }
+};
diff --git a/apps/docs/components/collapsible/Collapsible.tsx b/apps/docs/components/collapsible/Collapsible.tsx
new file mode 100644
index 000000000..169dc64de
--- /dev/null
+++ b/apps/docs/components/collapsible/Collapsible.tsx
@@ -0,0 +1,52 @@
+"use client";
+
+import clsx from "clsx";
+import { type ReactNode, useRef, useState } from "react";
+import { ToggleButton } from "react-aria-components";
+import { Icon, CollapseIcon } from "@/components/icon";
+
+import "./collapsible.css";
+
+export interface CollapsibleProps {
+ children: ReactNode;
+ title: ReactNode;
+ label?: string;
+ isOpen?: boolean;
+ className?: string;
+}
+
+const Collapsible = ({ children, title, label, isOpen = false, className }: CollapsibleProps) => {
+ const [open, setOpen] = useState(isOpen);
+ const contentRef = useRef(null);
+
+ let styles = { height: "0px" };
+
+ if (contentRef.current && open) {
+ styles = { height: contentRef.current.scrollHeight + "px" };
+ }
+
+ const toggle = () => {
+ setOpen(!open);
+ };
+
+ return (
+
+ );
+};
+
+export default Collapsible;
diff --git a/apps/docs/components/collapsible/collapsible.css b/apps/docs/components/collapsible/collapsible.css
new file mode 100644
index 000000000..6d0282a60
--- /dev/null
+++ b/apps/docs/components/collapsible/collapsible.css
@@ -0,0 +1,52 @@
+/* Collapse */
+.hd-collapsible__trigger {
+ --collapsible-trigger-background: transparent;
+
+ font-family: var(--hd-default-font-family);
+ font-size: var(--hd-default-font-size);
+ line-height: 1.35;
+ color: var(--hd-color-neutral-text);
+ display: flex;
+ width: 100%;
+ justify-content: space-between;
+ align-items: center;
+ padding-block: var(--hd-space-2);
+ padding-inline: var(--hd-space-2);
+ border: none;
+ border-radius: 0.5rem;
+ background: var(--collapsible-trigger-background);
+ box-shadow: none;
+ transition: box-shadow 0.15s ease-in-out;
+ margin-inline: calc(var(--hd-space-2) * -1);
+}
+
+.hd-collapsible__trigger[data-hovered="true"] {
+ --collapsible-trigger-background: var(--hd-color-neutral-surface);
+
+ cursor: pointer;
+ box-shadow: 0 0.25rem 0.625rem 0.25rem rgb(60 60 60 / 8%);
+}
+
+.hd-collapsible__trigger .hd-title {
+ margin-block: 0;
+ margin-inline: 0;
+}
+
+.hd-collapsible__trigger[data-focused="true"],
+.hd-collapsible__trigger[data-focus-visible="true"] {
+ outline: none;
+}
+
+.hd-collapsible__trigger[data-focus-visible="true"] {
+ box-shadow: var(--hd-focus-ring);
+}
+
+.hd-collapsible__content {
+ padding-block: var(--hd-space-1);
+}
+
+.hd-collapsible__content-parent {
+ height: 0;
+ overflow: hidden;
+ transition: height ease 0.15s;
+}
diff --git a/apps/docs/components/highlightCode/HighlightCode.stories.tsx b/apps/docs/components/highlightCode/HighlightCode.stories.tsx
new file mode 100644
index 000000000..9dffa52c0
--- /dev/null
+++ b/apps/docs/components/highlightCode/HighlightCode.stories.tsx
@@ -0,0 +1,23 @@
+import type { Meta, StoryObj } from "@storybook/react";
+
+import { HighlightCode, highlightCode } from "./";
+
+const meta = {
+ title: "components/HighlightCode",
+ component: HighlightCode
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+const code = await highlightCode(`
+\`\`\`shell showLineNumbers
+pnpm install @hoper-ui/icons
+\`\`\`
+`);
+
+export const Default: Story = {
+ args: {
+ code: code
+ }
+};
diff --git a/apps/docs/app/ui/components/codeBlock/CodeBlock.tsx b/apps/docs/components/highlightCode/HighlightCode.tsx
similarity index 86%
rename from apps/docs/app/ui/components/codeBlock/CodeBlock.tsx
rename to apps/docs/components/highlightCode/HighlightCode.tsx
index 45ffda18b..a205881ac 100644
--- a/apps/docs/app/ui/components/codeBlock/CodeBlock.tsx
+++ b/apps/docs/components/highlightCode/HighlightCode.tsx
@@ -8,6 +8,10 @@ import rehypeParse from "rehype-parse";
import Pre from "@/components/pre/Pre.tsx";
+export interface HighlightCodeProps {
+ code: string;
+}
+
const production = { Fragment: prod.Fragment, jsx: prod.jsx, jsxs: prod.jsxs, components: { pre: Pre } };
function useProcessor(text: string) {
@@ -27,6 +31,6 @@ function useProcessor(text: string) {
return Content;
}
-export default function CodeBlock({ code }: { code: string }) {
+export default function HighlightCode({ code }: HighlightCodeProps) {
return useProcessor(code);
}
diff --git a/apps/docs/components/highlightCode/highlightCode.ts b/apps/docs/components/highlightCode/highlightCode.ts
new file mode 100644
index 000000000..a2593942d
--- /dev/null
+++ b/apps/docs/components/highlightCode/highlightCode.ts
@@ -0,0 +1,16 @@
+import { type Plugin, unified } from "unified";
+import remarkParse from "remark-parse";
+import remarkRehype from "remark-rehype";
+import { rehypePluginOptions } from "@/app/lib/rehypeConfig";
+import rehypeStringify from "rehype-stringify";
+
+export async function highlightCode(code: string) {
+ const file = await unified()
+ .use(remarkParse as unknown as Plugin)
+ .use(remarkRehype as unknown as Plugin)
+ .use(rehypePluginOptions as unknown as Plugin)
+ .use(rehypeStringify as unknown as Plugin)
+ .process(code);
+
+ return String(file);
+}
diff --git a/apps/docs/components/highlightCode/index.ts b/apps/docs/components/highlightCode/index.ts
new file mode 100644
index 000000000..ad98271c0
--- /dev/null
+++ b/apps/docs/components/highlightCode/index.ts
@@ -0,0 +1,8 @@
+import { highlightCode } from "./highlightCode.ts";
+import HighlightCode, { type HighlightCodeProps } from "./HighlightCode.tsx";
+
+export {
+ highlightCode,
+ HighlightCode,
+ type HighlightCodeProps
+};
diff --git a/apps/docs/components/icon/assets/accessible.svg b/apps/docs/components/icon/assets/accessible.svg
new file mode 100644
index 000000000..dfeef8cf4
--- /dev/null
+++ b/apps/docs/components/icon/assets/accessible.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/apps/docs/components/icon/assets/arrow.svg b/apps/docs/components/icon/assets/arrow.svg
new file mode 100644
index 000000000..88f4a7332
--- /dev/null
+++ b/apps/docs/components/icon/assets/arrow.svg
@@ -0,0 +1 @@
+
diff --git a/apps/docs/components/icon/assets/collapse.svg b/apps/docs/components/icon/assets/collapse.svg
new file mode 100644
index 000000000..b69aec16d
--- /dev/null
+++ b/apps/docs/components/icon/assets/collapse.svg
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/apps/docs/components/icon/assets/dark-mode.svg b/apps/docs/components/icon/assets/dark-mode.svg
new file mode 100644
index 000000000..2eca64c38
--- /dev/null
+++ b/apps/docs/components/icon/assets/dark-mode.svg
@@ -0,0 +1 @@
+
diff --git a/apps/docs/components/icon/assets/font-size.svg b/apps/docs/components/icon/assets/font-size.svg
new file mode 100644
index 000000000..c90ece4a9
--- /dev/null
+++ b/apps/docs/components/icon/assets/font-size.svg
@@ -0,0 +1 @@
+
diff --git a/apps/docs/components/icon/assets/international.svg b/apps/docs/components/icon/assets/international.svg
new file mode 100644
index 000000000..364959b75
--- /dev/null
+++ b/apps/docs/components/icon/assets/international.svg
@@ -0,0 +1 @@
+
diff --git a/apps/docs/components/icon/assets/line-height.svg b/apps/docs/components/icon/assets/line-height.svg
new file mode 100644
index 000000000..76ce86cd7
--- /dev/null
+++ b/apps/docs/components/icon/assets/line-height.svg
@@ -0,0 +1 @@
+
diff --git a/apps/docs/components/icon/assets/margin.svg b/apps/docs/components/icon/assets/margin.svg
new file mode 100644
index 000000000..1a9f98949
--- /dev/null
+++ b/apps/docs/components/icon/assets/margin.svg
@@ -0,0 +1 @@
+
diff --git a/apps/docs/components/icon/assets/select-arrow.svg b/apps/docs/components/icon/assets/select-arrow.svg
new file mode 100644
index 000000000..736cf9ead
--- /dev/null
+++ b/apps/docs/components/icon/assets/select-arrow.svg
@@ -0,0 +1 @@
+
diff --git a/apps/docs/components/icon/assets/typescript.svg b/apps/docs/components/icon/assets/typescript.svg
new file mode 100644
index 000000000..a1c9844d7
--- /dev/null
+++ b/apps/docs/components/icon/assets/typescript.svg
@@ -0,0 +1 @@
+
diff --git a/apps/docs/components/icon/index.tsx b/apps/docs/components/icon/index.tsx
index adfbb8eeb..7364279df 100644
--- a/apps/docs/components/icon/index.tsx
+++ b/apps/docs/components/icon/index.tsx
@@ -1,16 +1,36 @@
-import NpmIcon from "./assets/npm.svg";
-import GithubIcon from "./assets/github.svg";
-import ExternalLinkIcon from "./assets/external-link.svg";
+import AccessibleIcon from "./assets/accessible.svg";
+import ArrowIcon from "./assets/arrow.svg";
import ComponentIcon from "./assets/component.svg";
+import DarkModeIcon from "./assets/dark-mode.svg";
+import ExternalLinkIcon from "./assets/external-link.svg";
+import FontSizeIcon from "./assets/font-size.svg";
+import GithubIcon from "./assets/github.svg";
+import InternationalIcon from "./assets/international.svg";
+import LineHeightIcon from "./assets/line-height.svg";
+import MarginIcon from "./assets/margin.svg";
+import NpmIcon from "./assets/npm.svg";
+import SelectArrowIcon from "./assets/select-arrow.svg";
import TokenIcon from "./assets/tokens.svg";
+import TypescriptIcon from "./assets/typescript.svg";
+import CollapseIcon from "./assets/collapse.svg";
import Icon, { type IconProps } from "./Icon.tsx";
export {
- Icon,
- NpmIcon,
- GithubIcon,
- ExternalLinkIcon,
+ AccessibleIcon,
+ ArrowIcon,
ComponentIcon,
+ DarkModeIcon,
+ ExternalLinkIcon,
+ FontSizeIcon,
+ GithubIcon,
+ InternationalIcon,
+ LineHeightIcon,
+ MarginIcon,
+ NpmIcon,
+ SelectArrowIcon,
TokenIcon,
+ CollapseIcon,
+ TypescriptIcon,
+ Icon,
IconProps
};
diff --git a/apps/docs/components/mdx/components.tsx b/apps/docs/components/mdx/components.tsx
index 0cc69939f..a3c0695c7 100644
--- a/apps/docs/components/mdx/components.tsx
+++ b/apps/docs/components/mdx/components.tsx
@@ -5,7 +5,7 @@ import Card from "@/components/card/Card.tsx";
import NextImage from "@/components/image/Image.tsx";
import Pre from "@/components/pre/Pre.tsx";
import InlineCode from "@/components/code/InlineCode.tsx";
-import Table from "@/app/ui/tokens/table/Table.tsx";
+import TokenTable from "@/app/ui/tokens/table/TokenTable.tsx";
import TypographyTable from "@/app/ui/tokens/table/TypographyTable.tsx";
import TypographyVariantTable from "@/app/ui/tokens/table/TypographyVariantTable.tsx";
import { IconTable } from "@/app/ui/icons/iconTable/IconTable.tsx";
@@ -16,13 +16,18 @@ import Switcher from "@/app/ui/icons/switcher/Switcher.tsx";
import Title from "@/components/title/Title.tsx";
import MotionPreview from "@/components/motionPreview/MotionPreview.tsx";
import Footnote from "@/components/footnote/Footnote.tsx";
+import PackageInstallation, {
+ type PackageInstallationProps
+} from "@/components/packageInstallation/PackageInstallation.tsx";
import type { PreviewComponentProps } from "@/app/ui/components/previewComponent/PreviewComponent.tsx";
import type { MigrateGuideProps } from "@/app/ui/components/migrateGuide/MigrateGuide.tsx";
+import type { PropTableProps } from "@/app/ui/components/propTable/PropTable.tsx";
type HeadingProps = React.DetailedHTMLProps, HTMLHeadingElement>;
const PreviewComponent = dynamic(() => import("@/app/ui/components/previewComponent/PreviewComponent.tsx"));
const MigrateGuide = dynamic(() => import("@/app/ui/components/migrateGuide/MigrateGuide.tsx"));
+const PropTable = dynamic(() => import("@/app/ui/components/propTable/PropTable.tsx"));
export const components = {
Card,
@@ -31,7 +36,7 @@ export const components = {
pre: Pre,
MotionPreview: MotionPreview,
Footnote: Footnote,
- Table: Table,
+ Table: TokenTable,
TypographyTable: TypographyTable,
TypographyVariantTable: TypographyVariantTable,
IconTable: IconTable,
@@ -39,12 +44,18 @@ export const components = {
Tabs: Tabs,
TableSection: TableSection,
Switcher: Switcher,
+ PackageInstallation: (props: PackageInstallationProps) => {
+ return ;
+ },
PreviewComponent: (props: PreviewComponentProps) => {
return ;
},
MigrateGuide: (props: MigrateGuideProps) => {
return ;
},
+ PropTable: (props: PropTableProps) => {
+ return ;
+ },
h1: (props: HeadingProps) => {
return ;
},
diff --git a/apps/docs/components/packageInstallation/PackageInstallation.tsx b/apps/docs/components/packageInstallation/PackageInstallation.tsx
new file mode 100644
index 000000000..45d1fc0d2
--- /dev/null
+++ b/apps/docs/components/packageInstallation/PackageInstallation.tsx
@@ -0,0 +1,75 @@
+import Tabs from "@/components/tabs/Tabs.tsx";
+import { HighlightCode, highlightCode } from "@/components/highlightCode";
+
+import type { ReactElement } from "react";
+
+export interface PackageInstallationProps {
+ library: string;
+ mode: "dev" | "prod";
+}
+
+type MethodIcons = Record;
+
+const methods = ["pnpm", "yarn", "npm"] as const;
+
+const methodsIcons: MethodIcons = {
+ pnpm:
+
+
+
+
+ ,
+ yarn:
+
+ {/* eslint-disable max-len */}
+
+ ,
+ npm:
+
+
+
+};
+
+const installMethods = methods.map(method => ({
+ category: method,
+ title: method,
+ titleIcon: methodsIcons[method]
+}));
+
+const formatCode = async (method: string, library: string, mode: string) => {
+ const code = `${method} add ${mode === "dev" ? "-D" : ""} @hopper-ui/${library}`;
+
+ return await highlightCode(`
+\`\`\`shell
+${code.replace(/\s{2,}/g, " ")}
+\`\`\`
+`);
+};
+
+const PackageInstallation = async ({ library, mode = "prod" }: PackageInstallationProps) => {
+ const tabsContent = await Promise.all(methods.map(async method => {
+ const code = await formatCode(method, library, mode);
+
+ return (
+
+
+
+ );
+ }));
+
+ return (
+
+ {tabsContent}
+
+ );
+};
+
+export default PackageInstallation;
diff --git a/apps/docs/components/pre/pre.css b/apps/docs/components/pre/pre.css
index 205c1e549..2e927d20e 100644
--- a/apps/docs/components/pre/pre.css
+++ b/apps/docs/components/pre/pre.css
@@ -8,6 +8,7 @@
margin-block: 0.25rem;
align-content: center;
color: var(--hd-color-neutral-text-strong);
+ overflow-x: auto;
}
.hd-pre--title,
diff --git a/apps/docs/components/table/Table.stories.tsx b/apps/docs/components/table/Table.stories.tsx
new file mode 100644
index 000000000..71eba3345
--- /dev/null
+++ b/apps/docs/components/table/Table.stories.tsx
@@ -0,0 +1,50 @@
+import type { Meta, StoryObj } from "@storybook/react";
+
+import Table from "./Table";
+import Code from "@/components/code/Code";
+import Preview from "@/app/ui/tokens/preview/Preview.tsx";
+
+const meta = {
+ title: "components/Table",
+ component: Table
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ head: ["Position", "Mass", "Symbol", "Name"],
+ data: [
+ { position: 6, mass: 12.011, symbol: "C", name: "Carbon" },
+ { position: 7, mass: 14.007, symbol: "N", name: "Nitrogen" },
+ { position: 39, mass: 88.906, symbol: "Y", name: "Yttrium" },
+ { position: 56, mass: 137.33, symbol: "Ba", name: "Barium" },
+ { position: 58, mass: 140.12, symbol: "Ce", name: "Cerium" }
+ ]
+ }
+};
+
+export const Tokens: Story = {
+ args: {
+ lastColumnAlignment: "right",
+ head: ["Token", "Value", "Preview"],
+ data: [
+ {
+ name: --hop-sapphire-200
,
+ value: "#95b1ff",
+ preview:
+ },
+ {
+ name: --hop-primary-surface-disabled
,
+ value: "#95b1ff",
+ preview:
+ },
+ {
+ name: --hop-primary-surface-disabled
,
+ value: "#2040c7",
+ preview:
+ }
+ ]
+ }
+};
diff --git a/apps/docs/components/table/Table.tsx b/apps/docs/components/table/Table.tsx
new file mode 100644
index 000000000..9a84d3db0
--- /dev/null
+++ b/apps/docs/components/table/Table.tsx
@@ -0,0 +1,68 @@
+"use client";
+
+import clsx from "clsx";
+import { Cell, Column, Row, Table as TableRA, TableBody, TableHeader } from "react-aria-components";
+import type { ReactNode } from "react";
+
+import "./table.css";
+
+interface dataType {
+ [key: string]: string | number | boolean | undefined | null | ReactNode;
+}
+
+interface TableProps {
+ head: (string | boolean)[];
+ data: dataType[];
+ lastColumnAlignment?: "left" | "right";
+ "ariaLabel"?: string;
+ className?: string;
+}
+
+function generateUniqueKey() {
+ return `${Date.now()}-${Math.random()}`;
+}
+
+const Table = ({ data, head, lastColumnAlignment = "left", ariaLabel = "standard table", className }: TableProps) => {
+ const textAlignRight = lastColumnAlignment === "right";
+ const lastColumn = head.length - 1;
+
+ const headItems = head.map((item, index) => {
+ return (
+
+ {item}
+
+ );
+ });
+
+ const dataItems = data.map(item => {
+ return (
+
+ {Object.keys(item).map((key, index) => {
+ return (
+
+ {item[key]}
+ |
+ );
+ })}
+
+ );
+ });
+
+ return (
+
+
+ {headItems}
+
+
+ {dataItems}
+
+
+ );
+};
+
+export default Table;
diff --git a/apps/docs/components/table/table.css b/apps/docs/components/table/table.css
new file mode 100644
index 000000000..195fba20c
--- /dev/null
+++ b/apps/docs/components/table/table.css
@@ -0,0 +1,40 @@
+.hd-table {
+ width: 100%;
+ outline: none;
+ border-spacing: 0;
+ align-self: start;
+}
+
+.hd-table__column {
+ padding: var(--hd-space-2) var(--hd-space-1);
+ text-align: left;
+ color: var(--hd-color-neutral-text-weakest);
+ font-size: 0.8125rem;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 0.8125rem;
+}
+
+.hd-table__column:first-child {
+ padding-left: 0;
+}
+
+.hd-table__column--size {
+ min-width: 3rem;
+}
+
+.hd-table__cell {
+ font-family: var(--hd-mono-font-family);
+ font-size: 0.8125rem;
+ padding: var(--hd-space-1);
+ border-bottom: var(--hd-border-size) solid var(--hd-color-neutral-border);
+}
+
+.hd-table__row > .hd-table__cell:first-child {
+ padding-left: 0;
+}
+
+.hd-table__colum--right,
+.hd-table__cell--right {
+ text-align: right;
+}
diff --git a/apps/docs/components/themeSwitch/themeSwitch.css b/apps/docs/components/themeSwitch/themeSwitch.css
index 82e247791..60b3b9abf 100644
--- a/apps/docs/components/themeSwitch/themeSwitch.css
+++ b/apps/docs/components/themeSwitch/themeSwitch.css
@@ -10,7 +10,7 @@
font-size: 1rem;
}
-@media screen and (width >= 48rem) {
+@media screen and (width >= 37.5rem) {
.hd-theme-switch__button {
width: var(--hd-space-4);
aspect-ratio: 1/1;
diff --git a/apps/docs/content/components/button.mdx b/apps/docs/content/components/button.mdx
index 7c253f9dc..d7c844de4 100644
--- a/apps/docs/content/components/button.mdx
+++ b/apps/docs/content/components/button.mdx
@@ -17,6 +17,10 @@ import { Button } from "@hopper-ui/components";
```tsx showLineNumbers
save
```
+## Props
+The table below contains all types of the props available in title component.
+
+
## Migration Notes
diff --git a/apps/docs/content/components/installation.mdx b/apps/docs/content/components/installation.mdx
index 50d842110..acea6300e 100644
--- a/apps/docs/content/components/installation.mdx
+++ b/apps/docs/content/components/installation.mdx
@@ -4,3 +4,7 @@ description: The installation proccess
---
# Installation
+
+## Install packages
+
+
diff --git a/apps/docs/content/icons/react-icons/icon-library.mdx b/apps/docs/content/icons/react-icons/icon-library.mdx
index cdc54e9da..907318784 100644
--- a/apps/docs/content/icons/react-icons/icon-library.mdx
+++ b/apps/docs/content/icons/react-icons/icon-library.mdx
@@ -9,6 +9,8 @@ export const usageMethods = [
{ title: "SVG" }
];
+# Icons
+
All available icons in the icon library are shown below.
Use the correct size for each icon. Icons should be used at their original size according to the design.
diff --git a/apps/docs/content/icons/react-icons/installation.mdx b/apps/docs/content/icons/react-icons/installation.mdx
index a84606049..ca1cd8255 100644
--- a/apps/docs/content/icons/react-icons/installation.mdx
+++ b/apps/docs/content/icons/react-icons/installation.mdx
@@ -4,12 +4,6 @@ description: Getting started with Workleap Design Icons
order: 1
---
-export const installMethods = [
- { title: "pnpm", titleIcon: },
- { title: "yarn", titleIcon: },
- { title: "npm", titleIcon: }
-];
-
React Icons are typically utilized alongside the `@hopper-ui/components`. If you want to use them without `@hopper-ui/components`, refer to the [standalone installation](/icons/react-icons/standalone-installation).
## Prerequisites
@@ -18,23 +12,7 @@ Follow the `@hopper-ui/components` procedure(coming soon).
## Install packages
-
-
- ```shell
- pnpm add @hopper-ui/icons
- ```
-
-
- ```shell
- yarn add -D @hopper-ui/icons
- ```
-
-
- ```shell
- npm add -D @hopper-ui/icons
- ```
-
-
+
## Import Styles
diff --git a/apps/docs/content/icons/react-icons/standalone-installation.mdx b/apps/docs/content/icons/react-icons/standalone-installation.mdx
index 47dc149ef..8562b7a98 100644
--- a/apps/docs/content/icons/react-icons/standalone-installation.mdx
+++ b/apps/docs/content/icons/react-icons/standalone-installation.mdx
@@ -4,33 +4,11 @@ description: Getting started with Workleap Design Icons
order: 2
---
-export const installMethods = [
- { title: "pnpm", titleIcon: },
- { title: "yarn", titleIcon: },
- { title: "npm", titleIcon: }
-];
-
It is recommended to use `@hopper-ui/icons` with `@hopper-ui/components` as detailed in the [installation section](/icons/react-icons/installation). The standalone installation procedure is detailed in case you only need the icons, and not the components.
## Install packages
-
-
- ```shell
- pnpm add @hopper-ui/icons @hopper-ui/styled-system react-aria-components
- ```
-
-
- ```shell
- yarn add @hopper-ui/icons @hopper-ui/styled-system react-aria-components
- ```
-
-
- ```shell
- npm add @hopper-ui/icons @hopper-ui/styled-system react-aria-components
- ```
-
-
+
## Import Styles
diff --git a/apps/docs/content/icons/svg/installation.mdx b/apps/docs/content/icons/svg/installation.mdx
index 2f922ed08..36083ff9a 100644
--- a/apps/docs/content/icons/svg/installation.mdx
+++ b/apps/docs/content/icons/svg/installation.mdx
@@ -4,31 +4,9 @@ description: Getting started with Workleap Design Icons
order: 1
---
-export const installMethods = [
- { title: "pnpm", titleIcon: },
- { title: "yarn", titleIcon: },
- { title: "npm", titleIcon: }
-];
-
## Install packages
-
-
- ```shell
- pnpm add @hopper-ui/svg-icons
- ```
-
-
- ```shell
- yarn add -D @hopper-ui/svg-icons
- ```
-
-
- ```shell
- npm add -D @hopper-ui/svg-icons
- ```
-
-
+
## Start using icons
diff --git a/apps/docs/content/tokens/getting-started/installation.mdx b/apps/docs/content/tokens/getting-started/installation.mdx
index 54a4ee9f7..19d9edb30 100644
--- a/apps/docs/content/tokens/getting-started/installation.mdx
+++ b/apps/docs/content/tokens/getting-started/installation.mdx
@@ -4,30 +4,8 @@ description: Getting started with Workleap Design Tokens
order: 2
---
-export const installMethods = [
- { title: "pnpm", titleIcon: },
- { title: "yarn", titleIcon: },
- { title: "npm", titleIcon: }
-];
-
## Package manager
Run the following command to install the tokens package.
-
-
- ```shell
- pnpm add @hopper-ui/tokens
- ```
-
-
- ```shell
- yarn add -D @hopper-ui/tokens
- ```
-
-
- ```shell
- npm add -D @hopper-ui/tokens
- ```
-
-
+
diff --git a/apps/docs/datas/components/Button.json b/apps/docs/datas/components/Button.json
new file mode 100644
index 000000000..9b7263605
--- /dev/null
+++ b/apps/docs/datas/components/Button.json
@@ -0,0 +1 @@
+[{"tags":{},"filePath":"/Users/franck.gaudin/Devel/DS/wl-hopper/packages/components/src/buttons/src/Button.tsx","description":"Buttons are used to initialize an action. Button labels express what action will occur when the user interacts with it.\n\n[View Documentation](TODO)","displayName":"Button","methods":[],"props":{"variant":{"defaultValue":{"value":"\"primary\""},"description":"The visual style of the button.\n*","name":"variant","parent":{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"},"declarations":[{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"}],"required":false,"type":{"name":"\"primary\" | \"secondary\" | \"danger\" | \"upsell\" | \"ghost-primary\" | \"ghost-secondary\" | \"ghost-danger\""}},"size":{"defaultValue":{"value":"\"md\""},"description":"A button can vary in size.","name":"size","parent":{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"},"declarations":[{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"}],"required":false,"type":{"name":"ResponsiveProp<\"sm\" | \"md\">"}},"fluid":{"defaultValue":null,"description":"Whether or not the button takes up the width of its container.","name":"fluid","parent":{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"},"declarations":[{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"}],"required":false,"type":{"name":"ResponsiveProp"}},"isLoading":{"defaultValue":null,"description":"","name":"isLoading","parent":{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"},"declarations":[{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"}],"required":false,"type":{"name":"boolean"}},"href":{"defaultValue":null,"description":"A URL to link to. Setting this makes the component render an `a` tag instead of a `button`","name":"href","parent":{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"},"declarations":[{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"}],"required":false,"type":{"name":"string"}},"target":{"defaultValue":null,"description":"The target window for the link.","name":"target","parent":{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"},"declarations":[{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"}],"required":false,"type":{"name":"string"}},"rel":{"defaultValue":null,"description":"The relationship between the linked resource and the current page. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel).","name":"rel","parent":{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"},"declarations":[{"fileName":"wl-hopper/packages/components/src/buttons/src/Button.tsx","name":"ButtonProps"}],"required":false,"type":{"name":"string"}},"form":{"defaultValue":null,"description":"The