Skip to content

Commit

Permalink
upcoming: [M3-8638] - Introduce the new (at)linode/ui package (#11057)
Browse files Browse the repository at this point in the history
* Introduce the new @linode/ui package

* Feedback @bnussman-akamai

* Move existing usages of  to new package

* Tweaks

* Fix unnecessary prop on  component

* Add CHANGELOG.md for UI package

* Added changeset: new `@linode/ui` package with `BetaChip` as the first component

* Add UI typechecking step to ci.yml
  • Loading branch information
hkhalil-akamai authored Oct 10, 2024
1 parent 9dfa675 commit dbf2e0c
Show file tree
Hide file tree
Showing 24 changed files with 342 additions and 8 deletions.
33 changes: 32 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
lint:
strategy:
matrix:
package: ["linode-manager", "@linode/api-v4", "@linode/validation"]
package: ["linode-manager", "@linode/api-v4", "@linode/validation", "@linode/ui"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -191,6 +191,37 @@ jobs:
- run: yarn --frozen-lockfile
- run: yarn workspace @linode/search run test

test-ui:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20.17"
- uses: actions/cache@v4
with:
path: |
**/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- run: yarn --frozen-lockfile
- run: yarn workspace @linode/ui run test

typecheck-ui:
runs-on: ubuntu-latest
needs: build-sdk
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20.17"
- uses: actions/cache@v4
with:
path: |
**/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- run: yarn --frozen-lockfile
- run: yarn workspace @linode/ui run typecheck

typecheck-manager:
runs-on: ubuntu-latest
needs: build-sdk
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

## Overview

This repository is home to the Akamai Connected **[Cloud Manager](https://cloud.linode.com)** and related [`@linode/api-v4`](packages/api-v4/) and [`@linode/validation`](packages/validation/) Typescript packages.
This repository is home to the Akamai Connected **[Cloud Manager](https://cloud.linode.com)** and related [`@linode/api-v4`](packages/api-v4/), [`@linode/validation`](packages/validation/) and [`@linode/ui`](packages/ui/) Typescript packages.

## Developing Locally

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"up": "yarn install:all && yarn build:validation && yarn build:sdk && yarn start:all",
"up:expose": "yarn install:all && yarn build:validation && yarn build:sdk && yarn start:all:expose",
"dev": "yarn install:all && yarn start:all",
"start:all": "concurrently -n api-v4,validation,manager -c blue,yellow,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace linode-manager start\"",
"start:all:expose": "concurrently -n api-v4,validation,manager -c blue,yellow,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace linode-manager start:expose\"",
"start:all": "concurrently -n api-v4,validation,ui,manager -c blue,yellow,magenta,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace @linode/ui start\" \"yarn workspace linode-manager start\"",
"start:all:expose": "concurrently -n api-v4,validation,ui,manager -c blue,yellow,magenta,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace @linode/ui start\" \"yarn workspace linode-manager start:expose\"",
"start:manager": "yarn workspace linode-manager start",
"start:manager:ci": "yarn workspace linode-manager start:ci",
"clean": "rm -rf node_modules && rm -rf packages/@linode/api-v4/node_modules && rm -rf packages/manager/node_modules && rm -rf packages/@linode/validation/node_modules",
Expand Down
1 change: 1 addition & 0 deletions packages/manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@linode/api-v4": "*",
"@linode/design-language-system": "^2.6.1",
"@linode/search": "*",
"@linode/ui": "*",
"@linode/validation": "*",
"@lukemorales/query-key-factory": "^1.3.4",
"@mui/icons-material": "^5.14.7",
Expand Down
2 changes: 1 addition & 1 deletion packages/manager/src/components/PrimaryNav/PrimaryNav.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BetaChip } from '@linode/ui';
import Grid from '@mui/material/Unstable_Grid2';
import * as React from 'react';
import { Link, useLocation } from 'react-router-dom';
Expand All @@ -22,7 +23,6 @@ import VPC from 'src/assets/icons/entityIcons/vpc.svg';
import TooltipIcon from 'src/assets/icons/get_help.svg';
import Longview from 'src/assets/icons/longview.svg';
import AkamaiLogo from 'src/assets/logo/akamai-logo.svg';
import { BetaChip } from 'src/components/BetaChip/BetaChip';
import { Box } from 'src/components/Box';
import { Divider } from 'src/components/Divider';
import { useIsACLPEnabled } from 'src/features/CloudPulse/Utils/utils';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BetaChip } from '@linode/ui';
import { createDatabaseSchema } from '@linode/validation/lib/databases.schema';
import Grid from '@mui/material/Unstable_Grid2';
import { createLazyRoute } from '@tanstack/react-router';
Expand All @@ -10,7 +11,6 @@ import { makeStyles } from 'tss-react/mui';
import MongoDBIcon from 'src/assets/icons/mongodb.svg';
import MySQLIcon from 'src/assets/icons/mysql.svg';
import PostgreSQLIcon from 'src/assets/icons/postgresql.svg';
import { BetaChip } from 'src/components/BetaChip/BetaChip';
import { Button } from 'src/components/Button/Button';
import { CircleProgress } from 'src/components/CircleProgress';
import { Divider } from 'src/components/Divider';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BetaChip } from '@linode/ui';
import { useTheme } from '@mui/material/styles';
import * as React from 'react';

import LogoWhite from 'src/assets/icons/db-logo-white.svg';
import Logo from 'src/assets/icons/db-logo.svg';
import { BetaChip } from 'src/components/BetaChip/BetaChip';
import { Box } from 'src/components/Box';
import { Typography } from 'src/components/Typography';

Expand Down
18 changes: 18 additions & 0 deletions packages/ui/.changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Changesets

This directory gets auto-populated when running `yarn changeset`.
You can however add your changesets manually as well, knowing that the [TYPE] is limited to the following options `Added`, `Fixed`, `Changed`, `Removed`, `Tech Stories`, `Tests`, `Upcoming Features` and follow this format:

```md
---
"@linode/[PACKAGE]": [TYPE]
---

My PR Description ([#`PR number`](`PR link`))
```

You must commit them to the repo so they can be picked up for the changelog generation.

This directory get wiped out when running `yarn generate-changelog`.

See `changeset.mjs` for implementation details.
5 changes: 5 additions & 0 deletions packages/ui/.changeset/pr-11057-added-1728496448213.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/ui": Added
---

new `@linode/ui` package with `BetaChip` as the first component ([#11057](https://github.com/linode/manager/pull/11057))
75 changes: 75 additions & 0 deletions packages/ui/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"ignorePatterns": [
"node_modules",
"lib",
"index.js",
"!.eslintrc.js"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"warnOnUnsupportedTypeScriptVersion": true
},
"plugins": [
"@typescript-eslint",
"sonarjs",
"prettier",
"@linode/eslint-plugin-cloud-manager"
],
"extends": [
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:sonarjs/recommended",
"plugin:prettier/recommended"
],
"rules": {
"no-unused-vars": [
"warn",
{
"argsIgnorePattern": "^_"
}
],
"no-unused-expressions": "warn",
"no-bitwise": "error",
"no-caller": "error",
"no-eval": "error",
"no-throw-literal": "warn",
"no-loop-func": "error",
"no-await-in-loop": "error",
"array-callback-return": "error",
"no-invalid-this": "off",
"no-new-wrappers": "error",
"no-restricted-imports": [
"error",
"rxjs"
],
"no-console": "error",
"no-undef-init": "off",
"radix": "error",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-namespace": "warn",
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-empty-interface": "warn",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/interface-name-prefix": "off",
"sonarjs/cognitive-complexity": "warn",
"sonarjs/no-duplicate-string": "warn",
"sonarjs/prefer-immediate-return": "warn",
"sonarjs/no-identical-functions": "warn",
"sonarjs/no-redundant-jump": "warn",
"sonarjs/no-small-switch": "warn",
"no-multiple-empty-lines": "error",
"curly": "warn",
"sort-keys": "off",
"comma-dangle": "off",
"no-trailing-spaces": "warn",
"no-mixed-requires": "warn",
"spaced-comment": "warn",
"object-shorthand": "warn",
"prettier/prettier": "warn"
}
}
4 changes: 4 additions & 0 deletions packages/ui/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"printWidth": 80,
"singleQuote": true
}
Empty file added packages/ui/CHANGELOG.md
Empty file.
61 changes: 61 additions & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "@linode/ui",
"author": "Linode",
"description": "Linode UI component library",
"version": "0.0.1",
"type": "module",
"main": "src/index.ts",
"module": "src/index.ts",
"types": "src/index.ts",
"exports": {
".": "./src/index.ts"
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/linode/manager/tree/develop/packages/ui"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/material": "^5.14.7",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"scripts": {
"start": "tsc -w --preserveWatchOutput",
"lint": "eslint . --quiet --ext .js,.ts,.tsx",
"typecheck": "tsc",
"precommit": "lint-staged",
"test": "vitest run",
"test:watch": "vitest",
"test:debug": "node --inspect-brk scripts/test.js --runInBand",
"coverage": "vitest run --coverage && open coverage/index.html",
"coverage:summary": "vitest run --coverage.enabled --reporter=junit --coverage.reporter=json-summary"
},
"lint-staged": {
"*.{ts,tsx,js}": [
"prettier --write",
"eslint --ext .js,.ts,.tsx --quiet"
]
},
"devDependencies": {
"@linode/eslint-plugin-cloud-manager": "^0.0.5",
"@testing-library/dom": "^10.1.0",
"@testing-library/jest-dom": "~6.4.2",
"@testing-library/react": "~16.0.0",
"@types/node": "^12.7.1",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.18",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vitest/ui": "^2.1.1",
"eslint": "^7.1.0",
"eslint-config-prettier": "~8.1.0",
"eslint-plugin-prettier": "~3.3.1",
"eslint-plugin-sonarjs": "^0.5.0",
"lint-staged": "^15.2.9",
"prettier": "~2.2.1",
"vitest": "^2.1.1"
}
}
33 changes: 33 additions & 0 deletions packages/ui/src/components/BetaChip/BetaChip.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { fireEvent, render } from '@testing-library/react';
import React from 'react';

import { BetaChip } from './BetaChip';

import { expect, vi, describe, it } from 'vitest';
import '@testing-library/jest-dom/vitest';

describe('BetaChip', () => {
it('renders with default color', () => {
const { getByTestId } = render(<BetaChip />);
const betaChip = getByTestId('betaChip');
expect(betaChip).toBeInTheDocument();
expect(betaChip).toHaveStyle('background-color: rgba(0, 0, 0, 0.08)');
});

it('renders with primary color', () => {
const { getByTestId } = render(<BetaChip color="primary" />);
const betaChip = getByTestId('betaChip');
expect(betaChip).toBeInTheDocument();
expect(betaChip).toHaveStyle('background-color: rgb(25, 118, 210)');
});

it('triggers an onClick callback', () => {
const onClickMock = vi.fn();
const { getByTestId } = render(
<BetaChip color="default" onClick={onClickMock} />
);
const betaChip = getByTestId('betaChip');
fireEvent.click(betaChip);
expect(onClickMock).toHaveBeenCalledTimes(1);
});
});
62 changes: 62 additions & 0 deletions packages/ui/src/components/BetaChip/BetaChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { styled } from '@mui/material/styles';
import * as React from 'react';
import { Chip } from '../Chip';
import type { ChipProps } from '@mui/material';

export interface BetaChipProps
extends Omit<
ChipProps,
| 'avatar'
| 'clickable'
| 'deleteIcon'
| 'disabled'
| 'icon'
| 'label'
| 'onDelete'
| 'outlineColor'
| 'size'
| 'variant'
> {
/**
* The color of the chip.
* default renders a gray chip, primary renders a blue chip.
*/
color?: 'default' | 'primary';
}

/**
* ## Usage
*
* Beta chips label features that are not yet part of Cloud Manager's core supported functionality.<br>
* **Example:** A beta chip may appear in the [primary navigation](https://github.com/linode/manager/pull/8104#issuecomment-1309334374),
* breadcrumbs, [banners](/docs/components-notifications-dismissible-banners--beta-banners), tabs, and/or plain text to designate beta functionality.<br>
* **Visual style:** bold, capitalized text; reduced height, letter spacing, and font size; solid color background.
*
*/
export const BetaChip = (props: BetaChipProps) => {
const { color } = props;

return (
<StyledBetaChip
{...props}
color={color}
data-testid="betaChip"
label="beta"
/>
);
};

const StyledBetaChip = styled(Chip, {
label: 'StyledBetaChip',
})<BetaChipProps>(({ theme }) => ({
'& .MuiChip-label': {
padding: 0,
},
fontSize: '0.625rem',
fontFamily: '"LatoWebBold", sans-serif', // TODO: remove hardcoded font once theme is added to this package
height: 16,
letterSpacing: '.25px',
marginLeft: theme.spacing(0.5),
padding: theme.spacing(0.5),
textTransform: 'uppercase',
}));
1 change: 1 addition & 0 deletions packages/ui/src/components/BetaChip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './BetaChip';
8 changes: 8 additions & 0 deletions packages/ui/src/components/Chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { default as _Chip } from '@mui/material/Chip';
import * as React from 'react';

import type { ChipProps } from '@mui/material/Chip';

export const Chip = (props: ChipProps) => {
return <_Chip {...props} />;
};
2 changes: 2 additions & 0 deletions packages/ui/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './Chip';
export * from './BetaChip';
1 change: 1 addition & 0 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components';
Loading

0 comments on commit dbf2e0c

Please sign in to comment.