@orangesk/orange-design-system 2.0.0-beta.2 → 2.0.0-beta.3

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 (90) hide show
  1. package/build/components/Accordion/tsconfig.tsbuildinfo +1 -1
  2. package/build/components/Alert/tsconfig.tsbuildinfo +1 -1
  3. package/build/components/AnchorNavigation/tsconfig.tsbuildinfo +1 -1
  4. package/build/components/Bar/tsconfig.tsbuildinfo +1 -1
  5. package/build/components/BlockAction/tsconfig.tsbuildinfo +1 -1
  6. package/build/components/BodyBanner/tsconfig.tsbuildinfo +1 -1
  7. package/build/components/Breadcrumbs/tsconfig.tsbuildinfo +1 -1
  8. package/build/components/Button/tsconfig.tsbuildinfo +1 -1
  9. package/build/components/Buttons/tsconfig.tsbuildinfo +1 -1
  10. package/build/components/Card/tsconfig.tsbuildinfo +1 -1
  11. package/build/components/Carousel/tsconfig.tsbuildinfo +1 -1
  12. package/build/components/CarouselPromotions/tsconfig.tsbuildinfo +1 -1
  13. package/build/components/CartTable/tsconfig.tsbuildinfo +1 -1
  14. package/build/components/Code/tsconfig.tsbuildinfo +1 -1
  15. package/build/components/Container/tsconfig.tsbuildinfo +1 -1
  16. package/build/components/Controls/tsconfig.tsbuildinfo +1 -1
  17. package/build/components/Cover/tsconfig.tsbuildinfo +1 -1
  18. package/build/components/Divider/tsconfig.tsbuildinfo +1 -1
  19. package/build/components/DocumentationSidebar/index.js +1 -1
  20. package/build/components/DocumentationSidebar/tsconfig.tsbuildinfo +1 -1
  21. package/build/components/Dropdown/tsconfig.tsbuildinfo +1 -1
  22. package/build/components/Expander/tsconfig.tsbuildinfo +1 -1
  23. package/build/components/FeatureAccordion/tsconfig.tsbuildinfo +1 -1
  24. package/build/components/Footer/index.js +3 -3
  25. package/build/components/Footer/index.js.map +1 -1
  26. package/build/components/Footer/tsconfig.tsbuildinfo +1 -1
  27. package/build/components/Forms/tsconfig.tsbuildinfo +1 -1
  28. package/build/components/Gauge/tsconfig.tsbuildinfo +1 -1
  29. package/build/components/Grid/tsconfig.tsbuildinfo +1 -1
  30. package/build/components/Hero/tsconfig.tsbuildinfo +1 -1
  31. package/build/components/Icon/tsconfig.tsbuildinfo +1 -1
  32. package/build/components/IconList/tsconfig.tsbuildinfo +1 -1
  33. package/build/components/Image/tsconfig.tsbuildinfo +1 -1
  34. package/build/components/Link/tsconfig.tsbuildinfo +1 -1
  35. package/build/components/List/tsconfig.tsbuildinfo +1 -1
  36. package/build/components/Loader/tsconfig.tsbuildinfo +1 -1
  37. package/build/components/Megamenu/tsconfig.tsbuildinfo +1 -1
  38. package/build/components/Modal/tsconfig.tsbuildinfo +1 -1
  39. package/build/components/Pagination/tsconfig.tsbuildinfo +1 -1
  40. package/build/components/Pill/tsconfig.tsbuildinfo +1 -1
  41. package/build/components/Preview/index.js +1 -1
  42. package/build/components/Preview/index.js.map +1 -1
  43. package/build/components/Preview/tsconfig.tsbuildinfo +1 -1
  44. package/build/components/Progress/tsconfig.tsbuildinfo +1 -1
  45. package/build/components/PromoBanner/tsconfig.tsbuildinfo +1 -1
  46. package/build/components/PromotionCard/tsconfig.tsbuildinfo +1 -1
  47. package/build/components/Section/tsconfig.tsbuildinfo +1 -1
  48. package/build/components/Skeleton/tsconfig.tsbuildinfo +1 -1
  49. package/build/components/SkipLink/tsconfig.tsbuildinfo +1 -1
  50. package/build/components/Stepbar/tsconfig.tsbuildinfo +1 -1
  51. package/build/components/Sticker/tsconfig.tsbuildinfo +1 -1
  52. package/build/components/Table/tsconfig.tsbuildinfo +1 -1
  53. package/build/components/Tabs/tsconfig.tsbuildinfo +1 -1
  54. package/build/components/Tag/tsconfig.tsbuildinfo +1 -1
  55. package/build/components/Testimonial/tsconfig.tsbuildinfo +1 -1
  56. package/build/components/Tile/tsconfig.tsbuildinfo +1 -1
  57. package/build/components/Tooltip/tsconfig.tsbuildinfo +1 -1
  58. package/build/components/index.css +1 -1
  59. package/build/components/index.css.map +1 -1
  60. package/build/components/index.js +6 -6
  61. package/build/components/index.js.map +1 -1
  62. package/build/components/tsconfig.tsbuildinfo +1 -1
  63. package/build/components/types/src/components/Footer/Footer.d.ts +1 -5
  64. package/build/components/types/src/components/Footer/constants.d.ts +9 -0
  65. package/build/components/types/src/components/index.d.ts +1 -2
  66. package/build/lib/after-components.css +1 -1
  67. package/build/lib/after-components.css.map +1 -1
  68. package/build/lib/before-components.css +1 -1
  69. package/build/lib/before-components.css.map +1 -1
  70. package/build/lib/components.css +1 -1
  71. package/build/lib/components.css.map +1 -1
  72. package/build/lib/footer.css +2 -0
  73. package/build/lib/footer.css.map +1 -0
  74. package/build/lib/style.css +1 -1
  75. package/build/lib/style.css.map +1 -1
  76. package/package.json +4 -2
  77. package/src/components/Footer/Footer.tsx +86 -70
  78. package/src/components/Footer/constants.ts +10 -0
  79. package/src/components/Footer/styles/config.scss +1 -0
  80. package/src/components/Footer/styles/mixins.scss +172 -0
  81. package/src/components/Footer/styles/style.scss +48 -0
  82. package/src/components/Footer/tests/Footer.conformance.test.js +133 -8
  83. package/src/components/Footer/tests/Footer.unit.test.js +71 -6
  84. package/src/components/Link/styles/style.scss +1 -0
  85. package/src/components/Preview/PreviewGenerator.tsx +2 -10
  86. package/src/components/index.ts +0 -2
  87. package/src/styles/shame.scss +1 -0
  88. package/src/styles/typography/mixins.scss +2 -0
  89. package/build/components/Footer/style.css +0 -2
  90. package/build/components/Footer/style.css.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orangesk/orange-design-system",
