athameui 0.0.2 → 0.0.5

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 (112) hide show
  1. package/components/Accordion/Accordion.tsx +62 -33
  2. package/components/Accordion/AccordionItem.tsx +93 -36
  3. package/components/Button/Button.tsx +74 -53
  4. package/components/Button/ButtonGroup.tsx +22 -3
  5. package/components/Button/{BackToTopButton.tsx → ScrollToTopButton.tsx} +13 -7
  6. package/components/Button/button.variants.ts +16 -8
  7. package/components/Button/index.ts +1 -1
  8. package/components/ContainerScalingText.tsx +72 -0
  9. package/components/FormElements/FormInput.tsx +227 -0
  10. package/components/FormElements/FormInputLabel.tsx +53 -0
  11. package/components/FormElements/index.ts +2 -0
  12. package/components/Header/Header.tsx +10 -2
  13. package/components/Layout/Footer.tsx +13 -0
  14. package/components/Layout/Main.tsx +30 -0
  15. package/components/Layout/index.ts +2 -0
  16. package/components/List/List.tsx +22 -13
  17. package/components/List/ListItem.tsx +16 -7
  18. package/components/List/index.ts +2 -0
  19. package/components/Search/Search.tsx +167 -0
  20. package/components/Search/index.ts +1 -0
  21. package/components/index.ts +5 -0
  22. package/dist/athameui.cjs +2963 -107
  23. package/dist/athameui.cjs.map +1 -1
  24. package/dist/athameui.mjs +2930 -104
  25. package/dist/athameui.mjs.map +1 -1
  26. package/dist/components/Accordion/Accordion.d.ts +26 -4
  27. package/dist/components/Accordion/Accordion.d.ts.map +1 -1
  28. package/dist/components/Accordion/AccordionItem.d.ts +24 -6
  29. package/dist/components/Accordion/AccordionItem.d.ts.map +1 -1
  30. package/dist/components/Button/Button.d.ts +20 -37
  31. package/dist/components/Button/Button.d.ts.map +1 -1
  32. package/dist/components/Button/ButtonGroup.d.ts +8 -2
  33. package/dist/components/Button/ButtonGroup.d.ts.map +1 -1
  34. package/dist/components/Button/ScrollToTopButton.d.ts +9 -0
  35. package/dist/components/Button/ScrollToTopButton.d.ts.map +1 -0
  36. package/dist/components/Button/button.variants.d.ts +14 -7
  37. package/dist/components/Button/button.variants.d.ts.map +1 -1
  38. package/dist/components/Button/index.d.ts +1 -1
  39. package/dist/components/Button/index.d.ts.map +1 -1
  40. package/dist/components/ContainerScalingText.d.ts +16 -0
  41. package/dist/components/ContainerScalingText.d.ts.map +1 -0
  42. package/dist/components/FormElements/FormInput.d.ts +41 -0
  43. package/dist/components/FormElements/FormInput.d.ts.map +1 -0
  44. package/dist/components/FormElements/FormInputLabel.d.ts +19 -0
  45. package/dist/components/FormElements/FormInputLabel.d.ts.map +1 -0
  46. package/dist/components/FormElements/index.d.ts +3 -0
  47. package/dist/components/FormElements/index.d.ts.map +1 -0
  48. package/dist/components/Header/Header.d.ts +5 -1
  49. package/dist/components/Header/Header.d.ts.map +1 -1
  50. package/dist/components/Layout/Footer.d.ts +9 -0
  51. package/dist/components/Layout/Footer.d.ts.map +1 -0
  52. package/dist/components/Layout/Main.d.ts +11 -0
  53. package/dist/components/Layout/Main.d.ts.map +1 -0
  54. package/dist/components/Layout/index.d.ts +3 -0
  55. package/dist/components/Layout/index.d.ts.map +1 -0
  56. package/dist/components/List/List.d.ts +6 -8
  57. package/dist/components/List/List.d.ts.map +1 -1
  58. package/dist/components/List/ListItem.d.ts +2 -2
  59. package/dist/components/List/ListItem.d.ts.map +1 -1
  60. package/dist/components/List/index.d.ts +3 -0
  61. package/dist/components/List/index.d.ts.map +1 -0
  62. package/dist/components/Search/Search.d.ts +40 -0
  63. package/dist/components/Search/Search.d.ts.map +1 -0
  64. package/dist/components/Search/index.d.ts +2 -0
  65. package/dist/components/Search/index.d.ts.map +1 -0
  66. package/dist/components/index.d.ts +5 -0
  67. package/dist/components/index.d.ts.map +1 -1
  68. package/dist/main.d.ts +2 -0
  69. package/dist/main.d.ts.map +1 -1
  70. package/dist/styles/components/accordion.css +98 -0
  71. package/dist/styles/components/button.css +232 -0
  72. package/dist/styles/components/footer.css +14 -0
  73. package/dist/styles/components/form-elements.css +158 -0
  74. package/dist/styles/components/header.css +12 -0
  75. package/dist/styles/components/list.css +20 -0
  76. package/dist/styles/components/main.css +14 -0
  77. package/dist/styles/components/search.css +49 -0
  78. package/dist/styles/index.d.ts +3 -0
  79. package/dist/styles/index.d.ts.map +1 -0
  80. package/dist/styles/index.ts +2 -0
  81. package/dist/styles/mediaQueries.d.ts +11 -0
  82. package/dist/styles/mediaQueries.d.ts.map +1 -0
  83. package/dist/styles/mediaQueries.ts +10 -0
  84. package/dist/styles/theme.css +9 -0
  85. package/dist/styles/tokens.css +214 -0
  86. package/dist/styles/tokens.d.ts +186 -0
  87. package/dist/styles/tokens.d.ts.map +1 -0
  88. package/dist/styles/tokens.ts +188 -0
  89. package/dist/utils/cx.d.ts +1 -1
  90. package/dist/utils/cx.d.ts.map +1 -1
  91. package/dist/utils/index.d.ts +3 -0
  92. package/dist/utils/index.d.ts.map +1 -0
  93. package/main.ts +2 -0
  94. package/package.json +13 -4
  95. package/styles/components/accordion.css +98 -0
  96. package/styles/components/button.css +232 -0
  97. package/styles/components/footer.css +14 -0
  98. package/styles/components/form-elements.css +158 -0
  99. package/styles/components/header.css +12 -0
  100. package/styles/components/list.css +20 -0
  101. package/styles/components/main.css +14 -0
  102. package/styles/components/search.css +49 -0
  103. package/styles/index.ts +2 -0
  104. package/styles/mediaQueries.ts +10 -0
  105. package/styles/theme.css +9 -0
  106. package/styles/tokens.css +214 -0
  107. package/styles/tokens.ts +188 -0
  108. package/components/Button/ButtonPrimitive.tsx +0 -16
  109. package/dist/components/Button/BackToTopButton.d.ts +0 -7
  110. package/dist/components/Button/BackToTopButton.d.ts.map +0 -1
  111. package/dist/components/Button/ButtonPrimitive.d.ts +0 -3
  112. package/dist/components/Button/ButtonPrimitive.d.ts.map +0 -1
