Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

task/TUP-272 - core components fixup #7

Merged
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2ed29dc
feat(core-components): copy & polish from cepv2
wesleyboar Jun 8, 2022
8260275
feat(comp…s): cepv2 update but w/ new styles paths
wesleyboar Jun 8, 2022
10b3838
feat(comp…s): 2nd cepv2 update (no path updates)
wesleyboar Jun 8, 2022
af596ef
feat(comp…s): cepv2 update: button tests, unmerged
wesleyboar Jun 8, 2022
a158f0e
fix(comp…s): fix core-styles paths (libs → lib)
wesleyboar Jun 8, 2022
97d858d
feat(comp…s): update all paths to core-styles src
wesleyboar Jun 8, 2022
fe84b23
feat(comp…s): fix paths that can use styles dist
wesleyboar Jun 8, 2022
aab21ba
fix(styles): all src/lib imports to use rel. paths
wesleyboar Jun 8, 2022
213ca2b
fix(styles): src/lib rel. paths need no _imports/
wesleyboar Jun 8, 2022
ee30835
fix(tup-ui): load CSS from correct path
wesleyboar Jun 10, 2022
7a9288c
Merge branch 'main' into task/tup-272-core-components
wesleyboar Jun 10, 2022
fc58dc4
Convert Button and dependencies to TS
jchuahtacc Jun 13, 2022
cc2c07e
Add reactstrap global
jchuahtacc Jun 13, 2022
34acd97
Replace temporary Message component to exports
jchuahtacc Jun 13, 2022
f736fcd
Use Button from core-components in tup-ui
jchuahtacc Jun 13, 2022
b1b4d22
Added babel-plugin-postcss for core-components
jchuahtacc Jun 13, 2022
c34cb01
Formatting
jchuahtacc Jun 13, 2022
febbc0f
linting
jchuahtacc Jun 13, 2022
f8ec70a
Formatting
jchuahtacc Jun 13, 2022
34dedf9
Merge branch 'milestone/001--core-components' into task/TUP-272--core…
jchuahtacc Jun 15, 2022
1105440
Task/tup 272 core components vite (#8)
jchuahtacc Jun 15, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@


# Tacc

This project was generated using [Nx](https://nx.dev).

Things to try:

- `npx nx serve tup-ui` to run the app
- `npx nx build core-components` to create a distributable library for the core components.
- `npx nx build core-styles` to build the style library.
Expand Down Expand Up @@ -84,8 +83,6 @@ Run `nx graph` to see a diagram of the dependencies of your projects.

Visit the [Nx Documentation](https://nx.dev) to learn more.



## ☁ Nx Cloud

### Distributed Computation Caching & Distributed Task Execution
Expand Down
10 changes: 7 additions & 3 deletions apps/tup-ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react';
import { Message } from '@tacc/core-components';
import { Button, Message } from '@tacc/core-components';

function App() {
const [count, setCount] = useState(0);
Expand All @@ -10,9 +10,13 @@ function App() {
<p>Hello Vite + React!</p>
<Message />
<p>
<button type="button" onClick={() => setCount((count) => count + 1)}>
<Button
onClick={() => setCount((count) => count + 1)}
size="long"
type="primary"
>
count is: {count}
</button>
</Button>
</p>
<p>
Edit <code>App.tsx</code> and save to test HMR updates.
Expand Down
12 changes: 6 additions & 6 deletions apps/tup-ui/src/index.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
/* SETTINGS */
@import url('@tacc/core-styles/lib/_imports/settings/border.css');
@import url('@tacc/core-styles/dist/settings/border.css');
/* below, import local styles (if any) */

/* GENERIC */
/* @import url('@tacc/core-styles/lib/_imports/generics/*.css'); */
/* @import url('@tacc/core-styles/dist/generics/*.css'); */
/* below, import local styles (if any) */

/* ELEMENTS */
/* @import url('@tacc/core-styles/lib/_imports/elements/*.css'); */
/* @import url('@tacc/core-styles/dist/elements/*.css'); */
/* below, import local styles (if any) */

/* OBJECTS */
@import url('@tacc/core-styles/lib/_imports/objects/o-flex-item-table-wrap.css');
@import url('@tacc/core-styles/dist/objects/o-flex-item-table-wrap.css');
/* below, import local styles (if any) */

/* COMPONENTS */
/* @import url('@tacc/core-styles/lib/_imports/components/*.css'); */
/* @import url('@tacc/core-styles/dist/components/*.css'); */
/* below, import local styles (if any) */

/* TRUMPS */
/* @import url('@tacc/core-styles/lib/_imports/trumps/*.css'); */
/* @import url('@tacc/core-styles/dist/trumps/*.css'); */
/* below, import local styles (if any) */
4 changes: 2 additions & 2 deletions apps/tup-ui/src/styles/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Global stylesheets may `@import` project stylesheets, e.g.:
**`index.css`**

```
@import url('styles/.../settings/color.css');
@import url('@tacc/core-styles/.../settings/color.css');
```

### Import from Component Stylesheets
Expand All @@ -24,7 +24,7 @@ Component stylesheets may `@import` project stylesheets, e.g.:
**`components/(.../)SomeProjectComponent.module.css`**

```
@import url('styles/tools/media-queries.css');
@import url('@tacc/core-styles/.../tools/media-queries.css');

@media screen and (--short-and-above) and (--medium-and-above) {
selector {
Expand Down
5 changes: 1 addition & 4 deletions apps/tup-ui/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ export default defineConfig({
__dirname,
'../../libs/core-components/src/index.ts'
),
'@tacc/core-styles': path.resolve(
__dirname,
'../../libs/core-styles/src/'
),
'@tacc/core-styles': path.resolve(__dirname, '../../libs/core-styles/'),
},
},
build: {
Expand Down
8 changes: 7 additions & 1 deletion libs/core-components/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,11 @@
}
]
],
"plugins": []
"plugins": [
[
"babel-plugin-postcss",
{
}
]
]
}
6 changes: 6 additions & 0 deletions libs/core-components/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
"input": ".",
"output": "."
}
],
"globals": [
{
"moduleId": "reactstrap",
"global": "reactstrap"
}
]
}
},
Expand Down
3 changes: 3 additions & 0 deletions libs/core-components/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export { default as Button } from './lib/Button';
export { default as Icon } from './lib/Icon';
export { default as LoadingSpinner } from './lib/LoadingSpinner';
export { default as Message } from './lib/core-components';
57 changes: 57 additions & 0 deletions libs/core-components/src/lib/Button/Button.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.root {
composes: c-button from '@tacc/core-styles/dist/components/c-button.css';
}

.primary {
composes: c-button--primary from '@tacc/core-styles/dist/components/c-button.css';
}
.secondary {
composes: c-button--secondary from '@tacc/core-styles/dist/components/c-button.css';
}
.tertiary {
composes: c-button--tertiary from '@tacc/core-styles/dist/components/c-button.css';
}
.active {
composes: c-button--is-active from '@tacc/core-styles/dist/components/c-button.css';
}

.size-small {
composes: c-button--size-small from '@tacc/core-styles/dist/components/c-button.css';
}
.width-short {
composes: c-button--width-short from '@tacc/core-styles/dist/components/c-button.css';
}
.width-medium {
composes: c-button--width-medium from '@tacc/core-styles/dist/components/c-button.css';
}
.width-long {
composes: c-button--width-long from '@tacc/core-styles/dist/components/c-button.css';
}

.as-link {
composes: c-button--as-link from '@tacc/core-styles/dist/components/c-button.css';
}

.icon--before {
composes: c-button__icon--before from '@tacc/core-styles/dist/components/c-button.css';
}
.icon--after {
composes: c-button__icon--after from '@tacc/core-styles/dist/components/c-button.css';
}

.loading {
composes: c-button--is-busy from '@tacc/core-styles/dist/components/c-button.css';
}
.root {
position: relative;
}
.root .loading-over-button {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

.text {
composes: c-button__text from '@tacc/core-styles/dist/components/c-button.css';
}
163 changes: 163 additions & 0 deletions libs/core-components/src/lib/Button/Button.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// WARNING: Relies on `Icon` because of `getByRole('img')`
import React from 'react';
import { render } from '@testing-library/react';
import Button, * as BTN from './Button';

import '@testing-library/jest-dom/extend-expect';

const TEST_TEXT = '…';
const TEST_TYPE = 'primary';
const TEST_SIZE = 'medium';

function testClassnamesByType(type, size, getByRole, getByTestId) {
const root = getByRole('button');
const text = getByTestId('text');
const typeClassName = BTN.TYPE_MAP[type];
const sizeClassName = BTN.SIZE_MAP[size];
expect(root.className).toMatch('root');
expect(root.className).toMatch(new RegExp(typeClassName));
expect(root.className).toMatch(new RegExp(sizeClassName));
expect(text.className).toMatch('text');
}

function muteTypeNotLinkNoSizeLog(type, size) {
if (type !== 'link' && !size) console.debug = jest.fn();
}

function isPropertyLimitation(type, size) {
let isLimited = false;

if (
(type === 'primary' && size === 'small') ||
(type !== 'link' && !size) ||
(type === 'link' && size)
)
isLimited = true;

return isLimited;
}

describe('Button', () => {
it('uses given text', () => {
muteTypeNotLinkNoSizeLog();
const { getByTestId } = render(<Button>{TEST_TEXT}</Button>);
expect(getByTestId('text').textContent).toEqual(TEST_TEXT);
});

describe('icons exist as expected when', () => {
test('only `iconNameBefore` is given', () => {
muteTypeNotLinkNoSizeLog();
const { queryByTestId } = render(
<Button iconNameBefore="folder">{TEST_TEXT}</Button>
);
expect(queryByTestId('icon-before')).toBeInTheDocument();
expect(queryByTestId('icon-after')).not.toBeInTheDocument();
});
test('only `iconNameAfter` is given', () => {
muteTypeNotLinkNoSizeLog();
const { queryByTestId } = render(
<Button iconNameAfter="folder">{TEST_TEXT}</Button>
);
expect(queryByTestId('icon-before')).not.toBeInTheDocument();
expect(queryByTestId('icon-after')).toBeInTheDocument();
});
test('both `iconNameAfter` and `iconNameBefore` are given', () => {
muteTypeNotLinkNoSizeLog();
const { queryByTestId } = render(
<Button iconNameBefore="folder" iconNameAfter="file">
{TEST_TEXT}
</Button>
);
expect(queryByTestId('icon-before')).toBeInTheDocument();
expect(queryByTestId('icon-after')).toBeInTheDocument();
});
});

describe('all type & size combinations render accurately', () => {
it.each(BTN.TYPES)('type is "%s"', (type) => {
muteTypeNotLinkNoSizeLog();
if (isPropertyLimitation(type, TEST_SIZE)) {
return Promise.resolve();
}
const { getByRole, getByTestId } = render(
<Button type={type} size={TEST_SIZE}>
{TEST_TEXT}
</Button>
);

testClassnamesByType(type, TEST_SIZE, getByRole, getByTestId);
});
it.each(BTN.SIZES)('size is "%s"', (size) => {
muteTypeNotLinkNoSizeLog();
if (isPropertyLimitation(TEST_TYPE, size)) {
return Promise.resolve();
}
const { getByRole, getByTestId } = render(
<Button type={TEST_TYPE} size={size}>
{TEST_TEXT}
</Button>
);

testClassnamesByType(TEST_TYPE, size, getByRole, getByTestId);
});
});

describe('loading', () => {
it('does not render button without text', () => {
muteTypeNotLinkNoSizeLog();
const { queryByTestId } = render(
<Button data-testid="no button here">{TEST_TEXT}</Button>
);
const el = queryByTestId('no button here');
expect(el).toBeNull();
});
it('disables button when in loading state', () => {
muteTypeNotLinkNoSizeLog();
const { queryByText } = render(
<Button isLoading={true}>Loading Button</Button>
);
const el = queryByText('Loading Button');
expect(el).toBeDisabled();
});
});

describe('property limitation', () => {
test('type is "link" & ANY size`', () => {
console.warn = jest.fn();
const { getByRole, getByTestId } = render(
<Button type="link" size={TEST_SIZE}>
{TEST_TEXT}
</Button>
);
const expectedType = 'link';
const expectedSize = '';

testClassnamesByType(expectedType, expectedSize, getByRole, getByTestId);
expect(console.warn).toHaveBeenCalled();
});
test('type is "primary" & size is "small"', () => {
console.error = jest.fn();
const { getByRole, getByTestId } = render(
<Button type="primary" size="small">
{TEST_TEXT}
</Button>
);
const expectedType = 'secondary';
const expectedSize = 'small';

testClassnamesByType(expectedType, expectedSize, getByRole, getByTestId);
expect(console.error).toHaveBeenCalled();
});
test('type is not "link" & NO size`', () => {
console.debug = jest.fn();
const { getByRole, getByTestId } = render(
<Button type="primary">{TEST_TEXT}</Button>
);
const expectedType = 'primary';
const expectedSize = 'short';

testClassnamesByType(expectedType, expectedSize, getByRole, getByTestId);
expect(console.debug).toHaveBeenCalled();
});
});
});
Loading