mirror of
https://github.com/wassname/talk.git
synced 2026-07-08 19:13:23 +08:00
Merge branch 'next' into next-passport
This commit is contained in:
@@ -4,6 +4,8 @@ import {
|
||||
Config,
|
||||
LongRunningExecutor,
|
||||
} from "../scripts/watcher";
|
||||
// Ensure environment variables are read.
|
||||
import "./env";
|
||||
|
||||
const config: Config = {
|
||||
rootDir: path.resolve(__dirname, "../src"),
|
||||
|
||||
@@ -25,6 +25,10 @@ export default {
|
||||
options: {
|
||||
modules: true,
|
||||
importLoaders: 1,
|
||||
localIdentName:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "[hash:base64]"
|
||||
: "[name]-[local]-[hash:base64:5]",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Generated
+18
@@ -14501,6 +14501,12 @@
|
||||
"css-mediaquery": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"material-design-icons": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/material-design-icons/-/material-design-icons-3.0.1.tgz",
|
||||
"integrity": "sha1-mnHEh0chjrylHlGmbaaCA4zct78=",
|
||||
"dev": true
|
||||
},
|
||||
"math-expression-evaluator": {
|
||||
"version": "1.2.17",
|
||||
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz",
|
||||
@@ -21985,6 +21991,18 @@
|
||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
||||
"dev": true
|
||||
},
|
||||
"typeface-manuale": {
|
||||
"version": "0.0.54",
|
||||
"resolved": "https://registry.npmjs.org/typeface-manuale/-/typeface-manuale-0.0.54.tgz",
|
||||
"integrity": "sha512-wWgWFPSvoxEDdm8Dmq0cZzgmBfRXho5WhxU6x4dKBk7WIBsyvRgcjT+j7cQ3ah/9VYp1+nJzQWhCue+TiqA7FA==",
|
||||
"dev": true
|
||||
},
|
||||
"typeface-source-sans-pro": {
|
||||
"version": "0.0.54",
|
||||
"resolved": "https://registry.npmjs.org/typeface-source-sans-pro/-/typeface-source-sans-pro-0.0.54.tgz",
|
||||
"integrity": "sha512-4nsvldyZsOBuvR4oEuUMTquJFVssP4iIVnMEIU4paCWo2940b6r/t95sk7KwDpCablS8DprM/YlhpgqnS7gpKg==",
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
|
||||
|
||||
@@ -130,6 +130,7 @@
|
||||
"jest-junit": "^5.1.0",
|
||||
"jsdom": "^11.11.0",
|
||||
"loader-utils": "^1.1.0",
|
||||
"material-design-icons": "^3.0.1",
|
||||
"npm-run-all": "^4.1.3",
|
||||
"postcss-advanced-variables": "^2.3.3",
|
||||
"postcss-css-variables": "^0.9.0",
|
||||
@@ -172,6 +173,8 @@
|
||||
"tslint-plugin-prettier": "^1.3.0",
|
||||
"tslint-react": "^3.6.0",
|
||||
"typed-css-modules": "^0.3.4",
|
||||
"typeface-manuale": "0.0.54",
|
||||
"typeface-source-sans-pro": "0.0.54",
|
||||
"typescript": "^2.9.2",
|
||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||
"webpack": "4.12.0",
|
||||
|
||||
@@ -22,10 +22,10 @@ function createMutationContainer<T extends string, I, R>(
|
||||
): InferableComponentEnhancer<{ [P in T]: (input: I) => Promise<R> }> {
|
||||
return compose(
|
||||
withContext(({ relayEnvironment }) => ({ relayEnvironment })),
|
||||
hoistStatics((WrappedComponent: React.ComponentType<any>) => {
|
||||
hoistStatics((BaseComponent: React.ComponentType<any>) => {
|
||||
class CreateMutationContainer extends React.Component<any> {
|
||||
public static displayName = wrapDisplayName(
|
||||
WrappedComponent,
|
||||
BaseComponent,
|
||||
"createMutationContainer"
|
||||
);
|
||||
|
||||
@@ -38,7 +38,7 @@ function createMutationContainer<T extends string, I, R>(
|
||||
const inject = {
|
||||
[propName]: this.commit,
|
||||
};
|
||||
return <WrappedComponent {...rest} {...inject} />;
|
||||
return <BaseComponent {...rest} {...inject} />;
|
||||
}
|
||||
}
|
||||
return CreateMutationContainer as React.ComponentType<any>;
|
||||
|
||||
@@ -34,7 +34,7 @@ function withLocalStateContainer<T>(
|
||||
): InferableComponentEnhancer<{ local: T }> {
|
||||
return compose(
|
||||
withContext(({ relayEnvironment }) => ({ relayEnvironment })),
|
||||
hoistStatics((WrappedComponent: React.ComponentType<any>) => {
|
||||
hoistStatics((BaseComponent: React.ComponentType<any>) => {
|
||||
class LocalStateContainer extends React.Component<Props, any> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
@@ -65,7 +65,7 @@ function withLocalStateContainer<T>(
|
||||
|
||||
public render() {
|
||||
const { relayEnvironment: _, ...rest } = this.props;
|
||||
return <WrappedComponent {...rest} local={this.state.data} />;
|
||||
return <BaseComponent {...rest} local={this.state.data} />;
|
||||
}
|
||||
}
|
||||
return LocalStateContainer as React.ComponentType<any>;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// TODO: (@cvle) Extract useful common types into its own package.
|
||||
export { Diff, Omit, Overwrite, PropTypesOf } from "talk-ui/types";
|
||||
export { Omit, Overwrite, PropTypesOf } from "talk-ui/types";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`renders correctly on big screens 1`] = `
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root TopBar-root Flex-itemGutter Flex-alignCenter Flex-directionRow"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`renders correctly on big screens 1`] = `
|
||||
<span
|
||||
className="Typography-root Typography-heading2 Username-root"
|
||||
className="Typography-root Typography-heading2 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Marvin
|
||||
</span>
|
||||
@@ -10,7 +10,7 @@ exports[`renders correctly on big screens 1`] = `
|
||||
|
||||
exports[`renders correctly on small screens 1`] = `
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Marvin
|
||||
</span>
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
}
|
||||
|
||||
.level0 {
|
||||
border-color: var(--palette-secondary-darkest);
|
||||
border-color: var(--palette-grey-darkest);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.textarea {
|
||||
composes: body1 from "talk-ui/shared/typography.css";
|
||||
composes: bodyCopy from "talk-ui/shared/typography.css";
|
||||
|
||||
display: block;
|
||||
height: 100px;
|
||||
|
||||
@@ -41,7 +41,7 @@ const PostCommentForm: StatelessComponent<PostCommentFormProps> = props => (
|
||||
</Field>
|
||||
<div className={styles.postButtonContainer}>
|
||||
<Localized id="comments-postCommentForm-post">
|
||||
<Button disabled={submitting} primary>
|
||||
<Button color="primary" variant="filled" disabled={submitting}>
|
||||
Post
|
||||
</Button>
|
||||
</Localized>
|
||||
|
||||
@@ -39,4 +39,11 @@ describe("when there is more", () => {
|
||||
.simulate("click");
|
||||
expect((props.onShowAll as SinonSpy).calledOnce).toBe(true);
|
||||
});
|
||||
|
||||
const wrapperDisabledButton = shallow(
|
||||
<ReplyList {...props} disableShowAll />
|
||||
);
|
||||
it("disables load more button", () => {
|
||||
expect(wrapperDisabledButton).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,8 +34,7 @@ const ReplyList: StatelessComponent<ReplyListProps> = props => {
|
||||
aria-controls={`talk-comments-replyList-log--${props.commentID}`}
|
||||
onClick={props.onShowAll}
|
||||
disabled={props.disableShowAll}
|
||||
secondary
|
||||
invert
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
>
|
||||
Show All Replies
|
||||
|
||||
@@ -42,8 +42,7 @@ const Stream: StatelessComponent<StreamProps> = props => {
|
||||
<Button
|
||||
id={"talk-comments-stream-loadMore"}
|
||||
onClick={props.onLoadMore}
|
||||
secondary
|
||||
invert
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
disabled={props.disableLoadMore}
|
||||
aria-controls="talk-comments-stream-log"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
className="App-root"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Relay(StreamContainer)
|
||||
asset={Object {}}
|
||||
/>
|
||||
</Flex>
|
||||
</withPropsOnChange(Flex)>
|
||||
`;
|
||||
|
||||
exports[`renders correctly when asset is null 1`] = `
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<Indent>
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
id="talk-comments-replyList-log--comment-id"
|
||||
itemGutter={true}
|
||||
@@ -24,13 +24,55 @@ exports[`renders correctly 1`] = `
|
||||
}
|
||||
key="comment-2"
|
||||
/>
|
||||
</Flex>
|
||||
</withPropsOnChange(Flex)>
|
||||
</Indent>
|
||||
`;
|
||||
|
||||
exports[`when there is more disables load more button 1`] = `
|
||||
<Indent>
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
id="talk-comments-replyList-log--comment-id"
|
||||
itemGutter={true}
|
||||
role="log"
|
||||
>
|
||||
<Relay(CommentContainer)
|
||||
data={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
}
|
||||
}
|
||||
key="comment-1"
|
||||
/>
|
||||
<Relay(CommentContainer)
|
||||
data={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
}
|
||||
}
|
||||
key="comment-2"
|
||||
/>
|
||||
<Localized
|
||||
id="comments-replyList-showAll"
|
||||
>
|
||||
<withPropsOnChange(Button)
|
||||
aria-controls="talk-comments-replyList-log--comment-id"
|
||||
disabled={true}
|
||||
fullWidth={true}
|
||||
id="talk-comments-replyList-showAll--comment-id"
|
||||
onClick={[Function]}
|
||||
variant="outlined"
|
||||
>
|
||||
Show All Replies
|
||||
</withPropsOnChange(Button)>
|
||||
</Localized>
|
||||
</withPropsOnChange(Flex)>
|
||||
</Indent>
|
||||
`;
|
||||
|
||||
exports[`when there is more renders a load more button 1`] = `
|
||||
<Indent>
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
id="talk-comments-replyList-log--comment-id"
|
||||
itemGutter={true}
|
||||
@@ -60,13 +102,12 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
disabled={false}
|
||||
fullWidth={true}
|
||||
id="talk-comments-replyList-showAll--comment-id"
|
||||
invert={true}
|
||||
onClick={[Function]}
|
||||
secondary={true}
|
||||
variant="outlined"
|
||||
>
|
||||
Show All Replies
|
||||
</withPropsOnChange(Button)>
|
||||
</Localized>
|
||||
</Flex>
|
||||
</withPropsOnChange(Flex)>
|
||||
</Indent>
|
||||
`;
|
||||
|
||||
@@ -10,14 +10,14 @@ exports[`renders correctly 1`] = `
|
||||
<withContext(createMutationContainer(PostCommentFormContainer))
|
||||
assetID="asset-id"
|
||||
/>
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
aria-live="polite"
|
||||
direction="column"
|
||||
id="talk-comments-stream-log"
|
||||
itemGutter={true}
|
||||
role="log"
|
||||
>
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
itemGutter={true}
|
||||
key="comment-1"
|
||||
@@ -36,8 +36,8 @@ exports[`renders correctly 1`] = `
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex
|
||||
</withPropsOnChange(Flex)>
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
itemGutter={true}
|
||||
key="comment-2"
|
||||
@@ -56,8 +56,8 @@ exports[`renders correctly 1`] = `
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</withPropsOnChange(Flex)>
|
||||
</withPropsOnChange(Flex)>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -71,14 +71,14 @@ exports[`when there is more disables load more button 1`] = `
|
||||
<withContext(createMutationContainer(PostCommentFormContainer))
|
||||
assetID="asset-id"
|
||||
/>
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
aria-live="polite"
|
||||
direction="column"
|
||||
id="talk-comments-stream-log"
|
||||
itemGutter={true}
|
||||
role="log"
|
||||
>
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
itemGutter={true}
|
||||
key="comment-1"
|
||||
@@ -97,8 +97,8 @@ exports[`when there is more disables load more button 1`] = `
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex
|
||||
</withPropsOnChange(Flex)>
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
itemGutter={true}
|
||||
key="comment-2"
|
||||
@@ -117,7 +117,7 @@ exports[`when there is more disables load more button 1`] = `
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</withPropsOnChange(Flex)>
|
||||
<Localized
|
||||
id="comments-stream-loadMore"
|
||||
>
|
||||
@@ -126,14 +126,13 @@ exports[`when there is more disables load more button 1`] = `
|
||||
disabled={true}
|
||||
fullWidth={true}
|
||||
id="talk-comments-stream-loadMore"
|
||||
invert={true}
|
||||
onClick={[Function]}
|
||||
secondary={true}
|
||||
variant="outlined"
|
||||
>
|
||||
Load More
|
||||
</withPropsOnChange(Button)>
|
||||
</Localized>
|
||||
</Flex>
|
||||
</withPropsOnChange(Flex)>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -147,14 +146,14 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
<withContext(createMutationContainer(PostCommentFormContainer))
|
||||
assetID="asset-id"
|
||||
/>
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
aria-live="polite"
|
||||
direction="column"
|
||||
id="talk-comments-stream-log"
|
||||
itemGutter={true}
|
||||
role="log"
|
||||
>
|
||||
<Flex
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
itemGutter={true}
|
||||
key="comment-1"
|
||||
@@ -173,8 +172,8 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex
|
||||
</withPropsOnChange(Flex)>
|
||||
<withPropsOnChange(Flex)
|
||||
direction="column"
|
||||
itemGutter={true}
|
||||
key="comment-2"
|
||||
@@ -193,7 +192,7 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</withPropsOnChange(Flex)>
|
||||
<Localized
|
||||
id="comments-stream-loadMore"
|
||||
>
|
||||
@@ -202,13 +201,12 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
disabled={false}
|
||||
fullWidth={true}
|
||||
id="talk-comments-stream-loadMore"
|
||||
invert={true}
|
||||
onClick={[Function]}
|
||||
secondary={true}
|
||||
variant="outlined"
|
||||
>
|
||||
Load More
|
||||
</withPropsOnChange(Button)>
|
||||
</Localized>
|
||||
</Flex>
|
||||
</withPropsOnChange(Flex)>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
exports[`loads more comments 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-justifyCenter"
|
||||
className="Flex-root App-root Flex-justifyCenter Flex-alignCenter"
|
||||
>
|
||||
<div
|
||||
className="Stream-root"
|
||||
>
|
||||
<h1
|
||||
className="Typography-root Typography-heading1 Typography-gutterBottom"
|
||||
className="Typography-root Typography-heading1 Typography-colorTextPrimary Typography-gutterBottom"
|
||||
>
|
||||
Talk NEO
|
||||
</h1>
|
||||
@@ -28,11 +28,14 @@ exports[`loads more comments 1`] = `
|
||||
className="PostCommentForm-postButtonContainer"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-primary"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Post
|
||||
</button>
|
||||
@@ -54,7 +57,7 @@ exports[`loads more comments 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
@@ -67,7 +70,7 @@ exports[`loads more comments 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
@@ -83,7 +86,7 @@ exports[`loads more comments 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
@@ -96,7 +99,7 @@ exports[`loads more comments 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
What's up?
|
||||
</p>
|
||||
@@ -112,7 +115,7 @@ exports[`loads more comments 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Isabelle
|
||||
</span>
|
||||
@@ -125,7 +128,7 @@ exports[`loads more comments 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Hey!
|
||||
</p>
|
||||
@@ -138,13 +141,13 @@ exports[`loads more comments 1`] = `
|
||||
|
||||
exports[`renders comment stream 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-justifyCenter"
|
||||
className="Flex-root App-root Flex-justifyCenter Flex-alignCenter"
|
||||
>
|
||||
<div
|
||||
className="Stream-root"
|
||||
>
|
||||
<h1
|
||||
className="Typography-root Typography-heading1 Typography-gutterBottom"
|
||||
className="Typography-root Typography-heading1 Typography-colorTextPrimary Typography-gutterBottom"
|
||||
>
|
||||
Talk NEO
|
||||
</h1>
|
||||
@@ -164,11 +167,14 @@ exports[`renders comment stream 1`] = `
|
||||
className="PostCommentForm-postButtonContainer"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-primary"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Post
|
||||
</button>
|
||||
@@ -190,7 +196,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
@@ -203,7 +209,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
@@ -219,7 +225,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
@@ -232,7 +238,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
What's up?
|
||||
</p>
|
||||
@@ -240,13 +246,16 @@ exports[`renders comment stream 1`] = `
|
||||
</div>
|
||||
<button
|
||||
aria-controls="talk-comments-stream-log"
|
||||
className="BaseButton-root Button-root Button-invert Button-fullWidth Button-secondary"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorRegular Button-variantOutlined Button-fullWidth"
|
||||
disabled={false}
|
||||
id="talk-comments-stream-loadMore"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Load More
|
||||
</button>
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
exports[`renders comment stream 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-justifyCenter"
|
||||
className="Flex-root App-root Flex-justifyCenter Flex-alignCenter"
|
||||
>
|
||||
<div
|
||||
className="Stream-root"
|
||||
>
|
||||
<h1
|
||||
className="Typography-root Typography-heading1 Typography-gutterBottom"
|
||||
className="Typography-root Typography-heading1 Typography-colorTextPrimary Typography-gutterBottom"
|
||||
>
|
||||
Talk NEO
|
||||
</h1>
|
||||
@@ -28,11 +28,14 @@ exports[`renders comment stream 1`] = `
|
||||
className="PostCommentForm-postButtonContainer"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-primary"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Post
|
||||
</button>
|
||||
@@ -54,7 +57,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
@@ -67,7 +70,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
@@ -83,7 +86,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
@@ -96,7 +99,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
I like yoghurt
|
||||
</p>
|
||||
@@ -116,7 +119,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
@@ -129,7 +132,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
@@ -141,7 +144,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
@@ -154,7 +157,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
What's up?
|
||||
</p>
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
exports[`renders comment stream 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-justifyCenter"
|
||||
className="Flex-root App-root Flex-justifyCenter Flex-alignCenter"
|
||||
>
|
||||
<div
|
||||
className="Stream-root"
|
||||
>
|
||||
<h1
|
||||
className="Typography-root Typography-heading1 Typography-gutterBottom"
|
||||
className="Typography-root Typography-heading1 Typography-colorTextPrimary Typography-gutterBottom"
|
||||
>
|
||||
Talk NEO
|
||||
</h1>
|
||||
@@ -28,11 +28,14 @@ exports[`renders comment stream 1`] = `
|
||||
className="PostCommentForm-postButtonContainer"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-primary"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Post
|
||||
</button>
|
||||
@@ -54,7 +57,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
@@ -67,7 +70,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
@@ -83,7 +86,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
@@ -96,7 +99,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
What's up?
|
||||
</p>
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
exports[`renders comment stream 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-justifyCenter"
|
||||
className="Flex-root App-root Flex-justifyCenter Flex-alignCenter"
|
||||
>
|
||||
<div
|
||||
className="Stream-root"
|
||||
>
|
||||
<h1
|
||||
className="Typography-root Typography-heading1 Typography-gutterBottom"
|
||||
className="Typography-root Typography-heading1 Typography-colorTextPrimary Typography-gutterBottom"
|
||||
>
|
||||
Talk NEO
|
||||
</h1>
|
||||
@@ -28,11 +28,14 @@ exports[`renders comment stream 1`] = `
|
||||
className="PostCommentForm-postButtonContainer"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-primary"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Post
|
||||
</button>
|
||||
@@ -54,7 +57,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
@@ -67,7 +70,7 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
@@ -87,7 +90,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
@@ -100,20 +103,23 @@ exports[`renders comment stream 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
What's up?
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
aria-controls="talk-comments-replyList-log--comment-0"
|
||||
className="BaseButton-root Button-root Button-invert Button-fullWidth Button-secondary"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorRegular Button-variantOutlined Button-fullWidth"
|
||||
disabled={false}
|
||||
id="talk-comments-replyList-showAll--comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Show All Replies
|
||||
</button>
|
||||
@@ -127,13 +133,13 @@ exports[`renders comment stream 1`] = `
|
||||
|
||||
exports[`show all replies 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-justifyCenter"
|
||||
className="Flex-root App-root Flex-justifyCenter Flex-alignCenter"
|
||||
>
|
||||
<div
|
||||
className="Stream-root"
|
||||
>
|
||||
<h1
|
||||
className="Typography-root Typography-heading1 Typography-gutterBottom"
|
||||
className="Typography-root Typography-heading1 Typography-colorTextPrimary Typography-gutterBottom"
|
||||
>
|
||||
Talk NEO
|
||||
</h1>
|
||||
@@ -153,11 +159,14 @@ exports[`show all replies 1`] = `
|
||||
className="PostCommentForm-postButtonContainer"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-primary"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Post
|
||||
</button>
|
||||
@@ -179,7 +188,7 @@ exports[`show all replies 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
@@ -192,7 +201,7 @@ exports[`show all replies 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
@@ -212,7 +221,7 @@ exports[`show all replies 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
@@ -225,7 +234,7 @@ exports[`show all replies 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
What's up?
|
||||
</p>
|
||||
@@ -237,7 +246,7 @@ exports[`show all replies 1`] = `
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Username-root"
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Isabelle
|
||||
</span>
|
||||
@@ -250,7 +259,7 @@ exports[`show all replies 1`] = `
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-body1"
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Hey!
|
||||
</p>
|
||||
|
||||
@@ -8,3 +8,6 @@
|
||||
outline-color: -webkit-focus-ring-color;
|
||||
outline-style: auto;
|
||||
}
|
||||
|
||||
.mouseHover {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
import TestRenderer from "react-test-renderer";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import BaseButton from "./BaseButton";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof BaseButton> = {
|
||||
className: "my-class",
|
||||
children: "Push Me",
|
||||
};
|
||||
const renderer = TestRenderer.create(<BaseButton {...props} />);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders as anchor", () => {
|
||||
const props: PropTypesOf<typeof BaseButton> = {
|
||||
anchor: true,
|
||||
children: "Push Me",
|
||||
};
|
||||
const renderer = TestRenderer.create(<BaseButton {...props} />);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -1,8 +1,13 @@
|
||||
import cn from "classnames";
|
||||
import React from "react";
|
||||
import React, { Ref } from "react";
|
||||
import { ButtonHTMLAttributes, StatelessComponent } from "react";
|
||||
|
||||
import { withKeyboardFocus, withStyles } from "talk-ui/hocs";
|
||||
import {
|
||||
withForwardRef,
|
||||
withKeyboardFocus,
|
||||
withMouseHover,
|
||||
withStyles,
|
||||
} from "talk-ui/hocs";
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import * as styles from "./BaseButton.css";
|
||||
@@ -10,7 +15,6 @@ import * as styles from "./BaseButton.css";
|
||||
interface InnerProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
/** If set renders an anchor tag instead */
|
||||
anchor?: boolean;
|
||||
|
||||
/**
|
||||
* This prop can be used to add custom classnames.
|
||||
* It is handled by the `withStyles `HOC.
|
||||
@@ -18,7 +22,13 @@ interface InnerProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
classes: typeof styles;
|
||||
|
||||
/** This is passed by the `withKeyboardFocus` HOC */
|
||||
keyboardFocus: boolean;
|
||||
keyboardFocus?: boolean;
|
||||
|
||||
/** This is passed by the `withMouseHover` HOC */
|
||||
mouseHover?: boolean;
|
||||
|
||||
/** Internal: Forwarded Ref */
|
||||
forwardRef?: Ref<HTMLButtonElement>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,6 +40,8 @@ const BaseButton: StatelessComponent<InnerProps> = ({
|
||||
className,
|
||||
classes,
|
||||
keyboardFocus,
|
||||
mouseHover,
|
||||
forwardRef,
|
||||
type: typeProp,
|
||||
...rest
|
||||
}) => {
|
||||
@@ -51,11 +63,14 @@ const BaseButton: StatelessComponent<InnerProps> = ({
|
||||
|
||||
const rootClassName = cn(classes.root, className, {
|
||||
[classes.keyboardFocus]: keyboardFocus,
|
||||
[classes.mouseHover]: mouseHover,
|
||||
});
|
||||
|
||||
return <Element {...rest} className={rootClassName} />;
|
||||
return <Element {...rest} className={rootClassName} ref={forwardRef} />;
|
||||
};
|
||||
|
||||
const enhanced = withStyles(styles)(withKeyboardFocus(BaseButton));
|
||||
const enhanced = withForwardRef(
|
||||
withStyles(styles)(withMouseHover(withKeyboardFocus(BaseButton)))
|
||||
);
|
||||
export type BaseButtonProps = PropTypesOf<typeof enhanced>;
|
||||
export default enhanced;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders as anchor 1`] = `
|
||||
<a
|
||||
className="BaseButton-root"
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Push Me
|
||||
</a>
|
||||
`;
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<button
|
||||
className="BaseButton-root my-class"
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Push Me
|
||||
</button>
|
||||
`;
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./BaseButton";
|
||||
export { default } from "./BaseButton";
|
||||
export { default, BaseButtonProps } from "./BaseButton";
|
||||
|
||||
@@ -1,99 +1,282 @@
|
||||
.root {
|
||||
composes: button from "talk-ui/shared/typography.css";
|
||||
border-radius: var(--round-corners);
|
||||
background-color: transparent;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid transparent;
|
||||
|
||||
&:enabled,
|
||||
&:disabled {
|
||||
padding: 5px 20px;
|
||||
border-radius: var(--round-corners);
|
||||
background-color: transparent;
|
||||
/* TODO: hover styles for the default button */
|
||||
& > * {
|
||||
margin: 0 calc(0.5 * var(--spacing-unit)) 0 0;
|
||||
/* convince safari */
|
||||
align-self: center;
|
||||
}
|
||||
& > *:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.root:disabled {
|
||||
.root.disabled {
|
||||
opacity: 0.4;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.fullWidth:enabled,
|
||||
.fullWidth:disabled {
|
||||
.fullWidth {
|
||||
display: block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.primary:enabled,
|
||||
.primary:disabled {
|
||||
background-color: var(--palette-primary-main);
|
||||
color: #fff;
|
||||
.sizeSmall {
|
||||
composes: button from "talk-ui/shared/typography.css";
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
.primary:enabled {
|
||||
&:hover {
|
||||
background-color: var(--palette-primary-light);
|
||||
.sizeRegular {
|
||||
composes: button from "talk-ui/shared/typography.css";
|
||||
padding: 8px 15px;
|
||||
}
|
||||
|
||||
.sizeLarge {
|
||||
composes: buttonLarge from "talk-ui/shared/typography.css";
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.variantRegular {
|
||||
&.colorRegular {
|
||||
color: var(--palette-grey-main);
|
||||
}
|
||||
&.colorPrimary {
|
||||
color: var(--palette-primary-main);
|
||||
}
|
||||
&.colorError {
|
||||
color: var(--palette-error-main);
|
||||
}
|
||||
&.colorSuccess {
|
||||
color: var(--palette-success-main);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--palette-primary-lighter);
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
&.mouseHover {
|
||||
color: var(--palette-grey-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-grey-lighter);
|
||||
}
|
||||
}
|
||||
&.colorPrimary {
|
||||
&.mouseHover {
|
||||
color: var(--palette-primary-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-primary-lighter);
|
||||
}
|
||||
}
|
||||
&.colorError {
|
||||
&.mouseHover {
|
||||
color: var(--palette-error-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-error-lighter);
|
||||
}
|
||||
}
|
||||
&.colorSuccess {
|
||||
&.mouseHover {
|
||||
color: var(--palette-success-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-success-lighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.primary:enabled.invert,
|
||||
.primary:disabled.invert {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--palette-primary-main);
|
||||
color: var(--palette-primary-main);
|
||||
}
|
||||
|
||||
.primary:enabled.invert {
|
||||
&:hover {
|
||||
border-color: var(--palette-primary-light);
|
||||
color: var(--palette-primary-light);
|
||||
.variantFilled {
|
||||
color: var(--palette-common-white);
|
||||
&.colorRegular {
|
||||
background-color: var(--palette-grey-main);
|
||||
}
|
||||
&.colorPrimary {
|
||||
background-color: var(--palette-primary-main);
|
||||
}
|
||||
&.colorError {
|
||||
background-color: var(--palette-error-main);
|
||||
}
|
||||
&.colorSuccess {
|
||||
background-color: var(--palette-success-main);
|
||||
}
|
||||
|
||||
&:active {
|
||||
border-color: var(--palette-primary-lighter);
|
||||
color: var(--palette-primary-lighter);
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
&.mouseHover {
|
||||
background-color: var(--palette-grey-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: var(--palette-grey-lighter);
|
||||
}
|
||||
}
|
||||
&.colorPrimary {
|
||||
&.mouseHover {
|
||||
background-color: var(--palette-primary-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: var(--palette-primary-lighter);
|
||||
}
|
||||
}
|
||||
&.colorError {
|
||||
&.mouseHover {
|
||||
background-color: var(--palette-error-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: var(--palette-error-lighter);
|
||||
}
|
||||
}
|
||||
&.colorSuccess {
|
||||
&.mouseHover {
|
||||
background-color: var(--palette-success-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: var(--palette-success-lighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.secondary:enabled,
|
||||
.secondary:disabled {
|
||||
background-color: var(--palette-secondary-main);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.secondary:enabled {
|
||||
&:hover {
|
||||
background-color: var(--palette-secondary-light);
|
||||
.variantOutlined {
|
||||
&.colorRegular {
|
||||
color: var(--palette-grey-main);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active {
|
||||
background-color: var(--palette-secondary-lighter);
|
||||
&.colorPrimary {
|
||||
color: var(--palette-primary-main);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&.colorError {
|
||||
color: var(--palette-error-main);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&.colorSuccess {
|
||||
color: var(--palette-success-main);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
&.mouseHover {
|
||||
color: var(--palette-grey-light);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-grey-lighter);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
}
|
||||
&.colorPrimary {
|
||||
&.mouseHover {
|
||||
color: var(--palette-primary-light);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-primary-lighter);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
}
|
||||
&.colorError {
|
||||
&.mouseHover {
|
||||
color: var(--palette-error-light);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-error-lighter);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
}
|
||||
&.colorSuccess {
|
||||
&.mouseHover {
|
||||
color: var(--palette-success-light);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-success-lighter);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.secondary:enabled.invert,
|
||||
.secondary:disabled.invert {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--palette-secondary-main);
|
||||
color: var(--palette-secondary-main);
|
||||
}
|
||||
|
||||
.secondary:enabled.invert {
|
||||
&:hover {
|
||||
border-color: var(--palette-secondary-light);
|
||||
color: var(--palette-secondary-light);
|
||||
.variantGhost {
|
||||
&.colorRegular {
|
||||
color: var(--palette-grey-main);
|
||||
}
|
||||
&.colorPrimary {
|
||||
color: var(--palette-primary-main);
|
||||
}
|
||||
&.colorError {
|
||||
color: var(--palette-error-main);
|
||||
}
|
||||
&.colorSuccess {
|
||||
color: var(--palette-success-main);
|
||||
}
|
||||
|
||||
&:active {
|
||||
border-color: var(--palette-secondary-lighter);
|
||||
color: var(--palette-secondary-lighter);
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
&.mouseHover {
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
border: 1px solid currentColor;
|
||||
color: var(--palette-common-white);
|
||||
background-color: var(--palette-grey-main);
|
||||
}
|
||||
}
|
||||
&.colorPrimary {
|
||||
&.mouseHover {
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
border: 1px solid currentColor;
|
||||
color: var(--palette-common-white);
|
||||
background-color: var(--palette-primary-main);
|
||||
}
|
||||
}
|
||||
&.colorError {
|
||||
&.mouseHover {
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
border: 1px solid currentColor;
|
||||
color: var(--palette-common-white);
|
||||
background-color: var(--palette-error-main);
|
||||
}
|
||||
}
|
||||
&.colorSuccess {
|
||||
&.mouseHover {
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
border: 1px solid currentColor;
|
||||
color: var(--palette-common-white);
|
||||
background-color: var(--palette-success-main);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This seems to be the best way to target modern touch device browsers.
|
||||
*/
|
||||
@media (-moz-touch-enabled: 1), (pointer: coarse) {
|
||||
/* TODO: Remove hover styles */
|
||||
}
|
||||
|
||||
@@ -5,23 +5,72 @@ menu: UI Kit
|
||||
|
||||
import { Playground } from 'docz'
|
||||
import Button from './Button'
|
||||
import ButtonIcon from './ButtonIcon'
|
||||
import Icon from '../Icon'
|
||||
import Flex from '../Flex'
|
||||
|
||||
# Button
|
||||
|
||||
## Basic usage
|
||||
## Regular Button
|
||||
<Playground>
|
||||
<Button style={{margin: "0 10px 10px 0"}}>Push Me</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} disabled>Push Me</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} anchor>I'm an Anchor Tag</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} primary>Primary</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} primary disabled>Primary</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} secondary>Secondary</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} secondary disabled>Secondary</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} primary invert>Primary</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} primary invert disabled>Primary</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} secondary invert>Secondary</Button>
|
||||
<Button style={{margin: "0 10px 10px 0"}} secondary invert disabled>Secondary</Button>
|
||||
<Button style={{marginBottom: "10px"}} primary fullWidth>Full Width</Button>
|
||||
<Button style={{marginBottom: "10px"}} primary invert fullWidth>Full Width Invert</Button>
|
||||
<Flex itemGutter wrap>
|
||||
<Button>Push Me</Button>
|
||||
<Button size="small">Push Me</Button>
|
||||
<Button size="large">Push Me</Button>
|
||||
<Button color="primary">Push Me</Button>
|
||||
<Button color="error">Push Me</Button>
|
||||
<Button color="success">Push Me</Button>
|
||||
<Button disabled>Push Me</Button>
|
||||
<Button active>Push Me</Button>
|
||||
<Button><ButtonIcon>face</ButtonIcon><span>Push Me</span></Button>
|
||||
<Button fullWidth>Push Me</Button>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
## Filled Button
|
||||
<Playground>
|
||||
<Flex itemGutter wrap>
|
||||
<Button variant="filled">Push Me</Button>
|
||||
<Button variant="filled" size="small">Push Me</Button>
|
||||
<Button variant="filled" size="large">Push Me</Button>
|
||||
<Button variant="filled" color="primary">Push Me</Button>
|
||||
<Button variant="filled" color="error">Push Me</Button>
|
||||
<Button variant="filled" color="success">Push Me</Button>
|
||||
<Button variant="filled" disabled>Push Me</Button>
|
||||
<Button variant="filled" active>Push Me</Button>
|
||||
<Button variant="filled"><ButtonIcon>face</ButtonIcon><span>Push Me</span></Button>
|
||||
<Button variant="filled" fullWidth>Push Me</Button>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
## Outlined Button
|
||||
<Playground>
|
||||
<Flex itemGutter wrap>
|
||||
<Button variant="outlined">Push Me</Button>
|
||||
<Button variant="outlined" size="small">Push Me</Button>
|
||||
<Button variant="outlined" size="large">Push Me</Button>
|
||||
<Button variant="outlined" color="primary">Push Me</Button>
|
||||
<Button variant="outlined" color="error">Push Me</Button>
|
||||
<Button variant="outlined" color="success">Push Me</Button>
|
||||
<Button variant="outlined" disabled>Push Me</Button>
|
||||
<Button variant="outlined" active>Push Me</Button>
|
||||
<Button variant="outlined"><ButtonIcon>face</ButtonIcon><span>Push Me</span></Button>
|
||||
<Button variant="outlined" fullWidth>Push Me</Button>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
## Ghost Button
|
||||
<Playground>
|
||||
<Flex itemGutter wrap>
|
||||
<Button variant="ghost">Push Me</Button>
|
||||
<Button variant="ghost" size="small">Push Me</Button>
|
||||
<Button variant="ghost" size="large">Push Me</Button>
|
||||
<Button variant="ghost" color="primary">Push Me</Button>
|
||||
<Button variant="ghost" color="error">Push Me</Button>
|
||||
<Button variant="ghost" color="success">Push Me</Button>
|
||||
<Button variant="ghost" disabled>Push Me</Button>
|
||||
<Button variant="ghost" active>Push Me</Button>
|
||||
<Button variant="ghost"><ButtonIcon>face</ButtonIcon><span>Push Me</span></Button>
|
||||
<Button variant="ghost" fullWidth>Push Me</Button>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import React from "react";
|
||||
import ShallowRenderer from "react-test-renderer/shallow";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import { Button } from "./Button";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof Button> = {
|
||||
classes: {
|
||||
mouseHover: "mouseHover",
|
||||
keyboardFocus: "keyboardFocus",
|
||||
} as any,
|
||||
children: "Push me",
|
||||
};
|
||||
const renderer = ShallowRenderer.createRenderer();
|
||||
renderer.render(<Button {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("forwards ref", () => {
|
||||
const props: PropTypesOf<typeof Button> = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
forwardRef: () => {},
|
||||
classes: {} as any,
|
||||
children: "Push me",
|
||||
};
|
||||
const renderer = ShallowRenderer.createRenderer();
|
||||
renderer.render(<Button {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders a regular sized, primary colored ghost button with fullWidth", () => {
|
||||
const props: PropTypesOf<typeof Button> = {
|
||||
color: "primary",
|
||||
variant: "ghost",
|
||||
fullWidth: true,
|
||||
classes: {
|
||||
colorPrimary: "colorPrimary",
|
||||
variantGhost: "variantGhost",
|
||||
sizeRegular: "sizeRegular",
|
||||
fullWidth: "fullWidth",
|
||||
} as any,
|
||||
children: "Push me",
|
||||
};
|
||||
const renderer = ShallowRenderer.createRenderer();
|
||||
renderer.render(<Button {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders active state", () => {
|
||||
const props: PropTypesOf<typeof Button> = {
|
||||
active: true,
|
||||
classes: {
|
||||
active: "active",
|
||||
} as any,
|
||||
children: "Push me",
|
||||
};
|
||||
const renderer = ShallowRenderer.createRenderer();
|
||||
renderer.render(<Button {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
@@ -1,8 +1,8 @@
|
||||
import cn from "classnames";
|
||||
import { pick } from "lodash";
|
||||
import React, { ButtonHTMLAttributes } from "react";
|
||||
import React, { ButtonHTMLAttributes, Ref } from "react";
|
||||
|
||||
import { withStyles } from "talk-ui/hocs";
|
||||
import { withForwardRef, withStyles } from "talk-ui/hocs";
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import BaseButton, { BaseButtonProps } from "../BaseButton";
|
||||
@@ -15,50 +15,76 @@ interface InnerProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
* This prop can be used to add custom classnames.
|
||||
* It is handled by the `withStyles `HOC.
|
||||
*/
|
||||
classes: typeof styles & Partial<BaseButtonProps["classes"]>;
|
||||
classes: typeof styles & BaseButtonProps["classes"];
|
||||
|
||||
/** Size of the button */
|
||||
size?: "small" | "regular" | "large";
|
||||
|
||||
/** Color of the button */
|
||||
color?: "regular" | "primary" | "error" | "success";
|
||||
|
||||
/** Variant of the button */
|
||||
variant?: "regular" | "filled" | "outlined" | "ghost";
|
||||
|
||||
/** If set renders a full width button */
|
||||
fullWidth?: boolean;
|
||||
|
||||
/** If set renders a button with inverted borders */
|
||||
invert?: boolean;
|
||||
/** If set renders active state e.g. to implement toggle buttons */
|
||||
active?: boolean;
|
||||
|
||||
/** If set renders a button with primary colors */
|
||||
primary?: boolean;
|
||||
|
||||
/** If set renders a button with secondary colors */
|
||||
secondary?: boolean;
|
||||
/** Internal: Forwarded Ref */
|
||||
forwardRef?: Ref<HTMLButtonElement>;
|
||||
}
|
||||
|
||||
class Button extends React.Component<InnerProps> {
|
||||
export class Button extends React.Component<InnerProps> {
|
||||
public static defaultProps: Partial<InnerProps> = {
|
||||
size: "regular",
|
||||
variant: "regular",
|
||||
color: "regular",
|
||||
};
|
||||
public render() {
|
||||
const {
|
||||
active,
|
||||
classes,
|
||||
color,
|
||||
className,
|
||||
size,
|
||||
fullWidth,
|
||||
invert,
|
||||
primary,
|
||||
secondary,
|
||||
disabled,
|
||||
forwardRef,
|
||||
variant,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
const rootClassName = cn(classes.root, className, {
|
||||
[classes.invert]: invert,
|
||||
[classes.sizeRegular]: size === "regular",
|
||||
[classes.sizeSmall]: size === "small",
|
||||
[classes.sizeLarge]: size === "large",
|
||||
[classes.colorRegular]: color === "regular",
|
||||
[classes.colorPrimary]: color === "primary",
|
||||
[classes.colorError]: color === "error",
|
||||
[classes.colorSuccess]: color === "success",
|
||||
[classes.variantRegular]: variant === "regular",
|
||||
[classes.variantFilled]: variant === "filled",
|
||||
[classes.variantOutlined]: variant === "outlined",
|
||||
[classes.variantGhost]: variant === "ghost",
|
||||
[classes.fullWidth]: fullWidth,
|
||||
[classes.primary]: primary,
|
||||
[classes.secondary]: secondary,
|
||||
[classes.active]: active,
|
||||
[classes.disabled]: disabled,
|
||||
});
|
||||
|
||||
return (
|
||||
<BaseButton
|
||||
className={rootClassName}
|
||||
classes={pick(classes, "keyboardFocus")}
|
||||
classes={pick(classes, "keyboardFocus", "mouseHover")}
|
||||
disabled={disabled}
|
||||
forwardRef={forwardRef}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const enhanced = withStyles(styles)(Button);
|
||||
const enhanced = withForwardRef(withStyles(styles)(Button));
|
||||
export type ButtonProps = PropTypesOf<typeof enhanced>;
|
||||
export default enhanced;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
.root {
|
||||
&:first-child {
|
||||
margin-left: -4px;
|
||||
}
|
||||
&:last-child {
|
||||
margin-right: -4px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import React from "react";
|
||||
import ShallowRenderer from "react-test-renderer/shallow";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import { ButtonIcon } from "./ButtonIcon";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof ButtonIcon> = {
|
||||
classes: {
|
||||
root: "root",
|
||||
} as any,
|
||||
children: "Push me",
|
||||
};
|
||||
const renderer = ShallowRenderer.createRenderer();
|
||||
renderer.render(<ButtonIcon {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("forwards ref", () => {
|
||||
const props: PropTypesOf<typeof ButtonIcon> = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
forwardRef: () => {},
|
||||
classes: {} as any,
|
||||
children: "Push me",
|
||||
};
|
||||
const renderer = ShallowRenderer.createRenderer();
|
||||
renderer.render(<ButtonIcon {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import cn from "classnames";
|
||||
import React, { HTMLAttributes, Ref, StatelessComponent } from "react";
|
||||
|
||||
import Icon, { IconProps } from "talk-ui/components/Icon";
|
||||
import { withForwardRef, withStyles } from "talk-ui/hocs";
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import * as styles from "./ButtonIcon.css";
|
||||
|
||||
interface InnerProps extends HTMLAttributes<HTMLSpanElement> {
|
||||
/**
|
||||
* This prop can be used to add custom classnames.
|
||||
* It is handled by the `withStyles `HOC.
|
||||
*/
|
||||
classes: typeof styles & IconProps["classes"];
|
||||
|
||||
size?: IconProps["size"];
|
||||
|
||||
/** The name of the icon to render */
|
||||
children: string;
|
||||
|
||||
/** Internal: Forwarded Ref */
|
||||
forwardRef?: Ref<HTMLSpanElement>;
|
||||
}
|
||||
|
||||
export const ButtonIcon: StatelessComponent<InnerProps> = props => {
|
||||
const { classes, className, forwardRef, ...rest } = props;
|
||||
const rootClassName = cn(classes.root, className);
|
||||
return <Icon className={rootClassName} {...rest} forwardRef={forwardRef} />;
|
||||
};
|
||||
|
||||
ButtonIcon.defaultProps = {
|
||||
size: "sm",
|
||||
};
|
||||
|
||||
const enhanced = withForwardRef(withStyles(styles)(ButtonIcon));
|
||||
export type ButtonIconProps = PropTypesOf<typeof enhanced>;
|
||||
export default enhanced;
|
||||
@@ -0,0 +1,43 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`forwards ref 1`] = `
|
||||
<withPropsOnChange(WithMouseHover)
|
||||
className=""
|
||||
classes={Object {}}
|
||||
forwardRef={[Function]}
|
||||
>
|
||||
Push me
|
||||
</withPropsOnChange(WithMouseHover)>
|
||||
`;
|
||||
|
||||
exports[`renders a regular sized, primary colored ghost button with fullWidth 1`] = `
|
||||
<withPropsOnChange(WithMouseHover)
|
||||
className="sizeRegular colorPrimary variantGhost fullWidth"
|
||||
classes={Object {}}
|
||||
>
|
||||
Push me
|
||||
</withPropsOnChange(WithMouseHover)>
|
||||
`;
|
||||
|
||||
exports[`renders active state 1`] = `
|
||||
<withPropsOnChange(WithMouseHover)
|
||||
className="active"
|
||||
classes={Object {}}
|
||||
>
|
||||
Push me
|
||||
</withPropsOnChange(WithMouseHover)>
|
||||
`;
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<withPropsOnChange(WithMouseHover)
|
||||
className=""
|
||||
classes={
|
||||
Object {
|
||||
"keyboardFocus": "keyboardFocus",
|
||||
"mouseHover": "mouseHover",
|
||||
}
|
||||
}
|
||||
>
|
||||
Push me
|
||||
</withPropsOnChange(WithMouseHover)>
|
||||
`;
|
||||
@@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`forwards ref 1`] = `
|
||||
<withPropsOnChange(Icon)
|
||||
className=""
|
||||
forwardRef={[Function]}
|
||||
size="sm"
|
||||
>
|
||||
Push me
|
||||
</withPropsOnChange(Icon)>
|
||||
`;
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<withPropsOnChange(Icon)
|
||||
className="root"
|
||||
size="sm"
|
||||
>
|
||||
Push me
|
||||
</withPropsOnChange(Icon)>
|
||||
`;
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "./Button";
|
||||
export { default } from "./Button";
|
||||
export { default, default as Button, ButtonProps } from "./Button";
|
||||
export { default as ButtonIcon, ButtonIconProps } from "./ButtonIcon";
|
||||
|
||||
@@ -1,52 +1,100 @@
|
||||
.root {
|
||||
display: flex;
|
||||
& > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.halfItemGutter {
|
||||
& > * {
|
||||
margin: 0 calc(0.5 * var(--spacing-unit)) 0 0;
|
||||
margin: 0 calc(0.5 * var(--spacing-unit)) 0 0 !important;
|
||||
}
|
||||
&.directionRowReverse {
|
||||
& > * {
|
||||
margin: 0 0 0 calc(0.5 * var(--spacing-unit));
|
||||
margin: 0 0 0 calc(0.5 * var(--spacing-unit)) !important;
|
||||
}
|
||||
}
|
||||
&.directionColumn {
|
||||
& > * {
|
||||
margin: 0 0 calc(0.5 * var(--spacing-unit)) 0;
|
||||
margin: 0 0 calc(0.5 * var(--spacing-unit)) 0 !important;
|
||||
}
|
||||
}
|
||||
&.directionColumnReverese {
|
||||
& > * {
|
||||
margin: calc(0.5 * var(--spacing-unit)) 0 0 0;
|
||||
margin: calc(0.5 * var(--spacing-unit)) 0 0 0 !important;
|
||||
}
|
||||
}
|
||||
& > *:last-child {
|
||||
margin: 0;
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.itemGutter {
|
||||
& > * {
|
||||
margin: 0 var(--spacing-unit) 0 0;
|
||||
margin: 0 var(--spacing-unit) 0 0 !important;
|
||||
}
|
||||
&.directionRowReverse {
|
||||
& > * {
|
||||
margin: 0 0 0 var(--spacing-unit);
|
||||
margin: 0 0 0 var(--spacing-unit) !important;
|
||||
}
|
||||
}
|
||||
&.directionColumn {
|
||||
& > * {
|
||||
margin: 0 0 var(--spacing-unit) 0;
|
||||
margin: 0 0 var(--spacing-unit) 0 !important;
|
||||
}
|
||||
}
|
||||
&.directionColumnReverese {
|
||||
& > * {
|
||||
margin: var(--spacing-unit) 0 0 0;
|
||||
margin: var(--spacing-unit) 0 0 0 !important;
|
||||
}
|
||||
}
|
||||
& > *:last-child {
|
||||
margin: 0;
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.wrapReverse {
|
||||
flex-wrap: wrap-reverse;
|
||||
}
|
||||
|
||||
.wrap,
|
||||
.wrapReverse {
|
||||
&.itemGutter {
|
||||
&:not(:empty) {
|
||||
margin-top: calc(-1 * var(--spacing-unit)) !important;
|
||||
}
|
||||
& > * {
|
||||
margin-top: var(--spacing-unit) !important;
|
||||
}
|
||||
}
|
||||
&.directionColumn.itemGutter {
|
||||
&:not(:empty) {
|
||||
margin-left: calc(-1 * var(--spacing-unit)) !important;
|
||||
}
|
||||
&.itemGutter > * {
|
||||
margin-left: var(--spacing-unit) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.halfItemGutter {
|
||||
&:not(:empty) {
|
||||
margin-top: calc(-0.5 * var(--spacing-unit)) !important;
|
||||
}
|
||||
& > * {
|
||||
margin-top: calc(0.5 * var(--spacing-unit)) !important;
|
||||
}
|
||||
}
|
||||
&.directionColumn.halfItemGutter {
|
||||
&:not(:empty) {
|
||||
margin-left: calc(-0.5 * var(--spacing-unit)) !important;
|
||||
}
|
||||
&.halfItemGutter > * {
|
||||
margin-left: calc(0.5 * var(--spacing-unit)) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,31 @@ menu: UI Kit
|
||||
|
||||
import { Playground, PropsTable } from 'docz'
|
||||
import Flex from './Flex'
|
||||
import Button from '../Button'
|
||||
|
||||
# Flex
|
||||
|
||||
`Flex` is a wrapper around `flexbox`.
|
||||
|
||||
## Basic usage
|
||||
## Justify content
|
||||
<Playground>
|
||||
<Flex justifyContent="center">I'm centered</Flex>
|
||||
</Playground>
|
||||
|
||||
## Align items
|
||||
<Playground>
|
||||
<Flex alignItems="center" itemGutter>
|
||||
<Button variant="filled">Push Me</Button>
|
||||
<Button variant="filled" size="small">Push Me</Button>
|
||||
<Button variant="filled" size="large">Push Me</Button>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
## Direction
|
||||
<Playground>
|
||||
<Flex direction="column" itemGutter>
|
||||
<Button variant="filled">Push Me</Button>
|
||||
<Button variant="filled">Push Me</Button>
|
||||
<Button variant="filled">Push Me</Button>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
import TestRenderer from "react-test-renderer";
|
||||
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
@@ -11,10 +11,58 @@ it("renders correctly", () => {
|
||||
alignItems: "center",
|
||||
direction: "row",
|
||||
};
|
||||
const wrapper = shallow(
|
||||
const renderer = TestRenderer.create(
|
||||
<Flex {...props}>
|
||||
<div>Hello World</div>
|
||||
</Flex>
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders with wrap", () => {
|
||||
const props: PropTypesOf<typeof Flex> = {
|
||||
wrap: true,
|
||||
};
|
||||
const renderer = TestRenderer.create(
|
||||
<Flex {...props}>
|
||||
<div>Hello World</div>
|
||||
</Flex>
|
||||
);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders with wrap reverse", () => {
|
||||
const props: PropTypesOf<typeof Flex> = {
|
||||
wrap: "reverse",
|
||||
};
|
||||
const renderer = TestRenderer.create(
|
||||
<Flex {...props}>
|
||||
<div>Hello World</div>
|
||||
</Flex>
|
||||
);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders with item gutter", () => {
|
||||
const props: PropTypesOf<typeof Flex> = {
|
||||
itemGutter: true,
|
||||
};
|
||||
const renderer = TestRenderer.create(
|
||||
<Flex {...props}>
|
||||
<div>Hello World</div>
|
||||
</Flex>
|
||||
);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders with halfe item gutter", () => {
|
||||
const props: PropTypesOf<typeof Flex> = {
|
||||
itemGutter: "half",
|
||||
};
|
||||
const renderer = TestRenderer.create(
|
||||
<Flex {...props}>
|
||||
<div>Hello World</div>
|
||||
</Flex>
|
||||
);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import cn from "classnames";
|
||||
import React from "react";
|
||||
import React, { Ref } from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
|
||||
import { pascalCase } from "talk-common/utils";
|
||||
import { withForwardRef, withStyles } from "talk-ui/hocs";
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import * as styles from "./Flex.css";
|
||||
|
||||
interface InnerProps {
|
||||
/**
|
||||
* This prop can be used to add custom classnames.
|
||||
* It is handled by the `withStyles `HOC.
|
||||
*/
|
||||
classes: typeof styles;
|
||||
id?: string;
|
||||
role?: string;
|
||||
justifyContent?:
|
||||
@@ -20,38 +27,58 @@ interface InnerProps {
|
||||
direction?: "row" | "column" | "row-reverse" | "column-reverse";
|
||||
itemGutter?: boolean | "half";
|
||||
className?: string;
|
||||
wrap?: boolean | "reverse";
|
||||
|
||||
/** Internal: Forwarded Ref */
|
||||
forwardRef?: Ref<HTMLDivElement>;
|
||||
}
|
||||
|
||||
const Flex: StatelessComponent<InnerProps> = props => {
|
||||
const {
|
||||
classes,
|
||||
className,
|
||||
justifyContent,
|
||||
alignItems,
|
||||
direction,
|
||||
itemGutter,
|
||||
wrap,
|
||||
forwardRef,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
let alignItemsWithDefault = alignItems;
|
||||
if (!direction || !direction.startsWith("column")) {
|
||||
alignItemsWithDefault = "center";
|
||||
}
|
||||
|
||||
const classObject: Record<string, boolean> = {
|
||||
[styles.itemGutter]: itemGutter === true,
|
||||
[styles.halfItemGutter]: itemGutter === "half",
|
||||
[classes.itemGutter]: itemGutter === true,
|
||||
[classes.halfItemGutter]: itemGutter === "half",
|
||||
[classes.wrap]: wrap === true,
|
||||
[classes.wrapReverse]: wrap === "reverse",
|
||||
};
|
||||
|
||||
if (justifyContent) {
|
||||
classObject[(styles as any)[`justify${pascalCase(justifyContent)}`]] = true;
|
||||
classObject[
|
||||
(classes as any)[`justify${pascalCase(justifyContent)}`]
|
||||
] = true;
|
||||
}
|
||||
|
||||
if (alignItems) {
|
||||
classObject[(styles as any)[`align${pascalCase(alignItems)}`]] = true;
|
||||
if (alignItemsWithDefault) {
|
||||
classObject[
|
||||
(classes as any)[`align${pascalCase(alignItemsWithDefault)}`]
|
||||
] = true;
|
||||
}
|
||||
|
||||
if (direction) {
|
||||
classObject[(styles as any)[`direction${pascalCase(direction)}`]] = true;
|
||||
classObject[(classes as any)[`direction${pascalCase(direction)}`]] = true;
|
||||
}
|
||||
|
||||
const classNames: string = cn(styles.root, className, classObject);
|
||||
const classNames: string = cn(classes.root, className, classObject);
|
||||
|
||||
return <div className={classNames} {...rest} />;
|
||||
return <div ref={forwardRef} className={classNames} {...rest} />;
|
||||
};
|
||||
|
||||
export default Flex;
|
||||
const enhanced = withForwardRef(withStyles(styles)(Flex));
|
||||
export default enhanced;
|
||||
export type FlexProps = PropTypesOf<typeof enhanced>;
|
||||
|
||||
@@ -9,3 +9,43 @@ exports[`renders correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders with halfe item gutter 1`] = `
|
||||
<div
|
||||
className="Flex-root Flex-halfItemGutter Flex-alignCenter"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders with item gutter 1`] = `
|
||||
<div
|
||||
className="Flex-root Flex-itemGutter Flex-alignCenter"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders with wrap 1`] = `
|
||||
<div
|
||||
className="Flex-root Flex-wrap Flex-alignCenter"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders with wrap reverse 1`] = `
|
||||
<div
|
||||
className="Flex-root Flex-wrapReverse Flex-alignCenter"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./Flex";
|
||||
export { default } from "./Flex";
|
||||
export { default, FlexProps } from "./Flex";
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
@font-face {
|
||||
font-family: "Material Icons";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("Material Icons"), local("MaterialIcons-Regular"),
|
||||
url(material-design-icons/iconfont/MaterialIcons-Regular.woff2)
|
||||
format("woff2"),
|
||||
url(material-design-icons/iconfont/MaterialIcons-Regular.woff)
|
||||
format("woff"),
|
||||
url(material-design-icons/iconfont/MaterialIcons-Regular.ttf)
|
||||
format("truetype");
|
||||
}
|
||||
|
||||
.root {
|
||||
font-family: "Material Icons";
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
letter-spacing: 0;
|
||||
|
||||
/* Enable Ligatures */
|
||||
font-feature-settings: "liga";
|
||||
font-variant-ligatures: "discretionary-ligatures";
|
||||
|
||||
/* Support for Safari and Chrome. */
|
||||
text-rendering: optimizeLegibility;
|
||||
|
||||
/* Better Font Rendering */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.sm {
|
||||
font-size: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
.md {
|
||||
font-size: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
.lg {
|
||||
font-size: 36px;
|
||||
width: 36px;
|
||||
}
|
||||
.xl {
|
||||
font-size: 48px;
|
||||
width: 48px;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: Icon
|
||||
menu: UI Kit
|
||||
---
|
||||
|
||||
import { Playground, PropsTable } from 'docz'
|
||||
import Icon from './Icon'
|
||||
|
||||
# Icon
|
||||
|
||||
Renders an icon.
|
||||
|
||||
Checkout available icons https://material.io/tools/icons/
|
||||
|
||||
## Basic usage
|
||||
<Playground>
|
||||
<Icon size="sm">face</Icon>
|
||||
<Icon size="md">face</Icon>
|
||||
<Icon size="lg">face</Icon>
|
||||
<Icon size="xl">face</Icon>
|
||||
</Playground>
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from "react";
|
||||
import TestRenderer from "react-test-renderer";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import Icon from "./Icon";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof Icon> = {
|
||||
children: "face",
|
||||
};
|
||||
const renderer = TestRenderer.create(<Icon {...props} />);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders correctly with specified size", () => {
|
||||
const props: PropTypesOf<typeof Icon> = {
|
||||
size: "lg",
|
||||
children: "bookmark",
|
||||
};
|
||||
const renderer = TestRenderer.create(<Icon {...props} />);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import cn from "classnames";
|
||||
import React, { HTMLAttributes, Ref, StatelessComponent } from "react";
|
||||
|
||||
import { withForwardRef, withStyles } from "talk-ui/hocs";
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import * as styles from "./Icon.css";
|
||||
|
||||
interface InnerProps extends HTMLAttributes<HTMLSpanElement> {
|
||||
/**
|
||||
* This prop can be used to add custom classnames.
|
||||
* It is handled by the `withStyles `HOC.
|
||||
*/
|
||||
classes: typeof styles;
|
||||
|
||||
size?: "sm" | "md" | "lg" | "xl";
|
||||
|
||||
/** The name of the icon to render */
|
||||
children: string;
|
||||
|
||||
/** Internal: Forwarded Ref */
|
||||
forwardRef?: Ref<HTMLSpanElement>;
|
||||
}
|
||||
|
||||
const Icon: StatelessComponent<InnerProps> = props => {
|
||||
const { classes, className, size, forwardRef, ...rest } = props;
|
||||
const rootClassName = cn(classes.root, className, classes[size!]);
|
||||
return <span className={rootClassName} {...rest} ref={forwardRef} />;
|
||||
};
|
||||
|
||||
Icon.defaultProps = {
|
||||
size: "sm",
|
||||
};
|
||||
|
||||
const enhanced = withForwardRef(withStyles(styles)(Icon));
|
||||
export type IconProps = PropTypesOf<typeof enhanced>;
|
||||
export default enhanced;
|
||||
@@ -0,0 +1,17 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<span
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
face
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`renders correctly with specified size 1`] = `
|
||||
<span
|
||||
className="Icon-root Icon-lg"
|
||||
>
|
||||
bookmark
|
||||
</span>
|
||||
`;
|
||||
@@ -0,0 +1 @@
|
||||
export { default, IconProps } from "./Icon";
|
||||
@@ -2,6 +2,8 @@ import React from "react";
|
||||
import { ReactNode, StatelessComponent } from "react";
|
||||
import Responsive, { MediaQueryMatchers } from "react-responsive";
|
||||
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import theme from "../../theme/variables";
|
||||
import UIContext from "../UIContext";
|
||||
|
||||
@@ -45,3 +47,4 @@ const MatchMediaWithContext: StatelessComponent<InnerProps> = props => (
|
||||
);
|
||||
|
||||
export default MatchMediaWithContext;
|
||||
export type MatchMediaProps = PropTypesOf<typeof MatchMediaWithContext>;
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./MatchMedia";
|
||||
export { default } from "./MatchMedia";
|
||||
export { default, MatchMediaProps } from "./MatchMedia";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.root {
|
||||
composes: body1 from "talk-ui/shared/typography.css";
|
||||
composes: bodyCopy from "talk-ui/shared/typography.css";
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import cn from "classnames";
|
||||
import React from "react";
|
||||
import React, { Ref } from "react";
|
||||
import TimeAgo, { Formatter } from "react-timeago";
|
||||
|
||||
import { UIContext } from "talk-ui/components";
|
||||
import { withStyles } from "talk-ui/hocs";
|
||||
import { withForwardRef, withStyles } from "talk-ui/hocs";
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import * as styles from "./RelativeTime.css";
|
||||
@@ -14,29 +14,30 @@ interface InnerProps {
|
||||
classes: typeof styles;
|
||||
className?: string;
|
||||
formatter?: Formatter;
|
||||
|
||||
/** Internal: Forwarded Ref */
|
||||
forwardRef?: Ref<HTMLDivElement>;
|
||||
}
|
||||
|
||||
const defaultFormatter: Formatter = (value, unit, suffix, timestamp: string) =>
|
||||
new Date(timestamp).toISOString();
|
||||
|
||||
class RelativeTime extends React.Component<InnerProps> {
|
||||
public render() {
|
||||
const { date, classes, live, className, formatter } = this.props;
|
||||
return (
|
||||
<UIContext.Consumer>
|
||||
{({ timeagoFormatter }) => (
|
||||
<TimeAgo
|
||||
date={date}
|
||||
className={cn(className, classes.root)}
|
||||
live={live}
|
||||
formatter={timeagoFormatter || formatter || defaultFormatter}
|
||||
/>
|
||||
)}
|
||||
</UIContext.Consumer>
|
||||
);
|
||||
}
|
||||
}
|
||||
const RelativeTime: React.StatelessComponent<InnerProps> = props => {
|
||||
const { date, classes, live, className, formatter } = props;
|
||||
return (
|
||||
<UIContext.Consumer>
|
||||
{({ timeagoFormatter }) => (
|
||||
<TimeAgo
|
||||
date={date}
|
||||
className={cn(className, classes.root)}
|
||||
live={live}
|
||||
formatter={timeagoFormatter || formatter || defaultFormatter}
|
||||
/>
|
||||
)}
|
||||
</UIContext.Consumer>
|
||||
);
|
||||
};
|
||||
|
||||
const enhanced = withStyles(styles)(RelativeTime);
|
||||
const enhanced = withForwardRef(withStyles(styles)(RelativeTime));
|
||||
export type RelativeTimeProps = PropTypesOf<typeof enhanced>;
|
||||
export default enhanced;
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./RelativeTime";
|
||||
export { default } from "./RelativeTime";
|
||||
export { default, RelativeTimeProps } from "./RelativeTime";
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import React from "react";
|
||||
import { create } from "react-test-renderer";
|
||||
|
||||
import ToggleShow from "./ToggleShow";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const tree = create(
|
||||
<ToggleShow>
|
||||
{({ toggleShow, show }) => (
|
||||
<div>
|
||||
{show && <div>SHOW ME</div>}
|
||||
<button onClick={toggleShow}>Click me and I disapear</button>
|
||||
</div>
|
||||
)}
|
||||
</ToggleShow>
|
||||
).toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should hide the div", () => {
|
||||
const renderer = create(
|
||||
<ToggleShow>
|
||||
{({ toggleShow, show }) => (
|
||||
<div>
|
||||
{show && <div>SHOW ME</div>}
|
||||
<button onClick={toggleShow}>Click me and I disappear</button>
|
||||
</div>
|
||||
)}
|
||||
</ToggleShow>
|
||||
);
|
||||
|
||||
renderer.root.findByType("button").props.onClick();
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
interface State {
|
||||
show: boolean;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
children: (props: RenderProps) => ReactNode;
|
||||
}
|
||||
|
||||
interface RenderProps {
|
||||
toggleShow: () => void;
|
||||
show: boolean;
|
||||
}
|
||||
|
||||
class ToggleShow extends React.Component<Props, State> {
|
||||
public state = {
|
||||
show: true,
|
||||
};
|
||||
|
||||
public toggleShow = () => {
|
||||
this.setState(state => ({ show: !state.show }));
|
||||
};
|
||||
|
||||
public render() {
|
||||
return this.props.children({
|
||||
toggleShow: this.toggleShow,
|
||||
show: this.state.show,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ToggleShow;
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: ToggleShow
|
||||
menu: UI Kit
|
||||
---
|
||||
|
||||
import { Playground } from 'docz'
|
||||
import ToggleShow from './ToggleShow'
|
||||
|
||||
# ToggleShow
|
||||
A Component that provides a render function to display nodes
|
||||
|
||||
## Basic usage
|
||||
<Playground>
|
||||
<ToggleShow>
|
||||
{({ toggleShow, show }) => (
|
||||
<div>
|
||||
{show && <div>SHOW ME</div>}
|
||||
<button onClick={toggleShow}>ClickMe and I disapear</button>
|
||||
</div>
|
||||
)}
|
||||
</ToggleShow>
|
||||
</Playground>
|
||||
@@ -0,0 +1,24 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
SHOW ME
|
||||
</div>
|
||||
<button
|
||||
onClick={[Function]}
|
||||
>
|
||||
Click me and I disapear
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`should hide the div 1`] = `
|
||||
<div>
|
||||
<button
|
||||
onClick={[Function]}
|
||||
>
|
||||
Click me and I disappear
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: TrapFocus
|
||||
menu: UI Kit
|
||||
---
|
||||
|
||||
import { Playground } from 'docz'
|
||||
import TrapFocus from './TrapFocus'
|
||||
|
||||
# TrapFocus
|
||||
|
||||
Traps focus inside component when using keyboard navigation for accessibility purposes.
|
||||
|
||||
## Basic usage
|
||||
|
||||
```ts
|
||||
import React from "react";
|
||||
|
||||
class Dialog extends React.Component {
|
||||
private firstFocusable: HTMLElement;
|
||||
private lastFocusable: HTMLElement;
|
||||
|
||||
private setFirstFocusable = (ref: HTMLElement) => (this.firstFocusable = ref);
|
||||
private setLastFocusable = (ref: HTMLElement) => (this.lastFocusable = ref);
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div>
|
||||
<TrapFocus
|
||||
firstFocusable={this.firstFocusable}
|
||||
lastFocusable={this.lastFocusable}
|
||||
>
|
||||
<TextField ref={this.setFirstFocusable} />
|
||||
<Button ref={this.setLastFocusable}>Send</Button>
|
||||
</TrapFocus>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,71 @@
|
||||
import React from "react";
|
||||
import { create } from "react-test-renderer";
|
||||
import Sinon from "sinon";
|
||||
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
import TrapFocus from "./TrapFocus";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<TrapFocus> = {
|
||||
firstFocusable: null,
|
||||
lastFocusable: null,
|
||||
children: (
|
||||
<>
|
||||
<span>child1</span>
|
||||
<span>child2</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
const renderer = create(
|
||||
<div>
|
||||
<TrapFocus {...props} />
|
||||
</div>
|
||||
);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("Change focus to `lastFocusable` when focus reaches beginning", () => {
|
||||
const fakeHTMLElementBegin = { focus: Sinon.spy() };
|
||||
const fakeHTMLElementEnd = { focus: Sinon.spy() };
|
||||
const props: PropTypesOf<TrapFocus> = {
|
||||
firstFocusable: fakeHTMLElementBegin as any,
|
||||
lastFocusable: fakeHTMLElementEnd as any,
|
||||
children: (
|
||||
<>
|
||||
<span>child1</span>
|
||||
<span>child2</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
const renderer = create(
|
||||
<div>
|
||||
<TrapFocus {...props} />
|
||||
</div>
|
||||
);
|
||||
renderer.root.findAllByProps({ tabIndex: 0 })[0].props.onFocus();
|
||||
expect(fakeHTMLElementBegin.focus.called).toBe(false);
|
||||
expect(fakeHTMLElementEnd.focus.called).toBe(true);
|
||||
});
|
||||
|
||||
it("Change focus to `firstFocusable` when focus reaches the end", () => {
|
||||
const fakeHTMLElementBegin = { focus: Sinon.spy() };
|
||||
const fakeHTMLElementEnd = { focus: Sinon.spy() };
|
||||
const props: PropTypesOf<TrapFocus> = {
|
||||
firstFocusable: fakeHTMLElementBegin as any,
|
||||
lastFocusable: fakeHTMLElementEnd as any,
|
||||
children: (
|
||||
<>
|
||||
<span>child1</span>
|
||||
<span>child2</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
const renderer = create(
|
||||
<div>
|
||||
<TrapFocus {...props} />
|
||||
</div>
|
||||
);
|
||||
renderer.root.findAllByProps({ tabIndex: 0 })[1].props.onFocus();
|
||||
expect(fakeHTMLElementBegin.focus.called).toBe(true);
|
||||
expect(fakeHTMLElementEnd.focus.called).toBe(false);
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from "react";
|
||||
|
||||
export interface Focusable {
|
||||
focus: () => void;
|
||||
}
|
||||
|
||||
export interface TrapFocusProps {
|
||||
firstFocusable: Focusable | null;
|
||||
lastFocusable: Focusable | null;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default class TrapFocus extends React.Component<TrapFocusProps> {
|
||||
// Trap keyboard focus inside the dropdown until a value has been chosen.
|
||||
public focusBegin = () => this.props.firstFocusable!.focus();
|
||||
public focusEnd = () => this.props.lastFocusable!.focus();
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<>
|
||||
<div tabIndex={0} onFocus={this.focusEnd} />
|
||||
{this.props.children}
|
||||
<div tabIndex={0} onFocus={this.focusBegin} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
onFocus={[Function]}
|
||||
tabIndex={0}
|
||||
/>
|
||||
<span>
|
||||
child1
|
||||
</span>
|
||||
<span>
|
||||
child2
|
||||
</span>
|
||||
<div
|
||||
onFocus={[Function]}
|
||||
tabIndex={0}
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1 @@
|
||||
export { default, TrapFocusProps } from "./TrapFocus";
|
||||
@@ -19,28 +19,16 @@
|
||||
composes: heading4 from "talk-ui/shared/typography.css";
|
||||
}
|
||||
|
||||
.subtitle1 {
|
||||
composes: subtitle1 from "talk-ui/shared/typography.css";
|
||||
}
|
||||
|
||||
.subtitle2 {
|
||||
composes: subtitle2 from "talk-ui/shared/typography.css";
|
||||
}
|
||||
|
||||
.body1 {
|
||||
composes: body1 from "talk-ui/shared/typography.css";
|
||||
}
|
||||
|
||||
.body2 {
|
||||
composes: body2 from "talk-ui/shared/typography.css";
|
||||
.bodyCopy {
|
||||
composes: bodyCopy from "talk-ui/shared/typography.css";
|
||||
}
|
||||
|
||||
.button {
|
||||
composes: button from "talk-ui/shared/typography.css";
|
||||
}
|
||||
|
||||
.overline {
|
||||
composes: overline from "talk-ui/shared/typography.css";
|
||||
.buttonLarge {
|
||||
composes: buttonLarge from "talk-ui/shared/typography.css";
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
@@ -85,8 +73,8 @@
|
||||
color: var(--palette-primary-main);
|
||||
}
|
||||
|
||||
.colorSecondary {
|
||||
color: var(--palette-secondary-main);
|
||||
.colorTextPrimary {
|
||||
color: var(--palette-text-primary);
|
||||
}
|
||||
|
||||
.colorTextSecondary {
|
||||
@@ -96,3 +84,7 @@
|
||||
.colorError {
|
||||
color: var(--palette-error-main);
|
||||
}
|
||||
|
||||
.colorSuccess {
|
||||
color: var(--palette-success-main);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
name: Typography
|
||||
menu: UI Kit
|
||||
---
|
||||
|
||||
import { Playground } from 'docz'
|
||||
import Typography from './Typography'
|
||||
import Flex from '../Flex'
|
||||
|
||||
# Typography
|
||||
|
||||
## Basic Use
|
||||
<Playground>
|
||||
<Flex itemGutter direction="column">
|
||||
<Typography variant="heading1">Heading1</Typography>
|
||||
<Typography variant="heading2">Heading2</Typography>
|
||||
<Typography variant="heading3">Heading3</Typography>
|
||||
<Typography variant="heading4">Heading4</Typography>
|
||||
<Typography variant="bodyCopy">BodyCopy</Typography>
|
||||
<Typography variant="timestamp">timestamp</Typography>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
## Using different colors
|
||||
<Playground>
|
||||
<Flex itemGutter direction="column">
|
||||
<Typography color="textPrimary">textPrimary</Typography>
|
||||
<Typography color="textSecondary">textSecondary</Typography>
|
||||
<Typography color="success">success</Typography>
|
||||
<Typography color="error">error</Typography>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
## Set align
|
||||
<Playground>
|
||||
<Flex itemGutter direction="column" alignItems="stretch" style={{width: "200px"}}>
|
||||
<Typography align="left">left</Typography>
|
||||
<Typography align="center">center</Typography>
|
||||
<Typography align="right">right</Typography>
|
||||
<Typography align="justify"> No hay nadie que ame el dolor mismo, que lo busque, lo encuentre y lo
|
||||
quiera, simplemente porque es el dolor.</Typography>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
## Cut off long text
|
||||
<Playground>
|
||||
<Typography noWrap style={{width: "200px"}}>No hay nadie que ame el dolor mismo, que lo busque, lo encuentre y lo quiera, simplemente porque es el dolor.</Typography>
|
||||
</Playground>
|
||||
|
||||
## Gutters
|
||||
<Playground>
|
||||
<Typography gutterBottom>I have a bottom gutter</Typography>
|
||||
<Typography paragraph>I have a paragraph gutter</Typography>
|
||||
<Typography>Just a normal text</Typography>
|
||||
</Playground>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from "react";
|
||||
import TestRenderer from "react-test-renderer";
|
||||
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import Typography from "./Typography";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof Typography> = {
|
||||
className: "custom",
|
||||
variant: "heading1",
|
||||
color: "textSecondary",
|
||||
gutterBottom: true,
|
||||
children: "Hello World",
|
||||
noWrap: true,
|
||||
align: "left",
|
||||
};
|
||||
const renderer = TestRenderer.create(<Typography {...props} />);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -1,8 +1,8 @@
|
||||
import cn from "classnames";
|
||||
import React from "react";
|
||||
import React, { Ref } from "react";
|
||||
import { HTMLAttributes, ReactNode, StatelessComponent } from "react";
|
||||
|
||||
import { withStyles } from "talk-ui/hocs";
|
||||
import { withForwardRef, withStyles } from "talk-ui/hocs";
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import * as styles from "./Typography.css";
|
||||
@@ -12,11 +12,7 @@ type Variant =
|
||||
| "heading2"
|
||||
| "heading3"
|
||||
| "heading4"
|
||||
| "subtitle1"
|
||||
| "subtitle2"
|
||||
| "body1"
|
||||
| "body2"
|
||||
| "button"
|
||||
| "bodyCopy"
|
||||
| "timestamp";
|
||||
|
||||
// Based on Typography Component of Material UI.
|
||||
@@ -45,10 +41,10 @@ interface InnerProps extends HTMLAttributes<any> {
|
||||
color?:
|
||||
| "inherit"
|
||||
| "primary"
|
||||
| "textPrimary"
|
||||
| "textSecondary"
|
||||
| "secondary"
|
||||
| "error"
|
||||
| "default";
|
||||
| "success";
|
||||
/**
|
||||
* The component used for the root node.
|
||||
* Either a string to use a DOM element or a component.
|
||||
@@ -77,6 +73,9 @@ interface InnerProps extends HTMLAttributes<any> {
|
||||
* Applies the theme typography styles.
|
||||
*/
|
||||
variant?: Variant;
|
||||
|
||||
/** Internal: Forwarded Ref */
|
||||
forwardRef?: Ref<HTMLElement>;
|
||||
}
|
||||
|
||||
const Typography: StatelessComponent<InnerProps> = props => {
|
||||
@@ -91,6 +90,7 @@ const Typography: StatelessComponent<InnerProps> = props => {
|
||||
noWrap,
|
||||
paragraph,
|
||||
variant,
|
||||
forwardRef,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
@@ -98,10 +98,11 @@ const Typography: StatelessComponent<InnerProps> = props => {
|
||||
classes.root,
|
||||
classes[variant!],
|
||||
{
|
||||
[classes.colorPrimary]: color === "primary",
|
||||
[classes.colorSecondary]: color === "secondary",
|
||||
[classes.colorError]: color === "error",
|
||||
[classes.colorTextPrimary]: color === "textPrimary",
|
||||
[classes.colorTextSecondary]: color === "textSecondary",
|
||||
[classes.colorPrimary]: color === "primary",
|
||||
[classes.colorError]: color === "error",
|
||||
[classes.colorSuccess]: color === "success",
|
||||
[classes.noWrap]: noWrap,
|
||||
[classes.gutterBottom]: gutterBottom,
|
||||
[classes.paragraph]: paragraph,
|
||||
@@ -116,29 +117,26 @@ const Typography: StatelessComponent<InnerProps> = props => {
|
||||
const Component =
|
||||
component || (paragraph ? "p" : headlineMapping![variant!]) || "span";
|
||||
|
||||
return <Component className={rootClassName} {...rest} />;
|
||||
return <Component ref={forwardRef} className={rootClassName} {...rest} />;
|
||||
};
|
||||
|
||||
Typography.defaultProps = {
|
||||
align: "inherit",
|
||||
color: "default",
|
||||
color: "textPrimary",
|
||||
gutterBottom: false,
|
||||
headlineMapping: {
|
||||
heading1: "h1",
|
||||
heading2: "h1",
|
||||
heading3: "h1",
|
||||
heading4: "h1",
|
||||
subtitle1: "h2",
|
||||
subtitle2: "h3",
|
||||
body1: "p",
|
||||
body2: "aside",
|
||||
bodyCopy: "p",
|
||||
timestamp: "span",
|
||||
},
|
||||
noWrap: false,
|
||||
paragraph: false,
|
||||
variant: "body1",
|
||||
variant: "bodyCopy",
|
||||
};
|
||||
|
||||
const enhanced = withStyles(styles)(Typography);
|
||||
export type CenterProps = PropTypesOf<typeof enhanced>;
|
||||
const enhanced = withForwardRef(withStyles(styles)(Typography));
|
||||
export type TypographyProps = PropTypesOf<typeof enhanced>;
|
||||
export default enhanced;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<h1
|
||||
className="Typography-root Typography-heading1 Typography-colorTextSecondary Typography-noWrap Typography-gutterBottom Typography-alignLeft custom"
|
||||
>
|
||||
Hello World
|
||||
</h1>
|
||||
`;
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./Typography";
|
||||
export { default } from "./Typography";
|
||||
export { default, TypographyProps } from "./Typography";
|
||||
|
||||
@@ -5,3 +5,4 @@ export { default as RelativeTime } from "./RelativeTime";
|
||||
export { default as UIContext, UIContextProps } from "./UIContext";
|
||||
export { default as Flex } from "./Flex";
|
||||
export { default as MatchMedia } from "./MatchMedia";
|
||||
export { default as TrapFocus } from "./TrapFocus";
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
export { default as withStyles } from "./withStyles";
|
||||
export { default as withKeyboardFocus } from "./withKeyboardFocus";
|
||||
export { default as withMouseHover } from "./withMouseHover";
|
||||
export { default as withForwardRef } from "./withForwardRef";
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import React, { Ref } from "react";
|
||||
|
||||
// TODO: ForwardRef API is not supported in enzymes shallow rendering
|
||||
// https://github.com/airbnb/enzyme/issues/1553
|
||||
// As for now we do props passing instead until full React16 support lands in
|
||||
// enzyme.
|
||||
|
||||
/**
|
||||
* withForwardRef provides a property called `forwardRef` using
|
||||
* the `React.forwardRef` api.
|
||||
*/
|
||||
/*
|
||||
function withForwardRef<P extends { ref?: Ref<any>; forwardRef?: Ref<any> }>(
|
||||
BaseComponent: React.ComponentType<P>
|
||||
): React.ComponentType<Omit<P, "forwardRef">> {
|
||||
const forwardRef: RefForwardingComponent<any, P> = (props, ref) => (
|
||||
<BaseComponent {...props} forwardRef={ref} />
|
||||
);
|
||||
return React.forwardRef<any, P>(forwardRef);
|
||||
}
|
||||
|
||||
// TODO: workaround, add bug link.
|
||||
export default withForwardRef as <
|
||||
P extends { ref?: Ref<any>; forwardRef?: Ref<any> }
|
||||
>(
|
||||
BaseComponent: React.ComponentType<P>
|
||||
) => React.ComponentType<P>;
|
||||
|
||||
*/
|
||||
|
||||
// Stub, currently doesn't do anything except adding types.
|
||||
export default function withForwardRef<P extends { forwardRef?: Ref<any> }>(
|
||||
BaseComponent: React.ComponentType<P>
|
||||
): React.ComponentType<P> {
|
||||
return BaseComponent;
|
||||
}
|
||||
@@ -3,10 +3,10 @@ import { FocusEvent, MouseEvent } from "react";
|
||||
import { hoistStatics } from "recompose";
|
||||
|
||||
interface InjectedProps {
|
||||
onFocus?: React.EventHandler<FocusEvent<any>>;
|
||||
onBlur?: React.EventHandler<FocusEvent<any>>;
|
||||
onMouseDown?: React.EventHandler<MouseEvent<any>>;
|
||||
keyboardFocus?: boolean;
|
||||
onFocus: React.EventHandler<FocusEvent<any>>;
|
||||
onBlur: React.EventHandler<FocusEvent<any>>;
|
||||
onMouseDown: React.EventHandler<MouseEvent<any>>;
|
||||
keyboardFocus: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -14,8 +14,8 @@ interface InjectedProps {
|
||||
* to indicate a focus on the element, that wasn't triggered by mouse
|
||||
* or touch.
|
||||
*/
|
||||
export default hoistStatics<InjectedProps>(
|
||||
<T extends InjectedProps>(WrappedComponent: React.ComponentType<T>) => {
|
||||
const withKeyboardFocus = hoistStatics<InjectedProps>(
|
||||
<T extends InjectedProps>(BaseComponent: React.ComponentType<T>) => {
|
||||
class WithKeyboardFocus extends React.Component<any> {
|
||||
public state = {
|
||||
keyboardFocus: false,
|
||||
@@ -48,7 +48,7 @@ export default hoistStatics<InjectedProps>(
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<WrappedComponent
|
||||
<BaseComponent
|
||||
{...this.props}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleBlur}
|
||||
@@ -62,3 +62,8 @@ export default hoistStatics<InjectedProps>(
|
||||
return WithKeyboardFocus as React.ComponentType<any>;
|
||||
}
|
||||
);
|
||||
|
||||
// TODO: workaround, add bug link.
|
||||
export default withKeyboardFocus as <P extends Partial<InjectedProps>>(
|
||||
BaseComponent: React.ComponentType<P>
|
||||
) => React.ComponentType<P>;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import * as React from "react";
|
||||
import { MouseEvent, TouchEvent } from "react";
|
||||
import { hoistStatics } from "recompose";
|
||||
|
||||
interface InjectedProps {
|
||||
onMouseOver: React.EventHandler<MouseEvent<any>>;
|
||||
onMouseOut: React.EventHandler<MouseEvent<any>>;
|
||||
onTouchEnd: React.EventHandler<TouchEvent<any>>;
|
||||
mouseHover: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* withMouseHover provides a property `MouseHover: boolean`
|
||||
* to indicate a focus on the element, that wasn't triggered by mouse
|
||||
* or touch.
|
||||
*/
|
||||
const withMouseHover = hoistStatics<InjectedProps>(
|
||||
<T extends InjectedProps>(BaseComponent: React.ComponentType<T>) => {
|
||||
class WithMouseHover extends React.Component<any> {
|
||||
public state = {
|
||||
mouseHover: false,
|
||||
lastTouchEndTime: 0,
|
||||
};
|
||||
|
||||
private handleTouchEnd: React.EventHandler<TouchEvent<any>> = event => {
|
||||
if (this.props.onTouchEnd) {
|
||||
this.props.onTouchEnd(event);
|
||||
}
|
||||
this.setState({ lastTouchEndTime: new Date().getTime() });
|
||||
};
|
||||
|
||||
private handleMouseOver: React.EventHandler<MouseEvent<any>> = event => {
|
||||
if (this.props.onMouseOver) {
|
||||
this.props.onMouseOver(event);
|
||||
}
|
||||
const now = new Date().getTime();
|
||||
if (now - this.state.lastTouchEndTime > 750) {
|
||||
this.setState({ mouseHover: true });
|
||||
}
|
||||
};
|
||||
|
||||
private handleMouseOut: React.EventHandler<MouseEvent<any>> = event => {
|
||||
if (this.props.onMouseOut) {
|
||||
this.props.onMouseOut(event);
|
||||
}
|
||||
this.setState({ mouseHover: false });
|
||||
};
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<BaseComponent
|
||||
{...this.props}
|
||||
onMouseOver={this.handleMouseOver}
|
||||
onMouseOut={this.handleMouseOut}
|
||||
onTouchEnd={this.handleTouchEnd}
|
||||
mouseHover={this.state.mouseHover}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return WithMouseHover as React.ComponentType<any>;
|
||||
}
|
||||
);
|
||||
|
||||
// TODO: workaround, add bug link.
|
||||
export default withMouseHover as <P extends Partial<InjectedProps>>(
|
||||
BaseComponent: React.ComponentType<P>
|
||||
) => React.ComponentType<P>;
|
||||
@@ -13,17 +13,18 @@ function withStyles<T>(
|
||||
): DefaultingInferableComponentEnhancer<{ classes?: Partial<T> }> {
|
||||
const classes = { ...(styles as any) };
|
||||
return withPropsOnChange<any, any>(["classes"], props => {
|
||||
const resolvedClasses = { ...classes };
|
||||
if (props.classes) {
|
||||
Object.keys(props.classes).forEach(k => {
|
||||
if (classes[k]) {
|
||||
classes[k] += ` ${props.classes[k]}`;
|
||||
resolvedClasses[k] += ` ${props.classes[k]}`;
|
||||
} else if (process.env.NODE_ENV !== "production") {
|
||||
// tslint:disable:next-line: no-console
|
||||
console.warn("Extending non existant className", k);
|
||||
}
|
||||
});
|
||||
}
|
||||
return { classes };
|
||||
return { classes: resolvedClasses };
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,61 @@
|
||||
@font-face {
|
||||
font-family: "Source Sans Pro";
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 300;
|
||||
src: local("Source Sans Pro Light "), local("Source Sans Pro-Light"),
|
||||
url("typeface-source-sans-pro/files/source-sans-pro-latin-300.woff2")
|
||||
format("woff2"),
|
||||
url("typeface-source-sans-pro/files/source-sans-pro-latin-300.woff")
|
||||
format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Sans Pro";
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 400;
|
||||
src: local("Source Sans Pro Regular italic"),
|
||||
local("Source Sans Pro-Regularitalic"),
|
||||
url("typeface-source-sans-pro/files/source-sans-pro-latin-400.woff2")
|
||||
format("woff2"),
|
||||
url("typeface-source-sans-pro/files/source-sans-pro-latin-400.woff")
|
||||
format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Source Sans Pro";
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 600;
|
||||
src: local("Source Sans Pro SemiBold italic"),
|
||||
local("Source Sans Pro-SemiBolditalic"),
|
||||
url("typeface-source-sans-pro/files/source-sans-pro-latin-600.woff2")
|
||||
format("woff2"),
|
||||
url("typeface-source-sans-pro/files/source-sans-pro-latin-600.woff")
|
||||
format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Manuale";
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 400;
|
||||
src: local("Manuale Regular "), local("Manuale-Regular"),
|
||||
url("typeface-manuale/files/manuale-latin-400.woff2") format("woff2"),
|
||||
url("typeface-manuale/files/manuale-latin-400.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Manuale";
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 600;
|
||||
src: local("Manuale SemiBold "), local("Manuale-SemiBold"),
|
||||
url("typeface-manuale/files/manuale-latin-600.woff2") format("woff2"),
|
||||
url("typeface-manuale/files/manuale-latin-600.woff") format("woff");
|
||||
}
|
||||
|
||||
.heading1 {
|
||||
font-size: calc(24rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-medium);
|
||||
@@ -33,16 +91,7 @@
|
||||
color: var(--palette-text-primary);
|
||||
}
|
||||
|
||||
.subtitle1 {
|
||||
}
|
||||
|
||||
.subtitle2 {
|
||||
}
|
||||
|
||||
.body2 {
|
||||
}
|
||||
|
||||
.body1 {
|
||||
.bodyCopy {
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-regular);
|
||||
font-family: "Source Sans Pro";
|
||||
@@ -55,11 +104,18 @@
|
||||
color: var(--palette-text-secondary);
|
||||
font-family: "Source Sans Pro";
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
line-height: calc(18em / 16);
|
||||
letter-spacing: calc(0.57em / 16);
|
||||
}
|
||||
|
||||
.overline {
|
||||
.buttonLarge {
|
||||
color: var(--palette-text-secondary);
|
||||
font-family: "Source Sans Pro";
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: 16px;
|
||||
line-height: calc(20em / 16);
|
||||
letter-spacing: calc(0.57em / 16);
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
|
||||
@@ -12,14 +12,16 @@ const variables = {
|
||||
main: "#3498DB",
|
||||
light: "#67B2E4",
|
||||
lighter: "#8DC5EB",
|
||||
lightest: "#EBF5FB",
|
||||
},
|
||||
/* Secondary colors */
|
||||
secondary: {
|
||||
grey: {
|
||||
darkest: "#404345",
|
||||
dark: "#65696B",
|
||||
main: "#787D80",
|
||||
light: "#9A9DA0",
|
||||
lighter: "#636E72",
|
||||
lighter: "#BBBEBF",
|
||||
lightest: "#F5F5F5",
|
||||
},
|
||||
/* Success colors */
|
||||
success: {
|
||||
@@ -28,21 +30,21 @@ const variables = {
|
||||
main: "#00CD73",
|
||||
light: "#40D996",
|
||||
lighter: "#83EBBD",
|
||||
lightest: "#E6FAF1",
|
||||
},
|
||||
/* Error colors */
|
||||
error: {
|
||||
darkest: "#F50F0C",
|
||||
dark: "#FF1F1C",
|
||||
main: "#FA4643",
|
||||
light: "#F26563",
|
||||
lighter: "#F26563",
|
||||
light: "#FB7472",
|
||||
lighter: "#FC9795",
|
||||
lightest: "#FEF0EF",
|
||||
},
|
||||
/* Text colors */
|
||||
text: {
|
||||
primary: "#3B4A53",
|
||||
secondary: "#787D80",
|
||||
disabled: "rgba(0, 0, 0, 0.38)",
|
||||
hint: "rgba(0, 0, 0, 0.38)",
|
||||
},
|
||||
/* Common colors */
|
||||
common: {
|
||||
@@ -51,11 +53,6 @@ const variables = {
|
||||
},
|
||||
/* Divider */
|
||||
divider: "rgba(0, 0, 0, 0.12)",
|
||||
/* The background colors used to style the surfaces. */
|
||||
background: {
|
||||
paper: "#FFF",
|
||||
default: "#FAFAFA",
|
||||
},
|
||||
},
|
||||
/* gitter and spacing */
|
||||
spacingUnitSmall: 5,
|
||||
@@ -68,7 +65,7 @@ const variables = {
|
||||
fontSize: 16,
|
||||
fontWeightLight: 300,
|
||||
fontWeightRegular: 400,
|
||||
fontWeightMedium: 550,
|
||||
fontWeightMedium: 600,
|
||||
/* Breakpoints */
|
||||
breakpoints: {
|
||||
xs: 320,
|
||||
|
||||
@@ -2,27 +2,19 @@ import React from "react";
|
||||
|
||||
// TODO: Extract useful common types into its own package.
|
||||
|
||||
/**
|
||||
* Returns literals types that are in T but not in U.
|
||||
*
|
||||
* E.g. Diff<"a" | "b", "a"> = "b"
|
||||
*/
|
||||
export type Diff<T extends keyof any, U extends keyof any> = ({ [P in T]: P } &
|
||||
{ [P in U]: never } & { [x: string]: never; [x: number]: never })[T];
|
||||
|
||||
/**
|
||||
* Overwrite properties of `T`.
|
||||
*
|
||||
* E.g. Omit<{a: boolean, b: boolean}, "b"> = {a: boolean}
|
||||
*/
|
||||
export type Omit<U, K extends keyof U> = Pick<U, Diff<keyof U, K>>;
|
||||
export type Omit<U, K extends keyof U> = Pick<U, Exclude<keyof U, K>>;
|
||||
|
||||
/**
|
||||
* Overwrite properties of `T`.
|
||||
*
|
||||
* E.g. Overwrite<{a: boolean}, {a: string}> = {a: string}
|
||||
*/
|
||||
export type Overwrite<T, U> = Pick<T, Diff<keyof T, keyof U>> & U;
|
||||
export type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;
|
||||
|
||||
/**
|
||||
* Returns the PropTypes from a React Component.
|
||||
|
||||
@@ -22,7 +22,7 @@ framework-timeago =
|
||||
*[other] Minuten
|
||||
}
|
||||
[hour] { $value ->
|
||||
[0] Stunde
|
||||
[1] Stunde
|
||||
*[other] Stunden
|
||||
}
|
||||
[day] { $value ->
|
||||
|
||||
@@ -18,7 +18,7 @@ framework-timeago-time =
|
||||
*[other] minutes
|
||||
}
|
||||
[hour] { $value ->
|
||||
[0] hour
|
||||
[1] hour
|
||||
*[other] hours
|
||||
}
|
||||
[day] { $value ->
|
||||
|
||||
@@ -22,7 +22,7 @@ framework-timeago =
|
||||
*[other] minutos
|
||||
}
|
||||
[hour] { $value ->
|
||||
[0] hora
|
||||
[1] hora
|
||||
*[other] horas
|
||||
}
|
||||
[day] { $value ->
|
||||
|
||||
Reference in New Issue
Block a user