@@ -1,6 +1,8 @@
1
1
  "use client";
2
2
  import { useState } from "react";
3
+ import { CSSObject } from "@emotion/react";
3
4
  import { AccordionItem } from "./AccordionItem";
5
+ import { List } from "../List/List";
4
6
  import type { AccordionItemType } from "./AccordionItem";
5
7
  import { cx } from "../../utils/cx";
6
8
 
@@ -9,15 +11,35 @@ type AccordionProps = {
9
11
  items: AccordionItemType[];
10
12
  childrenFirst?: boolean;
11
13
  expand?: "one" | "any";
12
- className?:
13
- | string
14
- | {
15
- accordion?: string | false | null | undefined;
16
- accordionItem?: string | false | null | undefined;
17
- }
18
- | false
19
- | undefined
20
- | null;
14
+ sx?: {
15
+ accordion: CSSObject;
16
+ accordionItem?: {
17
+ accordionItem?: CSSObject;
18
+ accordionHeading?: CSSObject;
19
+ accordionTitle?: CSSObject;
20
+ accordionExpansionWrapper?: CSSObject;
21
+ accordionContentWrapper?: CSSObject;
22
+ };
23
+ };
24
+ className?: {
25
+ accordion?: string | false | null | undefined;
26
+ accordionItem?: {
27
+ accordionItem?: string | false | null | undefined;
28
+ accordionHeading?: string | false | null | undefined;
29
+ accordionTitle?: string | false | null | undefined;
30
+ accordionExpansionWrapper?: string | false | null | undefined;
31
+ accordionContentWrapper?: string | false | null | undefined;
32
+ };
33
+ };
34
+
35
+ CustomAccordionItem?: React.ComponentType<
36
+ AccordionItemType & {
37
+ expanded: boolean;
38
+ onToggle: (id: string | number) => void;
39
+ className?: AccordionProps["className"];
40
+ }
41
+ >;
42
+
21
43
  expandToggleCallback?: (expandedItems: (string | number)[]) => void;
22
44
  };
