diff --git a/src/components/Button.js b/src/components/Button.js
index 3696babc..ef9e9769 100644
--- a/src/components/Button.js
+++ b/src/components/Button.js
@@ -1,10 +1,11 @@
import React from "react";
import PropTypes from "prop-types";
import useTheme from "../hooks/useTheme";
-import useContainer from "../hooks/useContainer";
-import { responsiveMargin } from "../utils/css";
-import { responsiveMarginType } from "../hooks/useResponsiveProp";
+import useBackground from "../hooks/useBackground";
import useResponsivePropsCSS from "../hooks/useResponsivePropsCSS";
+import { responsiveMarginType } from "../hooks/useResponsiveProp";
+import { responsiveMargin } from "../utils/css";
+import { mergeProps } from "../utils/component";
const VARIANTS = ["primary", "secondary", "icon"];
const COLORS = ["highlight.blue.t100", "white"];
@@ -23,10 +24,24 @@ Button.COLORS = COLORS;
Button.TYPES = TYPES;
Button.DEFAULT_PROPS = DEFAULT_PROPS;
-function Button(_props) {
- const props = { ...DEFAULT_PROPS, ..._props };
+function Button(props) {
+ const theme = useTheme();
+ const { background } = useBackground();
+ const inheritedColor =
+ background === "primary.blue.t100" ? "white" : "highlight.blue.t100";
+ const inheritedProps = {
+ color: inheritedColor
+ };
+ const mergedProps = mergeProps(props, DEFAULT_PROPS, inheritedProps, {
+ variant: variant => VARIANTS.includes(variant),
+ color: color => COLORS.includes(color),
+ isFullWidth: isFullWidth => typeof isFullWidth === "boolean",
+ isDisabled: isDisabled => typeof isDisabled === "boolean",
+ type: type => TYPES.includes(type)
+ });
const {
variant,
+ color,
isFullWidth,
isDisabled,
type,
@@ -36,14 +51,10 @@ function Button(_props) {
__internal__keyboardFocus,
__internal__hover,
__internal__active
- } = props;
- const theme = useTheme();
- const { buttonColor } = useContainer();
- const responsivePropsCSS = useResponsivePropsCSS(props, DEFAULT_PROPS, {
+ } = mergedProps;
+ const responsivePropsCSS = useResponsivePropsCSS(mergedProps, DEFAULT_PROPS, {
margin: responsiveMargin
});
- const color =
- !COLORS.includes(_props.color) && buttonColor ? buttonColor : props.color;
const colorStr = color === DEFAULT_PROPS.color ? "default" : color;
const css = {
...theme.button,
diff --git a/src/components/Checkbox.js b/src/components/Checkbox.js
index 2812c0d7..63db0dcf 100644
--- a/src/components/Checkbox.js
+++ b/src/components/Checkbox.js
@@ -1,11 +1,12 @@
import React, { useState } from "react";
import PropTypes from "prop-types";
import nanoid from "nanoid";
-import Field from "./internal/Field";
-import VisuallyHidden from "./VisuallyHidden";
-import useContainer from "../hooks/useContainer";
import useTheme from "../hooks/useTheme";
+import useBackground from "../hooks/useBackground";
import useValidation from "../hooks/useValidation";
+import { mergeProps } from "../utils/component";
+import Field from "./internal/Field";
+import VisuallyHidden from "./VisuallyHidden";
const COLORS = ["grey.t05", "white"];
@@ -69,10 +70,19 @@ CheckboxIcon.propTypes = {
isChecked: PropTypes.bool.isRequired
};
-function Checkbox(_props) {
- const props = { ...DEFAULT_PROPS, ..._props };
+function Checkbox(props) {
+ const { inputColor } = useBackground();
+ const inheritedProps = {
+ color: inputColor
+ };
+ const mergedProps = mergeProps(props, DEFAULT_PROPS, inheritedProps, {
+ color: color => COLORS.includes(color),
+ isOptional: isOptional => typeof isOptional === "boolean",
+ isDisabled: isDisabled => typeof isDisabled === "boolean"
+ });
const {
label,
+ color,
isOptional,
helpText,
isDisabled,
@@ -81,18 +91,15 @@ function Checkbox(_props) {
children,
testId,
__internal__keyboardFocus
- } = props;
+ } = mergedProps;
const theme = useTheme();
- const { inputColor } = useContainer();
- const color =
- !COLORS.includes(_props.color) && inputColor ? inputColor : props.color;
const [labelId] = useState(() => `radio-group-label-${nanoid()}`);
const [inputId] = useState(() => `checkbox-${nanoid()}`);
const [auxId] = useState(() => `checkbox-aux-${nanoid()}`);
const [isTouched, setIsTouched] = useState(false);
const { value: isChecked, errors } = data;
const validate = useValidation({
- props,
+ props: mergedProps,
extraData: {
isTouched
}
diff --git a/src/components/Container.js b/src/components/Container.js
index ca4088cc..7986059c 100644
--- a/src/components/Container.js
+++ b/src/components/Container.js
@@ -2,7 +2,8 @@ import React from "react";
import PropTypes from "prop-types";
import Text from "./Text";
import useTheme from "../hooks/useTheme";
-import { ContainerProvider } from "../hooks/useContainer";
+import { TextStyleProvider } from "../hooks/useTextStyle";
+import { BackgroundProvider } from "../hooks/useBackground";
import {
responsiveMarginType,
responsivePaddingType,
@@ -42,7 +43,14 @@ Container.DEFAULT_PROPS = DEFAULT_PROPS;
function Container(_props) {
const props = { ...DEFAULT_PROPS, ..._props };
- const { bg, boxShadow, hasBreakpointWidth, children, testId } = props;
+ const {
+ bg,
+ boxShadow,
+ hasBreakpointWidth,
+ textStyle,
+ children,
+ testId
+ } = props;
const theme = useTheme();
const responsivePropsCSS = useResponsivePropsCSS(props, DEFAULT_PROPS, {
margin: responsiveMargin,
@@ -88,22 +96,31 @@ function Container(_props) {
: {
boxShadow: tokens.shadows[boxShadow] || null
};
-
- return (
-
-
- {children}
-
-
+ let container = (
+
+ {children}
+
);
+
+ if (textStyle) {
+ container = (
+ {container}
+ );
+ }
+
+ if (bg) {
+ container = {container};
+ }
+
+ return container;
}
Container.propTypes = {
@@ -127,6 +144,7 @@ Container.propTypes = {
...responsivePaddingType,
...responsiveWidthType,
...responsiveHeightType,
+ ...responsivePropType("textStyle", PropTypes.oneOf(Text.TEXT_STYLES)),
...responsivePropType("textAlign", PropTypes.oneOf(Text.ALIGNS)),
hasBreakpointWidth: PropTypes.bool,
children: PropTypes.node,
diff --git a/src/components/Container.test.js b/src/components/Container.test.js
index e35dfdad..45520578 100644
--- a/src/components/Container.test.js
+++ b/src/components/Container.test.js
@@ -2,6 +2,7 @@ import React from "react";
import { render } from "../utils/test";
import "@testing-library/jest-dom/extend-expect";
import Container from "./Container";
+import Text from "./Text";
describe("Container", () => {
it("no props", () => {
@@ -53,6 +54,34 @@ describe("Container", () => {
`);
});
+ it("with textStyle parent", () => {
+ const { getByText } = render(
+
+ Hello World
+
+ );
+ const text = getByText("Hello World");
+
+ expect(text).toHaveStyle(`
+ font-size: 14px;
+ `);
+ });
+
+ it("with textStyle grandparent", () => {
+ const { getByText } = render(
+
+
+ Hello World
+
+
+ );
+ const text = getByText("Hello World");
+
+ expect(text).toHaveStyle(`
+ font-size: 104px;
+ `);
+ });
+
it("with textAlign", () => {
const { getByText } = render(
Hello World
diff --git a/src/components/DatePicker.js b/src/components/DatePicker.js
index 18963528..3db69b51 100644
--- a/src/components/DatePicker.js
+++ b/src/components/DatePicker.js
@@ -6,11 +6,12 @@ import {
format as formatDate
} from "date-fns";
import nanoid from "nanoid";
+import useBackground from "../hooks/useBackground";
+import useValidation from "../hooks/useValidation";
+import { mergeProps } from "../utils/component";
import Field from "./internal/Field";
-import useContainer from "../hooks/useContainer";
-import Grid from "./Grid";
import Input from "./Input";
-import useValidation from "../hooks/useValidation";
+import Grid from "./Grid";
const COLORS = ["grey.t05", "white"];
@@ -118,9 +119,18 @@ function getHelpText(day, month, year, defaultHelpText) {
return formatDate(new Date(yearInt, monthInt - 1, dayInt), "d MMMM, yyyy");
}
-function DatePicker(_props) {
- const props = { ...DEFAULT_PROPS, ..._props };
+function DatePicker(props) {
+ const { inputColor } = useBackground();
+ const inheritedProps = {
+ color: inputColor
+ };
+ const mergedProps = mergeProps(props, DEFAULT_PROPS, inheritedProps, {
+ color: color => COLORS.includes(color),
+ isOptional: isOptional => typeof isOptional === "boolean",
+ isDisabled: isDisabled => typeof isDisabled === "boolean"
+ });
const {
+ color,
label,
isOptional,
helpText: helpTextProp,
@@ -128,10 +138,7 @@ function DatePicker(_props) {
data,
onChange,
testId
- } = props;
- const { inputColor } = useContainer();
- const color =
- !COLORS.includes(_props.color) && inputColor ? inputColor : props.color;
+ } = mergedProps;
const [labelId] = useState(() => `date-picker-${nanoid()}`);
const [auxId] = useState(() => `date-picker-aux-${nanoid()}`);
const [isTouched, setIsTouched] = useState({
@@ -145,7 +152,7 @@ function DatePicker(_props) {
[value.day, value.month, value.year, helpTextProp]
);
const validate = useValidation({
- props,
+ props: mergedProps,
extraData: {
isTouched
}
diff --git a/src/components/Flex.js b/src/components/Flex.js
index 8c08c670..31b1d79b 100644
--- a/src/components/Flex.js
+++ b/src/components/Flex.js
@@ -2,10 +2,14 @@ import React from "react";
import PropTypes from "prop-types";
import useResponsivePropsCSS from "../hooks/useResponsivePropsCSS";
import {
+ responsiveMarginType,
+ responsiveWidthType,
responsiveHeightType,
responsivePropType
} from "../hooks/useResponsiveProp";
import {
+ responsiveMargin,
+ responsiveWidth,
responsiveHeight,
responsiveFlexDirection,
responsiveFlexGutter,
@@ -39,6 +43,7 @@ const PLACE_ITEMS = [
const DEFAULT_PROPS = {
direction: "row",
+ wrap: false,
placeItems: "top left"
};
@@ -48,44 +53,61 @@ Flex.DEFAULT_PROPS = DEFAULT_PROPS;
function Flex(_props) {
const props = { ...DEFAULT_PROPS, ..._props };
- const { children, testId } = props;
+ const { wrap, children, testId } = props;
const childrenArray = React.Children.toArray(children);
+ const wrapperCSS = useResponsivePropsCSS(props, DEFAULT_PROPS, {
+ margin: responsiveMargin,
+ width: responsiveWidth,
+ height: responsiveHeight
+ });
const flexCSS = useResponsivePropsCSS(props, DEFAULT_PROPS, {
- height: responsiveHeight,
+ gutter: responsiveFlexGutter("items-container"),
placeItems: responsiveFlexPlaceItems,
direction: responsiveFlexDirection
});
const flexItemCSS = useResponsivePropsCSS(props, DEFAULT_PROPS, {
- gutter: responsiveFlexGutter
+ gutter: responsiveFlexGutter("item")
});
return (
- {isObjectEmpty(flexItemCSS)
- ? childrenArray
- : childrenArray.map((child, index) => (
-
- {child}
-
- ))}
+
+ {isObjectEmpty(flexItemCSS)
+ ? childrenArray
+ : childrenArray.map((child, index) => (
+
+ {child}
+
+ ))}
+
);
}
Flex.propTypes = {
- ...responsivePropType("direction", PropTypes.oneOf(DIRECTIONS)),
+ ...responsiveMarginType,
+ ...responsiveWidthType,
...responsiveHeightType,
+ ...responsivePropType("direction", PropTypes.oneOf(DIRECTIONS)),
...responsivePropType(
"gutter",
PropTypes.oneOfType([PropTypes.number, PropTypes.string])
),
+ wrap: PropTypes.bool,
...responsivePropType("placeItems", PropTypes.oneOf(PLACE_ITEMS)),
children: PropTypes.node.isRequired,
testId: PropTypes.string
diff --git a/src/components/Footer.js b/src/components/Footer.js
index d4bdd022..2b63b582 100644
--- a/src/components/Footer.js
+++ b/src/components/Footer.js
@@ -1,17 +1,13 @@
import React from "react";
import PropTypes from "prop-types";
import Container from "./Container";
-import Flex from "./Flex";
-import Text from "./Text";
-import Link from "./Link";
-import useTheme from "../hooks/useTheme";
+import { Flex, Text, Link, Icon } from "..";
import Logo from "./internal/Logo";
-import tokens from "../themes/tokens";
function HeaderLogo({ name, testId }) {
return (
-
-
+
+
);
}
@@ -21,11 +17,130 @@ HeaderLogo.propTypes = {
testId: PropTypes.string
};
+function HeaderSocial({ children, testId }) {
+ return (
+
+
+ Connect with us
+
+
+ {children}
+
+
+ );
+}
+
+HeaderSocial.propTypes = {
+ children: PropTypes.node.isRequired,
+ testId: PropTypes.string
+};
+
+function SocialFacebook({ href, title, testId }) {
+ return (
+
+
+
+ );
+}
+
+SocialFacebook.propTypes = {
+ href: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ testId: PropTypes.string
+};
+
+function SocialTwitter({ href, title, testId }) {
+ return (
+
+
+
+ );
+}
+
+SocialTwitter.propTypes = {
+ href: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ testId: PropTypes.string
+};
+
+function SocialInstagram({ href, title, testId }) {
+ return (
+
+
+
+ );
+}
+
+SocialInstagram.propTypes = {
+ href: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ testId: PropTypes.string
+};
+
+function SocialLinkedIn({ href, title, testId }) {
+ return (
+
+
+
+ );
+}
+
+SocialLinkedIn.propTypes = {
+ href: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ testId: PropTypes.string
+};
+
function Header({ children, testId }) {
return (
- {children}
+
+ {children}
+
);
@@ -37,40 +152,15 @@ Header.propTypes = {
};
function LegalLinks({ children, testId }) {
- const theme = useTheme();
const links = React.Children.toArray(children).filter(
// Ignore all children that aren't a Link
child => child.type === Link
);
- const linksContainerCSS = {
- display: "flex",
- flexDirection: "column",
- flexWrap: "wrap",
- justifyContent: "center",
- [theme.minMediaQueries.md]: {
- flexDirection: "row"
- }
- };
return (
-
- {links.map((link, index) => {
- const linkItemCSS = {
- whiteSpace: "nowrap",
- marginTop: index > 0 && tokens.space[3],
- [theme.minMediaQueries.md]: {
- marginTop: 0,
- marginLeft: index > 0 && tokens.space[4]
- }
- };
-
- return (
-
- {link}
-
- );
- })}
-
+
+ {links}
+
);
}
@@ -81,15 +171,9 @@ LegalLinks.propTypes = {
function LegalCopy({ children, testId }) {
return (
-
+
{children}
-
+
);
}
@@ -101,11 +185,7 @@ LegalCopy.propTypes = {
function Legal({ children, testId }) {
return (
-
+
{children}
@@ -126,10 +206,16 @@ Footer.propTypes = {
testId: PropTypes.string
};
-Header.Logo = HeaderLogo;
Footer.Header = Header;
-Legal.Links = LegalLinks;
-Legal.Copy = LegalCopy;
+Footer.Header.Logo = HeaderLogo;
+Footer.Header.Social = HeaderSocial;
+Footer.Header.Social.Facebook = SocialFacebook;
+Footer.Header.Social.Twitter = SocialTwitter;
+Footer.Header.Social.Instagram = SocialInstagram;
+Footer.Header.Social.LinkedIn = SocialLinkedIn;
+
Footer.Legal = Legal;
+Footer.Legal.Links = LegalLinks;
+Footer.Legal.Copy = LegalCopy;
export default Footer;
diff --git a/src/components/Footer.test.js b/src/components/Footer.test.js
index e2e121a4..adf4baed 100644
--- a/src/components/Footer.test.js
+++ b/src/components/Footer.test.js
@@ -11,6 +11,28 @@ describe("Footer", () => {
diff --git a/website/src/components/kitchen-sink/List.js b/website/src/components/kitchen-sink/List.js
index 6f84181f..69fc0a16 100644
--- a/website/src/components/kitchen-sink/List.js
+++ b/website/src/components/kitchen-sink/List.js
@@ -48,7 +48,7 @@ function KitchenSinkList() {
Nested list
-
+
Hello
World
diff --git a/website/src/pages/components/flex/index.js b/website/src/pages/components/flex/index.js
index 4bcacbc0..676af8d3 100644
--- a/website/src/pages/components/flex/index.js
+++ b/website/src/pages/components/flex/index.js
@@ -42,6 +42,27 @@ function FlexPage() {
+
+ Wrapping items:
+
+
+
+ Item 1
+
+
+ Item 2
+
+
+ Item 3
+
+
+ Item 4
+
+
+ Item 5
+
+
+
`);
diff --git a/website/src/pages/components/footer/index.js b/website/src/pages/components/footer/index.js
index 310e126b..0f0d60d4 100644
--- a/website/src/pages/components/footer/index.js
+++ b/website/src/pages/components/footer/index.js
@@ -10,15 +10,82 @@ function FooterPage() {
+
+
+
+
+
+
- Link 1
- Link 2
- Link 3
+
+ Terms and conditions
+
+
+ Privacy and credit reporting policy
+
+
+ Security
+
+
+ Complaints
+
+
+ Financial hardship
+
+
+ Site map
+
- Legal copy goes here.
+
+ The Latitude Group recommends that you read the
+ Terms and conditions and
+ Privacy and Credit Reporting Policy of the website.
+ The Latitude Group is a leader in consumer finance in Australia and
+ New Zealand offering a range of services: including personal loans, car loans,
+ credit cards, personal insurance, interest free and promotional retail. In Australia,
+ the Latitude Group includes: Latitude Financial Services Australia Holdings Pty Ltd
+ (ABN 46 603 161 100); Latitude Finance Australia (ABN 42 008 583 588 Australian
+ Credit Licence Number 392145); Latitude Personal Finance Pty Ltd (ABN 54 008 443 810
+ Australian Credit Licence Number 392163) and Latitude Automotive Financial Services
+ (ABN 80 004 187 419 Australian Credit Licence Number 392178) trading as Latitude
+ Financial Services. LatitudePay Payment Plan provided by LatitudePay Australia Pty Ltd
+ ABN 23 633 528 873. In New Zealand, the Latitude Group includes: Latitude Financial
+ Services Limited (Company number 5624865). Latitude Financial Services 800 Collins Street,
+ Docklands, Victoria 3008.
+
diff --git a/website/src/pages/components/list/index.js b/website/src/pages/components/list/index.js
index 02493056..bc0fb5f3 100644
--- a/website/src/pages/components/list/index.js
+++ b/website/src/pages/components/list/index.js
@@ -41,17 +41,7 @@ function ListPage() {
Nested list
-
+
First
Second
Third
diff --git a/website/src/themes/website/link.js b/website/src/themes/website/link.js
index 9fed5b28..b971e178 100644
--- a/website/src/themes/website/link.js
+++ b/website/src/themes/website/link.js
@@ -3,8 +3,6 @@ import { designTokens as tokens } from "basis";
export default {
link: {
display: "inline-block",
- fontFamily: "inherit",
- fontWeight: "inherit",
textDecoration: "none"
},
"link:focus": {
@@ -14,15 +12,19 @@ export default {
borderRadius: tokens.radii[0],
boxShadow: tokens.shadows.focus
},
- "link.default": {
+ "link.text": {
+ fontFamily: "inherit",
+ fontWeight: "inherit"
+ },
+ "link.text.default": {
color: "inherit",
borderBottomColor: "inherit"
},
- "link.default:hover": {
+ "link.text.default:hover": {
color: "inherit",
borderBottomColor: "inherit"
},
- "link.default:active": {
+ "link.text.default:active": {
color: "inherit",
borderBottomColor: "inherit"
}