3
- "version": "2.0.0-beta.2",
3
+ "version": "2.0.0-beta.3",
4
4
  "private": false,
5
5
  "engines": {
6
6
  "node": ">=18.x"
@@ -16,9 +16,11 @@
16
16
  "scripts": {
17
17
  "dev": "npm run build:scss-exports && next dev",
18
18
  "build": "npm run build:scss-exports && next build && npm run sprite",
19
- "build:bundle": "npm run build:scss-exports && npx rollup -c && npm run build:megamenu",
19
+ "build:bundle": "npm run build:scss-exports && npx rollup -c && npm run build:megamenu && npm run build:footer",
20
20
  "build:megamenu": "npm run build:scss-exports && npx rollup -c rollup.megamenu.config.mjs",
21
21
  "dev:megamenu": "npm run build:scss-exports && npx rollup -c rollup.megamenu.config.mjs --watch",
22
+ "build:footer": "npm run build:scss-exports && npx rollup -c rollup.footer.config.mjs",
23
+ "dev:footer": "npm run build:scss-exports && npx rollup -c rollup.footer.config.mjs --watch",
22
24
  "build:scss-exports": "node scripts/build-scss-exports.js",
23
25
  "start": "next start",
24
26
  "lint": "next lint",
@@ -1,90 +1,106 @@
1
1
  import React from "react";
2
2
  import cx from "classnames";
3
3
 
4
- import { Section } from "../Section";
5
- import { SectionProps } from "../Section/Section";
6
- import { Image } from "../Image";
7
- import { Grid, GridCol } from "../Grid";
8
- import { Link } from "../Link";
9
4
  import footerData from "./data";
10
- import { Bar, BarItem } from "../Bar";
5
+ import {
6
+ CLASS_BOTTOM,
7
+ CLASS_BOTTOM_COPYRIGHT,
8
+ CLASS_CONTAINER,
9
+ CLASS_GRID,
10
+ CLASS_LIST,
11
+ CLASS_LIST_INLINE,
12
+ CLASS_LOGO,
13
+ CLASS_ROOT,
14
+ CLASS_TITLE,
15
+ } from "./constants";
11
16
 
12
17
  interface FooterProps extends React.HTMLAttributes<HTMLDivElement> {
13
- /** Sets Footer to use inverse color scheme */
14
- isInverse?: boolean;
15
- /** Custom data to override default footer data */
16
18
  data?: typeof footerData;
17
19
  className?: string;
18
20
  }
19
21
 
20
- const CLASS_ROOT = "footer";
21
-
22
- const Footer: React.FC<FooterProps & SectionProps> = ({
23
- className,
24
- isInverse,
25
- data = footerData,
26
- ...other
27
- }) => {
28
- const classes = cx(
29
- CLASS_ROOT,
30
- {
31
- [`${CLASS_ROOT}--inverse`]: isInverse,
32
- },
33
- className,
34
- );
35
-
22
+ const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
36
23
  return (
37
- <Section tag="footer" className={classes} {...other}>
38
- <Image src="/logo.svg" alt="logo" className="mb-xlarge" />
39
- <Grid rowGapSize="medium">
40
- {data.columns.map((column, index) => (
41
- <GridCol
42
- size={{
43
- lg: 3,
44
- md: 4,
45
- sm: 6,
46
- xs: 12,
47
- }}
48
- key={`footer-column-${index}`}
24
+ <footer className={cx(CLASS_ROOT, className)}>
25
+ <div className={CLASS_CONTAINER}>
26
+ <a href="/" aria-label="Odkaz na úvodnú stránku" className={CLASS_LOGO}>
27
+ <svg
28
+ width="48"
29
+ height="48"
30
+ viewBox="0 0 48 48"
31
+ fill="none"
32
+ xmlns="http://www.w3.org/2000/svg"
49
33
  >
50
- <h5 className="mb-large">{column.title}</h5>
51
- <ul className="list-unstyled">
52
- {column.links.map((link, linkIndex) => (
53
- <li
54
- className="mb-small"
55
- key={`footer-link-${index}-${linkIndex}`}
56
- >
57
- <Link className={`${CLASS_ROOT}__link`} href={link.url}>
58
- {link.label}
59
- </Link>
60
- </li>
61
- ))}
62
- </ul>
63
- </GridCol>
64
- ))}
65
- </Grid>
34
+ <path d="M48 0H0V48H48V0Z" fill="black" />
35
+ <path
36
+ fillRule="evenodd"
37
+ clipRule="evenodd"
38
+ d="M48 48H0V0H48V48Z"
39
+ fill="#FF7900"
40
+ />
41
+ <path
42
+ d="M5.9078 44.1298C4.1702 44.1298 2.60156 43.0229 2.60156 40.6047C2.60156 38.1855 4.16924 37.0796 5.9078 37.0796C7.6454 37.0796 9.21116 38.1865 9.21116 40.6047C9.21116 43.0229 7.64636 44.1298 5.9078 44.1298ZM5.9078 38.5657C4.59356 38.5657 4.35356 39.7494 4.35356 40.6047C4.35356 41.4591 4.59356 42.6457 5.9078 42.6457C7.22204 42.6457 7.46204 41.4601 7.46204 40.6047C7.46204 39.7503 7.22204 38.5657 5.9078 38.5657Z"
43
+ fill="white"
44
+ />
45
+ <path
46
+ fillRule="evenodd"
47
+ clipRule="evenodd"
48
+ d="M10.418 37.2559H12.0912V38.0412C12.41 37.6179 13.1952 37.1196 13.9316 37.1196C14.0016 37.1196 14.088 37.1196 14.16 37.1283V38.7795H14.0736C13.3095 38.7795 12.4733 38.8985 12.2026 39.4927V43.9356H10.418V37.2559Z"
49
+ fill="white"
50
+ />
51
+ <path
52
+ d="M18.831 43.3547C18.1777 43.7913 17.4087 44.0223 16.623 44.0181C15.375 44.0181 14.6367 43.1887 14.6367 42.0751C14.6367 40.5794 16.0114 39.7903 18.8444 39.4706V39.0981C18.8444 38.6133 18.4767 38.3291 17.7961 38.3291C17.1164 38.3291 16.5634 38.5989 16.165 39.0971L14.9794 38.4223C15.6015 37.5506 16.55 37.1147 17.8239 37.1147C19.5673 37.1147 20.5455 37.8703 20.5455 39.0981C20.5455 39.0981 20.5436 43.9269 20.5455 43.9394H18.9865L18.831 43.3547ZM16.3686 41.9474C16.3686 42.3967 16.6498 42.8162 17.1606 42.8162C17.7126 42.8162 18.2511 42.5877 18.7887 42.1125V40.5304C17.1471 40.733 16.3686 41.1573 16.3686 41.9474Z"
53
+ fill="white"
54
+ />
55
+ <path
56
+ fillRule="evenodd"
57
+ clipRule="evenodd"
58
+ d="M21.9336 37.4342L23.3899 37.2336L23.5512 38.0256C24.371 37.4246 25.0229 37.1059 25.8437 37.1059C27.2184 37.1059 27.9288 37.8355 27.9288 39.2793V43.9296H26.1691V39.5846C26.1691 38.7667 25.9579 38.399 25.3214 38.399C24.7973 38.399 24.2731 38.6361 23.6741 39.1392V43.9296H21.9336V37.4342Z"
59
+ fill="white"
60
+ />
61
+ <path
62
+ d="M32.2317 42.5003C33.5642 42.4907 33.6784 41.1323 33.6784 40.2491C33.6784 39.2008 33.1677 38.355 32.2192 38.355C31.5885 38.355 30.8819 38.8158 30.8819 40.3221C30.8819 41.1438 30.9405 42.5118 32.2317 42.5003ZM35.3671 37.2328V43.5582C35.3671 44.6718 35.2787 46.515 32.0983 46.5314C30.785 46.541 29.5658 46.013 29.3239 44.8677L31.0567 44.5874C31.1296 44.9166 31.3322 45.2421 32.3152 45.2421C33.2263 45.2421 33.664 44.8072 33.664 43.7637V42.9851L33.641 42.9611C33.3616 43.4622 32.9373 43.9355 31.9168 43.9355C30.3578 43.9355 29.1328 42.8546 29.1328 40.5966C29.1328 38.3627 30.3981 37.1118 31.817 37.109C33.1514 37.107 33.6429 37.7147 33.76 38.0334L33.736 38.0315L33.8829 37.2328H35.3671ZM39.5709 44.0584C37.6029 44.0584 36.4279 42.7912 36.4279 40.5928C36.4279 38.3704 37.6163 37.1051 39.5431 37.1051C41.4698 37.1051 42.616 38.3339 42.616 40.5045C42.616 40.6216 42.6016 40.7349 42.6016 40.8501H38.1539C38.1664 42.1173 38.6925 42.7557 39.7274 42.7557C40.3907 42.7557 40.8314 42.4869 41.2442 41.9003L42.5306 42.6136C41.9642 43.5611 40.9427 44.0584 39.5709 44.0584ZM40.8899 39.7096C40.8899 38.8178 40.3773 38.2917 39.5431 38.2917C38.7482 38.2917 38.2519 38.8062 38.1827 39.7106L40.8899 39.7096ZM45.6256 34.7214L44.9776 36.3966L44.3191 34.7214H43.7546V36.9294H44.1203V35.0872H44.1299L44.8547 36.9304H45.088L45.808 35.0872H45.8195V36.9304H46.1824V34.7224L45.6256 34.7214ZM41.56 34.7214V35.0152H42.2503V36.9304H42.6151V35.0152H43.3072V34.7214H41.56Z"
63
+ fill="white"
64
+ />
65
+ </svg>
66
+ </a>
67
+
68
+ <div className={CLASS_GRID}>
69
+ {data.columns.map((column, index) => (
70
+ <div key={`footer-column-${index}`}>
71
+ <h5 className={CLASS_TITLE}>{column.title}</h5>
72
+ <ul className={CLASS_LIST}>
73
+ {column.links.map((link, linkIndex) => (
74
+ <li
75
+ className="mb-small"
76
+ key={`footer-link-${index}-${linkIndex}`}
77
+ >
78
+ <a href={link.url}>{link.label}</a>
79
+ </li>
80
+ ))}
81
+ </ul>
82
+ </div>
83
+ ))}
84
+ </div>
66
85
 
67
- <hr />
68
- {/* TODO - socky siete */}
69
- <p className="small">Sledujte nás</p>
86
+ <hr />
87
+ {/* TODO - socky siete */}
88
+ <p>Sledujte nás</p>
70
89
 
71
- <hr />
90
+ <hr />
72
91
 
73
- <Grid className="align-items-end" rowGapSize="xlarge">
74
- <GridCol size={{ xs: 12, md: 9 }}>
75
- <Bar className="mb-none" space="small">
92
+ <div className={CLASS_BOTTOM}>
93
+ <ul className={cx(CLASS_LIST, CLASS_LIST_INLINE)}>
76
94
  {data.bottomLinks?.map((link, index) => (
77
- <BarItem key={`footer-bottom-link-${index}`}>
78
- <Link href={link.url} isNormal>
79
- {link.label}
80
- </Link>
81
- </BarItem>
95
+ <li className="mr-small" key={`footer-legal-link-${index}`}>
96
+ <a href={link.url}>{link.label}</a>
97
+ </li>
82
98
  ))}
83
- </Bar>
84
- </GridCol>
85
- <GridCol size={{ xs: 12, md: 3 }}>{data.copyright}</GridCol>
86
- </Grid>
87
- </Section>
99
+ </ul>
100
+ <span className={CLASS_BOTTOM_COPYRIGHT}>{data.copyright}</span>
101
+ </div>
102
+ </div>
103
+ </footer>
88
104
  );
89
105
  };
90
106
 
@@ -0,0 +1,10 @@
1
+ export const CLASS_ROOT = "footer";
2
+
3
+ export const CLASS_CONTAINER = `${CLASS_ROOT}__container`;
4
+ export const CLASS_GRID = `${CLASS_ROOT}__grid`;
5
+ export const CLASS_LOGO = `${CLASS_ROOT}__logo`;
6
+ export const CLASS_TITLE = `${CLASS_ROOT}__title`;
7
+ export const CLASS_LIST = `${CLASS_ROOT}__list`;
8
+ export const CLASS_LIST_INLINE = `${CLASS_ROOT}__list--inline`;
9
+ export const CLASS_BOTTOM = `${CLASS_ROOT}__bottom`;
10
+ export const CLASS_BOTTOM_COPYRIGHT = `${CLASS_ROOT}__bottom-copyright`;
@@ -0,0 +1 @@
1
+ $class-root: ".footer" !default;
@@ -0,0 +1,172 @@
1
+ @use "sass:map";
2
+ @use "../../../styles/tools/convert";
3
+ @use "../../../styles/tokens/color";
4
+ @use "../../../styles/tokens/base";
5
+ @use "../../../styles/tokens/breakpoint";
6
+ @use "../../../styles/tools/generate";
7
+ @use "../../../styles/tools/visibility" as visibility;
8
+ @use "../../Container/styles/mixins" as container;
9
+ @use "../../../styles/typography/mixins" as typography;
10
+ @use "../../../styles/typography/config" as typographyConfig;
11
+
12
+ @mixin globals {
13
+ .sr-only {
14
+ @include visibility.visually-hidden;
15
+ }
16
+
17
+ a {
18
+ color: var(--color-text-default);
19
+ text-decoration: none;
20
+ font-size: inherit;
21
+
22
+ &:hover,
23
+ &:focus,
24
+ &:active {
25
+ text-decoration: underline;
26
+ text-underline-offset: convert.to-rem(4px);
27
+ }
28
+
29
+ &:focus-visible {
30
+ outline: 2px solid var(--color-border-accent);
31
+ outline-offset: 2px;
32
+ }
33
+ }
34
+
35
+ a[href],
36
+ area[href],
37
+ input,
38
+ select,
39
+ textarea,
40
+ button,
41
+ [type="button"],
42
+ iframe,
43
+ [tabindex]:not([tabindex="-1"]),
44
+ [contentEditable="true"] {
45
+ @include base.focusring;
46
+ }
47
+
48
+ * {
49
+ box-sizing: border-box;
50
+ letter-spacing: convert.to-rem(-0.1px);
51
+ line-height: convert.to-rem(18px);
52
+ }
53
+
54
+ ::selection {
55
+ background-color: base.$selection-background;
56
+ color: base.$text-color;
57
+ }
58
+
59
+ hr {
60
+ margin-top: convert.to-rem(30px);
61
+ margin-bottom: convert.to-rem(30px);
62
+ border: 0;
63
+ border-top: 1px solid var(--color-border-subtle);
64
+ }
65
+
66
+ p,
67
+ ul {
68
+ font-size: convert.to-rem(14px);
69
+ line-height: convert.to-rem(17.5px);
70
+ }
71
+ }
72
+
73
+ @mixin base {
74
+ font-size: 1rem;
75
+ color: var(--color-text-default);
76
+ background-color: var(--color-surface-primary);
77
+ box-sizing: border-box;
78
+ font-family: #{base.$font-family};
79
+ padding: convert.to-rem(60px) 0;
80
+
81
+ @include breakpoint.get("md", "down") {
82
+ padding: convert.to-rem(30px) 0;
83
+ }
84
+ }
85
+
86
+ @mixin container {
87
+ @include container.base;
88
+
89
+ margin-top: 0;
90
+ margin-bottom: 0;
91
+ }
92
+
93
+ @mixin grid {
94
+ display: grid;
95
+ gap: convert.to-rem(30px);
96
+ row-gap: convert.to-rem(40px);
97
+ grid-template-columns: repeat(1, 1fr);
98
+
99
+ @include breakpoint.get("sm") {
100
+ grid-template-columns: repeat(2, 1fr);
101
+ }
102
+
103
+ @include breakpoint.get("md") {
104
+ grid-template-columns: repeat(3, 1fr);
105
+ gap: convert.to-rem(15px);
106
+ row-gap: convert.to-rem(20px);
107
+ }
108
+
109
+ @include breakpoint.get("lg") {
110
+ grid-template-columns: repeat(4, 1fr);
111
+ gap: convert.to-rem(30px);
112
+ row-gap: convert.to-rem(40px);
113
+ }
114
+ }
115
+
116
+ @mixin logo {
117
+ display: inline-flex;
118
+ margin-bottom: convert.to-rem(60px);
119
+
120
+ @include breakpoint.get("md", "down") {
121
+ margin-bottom: convert.to-rem(30px);
122
+ }
123
+ }
124
+
125
+ @mixin title {
126
+ @include generate.responsive-css-map(map.get(typographyConfig.$headings, 5));
127
+ margin-top: 0;
128
+ margin-bottom: convert.to-rem(30px);
129
+ color: var(--color-text-default);
130
+
131
+ @include breakpoint.get("md", "down") {
132
+ margin-bottom: convert.to-rem(25px);
133
+ }
134
+ }
135
+
136
+ @mixin list {
137
+ @include typography.list-unstyled;
138
+
139
+ li {
140
+ margin-bottom: convert.to-rem(10px);
141
+ }
142
+ }
143
+
144
+ @mixin list-inline {
145
+ display: flex;
146
+ flex-wrap: wrap;
147
+ gap: convert.to-rem(10px);
148
+
149
+ li {
150
+ margin: 0;
151
+ }
152
+ }
153
+
154
+ @mixin bottom {
155
+ display: grid;
156
+ gap: convert.to-rem(30px);
157
+ row-gap: convert.to-rem(40px);
158
+ grid-template-columns: repeat(1, 1fr);
159
+ align-items: end;
160
+
161
+ @include breakpoint.get("md") {
162
+ grid-template-columns: 3fr 1fr;
163
+ }
164
+ }
165
+
166
+ @mixin bottom-copyright {
167
+ text-align: right;
168
+
169
+ @include breakpoint.get("md", "down") {
170
+ text-align: inherit;
171
+ }
172
+ }
@@ -0,0 +1,48 @@
1
+ @use "./config";
2
+ @use "./mixins";
3
+ @use "../../Megamenu/styles/mixins" as megamenuMixins;
4
+
5
+ #{config.$class-root} {
6
+ @include mixins.globals;
7
+ }
8
+
9
+ #{config.$class-root},
10
+ #{config.$class-root}.is-light {
11
+ @include megamenuMixins.light-vars;
12
+ }
13
+
14
+ #{config.$class-root}.is-dark {
15
+ @include megamenuMixins.dark-vars;
16
+ }
17
+
18
+ #{config.$class-root} {
19
+ @include mixins.base;
20
+
21
+ &__container {
22
+ @include mixins.container;
23
+ }
24
+
25
+ &__grid {
26
+ @include mixins.grid;
27
+ }
28
+
29
+ &__logo {
30
+ @include mixins.logo;
31
+ }
32
+
33
+ &__title {
34
+ @include mixins.title;
35
+ }
36
+
37
+ &__list {
38
+ @include mixins.list;
39
+
40
+ &--inline {
41
+ @include mixins.list-inline;
42
+ }
43
+ }
44
+
45
+ &__bottom {
46
+ @include mixins.bottom;
47
+ }
48
+ }
@@ -1,13 +1,138 @@
1
+ /**
2
+ * Conformance tests for the Footer component
3
+ *
4
+ * Covered use cases:
5
+ * 1. HTML Validity:
6
+ * - Validates HTML structure compliance with default props
7
+ * - Tests with custom data to ensure flexibility
8
+ * - Tests with custom className
9
+ * 2. Accessibility (a11y):
10
+ * - Tests with default props for comprehensive accessibility validation
11
+ * - Tests logo accessibility with aria-label
12
+ * - Tests navigation structure and semantic HTML
13
+ * - Uses axe-core for comprehensive accessibility validation
14
+ * 3. Semantic HTML:
15
+ * - Verifies correct HTML element rendering (footer, nav, headings)
16
+ * - Tests proper heading hierarchy (h5 for section titles)
17
+ * - Tests landmark roles (contentinfo for footer)
18
+ * 4. Theme Support:
19
+ * - Tests light theme context
20
+ * - Tests dark theme context
21
+ */
1
22
  import { render } from "@testing-library/react";
