From 4b1127fe1e526de1dedbf6b9c761573e6128f8b0 Mon Sep 17 00:00:00 2001 From: Francis Thibault Date: Wed, 8 Nov 2023 13:10:26 -0500 Subject: [PATCH] Feature/hop-37 - Feature/hop-30 (#80) Co-authored-by: Francis Thibault --- apps/docs/.eslintrc.json | 1 + apps/docs/app/layout.css | 7 +- .../docs/components/copyButton/copyButton.css | 10 +- .../components/preview/TypographyPreview.tsx | 21 +++ apps/docs/components/ui/mdx/Mdx.tsx | 2 + apps/docs/components/ui/pre/Pre.tsx | 2 +- apps/docs/components/ui/table/Table.tsx | 2 +- .../components/ui/table/TypographyTable.tsx | 164 ++++++++++++++++++ apps/docs/components/ui/table/table.css | 31 +++- .../tokens/getting-started/installation.mdx | 22 ++- .../tokens/getting-started/introduction.mdx | 99 +++++++---- .../content/tokens/getting-started/usage.mdx | 47 +++++ .../content/tokens/semantic/font-family.mdx | 11 -- .../content/tokens/semantic/font-size.mdx | 11 -- .../content/tokens/semantic/font-weight.mdx | 11 -- .../content/tokens/semantic/line-height.mdx | 11 -- .../content/tokens/semantic/typography.mdx | 36 ++++ apps/docs/styles/themes/rehype.css | 2 +- 18 files changed, 404 insertions(+), 86 deletions(-) create mode 100644 apps/docs/components/preview/TypographyPreview.tsx create mode 100644 apps/docs/components/ui/table/TypographyTable.tsx create mode 100644 apps/docs/content/tokens/getting-started/usage.mdx delete mode 100644 apps/docs/content/tokens/semantic/font-family.mdx delete mode 100644 apps/docs/content/tokens/semantic/font-size.mdx delete mode 100644 apps/docs/content/tokens/semantic/font-weight.mdx delete mode 100644 apps/docs/content/tokens/semantic/line-height.mdx create mode 100644 apps/docs/content/tokens/semantic/typography.mdx diff --git a/apps/docs/.eslintrc.json b/apps/docs/.eslintrc.json index 861810985..7bf8ccfcb 100644 --- a/apps/docs/.eslintrc.json +++ b/apps/docs/.eslintrc.json @@ -13,6 +13,7 @@ "globals": { "Card": true, "Table": true, + "TypographyTable": true, "Tabs": true, "TableSection": true } diff --git a/apps/docs/app/layout.css b/apps/docs/app/layout.css index f04fef74b..0063ad8e6 100644 --- a/apps/docs/app/layout.css +++ b/apps/docs/app/layout.css @@ -48,7 +48,7 @@ main { p { font-size: 1rem; - line-height: 1.5rem; + line-height: 1.5; } p:not(:last-child) { @@ -58,3 +58,8 @@ p:not(:last-child) { p + * { margin-block-start: var(--hd-space-3); } + +article ul { + line-height: 1.5rem; + padding-left: 1rem; +} diff --git a/apps/docs/components/copyButton/copyButton.css b/apps/docs/components/copyButton/copyButton.css index 46494f06a..63027b8b1 100644 --- a/apps/docs/components/copyButton/copyButton.css +++ b/apps/docs/components/copyButton/copyButton.css @@ -5,8 +5,8 @@ background-color: transparent; border: none; stroke: var(--hd-icon-button-color); - width: var(--hd-space-4); aspect-ratio: 1/1; + width: var(--hd-space-4); border-radius: var(--hd-space-1); cursor: pointer; } @@ -27,3 +27,11 @@ .hd-copy-button--inlined { background: var(--hd-color-neutral-surface); } + +.hd-copy-button--on-dark { + stroke: var(--hd-neutral-20); +} + +.hd-copy-button--on-dark:hover { + stroke: var(--hd-neutral-900); +} diff --git a/apps/docs/components/preview/TypographyPreview.tsx b/apps/docs/components/preview/TypographyPreview.tsx new file mode 100644 index 000000000..bd6ab3709 --- /dev/null +++ b/apps/docs/components/preview/TypographyPreview.tsx @@ -0,0 +1,21 @@ +import "@hopper-ui/tokens/fonts.css"; +import "./preview.css"; + +interface TypographyPreviewProps { + values?: TypographyValues; + style?: React.CSSProperties; +} + +interface TypographyValues { + lineHeight?: string; + fontWeight?: string; + fontSize?: string; + fontFamily?: string; +} + +const TypographyPreview = ({ values, style }: TypographyPreviewProps) => { + return
Aa
; +}; + +export default TypographyPreview; + diff --git a/apps/docs/components/ui/mdx/Mdx.tsx b/apps/docs/components/ui/mdx/Mdx.tsx index 2587f0c22..2ed00e745 100644 --- a/apps/docs/components/ui/mdx/Mdx.tsx +++ b/apps/docs/components/ui/mdx/Mdx.tsx @@ -6,6 +6,7 @@ import Card from "@/components/ui/card/Card"; import Pre from "@/components/ui/pre/Pre"; import Title from "@/components/ui/title/Title"; import Table from "@/components/ui/table/Table"; +import TypographyTable from "@/components/ui/table/TypographyTable"; import Tabs from "@/components/tabs/Tabs"; import TableSection from "@/components/tableSection/TableSection"; @@ -16,6 +17,7 @@ const components = { Image: NextImage, pre: Pre, Table: Table, + TypographyTable: TypographyTable, Tabs: Tabs, TableSection: TableSection, h1: (props: HeadingProps) => { diff --git a/apps/docs/components/ui/pre/Pre.tsx b/apps/docs/components/ui/pre/Pre.tsx index 3aa832dc4..f182132d4 100644 --- a/apps/docs/components/ui/pre/Pre.tsx +++ b/apps/docs/components/ui/pre/Pre.tsx @@ -22,7 +22,7 @@ const Pre = ({ children, title, "data-language": dataLanguage, raw, ...props }: } {title} - {raw && } + {raw && } {children} diff --git a/apps/docs/components/ui/table/Table.tsx b/apps/docs/components/ui/table/Table.tsx index 78b1df7dc..6d617449a 100644 --- a/apps/docs/components/ui/table/Table.tsx +++ b/apps/docs/components/ui/table/Table.tsx @@ -20,7 +20,7 @@ const Table = ({ category, data }: TableProps) => { const { name, value } = token; return ( - + {`--${name}`} diff --git a/apps/docs/components/ui/table/TypographyTable.tsx b/apps/docs/components/ui/table/TypographyTable.tsx new file mode 100644 index 000000000..1814768f8 --- /dev/null +++ b/apps/docs/components/ui/table/TypographyTable.tsx @@ -0,0 +1,164 @@ +"use client"; + +import React from "react"; +import TypographyPreview from "@/components/preview/TypographyPreview"; +import Code from "@/components/ui/code/Code"; + +import "./table.css"; + +interface TypographyTableProps { + type: string; + data: Record; +} + +const Sizes = ["3xl", "2xl", "xl", "lg", "md", "sm", "xs"] as const; + +const FontProperties = ["fontFamily", "fontSize", "fontWeight", "lineHeight"] as const; + +type GroupedItems = Record>; + +interface TokenData { + [category: string]: { name: string; value: string }[]; +} + +function transformDataToTokenData(inputData: Record): TokenData { + const tokenData: TokenData = {}; + + for (const propertyKey in inputData) { + const items = inputData[propertyKey]; + + if (Array.isArray(items)) { + tokenData[propertyKey] = items; + } + } + + return tokenData; +} + +function groupItemsByPropertiesAndSizes(tokenData: TokenData, itemType: string): GroupedItems { + const groupedItems: GroupedItems = {} as GroupedItems; + + Sizes.forEach(size => { + const sizeKey = size as typeof Sizes[number]; + groupedItems[sizeKey] = {} as Record; + + FontProperties.forEach(property => { + const propertyKey = property; + + if (!tokenData[propertyKey]) { + return; + } + + const matchingItem = tokenData[propertyKey].find(item => { + const nameParts = item.name.split("-"); + + return nameParts.includes(itemType === "overline" ? "md" : itemType) && nameParts.includes(size); + }); + + if (matchingItem) { + groupedItems[sizeKey][propertyKey] = matchingItem.value; + } + }); + + if (Object.values(groupedItems[sizeKey]).every(value => !value)) { + delete groupedItems[sizeKey]; + } + }); + + return groupedItems; +} + +const TypographyTable = ({ type, data }: TypographyTableProps) => { + const tokenData = transformDataToTokenData(data); + const filteredData = groupItemsByPropertiesAndSizes(tokenData, type); + + const listItems = Object.keys(filteredData).map(size => { + const { + fontFamily, + fontSize, + fontWeight, + lineHeight + } = filteredData[size as typeof Sizes[number]]; + + // If the itemType is 'overline', set displaySize to an empty string + let displaySize = `-${size}`; + let previewAdditionalStyles = {}; + + if (type === "overline") { + displaySize = ""; + previewAdditionalStyles = { + textTransform: "uppercase" + }; + } + + return ( + + + {type !== "overline" && {size}} + + Font Size + + + {`--hop-${type}${displaySize}-font-size`} + + + {fontSize} + + + + + + + + Font Weight + + + {`--hop-${type}${displaySize}-font-weight`} + + + {fontWeight} + + + + + Line Height + + + {`--hop-${type}${displaySize}-line-height`} + + + {lineHeight} + + + + + Font Family + + + {`--hop-${type}${displaySize}-font-family`} + + + {fontFamily} + + + + ); + }); + + return ( + + + + {type !== "overline" && } + + + + + + {listItems} + +
NameValuesPreview
+ ); +}; + +export default TypographyTable; diff --git a/apps/docs/components/ui/table/table.css b/apps/docs/components/ui/table/table.css index af290c64a..d895cfb55 100644 --- a/apps/docs/components/ui/table/table.css +++ b/apps/docs/components/ui/table/table.css @@ -6,7 +6,7 @@ } .hd-table__column { - padding-block: var(--hd-space-2); + padding: var(--hd-space-2) var(--hd-space-1); text-align: left; color: var(--hd-color-neutral-text-weakest); font-size: 0.8125rem; @@ -15,6 +15,10 @@ 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; @@ -23,6 +27,29 @@ .hd-table__cell { font-family: var(--hd-mono-font-family); font-size: 0.8125rem; - padding-block: var(--hd-space-1); + 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; + border-bottom: 0; +} + +.hd-top__row .hd-table__cell { + border-top: var(--hd-border-size) solid var(--hd-color-neutral-border); +} + +.hd-typo__row:has(> :nth-child(5)) .hd-typo__cell:first-child { + padding-left: 0; +} + +.hd-typo__row:has(> :nth-child(3)) > .hd-typo__cell, +.hd-typo__row:has(> :nth-child(4)) > .hd-typo__cell { + padding-left: 0; +} diff --git a/apps/docs/content/tokens/getting-started/installation.mdx b/apps/docs/content/tokens/getting-started/installation.mdx index 633d72bfd..3fef20880 100644 --- a/apps/docs/content/tokens/getting-started/installation.mdx +++ b/apps/docs/content/tokens/getting-started/installation.mdx @@ -6,6 +6,24 @@ order: 2 # Installation -At the heart of Workleap Design language are tokens, which drive its functionality. They are the key ingredients to everything UI. Workleap brand is dissected into design tokens, they live in the Hopper Design System. +## Package manager -## Command Line +Using your package manager of choice, run the following command to install the tokens package. + +### Pnpm + +```shell +pnpm add @hopper-ui/tokens +``` + +### Yarn + +```shell +yarn add @hopper-ui/tokens +``` + +### With Npm + +```shell +npm add @hopper-ui/tokens +``` diff --git a/apps/docs/content/tokens/getting-started/introduction.mdx b/apps/docs/content/tokens/getting-started/introduction.mdx index 1ae201092..d880ab220 100644 --- a/apps/docs/content/tokens/getting-started/introduction.mdx +++ b/apps/docs/content/tokens/getting-started/introduction.mdx @@ -8,41 +8,74 @@ order: 1 At the heart of Workleap Design language are tokens, which drive its functionality. They are the key ingredients to everything UI. Workleap brand is dissected into design tokens, they live in the Hopper Design System. +A design token can store any of the following elements: + +- A single value such as a `color`, `font-size`, or `border-width`. +- A collection of indivisible values such as a `box-shadow`. + +## Definitions + +Hopper aims to provide a three tier token system, where each tier has their specific purpose. + Token tiers diagram -## Definitions +### Core tokens + +These tokens are referring to raw values such as a hexadecimal color code, border-width, or font-size. They are the building blocks of the design system. + + + +### Semantic tokens + +Semantic tokens carry design intent and are design context aware. They are the tokens that should be used in most cases. + +#### Light + +
+ +#### Dark + +
+ +### Component tokens + +Refers to the nuts and bolts of the components and their implementation details; they are the tokens exposed by components. They are tied to their respective component. These should not be used directly, unless you are building a component in a different stack than React. + +_Note: As no components are currently available, these tokens are not yet available._ + +#### Light + +
+ +#### Dark + +
+ +## When to use + +### For Developers + +Tokens should be used whenever Hopper components do not suit your current use case or if you can't use Hopper React components. They are also useful for situations where using a component does not make sense, such as adding a color for a background. + +It should be noted that if your current stack prevents you from directly using Hopper components, it is recommended to use component tokens in priority as they are mapped 1:1 with Hopper implementation. + +### For Designers -**Core tokens** are referring to raw values such as an hexadecimal color code, a border-width, a font-size. Think of them as paint name, Chocolate Frost is easier to use in a conversation than the exact color recipe. - -**Semantic tokens** adds the intention layer to tokens, they map to a core token, or tokens should we say as the semantic tier has a notion of themability. Using our Chocolate Frost paint color example this would dictate where the paint color should be used, on dry walls or plastic, inside or outside. - -**Component tokens** refers to the nuts and bolts of the components and their implementation details. They are tied to their component. In our paint color example, this would be where a specific color is actually used, in which room and on which architectural part of it(ceiling, doors, wall). - -```json title="package.json" -{ - "name": "wl-hopper", - "version": "0.0.0", - "description": "", - "keywords": [], - "author": "", - "private": true, - "license": "Apache-2.0", - "packageManager": "pnpm@8.3.1", - "scripts": { - "doc:start": "pnpm --filter=docs dev", - "doc:storybook": "pnpm --filter=docs storybook", - "doc:build": "pnpm --filter=docs build", - "lint": "pnpm run \"/^lint:.*/\"", - "lint:eslint": "eslint . --ext .js,.jsx,.ts,.tsx --cache --cache-location node_modules/.cache/eslint", - "lint:types": "pnpm -r lint:types", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "dependencies": { - "@netlify/plugin-nextjs": "^4.36.0", - "@workleap/eslint-plugin": "^1.0.0", - "@workleap/typescript-configs": "^1.0.0" - } -} -``` +While developing features for Workleap, you might need to create new components or add new features to existing ones. In this case, you should use semantic tokens to create your components. This will ensure that your components are consistent with the rest of the design system. Only semantic tokens are available in Figma. diff --git a/apps/docs/content/tokens/getting-started/usage.mdx b/apps/docs/content/tokens/getting-started/usage.mdx new file mode 100644 index 000000000..4f156eed2 --- /dev/null +++ b/apps/docs/content/tokens/getting-started/usage.mdx @@ -0,0 +1,47 @@ +--- +title: Usage +description: Getting started with Workleap Design Tokens +order: 3 +--- + +# Usage + +## CSS Variables + +### Tokens + +Import the tokens in your project by doing the following: + +```css title="myfile.css" +@import "@hopper-ui/tokens/tokens.css"; +``` + +If your application supports a dark mode, import dark mode tokens as well: + +```css title="myfile.css" +@import "@hopper-ui/tokens/dark/tokens.css"; +``` + +You can now use the tokens in your project by using the following syntax: + +```css title="myfile.css" +.my-class { + background-color: var(--hop-primary-surface-weak); +} +``` + +### Fonts + +In order to use Hopper fonts in your project, import the following: + +```css title="myfile.css" +@import '@hopper-ui/tokens/fonts.css'; +``` + +Font-face declarations are now imported in your project. + +Failing to do so would prevent you from using font family tokens such as `var(--hop-font-family-primary)`. + +## Styled System + +We will be releasing a styled system package inspired by styled-components that will allow you to use these tokens as Javascript props at a later time. diff --git a/apps/docs/content/tokens/semantic/font-family.mdx b/apps/docs/content/tokens/semantic/font-family.mdx deleted file mode 100644 index c1a6ced1e..000000000 --- a/apps/docs/content/tokens/semantic/font-family.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Font Family -description: Getting started with Workleap Design Tokens ---- -import tokens from '../../../datas/tokens.json'; - -# Font Family - -export const categoryKey = "fontFamily"; - -
diff --git a/apps/docs/content/tokens/semantic/font-size.mdx b/apps/docs/content/tokens/semantic/font-size.mdx deleted file mode 100644 index 65129c7fe..000000000 --- a/apps/docs/content/tokens/semantic/font-size.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Font Size -description: Getting started with Workleap Design Tokens ---- -import tokens from '../../../datas/tokens.json'; - -# Font Size - -export const categoryKey = "fontSize"; - -
diff --git a/apps/docs/content/tokens/semantic/font-weight.mdx b/apps/docs/content/tokens/semantic/font-weight.mdx deleted file mode 100644 index 1f0508e3b..000000000 --- a/apps/docs/content/tokens/semantic/font-weight.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Font Weight -description: Getting started with Workleap Design Tokens ---- -import tokens from '../../../datas/tokens.json'; - -# Font Weight - -export const categoryKey = "fontWeight"; - -
\ No newline at end of file diff --git a/apps/docs/content/tokens/semantic/line-height.mdx b/apps/docs/content/tokens/semantic/line-height.mdx deleted file mode 100644 index be17a35b7..000000000 --- a/apps/docs/content/tokens/semantic/line-height.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Line Height -description: Getting started with Workleap Design Tokens ---- -import tokens from '../../../datas/tokens.json'; - -# Line Height - -export const categoryKey = "lineHeight"; - -
diff --git a/apps/docs/content/tokens/semantic/typography.mdx b/apps/docs/content/tokens/semantic/typography.mdx new file mode 100644 index 000000000..37c062f99 --- /dev/null +++ b/apps/docs/content/tokens/semantic/typography.mdx @@ -0,0 +1,36 @@ +--- +title: Typography +description: Getting started with Workleap Design Tokens +--- + +import tokens from '../../../datas/tokens.json'; + +# Typography + +Typography tokens are composite tokens, meaning they are made up of multiple other tokens. This allows us to create a consistent typographic scale across our products. + +## Heading + +Headings are used to create a hierarchy of content. They are used to help users scan and understand the content on a page. + + + +## Overline + +Used to introduce a headline. + +_Adding a text-transform of uppercase is necessary in order to render overline as intended by the Design._ + + + +## Body + +Body text is used to communicate the main content of a page. + + + +## Accent + +Accent text is used to highlight important information on a page. + + diff --git a/apps/docs/styles/themes/rehype.css b/apps/docs/styles/themes/rehype.css index 5bb10ddc3..5116da5f9 100644 --- a/apps/docs/styles/themes/rehype.css +++ b/apps/docs/styles/themes/rehype.css @@ -33,7 +33,7 @@ [data-rehype-pretty-code-fragment] pre code { display: grid; - padding: var(--hd-space-1) 0; + padding: var(--hd-space-1) var(--hd-space-1) var(--hd-space-1) var(--hd-space-2); overflow-x: auto; }