23
45
 
@@ -27,24 +49,19 @@ export const Accordion = ({
27
49
  items,
28
50
  childrenFirst,
29
51
  expand = "one",
52
+ sx,
53
+
54
+ CustomAccordionItem,
30
55
 
31
56
  expandToggleCallback,
32
57
  }: AccordionProps) => {
33
58
  const [expandedItems, setExpandedItems] = useState<(string | number)[]>([]);
34
- const classes = cx(
59
+ const accordionClasses = cx(
35
60
  "ath-accordion",
36
- typeof className === "object" && className !== null
37
- ? className.accordion
38
- : className
61
+ className?.accordion ? className.accordion : undefined,
39
62
  );
40
63
 
41
64
  const expandToggle = (itemId: string | number) => {
42
- console.log(
43
- "Rendering AccordionItem:",
44
- itemId,
45
- "Expanded:",
46
- expandedItems.includes(itemId)
47
- );
48
65
  if (expandedItems.includes(itemId)) {
49
66
  setExpandedItems(expandedItems.filter((id) => id !== itemId));
50
67
  } else {
@@ -60,21 +77,33 @@ export const Accordion = ({
60
77
  };
61
78
 
62
79
  return (
63
- <div className={classes}>
80
+ <div className={accordionClasses} css={sx?.accordion}>
64
81
  {childrenFirst && children}
65
- {items.map((item) => (
66
- <AccordionItem
67
- key={item.id}
68
- item={item}
69
- expanded={expandedItems.includes(item.id)}
70
- onToggle={expandToggle}
71
- className={
72
- typeof className === "object" && className !== null
73
- ? className.accordionItem
74
- : undefined
75
- }
76
- />
77
- ))}
82
+ <List>
83
+ {items.map((item) => (
84
+ <div key={item.id}>
85
+ {CustomAccordionItem ? (
86
+ <CustomAccordionItem
87
+ expanded={expandedItems.includes(item.id)}
88
+ onToggle={expandToggle}
89
+ {...item}
90
+ />
91
+ ) : (
92
+ <AccordionItem
93
+ sx={sx}
94
+ item={item}
95
+ expanded={expandedItems.includes(item.id)}
96
+ onToggle={expandToggle}
97
+ className={
98
+ className?.accordionItem
99
+ ? { ...className.accordionItem }
100
+ : undefined
101
+ }
102
+ />
103
+ )}
104
+ </div>
105
+ ))}
106
+ </List>
78
107
  {!childrenFirst && children}
79
108
  </div>
80
109
  );
@@ -1,65 +1,122 @@
1
1
  "use client";
2
+ import { CSSObject } from "@emotion/react";
2
3
  import { useRef } from "react";
3
4
  import { Button } from "../Button/Button";
5
+ import type {
6
+ ButtonSize,
7
+ ButtonTextPosition,
8
+ ButtonVariant,
9
+ } from "../Button/button.variants";
4
10
  import { cx } from "../../utils/cx";
5
11
 
6
12
  export type AccordionItemType = {
7
13
  id: string | number;
8
- heading: string;
14
+ heading: React.ReactNode;
9
15
  content: React.ReactNode;
10
16
  };
11
17
 
12
18
  export type AccordionItemProps = {
13
- item: AccordionItemType;
19
+ children?: React.ReactNode;
20
+ className?: {
21
+ accordionItem?: string | false | null | undefined;
22
+ accordionHeading?: string | false | null | undefined;
23
+ accordionTitle?: string | false | null | undefined;
24
+ accordionExpansionWrapper?: string | false | null | undefined;
25
+ accordionContentWrapper?: string | false | null | undefined;
26
+ };
27
+
28
+ disabled?: boolean;
14
29
  expanded: boolean;
30
+ headingSize?: ButtonSize;
31
+ headingTextPosition?: ButtonTextPosition;
32
+ headingVariant?: ButtonVariant;
33
+ item: AccordionItemType;
34
+ sx?: {
35
+ accordionItem?: CSSObject;
36
+ accordionHeading?: CSSObject;
37
+ accordionTitle?: CSSObject;
38
+ accordionExpansionWrapper?: CSSObject;
39
+ accordionContentWrapper?: CSSObject;
40
+ };
41
+
15
42
  onToggle: (id: string | number) => void;
16
- className?:
17
- | string
18
- | { accordionItem?: string | false | null | undefined }
19
- | false
20
- | undefined
21
- | null;
22
43
  };
23
44
 
24
45
  export const AccordionItem = ({
25
- item,
46
+ className,
47
+ disabled,
26
48
  expanded,
49
+ item,
50
+ headingSize = "full",
51
+ headingTextPosition = "left",
52
+ headingVariant = "ghost",
53
+ sx,
54
+
27
55
  onToggle,
28
- className,
29
56
  }: AccordionItemProps) => {
30
57
  const contentRef = useRef<HTMLDivElement>(null);
31
58
  const contentHeight = contentRef.current?.scrollHeight;
32
59
 
33
- const classes = cx(
60
+ const itemClasses = cx(
34
61
  "ath-accordion-item",
35
- typeof className === "object" && className !== null
36
- ? className.accordionItem
37
- : className
62
+ disabled && "ath-accordion-item-heading-disabled",
63
+ className?.accordionItem ? className.accordionItem : undefined,
38
64
  );
39
65
 
66
+ const headingClasses = cx(
67
+ "ath-accordion-item-heading",
68
+ disabled && "ath-accordion-item-heading-disabled",
69
+ className?.accordionHeading ? className.accordionHeading : "",
70
+ );
71
+
72
+ const titleClasses = cx(
73
+ "ath-accordion-item-title",
74
+ className?.accordionTitle ? className.accordionTitle : "",
75
+ );
76
+
77
+ const expansionClasses = cx(
78
+ "ath-accordion-expansion-wrapper",
79
+ expanded && "expanded",
80
+ className?.accordionExpansionWrapper
81
+ ? className.accordionExpansionWrapper
82
+ : "",
83
+ );
84
+
85
+ const contentWrapperClasses = cx(
86
+ "ath-accordion-content-wrapper",
87
+ className?.accordionContentWrapper ? className.accordionContentWrapper : "",
88
+ );
89
+
90
+ const onToggleHandler = () => {
91
+ if (!disabled) {
92
+ onToggle(item.id);
93
+ }
94
+ };
95
+
40
96
  return (
41
- <div className={classes}>
42
- <Button
43
- className="ath-accordion-item-heading"
44
- variant="ghost"
45
- size="full"
46
- textAlign="left"
47
- onClick={() => onToggle(item.id)}
48
- dark
49
- >
50
- <h4>{item.heading}</h4>
51
- </Button>
52
- <div
53
- className={cx(
54
- "ath-accordion-expansion-wrapper",
55
- expanded && "expanded"
56
- )}
57
- style={{ height: expanded ? contentHeight : 0 }}
58
- >
59
- <div ref={contentRef} className="ath-accordion-item-content">
60
- {item.content}
97
+ <li className={itemClasses} css={sx?.accordionItem}>
98
+ <>
99
+ <Button
100
+ className={{ button: headingClasses }}
101
+ variant={headingVariant}
102
+ size={headingSize}
103
+ textPosition={headingTextPosition}
104
+ onClick={onToggleHandler}
105
+ disabled={disabled}
106
+ sx={sx?.accordionHeading}
107
+ dark
108
+ >
109
+ <div className={titleClasses}>{item.heading}</div>
110
+ </Button>
111
+ <div
112
+ className={expansionClasses}
113
+ style={{ height: expanded ? contentHeight : 0 }}
114
+ >
115
+ <div ref={contentRef} className={contentWrapperClasses}>
116
+ {item.content}
117
+ </div>
61
118
  </div>
62
- </div>
63
- </div>
119
+ </>
120
+ </li>
64
121
  );
65
122
  };
@@ -1,40 +1,39 @@
1
1
  "use client";
2
- import { ButtonPrimitive, type ButtonPrimitiveProps } from "./ButtonPrimitive";
3
- import { cx } from "../../utils/cx";
4
- import { buttonVariants, ButtonSize, ButtonVariant } from "./button.variants";
5
-
2
+ import { forwardRef } from "react";
6
3
  import type {
7
4
  KeyboardEventHandler,
8
5
  MouseEventHandler,
9
6
  ReactElement,
10
7
  } from "react";
11
- import { forwardRef } from "react";
8
+ import { cx } from "../../utils/cx";
9
+ import {
10
+ buttonVariants,
11
+ type ButtonSize,
12
+ type ButtonVariant,
13
+ } from "./button.variants";
14
+ import { CSSObject } from "@emotion/react";
12
15
 
13
- export type ButtonProps = Omit<ButtonPrimitiveProps, "className"> & {
16
+ export type ButtonProps = {
14
17
  children?: ReactElement | string;
15
- className?:
16
- | string
17
- | { button?: string | false | null | undefined }
18
- | false
19
- | undefined
20
- | null;
21
- type?: "button" | "submit" | "reset";
22
- variant?: ButtonVariant;
23
- size?: ButtonSize;
18
+ className?: {
19
+ button?: string | false | null | undefined;
20
+ icon?: string | false | null | undefined;
21
+ };
24
22
  dark?: boolean;
25
- iconOnly?: boolean;
26
- icon?: ReactElement | string;
27
- title?: string;
28
23
  disabled?: boolean;
29
- autoFocus?: boolean;
24
+ icon?: React.ComponentType<{ className?: string }> | string;
25
+ size?: ButtonSize;
26
+ sx?: CSSObject | { button?: CSSObject; icon?: CSSObject };
27
+ title?: string;
30
28
  tabIndex?: number;
31
- testId?: string;
32
- textAlign?: "left" | "center" | "right";
29
+ textPosition?: "left" | "center" | "right";
30
+ type?: "button" | "submit" | "reset";
31
+ variant?: ButtonVariant;
33
32
 
33
+ onBlur?: (event: React.FocusEvent<HTMLButtonElement>) => void;
34
34
  onClick?: MouseEventHandler<HTMLButtonElement>;
35
- onKeyDown?: KeyboardEventHandler<HTMLButtonElement>;
36
35
  onFocus?: (event: React.FocusEvent<HTMLButtonElement>) => void;
37
- onBlur?: (event: React.FocusEvent<HTMLButtonElement>) => void;
36
+ onKeyDown?: KeyboardEventHandler<HTMLButtonElement>;
38
37
  };
39
38
 
40
39
  export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
@@ -42,18 +41,15 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
42
41
  {
43
42
  children,
44
43
  className,
45
- variant = "primary",
46
- size = "medium",
47
44
  dark = false,
48
45
  disabled = false,
49
- icon,
50
- iconOnly,
46
+ icon: Icon,
47
+ size = "medium",
48
+ sx,
51
49
  tabIndex,
52
- testId,
53
50
  type = "button",
54
- title,
55
- autoFocus = false,
56
- textAlign = "center",
51
+ textPosition = "center",
52
+ variant = "secondary",
57
53
 
58
54
  onBlur,
59
55
  onClick,
@@ -61,54 +57,79 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
61
57
  onKeyDown,
62
58
  ...rest
63
59
  },
64
- ref
60
+ ref,
65
61
  ) => {
66
- const classes = cx(
62
+ const isIconOnly = Icon && !children;
63
+
64
+ const sharedClasses = cx(
67
65
  "ath-button",
68
66
  buttonVariants.size[size],
69
67
  buttonVariants.variant[variant],
70
- buttonVariants.textAlign[textAlign],
68
+ isIconOnly ? "ath-button-icon-only" : "",
71
69
  dark ? buttonVariants.dark : "",
70
+ );
71
+
72
+ const buttonClasses = cx(
73
+ sharedClasses,
74
+ buttonVariants.textPosition[textPosition],
72
75
  typeof className === "object" && className !== null
73
76
  ? className.button
74
- : className
77
+ : className,
78
+ );
79
+
80
+ const iconClasses = cx(
81
+ sharedClasses,
82
+ "ath-button-icon",
83
+ typeof className === "object" && className !== null
84
+ ? className.icon
85
+ : undefined,
75
86
  );
76
87
 
77
88
  const onClickHandler: MouseEventHandler<HTMLButtonElement> = (e) => {
78
89
  onClick?.(e);
79
90
  };
80
91
 
92
+ const onKeyDownHandler: KeyboardEventHandler<HTMLButtonElement> = (e) => {
93
+ onKeyDown?.(e);
94
+ };
95
+
96
+ const onFocusHandler = (e: React.FocusEvent<HTMLButtonElement>) => {
97
+ onFocus?.(e);
98
+ };
99
+
100
+ const onBlurHandler = (e: React.FocusEvent<HTMLButtonElement>) => {
101
+ onBlur?.(e);
102
+ };
103
+
81
104
  return (
82
- <ButtonPrimitive
105
+ <button
83
106
  ref={ref}
84
- type={type}
85
- title={title}
86
- className={classes}
107
+ className={buttonClasses}
108
+ css={sx?.button ? sx.button : sx}
87
109
  disabled={disabled}
88
- autoFocus={autoFocus}
89
110
  tabIndex={disabled ? -1 : tabIndex}
90
- data-testid={testId}
111
+ type={type}
91
112
  onClick={onClickHandler}
92
- onKeyDown={onKeyDown}
93
- onFocus={onFocus}
94
- onBlur={onBlur}
113
+ onKeyDown={onKeyDownHandler}
114
+ onFocus={onFocusHandler}
115
+ onBlur={onBlurHandler}
95
116
  {...rest}
96
117
  >
97
- {icon ? (
118
+ {Icon ? (
98
119
  <>
99
- {typeof icon === "string" ? (
100
- <span aria-hidden="true">{icon}</span>
101
- ) : (
102
- icon
103
- )}
104
- {!iconOnly && children}
120
+ <Icon
121
+ className={iconClasses}
122
+ css={sx?.icon ? sx.icon : undefined}
123
+ />
124
+
125
+ {!isIconOnly && children}
105
126
  </>
106
127
  ) : (
107
128
  <>{children}</>
108
129
  )}
109
- </ButtonPrimitive>
130
+ </button>
110
131
  );
111
- }
132
+ },
112
133
  );
113
134
 
114
135
  Button.displayName = "Button";
@@ -1,13 +1,32 @@
1
+ import { CSSObject } from "@emotion/react";
2
+ import { cx } from "../../utils";
3
+
1
4
  type ButtonGroupProps = {
2
5
  children: React.ReactNode;
3
- gap?: string;
6
+ className?: {
7
+ buttonGroup?: string | false | null | undefined;
8
+ };
4
9
  direction?: "row" | "column";
10
+ sx?: {
11
+ buttonGroup?: CSSObject | string;
12
+ };
5
13
  };
6
14
 
7
15
  export const ButtonGroup = ({
8
16
  children,
9
- gap = "2",
17
+ className,
10
18
  direction = "row",
19
+ sx,
11
20
  }: ButtonGroupProps) => {
12
- return <div className={`flex flex-${direction} gap-${gap}`}>{children}</div>;
21
+ const buttonGroupClasses = cx(
22
+ "ath-button-group",
23
+ `ath-button-group-direction-${direction}`,
24
+ className?.buttonGroup ? className.buttonGroup : undefined,
25
+ );
26
+
27
+ return (
28
+ <div className={buttonGroupClasses} css={sx?.buttonGroup}>
29
+ {children}
30
+ </div>
31
+ );
13
32
  };
@@ -6,12 +6,18 @@ import { CircleArrowUp02Icon } from "@hugeicons/core-free-icons";
6
6
  import type { ButtonProps } from "./Button";
7
7
  import { cx } from "../../utils/cx";
8
8
 
9
- type BackToTopButtonProps = ButtonProps & {
10
- className?: string;
9
+ type ScrollToTopButtonProps = ButtonProps & {
10
+ className?: {
11
+ button?: string | false | null | undefined;
12
+ };
11
13
  };
12
14
 
13
- export const BackToTopButton = (props: BackToTopButtonProps) => {
14
- const { className, variant, dark = false, testId, title } = props;
15
+ export const ScrollToTopButton = ({
16
+ className,
17
+ variant,
18
+ dark = false,
19
+ title,
20
+ }: ScrollToTopButtonProps) => {
15
21
  const [visible, setVisible] = useState(false);
16
22
 
17
23
  useEffect(() => {
@@ -36,12 +42,12 @@ export const BackToTopButton = (props: BackToTopButtonProps) => {
36
42
 
37
43
  if (!visible) return null;
38
44
 
39
- const classes = cx("ath-back-to-top-button", className);
45
+ const buttonClasses = cx("ath-scroll-to-top-button", className?.button);
40
46
 
41
47
  return (
42
48
  <Button
43
- className={classes}
44
- data-testid={`${testId} "ath-back-to-top-button"`}
49
+ className={{ button: buttonClasses }}
50
+ data-testid="ath-scroll-to-top-button"
45
51
  onClick={scrollToTop}
46
52
  variant={variant ?? "secondary"}
47
53
  title={title ?? "Back to Top"}
@@ -1,4 +1,3 @@
1
- // button.variants.ts
2
1
  export const buttonVariants = {
3
2
  size: {
4
3
  small: "ath-button-small",
@@ -6,6 +5,11 @@ export const buttonVariants = {
6
5
  large: "ath-button-large",
7
6
  full: "ath-button-full",
8
7
  },
8
+ textPosition: {
9
+ left: "ath-button-text-left",
10
+ center: "ath-button-text-center",
11
+ right: "ath-button-text-right",
12
+ },
9
13
  variant: {
10
14
  primary: "ath-button-primary",
11
15
  secondary: "ath-button-secondary",
@@ -16,15 +20,19 @@ export const buttonVariants = {
16
20
  outline: "ath-button-outline",
17
21
  ghost: "ath-button-ghost",
18
22
  },
19
- textAlign: {
20
- left: "ath-button-text-left",
21
- center: "ath-button-text-center",
22
- right: "ath-button-text-right",
23
- },
23
+
24
24
  dark: "ath-button-dark",
25
25
  } as const;
26
26
 
27
+ export const ButtonGroupVariants = {
28
+ direction: {
29
+ row: "ath-button-group-direction-row",
30
+ column: "ath-button-group-direction-column",
31
+ },
32
+ } as const;
33
+
27
34
  export type ButtonSize = keyof typeof buttonVariants.size;
28
35
  export type ButtonVariant = keyof typeof buttonVariants.variant;
29
- export type ButtonDark = keyof typeof buttonVariants.dark;
30
- export type ButtonTextAlign = keyof typeof buttonVariants.textAlign;
36
+ export type ButtonDark = typeof buttonVariants.dark;
37
+ export type ButtonTextPosition = keyof typeof buttonVariants.textPosition;
38
+ export type ButtonGroupDirection = keyof typeof ButtonGroupVariants.direction;
@@ -1,3 +1,3 @@
1
1
  export * from "./Button";
2
2
  export * from "./ButtonGroup";
3
- export * from "./BackToTopButton";
3
+ export * from "./ScrollToTopButton";
@@ -0,0 +1,72 @@
1
+ "use client";
2
+ import { CSSObject } from "@emotion/react";
3
+ import React, { useRef, useEffect, useState } from "react";
4
+
5
+ type ContainerScalingTextProps = {
6
+ children: React.ReactNode;
7
+ className?: { container?: string };
8
+ maxFontSize?: number;
9
+ minFontSize?: number;
10
+ sx?: { container?: CSSObject };
11
+ };
12
+
13
+ export const ContainerScalingText: React.FC<ContainerScalingTextProps> = ({
14
+ children,
15
+ maxFontSize = 48,
16
+ minFontSize = 14,
17
+ className,
18
+ sx,
19
+ }) => {
20
+ const containerRef = useRef<HTMLDivElement>(null);
21
+ const textRef = useRef<HTMLDivElement>(null);
22
+ const [fontSize, setFontSize] = useState(maxFontSize);
23
+
24
+ useEffect(() => {
25
+ const resizeText = () => {
26
+ if (!containerRef.current || !textRef.current) return;
27
+
28
+ const container = containerRef.current;
29
+ const text = textRef.current;
30
+
31
+ let currentSize = maxFontSize;
32
+ text.style.fontSize = `${currentSize}px`;
33
+
34
+ while (
35
+ (text.scrollWidth > container.clientWidth ||
36
+ text.scrollHeight > container.clientHeight) &&
37
+ currentSize > minFontSize
38
+ ) {
39
+ currentSize -= 1;
40
+ text.style.fontSize = `${currentSize}px`;
41
+ }
42
+
43
+ setFontSize(currentSize);
44
+ };
45
+
46
+ resizeText();
47
+
48
+ const resizeObserver = new ResizeObserver(resizeText);
49
+ if (containerRef.current) {
50
+ resizeObserver.observe(containerRef.current);
51
+ }
52
+
53
+ return () => resizeObserver.disconnect();
54
+ }, [children, maxFontSize, minFontSize, sx, className]);
55
+
56
+ return (
57
+ <div
58
+ ref={containerRef}
59
+ className={`overflow-hidden ${className?.container}`}
60
+ style={{ width: "100%", height: "100%" }}
61
+ css={sx?.container}
62
+ >
63
+ <div
64
+ ref={textRef}
65
+ className="whitespace-pre-line"
66
+ style={{ fontSize: `${fontSize}px` }}
67
+ >
68
+ {children}
69
+ </div>
70
+ </div>
71
+ );
72
+ };