2
- import { axe } from "jest-axe";
23
+ import { axe, toHaveNoViolations } from "jest-axe";
24
+ import "jest-axe/extend-expect";
25
+
3
26
  import { Footer } from "../Footer";
4
27
 
5
- it("is valid html", () => {
6
- const { container } = render(<Footer />);
7
- expect(container).toHTMLValidate();
8
- });
28
+ // Extension of expect for axe
29
+ expect.extend(toHaveNoViolations);
30
+
31
+ describe("Footer Conformance Tests", () => {
32
+ describe("HTML Validity", () => {
33
+ it("is valid html with default props", () => {
34
+ const { container } = render(<Footer />);
35
+ expect(container).toHTMLValidate();
36
+ });
37
+
38
+ it("is valid html with custom data", () => {
39
+ const customData = {
40
+ columns: [
41
+ {
42
+ title: "Test Column",
43
+ links: [
44
+ { label: "Test Link 1", url: "/test1" },
45
+ { label: "Test Link 2", url: "/test2" },
46
+ ],
47
+ },
48
+ ],
49
+ bottomLinks: [
50
+ { label: "Privacy", url: "/privacy" },
51
+ { label: "Terms", url: "/terms" },
52
+ ],
53
+ copyright: "© 2024 Test Company",
54
+ };
55
+ const { container } = render(<Footer data={customData} />);
56
+ expect(container).toHTMLValidate();
57
+ });
58
+
59
+ it("is valid html with custom className", () => {
60
+ const { container } = render(<Footer className="custom-footer-class" />);
61
+ expect(container).toHTMLValidate();
62
+ });
63
+ });
64
+
65
+ describe("Accessibility", () => {
66
+ it("is accessible with default props", async () => {
67
+ const { container } = render(<Footer />);
68
+ expect(await axe(container)).toHaveNoViolations();
69
+ });
70
+
71
+ it("is accessible with custom data", async () => {
72
+ const customData = {
73
+ columns: [
74
+ {
75
+ title: "Accessibility Test",
76
+ links: [
77
+ { label: "Link with Special Chars & Symbols", url: "/test" },
78
+ { label: "Another Link", url: "/another" },
79
+ ],
80
+ },
81
+ ],
82
+ bottomLinks: [{ label: "Legal Info", url: "/legal" }],
83
+ copyright: "© 2024 Accessible Company",
84
+ };
85
+ const { container } = render(<Footer data={customData} />);
86
+ expect(await axe(container)).toHaveNoViolations();
87
+ });
88
+
89
+ it("is accessible in light theme context", async () => {
90
+ const { container } = render(
91
+ <div className="is-light">
92
+ <Footer />
93
+ </div>,
94
+ );
95
+ expect(await axe(container)).toHaveNoViolations();
96
+ });
97
+
98
+ it("is accessible in dark theme context", async () => {
99
+ const { container } = render(
100
+ <div className="is-dark">
101
+ <Footer />
102
+ </div>,
103
+ );
104
+ expect(await axe(container)).toHaveNoViolations();
105
+ });
106
+ });
107
+
108
+ describe("Semantic HTML", () => {
109
+ it("uses proper semantic elements", () => {
110
+ const { getByRole, getAllByRole } = render(<Footer />);
111
+
112
+ // Footer should be a landmark
113
+ expect(getByRole("contentinfo")).toBeInTheDocument();
114
+
115
+ // Should have proper heading structure
116
+ const headings = getAllByRole("heading", { level: 5 });
117
+ expect(headings.length).toBe(4); // One for each column
118
+
119
+ // Should have navigation lists
120
+ const lists = getAllByRole("list");
121
+ expect(lists.length).toBeGreaterThanOrEqual(4); // At least 4 column lists
122
+ });
123
+
124
+ it("has proper link structure", () => {
125
+ const { getAllByRole } = render(<Footer />);
126
+
127
+ // Should have multiple links
128
+ const links = getAllByRole("link");
129
+ expect(links.length).toBeGreaterThan(20); // Many navigation links
9
130
 
10
- it("is accessible", async () => {
11
- const { container } = render(<Footer />);
12
- expect(await axe(container)).toHaveNoViolations();
131
+ // Logo link should exist
132
+ const logoLink = links.find(
133
+ (link) => link.getAttribute("aria-label") === "Odkaz na úvodnú stránku",
134
+ );
135
+ expect(logoLink).toBeInTheDocument();
136
+ });
137
+ });
13
138
  });
@@ -9,9 +9,9 @@ describe("Footer", () => {
9
9
  expect(getByRole("contentinfo")).toBeInTheDocument();
10
10
  });
11
11
 
12
- it("renders logo image", () => {
13
- const { getByAltText } = render(<Footer />);
14
- expect(getByAltText("logo")).toBeInTheDocument();
12
+ it("renders logo with aria-label", () => {
13
+ const { getByLabelText } = render(<Footer />);
14
+ expect(getByLabelText("Odkaz na úvodnú stránku")).toBeInTheDocument();
15
15
  });
16
16
 
17
17
  it("renders all columns and links", () => {
@@ -36,9 +36,14 @@ describe("Footer", () => {
36
36
  expect(getByText(footerData.copyright)).toBeInTheDocument();
37
37
  });
38
38
 
39
- it("applies inverse class when isInverse is true", () => {
40
- const { container } = render(<Footer isInverse />);
41
- expect(container.querySelector(".footer--inverse")).toBeInTheDocument();
39
+ it("applies is-dark class when container has dark theme", () => {
40
+ const { container } = render(
41
+ <div className="is-dark">
42
+ <Footer />
43
+ </div>,
44
+ );
45
+ expect(container.querySelector(".footer")).toBeInTheDocument();
46
+ expect(container.querySelector(".is-dark")).toBeInTheDocument();
42
47
  });
43
48
 
44
49
  it("accepts custom className", () => {
@@ -63,4 +68,64 @@ describe("Footer", () => {
63
68
  expect(getByText("Bottom")).toBeInTheDocument();
64
69
  expect(getByText("Custom Copyright")).toBeInTheDocument();
65
70
  });
71
+
72
+ it("renders proper HTML structure", () => {
73
+ const { container } = render(<Footer />);
74
+ const footer = container.querySelector("footer");
75
+ const container_ = footer?.querySelector(".footer__container");
76
+ const grid = container_?.querySelector(".footer__grid");
77
+ const bottom = container_?.querySelector(".footer__bottom");
78
+
79
+ expect(footer).toBeInTheDocument();
80
+ expect(container_).toBeInTheDocument();
81
+ expect(grid).toBeInTheDocument();
82
+ expect(bottom).toBeInTheDocument();
83
+ });
84
+
85
+ it("renders logo with correct href", () => {
86
+ const { container } = render(<Footer />);
87
+ const logoLink = container.querySelector(".footer__logo");
88
+ expect(logoLink).toBeInTheDocument();
89
+ expect(logoLink).toHaveAttribute("href", "/");
90
+ });
91
+
92
+ it("renders all links with correct hrefs", () => {
93
+ const { container } = render(<Footer />);
94
+ const firstColumnFirstLink = container.querySelector(
95
+ 'a[href="/eshop/telefony"]',
96
+ );
97
+ expect(firstColumnFirstLink).toBeInTheDocument();
98
+ });
99
+
100
+ it("renders copyright with current year", () => {
101
+ const { getByText } = render(<Footer />);
102
+ const currentYear = new Date().getFullYear();
103
+ expect(getByText(`© 1997 - ${currentYear} Orange`)).toBeInTheDocument();
104
+ });
105
+
106
+ it("renders follow us section", () => {
107
+ const { getByText } = render(<Footer />);
108
+ expect(getByText("Sledujte nás")).toBeInTheDocument();
109
+ });
110
+
111
+ it("renders horizontal separators", () => {
112
+ const { container } = render(<Footer />);
113
+ const hrs = container.querySelectorAll("hr");
114
+ expect(hrs).toHaveLength(2);
115
+ });
116
+
117
+ it("has proper semantic structure", () => {
118
+ const { getByRole, getAllByRole } = render(<Footer />);
119
+
120
+ // Should have footer landmark
121
+ expect(getByRole("contentinfo")).toBeInTheDocument();
122
+
123
+ // Should have headings for each column
124
+ const headings = getAllByRole("heading", { level: 5 });
125
+ expect(headings).toHaveLength(4); // 4 columns
126
+
127
+ // Should have lists for navigation
128
+ const lists = getAllByRole("list");
129
+ expect(lists.length).toBeGreaterThanOrEqual(5); // 4 column lists + 1 bottom list
130
+ });
66
131
  });
@@ -4,6 +4,7 @@
4
4
  a:not(
5
5
  .link,
6
6
  .btn,
7
+ .mm-link,
7
8
  .megamenu-link,
8
9
  .list__control,
9
10
  .tab-list__tab,