property-practice-ui 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{Textarea-u7ONHI5M.d.cts → Textarea-BNvLsAXP.d.cts} +1 -10
  3. package/dist/{Textarea-u7ONHI5M.d.ts → Textarea-BNvLsAXP.d.ts} +1 -10
  4. package/dist/atoms.cjs +5 -3
  5. package/dist/atoms.cjs.map +1 -1
  6. package/dist/atoms.d.cts +12 -3
  7. package/dist/atoms.d.ts +12 -3
  8. package/dist/atoms.js +5 -3
  9. package/dist/atoms.js.map +1 -1
  10. package/dist/index.cjs +794 -300
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +34 -17
  13. package/dist/index.d.ts +34 -17
  14. package/dist/index.js +790 -296
  15. package/dist/index.js.map +1 -1
  16. package/package.json +1 -1
  17. package/src/atoms/Chip/Chip.tsx +29 -0
  18. package/src/atoms/SecondaryInput/SecondaryInput.tsx +5 -3
  19. package/src/molecules/Address/Address.tsx +113 -26
  20. package/src/molecules/CTAContainer/CTAContainer.tsx +28 -2
  21. package/src/molecules/ContentCard/ContentCard.tsx +5 -0
  22. package/src/molecules/ExtendedButton/ExtendedButton.stories.tsx +31 -0
  23. package/src/molecules/ExtendedButton/ExtendedButton.tsx +29 -0
  24. package/src/molecules/ProductInfo/ProductInfo.tsx +18 -0
  25. package/src/molecules/SideNav/SideNav.stories.tsx +161 -11
  26. package/src/molecules/SideNav/SideNav.tsx +219 -44
  27. package/src/organism/ContactForm/ContactForm.tsx +13 -2
  28. package/src/organism/FeatureCarousel/FeatureCarousel.tsx +130 -45
  29. package/src/organism/Footer/Footer.tsx +2 -2
  30. package/src/organism/Header/Header.tsx +70 -0
  31. package/src/templates/AboutUs/AboutUs.tsx +2 -2
  32. package/src/templates/Contact/Contact.tsx +21 -6
  33. package/src/templates/FAQ/FAQ.tsx +0 -1
  34. package/src/templates/Features/Features.tsx +26 -18
  35. package/src/templates/Hero/Hero.tsx +34 -8
  36. package/src/templates/OtherProducts/OtherProducts.tsx +73 -22
  37. package/src/tokens/colors.ts +1 -0
@@ -1,5 +1,8 @@
1
1
  import styled from 'styled-components';
2
2
  import { ExtendedButton, TextButton } from '../../atoms';
3
+ import { colors } from '../../tokens/colors';
4
+
5
+ type BorderColor = keyof typeof colors.border;
3
6
 
4
7
  const HeaderContainer = styled.header`
5
8
  display: flex;
@@ -7,6 +10,7 @@ const HeaderContainer = styled.header`
7
10
  align-items: center;
8
11
  background-color: #ffffff;
9
12
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
13
+ padding: 0 1rem;
10
14
  `;
11
15
 
12
16
  const LogoWrapper = styled.div`
@@ -23,6 +27,55 @@ const ButtonGroup = styled.div`
23
27
  display: flex;
24
28
  gap: 1rem;
25
29
  align-items: center;
30
+
31
+ /* Hide on mobile */
32
+ @media (max-width: 767px) {
33
+ display: none;
34
+ }
35
+ `;
36
+
37
+ const BurgerButton = styled.button<{ $burgerVariant: BorderColor }>`
38
+ display: none;
39
+
40
+ /* Show only on mobile */
41
+ @media (max-width: 767px) {
42
+ display: flex;
43
+ flex-direction: column;
44
+ justify-content: space-around;
45
+ width: 2rem;
46
+ height: 2rem;
47
+ background: transparent;
48
+ border: none;
49
+ cursor: pointer;
50
+ padding: 0;
51
+
52
+ &:focus {
53
+ outline: none;
54
+ }
55
+ }
56
+ `;
57
+
58
+ const BurgerLine = styled.div<{ $isOpen: boolean; $burgerVariant: BorderColor }>`
59
+ width: 2rem;
60
+ height: 0.25rem;
61
+ background-color: ${props => colors.border[props.$burgerVariant]};
62
+ border-radius: 10px;
63
+ transition: all 0.3s linear;
64
+ position: relative;
65
+ transform-origin: 1px;
66
+
67
+ &:first-child {
68
+ transform: ${({ $isOpen }) => $isOpen ? 'rotate(45deg)' : 'rotate(0)'};
69
+ }
70
+
71
+ &:nth-child(2) {
72
+ opacity: ${({ $isOpen }) => $isOpen ? '0' : '1'};
73
+ transform: ${({ $isOpen }) => $isOpen ? 'translateX(20px)' : 'translateX(0)'};
74
+ }
75
+
76
+ &:nth-child(3) {
77
+ transform: ${({ $isOpen }) => $isOpen ? 'rotate(-45deg)' : 'rotate(0)'};
78
+ }
26
79
  `;
27
80
 
28
81
  interface HeaderProps {
@@ -31,6 +84,11 @@ interface HeaderProps {
31
84
  secondaryButtonText: string;
32
85
  onPrimaryClick?: () => void;
33
86
  onSecondaryClick?: () => void;
87
+ // Mobile menu props
88
+ isMobileMenuOpen?: boolean;
89
+ onMobileMenuToggle?: () => void;
90
+ burgerVariant?: BorderColor;
91
+ // Button variants
34
92
  primaryArrowVariant?: 'brand' | 'teal' | 'blue';
35
93
  primaryTextBgVariant?: 'primary' | 'secondary' | 'tertiary' | 'subtle' | 'blue' | 'brand' | 'light' | 'transparent';
36
94
  primaryTextVariant?: 'brand' | 'primary' | 'secondary' | 'tertiary' | 'subtle' | 'light' | 'error' | 'blue';
@@ -44,6 +102,9 @@ export const Header = ({
44
102
  secondaryButtonText,
45
103
  onPrimaryClick,
46
104
  onSecondaryClick,
105
+ isMobileMenuOpen = false,
106
+ onMobileMenuToggle,
107
+ burgerVariant = 'primary',
47
108
  primaryArrowVariant = 'blue',
48
109
  primaryTextBgVariant = 'brand',
49
110
  primaryTextVariant = 'secondary',
@@ -55,6 +116,8 @@ export const Header = ({
55
116
  <LogoWrapper>
56
117
  <img src={logo} alt="Logo" />
57
118
  </LogoWrapper>
119
+
120
+ {/* Desktop buttons - hidden on mobile */}
58
121
  <ButtonGroup>
59
122
  <ExtendedButton
60
123
  text={primaryButtonText}
@@ -71,6 +134,13 @@ export const Header = ({
71
134
  uppercase={true}
72
135
  />
73
136
  </ButtonGroup>
137
+
138
+ {/* Mobile burger - shown only on mobile */}
139
+ <BurgerButton onClick={onMobileMenuToggle} $burgerVariant={burgerVariant}>
140
+ <BurgerLine $isOpen={isMobileMenuOpen} $burgerVariant={burgerVariant} />
141
+ <BurgerLine $isOpen={isMobileMenuOpen} $burgerVariant={burgerVariant} />
142
+ <BurgerLine $isOpen={isMobileMenuOpen} $burgerVariant={burgerVariant} />
143
+ </BurgerButton>
74
144
  </HeaderContainer>
75
145
  );
76
146
  };
@@ -9,10 +9,9 @@ const AboutUsContainer = styled.section`
9
9
  grid-template-columns: 35% 65%;
10
10
  gap: 3rem;
11
11
  padding: 4rem 2rem;
12
- max-width: 1200px;
13
12
  margin: 0 auto;
14
13
  align-items: start;
15
- background-color: ${colors.background?.light || '#000'};
14
+ background-color: ${colors.background?.secondary || '#000'};
16
15
 
17
16
  @media (max-width: 768px) {
18
17
  grid-template-columns: 1fr;
@@ -38,6 +37,7 @@ const ContentWrapper = styled.div`
38
37
  flex-direction: column;
39
38
  gap: 1.5rem;
40
39
  align-items: flex-start;
40
+ padding: 1rem 4rem 1rem 1rem;
41
41
  `;
42
42
 
43
43
  interface AboutUsProps {
@@ -1,4 +1,3 @@
1
- import { ComponentProps } from 'react';
2
1
  import styled from 'styled-components';
3
2
  import { ExtendedButton, Header, TermsCheckbox } from '../../atoms';
4
3
  import { ContactForm } from '../../organism';
@@ -13,7 +12,12 @@ const ContactSection = styled.section`
13
12
  align-items: center;
14
13
  padding: 4rem 2rem;
15
14
  min-height: 100vh;
16
- background-color: ${colors.background?.light || '#f9fafb'};
15
+ background-color: ${colors.background?.secondary || '#f9fafb'};
16
+
17
+ /* Mobile adjustments */
18
+ @media (max-width: 767px) {
19
+ padding: 2rem 1rem;
20
+ }
17
21
  `;
18
22
 
19
23
  const ContentWrapper = styled.div`
@@ -41,8 +45,9 @@ const ImageWrapper = styled.div`
41
45
  display: block;
42
46
  }
43
47
 
44
- @media (max-width: 768px) {
45
- min-height: 400px;
48
+ /* Hide on mobile */
49
+ @media (max-width: 767px) {
50
+ display: none;
46
51
  }
47
52
  `;
48
53
 
@@ -52,6 +57,11 @@ const FormContainer = styled.div`
52
57
  gap: 2rem;
53
58
  padding: 4rem 3rem;
54
59
  background-color: #ffffff;
60
+
61
+ /* Mobile adjustments */
62
+ @media (max-width: 767px) {
63
+ padding: 2rem 1.5rem;
64
+ }
55
65
  `;
56
66
 
57
67
  const FormWrapper = styled.div`
@@ -63,6 +73,11 @@ const FormWrapper = styled.div`
63
73
  const ButtonWrapper = styled.div`
64
74
  display: flex;
65
75
  justify-content: flex-start;
76
+
77
+ /* Mobile: full width button */
78
+ @media (max-width: 767px) {
79
+ width: 100%;
80
+ }
66
81
  `;
67
82
 
68
83
  interface ContactProps {
@@ -76,7 +91,7 @@ interface ContactProps {
76
91
  termsVariant?: 'primary' | 'secondary' | 'subtle';
77
92
  buttonArrowVariant?: 'brand' | 'teal' | 'blue';
78
93
  buttonTextBgVariant?: 'primary' | 'secondary' | 'tertiary' | 'subtle' | 'blue' | 'brand' | 'light' | 'transparent';
79
- buttonTextVariant?: ComponentProps<typeof ExtendedButton>['textVariant'];
94
+ buttonTextVariant?: "brand" | "blue" | "primary" | "secondary" | "tertiary" | "subtle" | "light" ;
80
95
  }
81
96
 
82
97
  export const Contact = ({
@@ -90,7 +105,7 @@ export const Contact = ({
90
105
  termsVariant = 'primary',
91
106
  buttonArrowVariant = 'teal',
92
107
  buttonTextBgVariant = 'brand',
93
- buttonTextVariant = 'secondary',
108
+ buttonTextVariant = 'primary',
94
109
  }: ContactProps) => {
95
110
  return (
96
111
  <ContactSection>
@@ -24,7 +24,6 @@ const HeaderSection = styled.div`
24
24
  const AccordionList = styled.div`
25
25
  display: flex;
26
26
  flex-direction: column;
27
- max-width: 900px;
28
27
  width: 100%;
29
28
  `;
30
29
 
@@ -14,7 +14,12 @@ const FeaturesContainer = styled.section`
14
14
  gap: 2rem;
15
15
  padding: 4rem 2rem;
16
16
  min-height: 100vh;
17
- background-color: ${colors.background?.light || '#000'};
17
+ background-color: ${colors.background?.secondary || '#000'};
18
+ `;
19
+
20
+ const InnerWrapper = styled.div`
21
+ width: 100%;
22
+ margin: 0 auto;
18
23
  `;
19
24
 
20
25
  const HeaderWrapper = styled.div`
@@ -57,23 +62,26 @@ export const Features = ({
57
62
  }: FeaturesProps) => {
58
63
  return (
59
64
  <FeaturesContainer>
60
- <Pill variant={pillVariant} inverse={true}>
61
- {pillText}
62
- </Pill>
63
- <HeaderWrapper>
64
- <Header variant="h1" color={headerColor}>
65
- {headerText}
66
- </Header>
67
- </HeaderWrapper>
68
- <FeatureCarousel
69
- cards={cards}
70
- cardTitleColor={cardTitleColor}
71
- cardDescriptionVariant={cardDescriptionVariant}
72
- cardArrowVariant={cardArrowVariant}
73
- cardThumbnailBgColor={cardThumbnailBgColor}
74
- navButtonColor={navButtonColor}
75
- indicatorColor={indicatorColor}
76
- />
65
+ <InnerWrapper>
66
+
67
+ <Pill variant={pillVariant} inverse={true}>
68
+ {pillText}
69
+ </Pill>
70
+ <HeaderWrapper>
71
+ <Header variant="h1" color={headerColor}>
72
+ {headerText}
73
+ </Header>
74
+ </HeaderWrapper>
75
+ <FeatureCarousel
76
+ cards={cards}
77
+ cardTitleColor={cardTitleColor}
78
+ cardDescriptionVariant={cardDescriptionVariant}
79
+ cardArrowVariant={cardArrowVariant}
80
+ cardThumbnailBgColor={cardThumbnailBgColor}
81
+ navButtonColor={navButtonColor}
82
+ indicatorColor={indicatorColor}
83
+ />
84
+ </InnerWrapper>
77
85
  </FeaturesContainer>
78
86
  );
79
87
  };
@@ -29,27 +29,53 @@ const HeroContainer = styled.section<{ $bgImage?: string; $overlayColor?: string
29
29
  right: 0;
30
30
  bottom: 0;
31
31
  background-color: ${props => props.$overlayColor || 'rgba(30, 64, 175, 0.7)'};
32
- z-index: 1;
33
32
  }
34
33
 
35
- /* Mobile/Tablet: Single column, hide features */
34
+
35
+ /* Mobile/Tablet: Single column, features below CTA */
36
36
  @media (max-width: 1024px) {
37
37
  grid-template-columns: 1fr;
38
- padding: 2rem;
38
+ grid-template-rows: auto auto;
39
+ padding: 2rem 1rem;
40
+ gap: 3rem;
41
+ }
42
+
43
+ /* Very small mobile */
44
+ @media (max-width: 480px) {
45
+ padding: 1.5rem 1rem;
39
46
  }
40
47
  `;
41
48
 
42
49
  const Column = styled.div`
43
50
  position: relative;
44
- z-index: 2;
45
51
  display: flex;
46
52
  align-items: center;
53
+
54
+ /* Constrain text width on mobile */
55
+ @media (max-width: 1024px) {
56
+ max-width: 100%;
57
+ width: 100%;
58
+ }
47
59
  `;
48
60
 
49
61
  const FeaturesColumn = styled(Column)`
50
- /* Hide on mobile and tablet */
62
+ /* On desktop: normal column */
63
+ @media (min-width: 1025px) {
64
+ display: flex;
65
+ }
66
+
67
+ /* On mobile: show below CTA, order it second */
68
+ @media (max-width: 1024px) {
69
+ display: flex;
70
+ order: 2;
71
+ align-items: flex-start;
72
+ }
73
+ `;
74
+
75
+ const CTAColumn = styled(Column)`
76
+ /* Ensure CTA comes first on mobile */
51
77
  @media (max-width: 1024px) {
52
- display: none;
78
+ order: 1;
53
79
  }
54
80
  `;
55
81
 
@@ -107,7 +133,7 @@ export const Hero = ({
107
133
  }: HeroProps) => {
108
134
  return (
109
135
  <HeroContainer $bgImage={bgImage} $overlayColor={overlayColor}>
110
- <Column>
136
+ <CTAColumn>
111
137
  <CTAContainer
112
138
  header={ctaHeader}
113
139
  description={ctaDescription}
@@ -125,7 +151,7 @@ export const Hero = ({
125
151
  primaryTextBgVariant={primaryTextBgVariant}
126
152
  primaryTextVariant={primaryTextVariant}
127
153
  />
128
- </Column>
154
+ </CTAColumn>
129
155
  <FeaturesColumn>
130
156
  <FeatureContainer
131
157
  items={featureItems}
@@ -1,4 +1,3 @@
1
- import { ComponentProps } from 'react';
2
1
  import styled from 'styled-components';
3
2
  import { Header } from '../../atoms';
4
3
  import { ProductInfo } from '../../molecules';
@@ -13,19 +12,69 @@ const SectionContainer = styled.section`
13
12
  padding: 4rem 2rem;
14
13
  max-width: 1200px;
15
14
  margin: 0 auto;
15
+
16
+ /* Mobile adjustments */
17
+ @media (max-width: 767px) {
18
+ padding: 2rem 1rem;
19
+ }
16
20
  `;
17
21
 
18
22
  const SectionHeader = styled.div`
19
23
  padding-bottom: 2rem;
20
24
  border-bottom: 1px solid ${colors.text.light || '#d1d5db'};
25
+
26
+ /* Mobile: remove border, adjust padding */
27
+ @media (max-width: 767px) {
28
+ border-bottom: none;
29
+ padding-bottom: 1rem;
30
+ }
31
+ `;
32
+
33
+ const ProductsWrapper = styled.div`
34
+ /* Desktop: normal vertical stack */
35
+ @media (min-width: 768px) {
36
+ display: flex;
37
+ flex-direction: column;
38
+ }
39
+
40
+ /* Mobile: horizontal scroll carousel */
41
+ @media (max-width: 767px) {
42
+ display: flex;
43
+ overflow-x: auto;
44
+ scroll-snap-type: x mandatory;
45
+ gap: 1rem;
46
+ padding: 1rem 0;
47
+ -webkit-overflow-scrolling: touch;
48
+ scrollbar-width: none; /* Firefox */
49
+
50
+ &::-webkit-scrollbar {
51
+ display: none; /* Chrome, Safari */
52
+ }
53
+ }
21
54
  `;
22
55
 
23
56
  const ProductItem = styled.div`
24
- padding: 2rem 0;
25
- border-bottom: 1px solid ${colors.text.light || '#d1d5db'};
57
+ /* Desktop: vertical stack with borders */
58
+ @media (min-width: 768px) {
59
+ padding: 2rem 0;
60
+ border-bottom: 1px solid ${colors.text.light || '#d1d5db'};
26
61
 
27
- &:last-child {
28
- border-bottom: none;
62
+ &:last-child {
63
+ border-bottom: none;
64
+ }
65
+ }
66
+
67
+ /* Mobile: carousel item */
68
+ @media (max-width: 767px) {
69
+ flex: 0 0 80%; /* CHANGED from 85% - shows more of next card */
70
+ scroll-snap-align: center;
71
+ padding: 0;
72
+ border: none;
73
+ }
74
+
75
+ /* Very small mobile */
76
+ @media (max-width: 480px) {
77
+ flex: 0 0 85%; /* CHANGED from 90% */
29
78
  }
30
79
  `;
31
80
 
@@ -46,7 +95,7 @@ interface OtherProductsProps {
46
95
  productTitleColor?: ComponentTextColor;
47
96
  productButtonArrowVariant?: 'brand' | 'teal' | 'blue';
48
97
  productButtonTextBgVariant?: 'primary' | 'secondary' | 'tertiary' | 'subtle' | 'blue' | 'brand' | 'light' | 'transparent';
49
- productButtonTextVariant?: ComponentProps<typeof ProductInfo>['buttonTextVariant'];
98
+ productButtonTextVariant?: "brand" | "blue" | "primary" | "secondary" | "tertiary" | "subtle" | "light";
50
99
  }
51
100
 
52
101
  export const OtherProducts = ({
@@ -66,22 +115,24 @@ export const OtherProducts = ({
66
115
  {headerText}
67
116
  </Header>
68
117
  </SectionHeader>
69
- {products.map((product, index) => (
70
- <ProductItem key={index}>
71
- <ProductInfo
72
- image={product.image}
73
- logoImage={product.logoImage}
74
- title={product.title}
75
- buttonText={product.buttonText}
76
- onButtonClick={product.onButtonClick}
77
- titleVariant={product.titleVariant}
78
- titleColor={productTitleColor}
79
- buttonArrowVariant={productButtonArrowVariant}
80
- buttonTextBgVariant={productButtonTextBgVariant}
81
- buttonTextVariant={productButtonTextVariant}
82
- />
83
- </ProductItem>
84
- ))}
118
+ <ProductsWrapper>
119
+ {products.map((product, index) => (
120
+ <ProductItem key={index}>
121
+ <ProductInfo
122
+ image={product.image}
123
+ logoImage={product.logoImage}
124
+ title={product.title}
125
+ buttonText={product.buttonText}
126
+ onButtonClick={product.onButtonClick}
127
+ titleVariant={product.titleVariant}
128
+ titleColor={productTitleColor}
129
+ buttonArrowVariant={productButtonArrowVariant}
130
+ buttonTextBgVariant={productButtonTextBgVariant}
131
+ buttonTextVariant={productButtonTextVariant}
132
+ />
133
+ </ProductItem>
134
+ ))}
135
+ </ProductsWrapper>
85
136
  </SectionContainer>
86
137
  );
87
138
  };
@@ -39,6 +39,7 @@ export const colors: Record<Token, Partial<TokenVariant>> = {
39
39
  error: '#F87171',
40
40
  focus: '#3B82F6',
41
41
  brand: '#1D3C77',
42
+ light: '#f3f3f3',
42
43
  },
43
44
  text: {
44
45
  brand: '#1D3C77',