@recursica/mantine-adapter 0.14.0 → 0.16.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.
- package/CHANGELOG.md +12 -0
- package/dist/mantine-adapter.cjs +1 -1
- package/dist/mantine-adapter.cjs.map +1 -1
- package/dist/mantine-adapter.css +1 -1
- package/dist/mantine-adapter.js +1439 -1251
- package/dist/mantine-adapter.js.map +1 -1
- package/dist/src/components/Button/Button.d.ts +7 -1
- package/dist/src/components/Link/Link.d.ts +32 -2
- package/dist/src/components/Link/index.d.ts +1 -0
- package/dist/src/components/Pagination/Pagination.d.ts +50 -2
- package/dist/src/components/Pagination/Pagination.icons.d.ts +8 -0
- package/dist/src/components/Pagination/index.d.ts +1 -0
- package/dist/src/components/Panel/Panel.d.ts +10 -2
- package/package.json +1 -1
- package/src/components/Button/Button.stories.tsx +11 -0
- package/src/components/Button/Button.tsx +7 -1
- package/src/components/Card/Card.module.css +1 -0
- package/src/components/Card/Card.stories.tsx +48 -58
- package/src/components/Link/IMPLEMENTATION_NOTES.md +26 -0
- package/src/components/Link/Link.module.css +133 -0
- package/src/components/Link/Link.stories.tsx +46 -4
- package/src/components/Link/Link.tsx +82 -5
- package/src/components/Link/index.ts +1 -0
- package/src/components/Pagination/IMPLEMENTATION_NOTES.md +16 -0
- package/src/components/Pagination/Pagination.icons.tsx +66 -0
- package/src/components/Pagination/Pagination.module.css +225 -0
- package/src/components/Pagination/Pagination.stories.tsx +44 -4
- package/src/components/Pagination/Pagination.tsx +214 -4
- package/src/components/Pagination/index.ts +5 -0
- package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +3 -3
- package/src/components/Panel/Panel.module.css +11 -0
- package/src/components/Panel/Panel.stories.tsx +12 -1
- package/src/components/Panel/Panel.tsx +12 -2
|
@@ -11,9 +11,15 @@ export type ButtonProps = RecursicaOverStyled<Omit<MantineButtonProps, "variant"
|
|
|
11
11
|
* Recursica Button component wrapping Mantine's Button.
|
|
12
12
|
*
|
|
13
13
|
* Supports polymorphism via the `component` prop or `renderRoot` for custom element rendering.
|
|
14
|
+
* This is particularly useful when you need a button that behaves as a hyperlink (rendering an `<a>` tag)
|
|
15
|
+
* or integrates with a routing library (e.g., `react-router-dom` or Next.js), while preserving full visual styling.
|
|
16
|
+
*
|
|
14
17
|
* @example
|
|
15
18
|
* ```tsx
|
|
16
|
-
* <
|
|
19
|
+
* // Renders as an <a> tag natively
|
|
20
|
+
* <Button component="a" href="/dashboard" target="_blank">Navigate</Button>
|
|
21
|
+
*
|
|
22
|
+
* // Renders using a custom router link
|
|
17
23
|
* <Button renderRoot={(props) => <Link to="/home" {...props} />}>Home</Button>
|
|
18
24
|
* ```
|
|
19
25
|
*/
|
|
@@ -1,3 +1,33 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { AnchorProps as MantineAnchorProps } from '@mantine/core';
|
|
3
|
+
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
4
|
+
export interface RecursicaLinkProps {
|
|
5
|
+
/**
|
|
6
|
+
* Optional leading icon to display next to the link text.
|
|
7
|
+
*/
|
|
8
|
+
icon?: React.ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* The text or elements to display inside the link.
|
|
11
|
+
*/
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export type LinkProps = RecursicaOverStyled<Omit<MantineAnchorProps, "underline"> & RecursicaLinkProps>;
|
|
15
|
+
/**
|
|
16
|
+
* Recursica Link component wrapping Mantine's Anchor.
|
|
17
|
+
*
|
|
18
|
+
* Supports polymorphism via the `component` prop or `renderRoot` for custom element rendering (e.g. react-router Link).
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <Link component="a" href="https://example.com">External Link</Link>
|
|
22
|
+
* <Link renderRoot={(props) => <RouterLink to="/home" {...props} />}>Home</Link>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare const Link: (<C = "a">(props: import('@mantine/core').PolymorphicComponentProps<C, LinkProps>) => React.ReactElement) & Omit<React.FunctionComponent<((LinkProps & {
|
|
26
|
+
component?: any;
|
|
27
|
+
}) & Omit<Omit<any, "ref">, "className" | "classNames" | "style" | "styles" | "vars" | "p" | "px" | "py" | "pt" | "pb" | "pl" | "pr" | "bg" | "c" | "opacity" | "ff" | "fz" | "fw" | "lts" | "ta" | "lh" | "fs" | "tt" | "td" | "bd" | "w" | "miw" | "maw" | "h" | "mih" | "mah" | "m" | "my" | "mx" | "mt" | "mb" | "ml" | "mr" | "top" | "left" | "bottom" | "right" | "color" | "children" | "__vars" | "__size" | "hiddenFrom" | "visibleFrom" | "lightHidden" | "darkHidden" | "mod" | "ms" | "me" | "ps" | "pe" | "bdrs" | "bgsz" | "bgp" | "bgr" | "bga" | "pos" | "inset" | "display" | "flex" | "unstyled" | "variant" | "attributes" | "overStyled" | "icon" | "inherit" | "inline" | "size" | "gradient" | "component" | "__staticSelector" | "lineClamp" | "truncate"> & {
|
|
28
|
+
ref?: any;
|
|
29
|
+
renderRoot?: (props: any) => any;
|
|
30
|
+
}) | (LinkProps & {
|
|
31
|
+
component: React.ElementType;
|
|
32
|
+
renderRoot?: (props: Record<string, any>) => any;
|
|
33
|
+
})>, never> & Record<string, never>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Link';
|
|
@@ -1,3 +1,51 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { Pagination as MantinePagination, PaginationProps as MantinePaginationProps, PaginationRootProps as MantinePaginationRootProps } from '@mantine/core';
|
|
3
|
+
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
4
|
+
import { PaginationIcon } from './Pagination.icons';
|
|
5
|
+
export type PaginationProps = RecursicaOverStyled<MantinePaginationProps> & {
|
|
6
|
+
/** If set to true, displays text labels alongside the icons for next/previous/first/last edges. */
|
|
7
|
+
withLabels?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type PaginationRootProps = RecursicaOverStyled<MantinePaginationRootProps>;
|
|
10
|
+
export type PaginationEdgeProps<T extends React.ElementType> = React.ComponentProps<T> & {
|
|
11
|
+
/** If set to true, displays text labels alongside the icon. */
|
|
12
|
+
withLabel?: boolean;
|
|
13
|
+
icon?: any;
|
|
14
|
+
};
|
|
15
|
+
declare const _PaginationRoot: React.ForwardRefExoticComponent<PaginationRootProps & React.RefAttributes<HTMLDivElement>>;
|
|
16
|
+
declare const _PaginationNext: React.ForwardRefExoticComponent<{
|
|
17
|
+
/** If set to true, displays text labels alongside the icon. */
|
|
18
|
+
withLabel?: boolean;
|
|
19
|
+
icon?: any;
|
|
20
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
21
|
+
declare const _PaginationPrevious: React.ForwardRefExoticComponent<{
|
|
22
|
+
/** If set to true, displays text labels alongside the icon. */
|
|
23
|
+
withLabel?: boolean;
|
|
24
|
+
icon?: any;
|
|
25
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
26
|
+
declare const _PaginationFirst: React.ForwardRefExoticComponent<{
|
|
27
|
+
/** If set to true, displays text labels alongside the icon. */
|
|
28
|
+
withLabel?: boolean;
|
|
29
|
+
icon?: any;
|
|
30
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
31
|
+
declare const _PaginationLast: React.ForwardRefExoticComponent<{
|
|
32
|
+
/** If set to true, displays text labels alongside the icon. */
|
|
33
|
+
withLabel?: boolean;
|
|
34
|
+
icon?: any;
|
|
35
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
36
|
+
declare const _Pagination: React.ForwardRefExoticComponent<PaginationProps & React.RefAttributes<HTMLDivElement>>;
|
|
37
|
+
/**
|
|
38
|
+
* Recursica Pagination component wrapping Mantine's Pagination.
|
|
39
|
+
*/
|
|
40
|
+
export declare const Pagination: typeof _Pagination & {
|
|
41
|
+
Root: typeof _PaginationRoot;
|
|
42
|
+
Items: typeof MantinePagination.Items;
|
|
43
|
+
Control: typeof MantinePagination.Control;
|
|
44
|
+
Dots: typeof MantinePagination.Dots;
|
|
45
|
+
Next: typeof _PaginationNext;
|
|
46
|
+
Previous: typeof _PaginationPrevious;
|
|
47
|
+
First: typeof _PaginationFirst;
|
|
48
|
+
Last: typeof _PaginationLast;
|
|
49
|
+
Icon: typeof PaginationIcon;
|
|
50
|
+
};
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type PaginationIconType = "next" | "prev" | "first" | "last";
|
|
2
|
+
export declare const PaginationIcon: ({ type, className, ...props }: React.ComponentProps<"svg"> & {
|
|
3
|
+
type: PaginationIconType;
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare const NextWithLabel: (props: any) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare const PrevWithLabel: (props: any) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare const FirstWithLabel: (props: any) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare const LastWithLabel: (props: any) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Pagination, type PaginationProps, type PaginationRootProps, } from './Pagination';
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { Drawer as MantineDrawer, DrawerProps as MantineDrawerProps } from '@mantine/core';
|
|
2
2
|
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
3
|
+
export interface RecursicaPanelProps extends MantineDrawerProps {
|
|
4
|
+
/**
|
|
5
|
+
* If true, forces the header text to a single line and truncates with an ellipsis.
|
|
6
|
+
* Note: While the prop is named `wrapHeaderText` for backward compatibility,
|
|
7
|
+
* setting it to `true` actually PREVENTS wrapping (it forces truncation).
|
|
8
|
+
*/
|
|
9
|
+
wrapHeaderText?: boolean;
|
|
10
|
+
}
|
|
3
11
|
/**
|
|
4
12
|
* Recursica Panel root props. Extends Mantine Drawer.
|
|
5
13
|
*/
|
|
6
|
-
export type PanelProps = RecursicaOverStyled<
|
|
14
|
+
export type PanelProps = RecursicaOverStyled<RecursicaPanelProps>;
|
|
7
15
|
/**
|
|
8
16
|
* Recursica Panel component wrapping Mantine's Drawer.
|
|
9
17
|
*
|
|
@@ -31,7 +39,7 @@ export type PanelProps = RecursicaOverStyled<MantineDrawerProps>;
|
|
|
31
39
|
* - `Panel.Stack` — Stacked drawer context
|
|
32
40
|
*/
|
|
33
41
|
declare const PanelBase: {
|
|
34
|
-
({ overStyled, position, keepMounted, ...rest }: PanelProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
({ overStyled, position, keepMounted, wrapHeaderText, ...rest }: PanelProps): import("react/jsx-runtime").JSX.Element;
|
|
35
43
|
displayName: string;
|
|
36
44
|
};
|
|
37
45
|
export type PanelFooterProps = RecursicaOverStyled<React.HTMLAttributes<HTMLDivElement>>;
|
package/package.json
CHANGED
|
@@ -101,3 +101,14 @@ export const DisabledSolid: Story = {
|
|
|
101
101
|
disabled: true,
|
|
102
102
|
},
|
|
103
103
|
};
|
|
104
|
+
|
|
105
|
+
export const PolymorphicAsLink: Story = {
|
|
106
|
+
args: {
|
|
107
|
+
children: "Button as Link",
|
|
108
|
+
variant: "solid",
|
|
109
|
+
size: "default",
|
|
110
|
+
component: "a",
|
|
111
|
+
href: "https://example.com",
|
|
112
|
+
target: "_blank",
|
|
113
|
+
},
|
|
114
|
+
};
|
|
@@ -123,9 +123,15 @@ _Button.displayName = "Button";
|
|
|
123
123
|
* Recursica Button component wrapping Mantine's Button.
|
|
124
124
|
*
|
|
125
125
|
* Supports polymorphism via the `component` prop or `renderRoot` for custom element rendering.
|
|
126
|
+
* This is particularly useful when you need a button that behaves as a hyperlink (rendering an `<a>` tag)
|
|
127
|
+
* or integrates with a routing library (e.g., `react-router-dom` or Next.js), while preserving full visual styling.
|
|
128
|
+
*
|
|
126
129
|
* @example
|
|
127
130
|
* ```tsx
|
|
128
|
-
* <
|
|
131
|
+
* // Renders as an <a> tag natively
|
|
132
|
+
* <Button component="a" href="/dashboard" target="_blank">Navigate</Button>
|
|
133
|
+
*
|
|
134
|
+
* // Renders using a custom router link
|
|
129
135
|
* <Button renderRoot={(props) => <Link to="/home" {...props} />}>Home</Button>
|
|
130
136
|
* ```
|
|
131
137
|
*/
|
|
@@ -2,6 +2,8 @@ import type { Meta, StoryObj } from "@storybook/react";
|
|
|
2
2
|
import { Card } from "./Card";
|
|
3
3
|
import { Layer } from "@recursica/adapter-common";
|
|
4
4
|
import { Button } from "../Button/Button";
|
|
5
|
+
import { Group } from "../Group/Group";
|
|
6
|
+
import { Text } from "../Text/Text";
|
|
5
7
|
|
|
6
8
|
const meta: Meta<typeof Card> = {
|
|
7
9
|
title: "UI-Kit/Card",
|
|
@@ -32,46 +34,33 @@ export const Default: Story = {
|
|
|
32
34
|
args: {},
|
|
33
35
|
render: ({ ...args }) => {
|
|
34
36
|
return (
|
|
35
|
-
<
|
|
36
|
-
layer={0}
|
|
37
|
+
<div
|
|
37
38
|
style={{
|
|
38
39
|
padding: "48px",
|
|
39
40
|
backgroundColor: "var(--recursica_brand_palettes_neutral_050)",
|
|
40
41
|
}}
|
|
41
42
|
>
|
|
42
|
-
<
|
|
43
|
-
<Card
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
marginTop: "16px",
|
|
64
|
-
marginBottom: "8px",
|
|
65
|
-
}}
|
|
66
|
-
>
|
|
67
|
-
<span style={{ color: "#868e96", fontSize: "0.75rem" }}>
|
|
68
|
-
Generated today
|
|
69
|
-
</span>
|
|
70
|
-
<Button variant="solid">View Details</Button>
|
|
71
|
-
</div>
|
|
72
|
-
</Card.Footer>
|
|
73
|
-
</Card>
|
|
74
|
-
</Layer>
|
|
43
|
+
<Layer layer={0}>
|
|
44
|
+
<Card {...args}>
|
|
45
|
+
<Card.Header>Customer Activity Report</Card.Header>
|
|
46
|
+
<Card.Content>
|
|
47
|
+
<Text>
|
|
48
|
+
Card inner section content body. Notice how this acts as padded
|
|
49
|
+
content natively based on the overarching properties.
|
|
50
|
+
Recursica's vertical gutter governs vertical spacing between
|
|
51
|
+
siblings in the flex container.
|
|
52
|
+
</Text>
|
|
53
|
+
<Text>Another section showing the vertical gutter spacing.</Text>
|
|
54
|
+
</Card.Content>
|
|
55
|
+
<Card.Footer>
|
|
56
|
+
<Group justify="space-between" align="center">
|
|
57
|
+
<Text variant="caption">Generated today</Text>
|
|
58
|
+
<Button variant="solid">View Details</Button>
|
|
59
|
+
</Group>
|
|
60
|
+
</Card.Footer>
|
|
61
|
+
</Card>
|
|
62
|
+
</Layer>
|
|
63
|
+
</div>
|
|
75
64
|
);
|
|
76
65
|
},
|
|
77
66
|
};
|
|
@@ -80,29 +69,26 @@ export const HeaderlessAndFooterless: Story = {
|
|
|
80
69
|
args: {},
|
|
81
70
|
render: ({ ...args }) => {
|
|
82
71
|
return (
|
|
83
|
-
<
|
|
84
|
-
layer={0}
|
|
72
|
+
<div
|
|
85
73
|
style={{
|
|
86
74
|
padding: "48px",
|
|
87
75
|
backgroundColor: "var(--recursica_brand_palettes_neutral_050)",
|
|
88
76
|
}}
|
|
89
77
|
>
|
|
90
|
-
<
|
|
91
|
-
<Card
|
|
92
|
-
<
|
|
93
|
-
Notice
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
</Card>
|
|
105
|
-
</Layer>
|
|
78
|
+
<Layer layer={0}>
|
|
79
|
+
<Card {...args}>
|
|
80
|
+
<Card.Content>
|
|
81
|
+
<Text variant="subtitle">Notice</Text>
|
|
82
|
+
<Text>
|
|
83
|
+
This is a completely generic card payload dropping the Header
|
|
84
|
+
and Footer specific elements, simply acting as a padded
|
|
85
|
+
elevation boundary box directly mirroring native composability!
|
|
86
|
+
</Text>
|
|
87
|
+
<Button variant="solid">Acknowledge</Button>
|
|
88
|
+
</Card.Content>
|
|
89
|
+
</Card>
|
|
90
|
+
</Layer>
|
|
91
|
+
</div>
|
|
106
92
|
);
|
|
107
93
|
},
|
|
108
94
|
};
|
|
@@ -122,17 +108,21 @@ export const LayerDemonstration: Story = {
|
|
|
122
108
|
<Layer layer={1}>
|
|
123
109
|
<Card {...args}>
|
|
124
110
|
<Card.Header>Layer 1 Wrapper</Card.Header>
|
|
125
|
-
<
|
|
111
|
+
<Card.Content>
|
|
112
|
+
<Text>Content inside layer 1 card.</Text>
|
|
113
|
+
</Card.Content>
|
|
126
114
|
</Card>
|
|
127
115
|
</Layer>
|
|
128
116
|
|
|
129
117
|
<Layer layer={2}>
|
|
130
118
|
<Card {...args}>
|
|
131
119
|
<Card.Header>Layer 2 Wrapper</Card.Header>
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
120
|
+
<Card.Content>
|
|
121
|
+
<Text>
|
|
122
|
+
Content inside layer 2 card exposing a higher elevation drop
|
|
123
|
+
shadow inherently cascaded.
|
|
124
|
+
</Text>
|
|
125
|
+
</Card.Content>
|
|
136
126
|
</Card>
|
|
137
127
|
</Layer>
|
|
138
128
|
</div>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Link Component Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Missing States in Design Tokens
|
|
4
|
+
|
|
5
|
+
Currently, the design tokens (`recursica_variables_scoped.css`) only provide states for:
|
|
6
|
+
|
|
7
|
+
- `default`
|
|
8
|
+
- `hover`
|
|
9
|
+
- `visited`
|
|
10
|
+
- `visited-hover`
|
|
11
|
+
|
|
12
|
+
There are no tokens for the `active` or `focus` states. If these are needed, they must be added to the Figma variables and exported via the token pipeline. The component relies on the browser's default focus outline for accessibility unless overriden by a global reset.
|
|
13
|
+
|
|
14
|
+
## Overriding Mantine's underline Prop
|
|
15
|
+
|
|
16
|
+
Mantine's `Anchor` component uses `underline="hover"` by default. Because our design system specifies exact `text-decoration` styles via CSS tokens, we explicitly pass `underline="never"` to the underlying Mantine component. This prevents Mantine from injecting its own text-decoration inline or via generic classnames, ensuring our scoped CSS remains the single source of truth.
|
|
17
|
+
|
|
18
|
+
## Base Layout
|
|
19
|
+
|
|
20
|
+
Mantine's `Anchor` renders an inline element by default and does not natively support `leftSection` like the `Button` component. To support an optional `icon` alongside the text, we enforce a baseline layout of `display: inline-flex` and `align-items: center` in `Link.module.css`.
|
|
21
|
+
|
|
22
|
+
When an icon is present, the component conditionally passes a `data-has-icon` attribute to the root element. The CSS module uses this attribute to apply the `icon-text-gap` token via the CSS `gap` property.
|
|
23
|
+
|
|
24
|
+
## Inner Wrappers
|
|
25
|
+
|
|
26
|
+
The icon and children are wrapped in internal `<span>` tags (`.iconWrapper` and `.labelText` respectively). This follows the component development guide for structural robustness, allowing us to enforce specific sizing on the icon and intrinsic text truncation behavior if the link is placed in a bounded container.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/*
|
|
2
|
+
HARDCODED VALUES:
|
|
3
|
+
- display: inline-flex; (Base layout to align icon and text correctly)
|
|
4
|
+
- align-items: center;
|
|
5
|
+
- cursor: pointer;
|
|
6
|
+
- text-decoration: none; (Overridden by our design tokens instead of using Mantine's underline prop)
|
|
7
|
+
- color: inherit; (Reset before applying token)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.root {
|
|
11
|
+
/* HARDCODE: base layout to support optional icon gaps */
|
|
12
|
+
display: inline-flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
|
|
16
|
+
/* HARDCODE: Reset underline and color so we can explicitly use our tokens */
|
|
17
|
+
text-decoration: none;
|
|
18
|
+
color: inherit;
|
|
19
|
+
|
|
20
|
+
/* Typography Default Tokens */
|
|
21
|
+
font-family: var(
|
|
22
|
+
--recursica_ui-kit_components_link_properties_text_font-family
|
|
23
|
+
);
|
|
24
|
+
font-size: var(--recursica_ui-kit_components_link_properties_text_font-size);
|
|
25
|
+
letter-spacing: var(
|
|
26
|
+
--recursica_ui-kit_components_link_properties_text_letter-spacing
|
|
27
|
+
);
|
|
28
|
+
line-height: var(
|
|
29
|
+
--recursica_ui-kit_components_link_properties_text_line-height
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/* Default State Tokens */
|
|
33
|
+
font-style: var(
|
|
34
|
+
--recursica_ui-kit_components_link_variants_states_default_properties_text_font-style
|
|
35
|
+
);
|
|
36
|
+
font-weight: var(
|
|
37
|
+
--recursica_ui-kit_components_link_variants_states_default_properties_text_font-weight
|
|
38
|
+
);
|
|
39
|
+
text-decoration: var(
|
|
40
|
+
--recursica_ui-kit_components_link_variants_states_default_properties_text_text-decoration
|
|
41
|
+
);
|
|
42
|
+
color: var(
|
|
43
|
+
--recursica_ui-kit_components_link_variants_states_default_properties_colors_text
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.root[data-has-icon] {
|
|
48
|
+
gap: var(--recursica_ui-kit_components_link_properties_icon-text-gap);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.root:hover {
|
|
52
|
+
/* Reset Mantine's potential hover override */
|
|
53
|
+
text-decoration: var(
|
|
54
|
+
--recursica_ui-kit_components_link_variants_states_hover_properties_text_text-decoration
|
|
55
|
+
);
|
|
56
|
+
font-style: var(
|
|
57
|
+
--recursica_ui-kit_components_link_variants_states_hover_properties_text_font-style
|
|
58
|
+
);
|
|
59
|
+
font-weight: var(
|
|
60
|
+
--recursica_ui-kit_components_link_variants_states_hover_properties_text_font-weight
|
|
61
|
+
);
|
|
62
|
+
color: var(
|
|
63
|
+
--recursica_ui-kit_components_link_variants_states_hover_properties_colors_text
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.root:visited {
|
|
68
|
+
text-decoration: var(
|
|
69
|
+
--recursica_ui-kit_components_link_variants_states_visited_properties_text_text-decoration
|
|
70
|
+
);
|
|
71
|
+
font-style: var(
|
|
72
|
+
--recursica_ui-kit_components_link_variants_states_visited_properties_text_font-style
|
|
73
|
+
);
|
|
74
|
+
font-weight: var(
|
|
75
|
+
--recursica_ui-kit_components_link_variants_states_visited_properties_text_font-weight
|
|
76
|
+
);
|
|
77
|
+
color: var(
|
|
78
|
+
--recursica_ui-kit_components_link_variants_states_visited_properties_colors_text
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.root:visited:hover {
|
|
83
|
+
text-decoration: var(
|
|
84
|
+
--recursica_ui-kit_components_link_variants_states_visited-hover_properties_text_text-decoration
|
|
85
|
+
);
|
|
86
|
+
font-style: var(
|
|
87
|
+
--recursica_ui-kit_components_link_variants_states_visited-hover_properties_text_font-style
|
|
88
|
+
);
|
|
89
|
+
font-weight: var(
|
|
90
|
+
--recursica_ui-kit_components_link_variants_states_visited-hover_properties_text_font-weight
|
|
91
|
+
);
|
|
92
|
+
color: var(
|
|
93
|
+
--recursica_ui-kit_components_link_variants_states_visited-hover_properties_colors_text
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Icon Support */
|
|
98
|
+
.iconWrapper {
|
|
99
|
+
/* HARDCODE: maintain intrinsic icon bounds */
|
|
100
|
+
display: flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
justify-content: center;
|
|
103
|
+
|
|
104
|
+
width: var(--recursica_ui-kit_components_link_properties_icon-size);
|
|
105
|
+
height: var(--recursica_ui-kit_components_link_properties_icon-size);
|
|
106
|
+
color: var(
|
|
107
|
+
--recursica_ui-kit_components_link_variants_states_default_properties_colors_icon
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.root:hover .iconWrapper {
|
|
112
|
+
color: var(
|
|
113
|
+
--recursica_ui-kit_components_link_variants_states_hover_properties_colors_icon
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.root:visited .iconWrapper {
|
|
118
|
+
color: var(
|
|
119
|
+
--recursica_ui-kit_components_link_variants_states_visited_properties_colors_icon
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.root:visited:hover .iconWrapper {
|
|
124
|
+
color: var(
|
|
125
|
+
--recursica_ui-kit_components_link_variants_states_visited-hover_properties_colors_icon
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* Label text wrapper */
|
|
130
|
+
.labelText {
|
|
131
|
+
/* HARDCODE: allows text truncation if bounded */
|
|
132
|
+
min-width: 0;
|
|
133
|
+
}
|
|
@@ -1,17 +1,59 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1
3
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
4
|
import { Link } from "./Link";
|
|
3
|
-
import {
|
|
5
|
+
import { Text } from "@mantine/core";
|
|
4
6
|
|
|
5
7
|
const meta: Meta<typeof Link> = {
|
|
6
|
-
title: "UI-Kit
|
|
8
|
+
title: "UI-Kit/Link",
|
|
7
9
|
component: Link,
|
|
8
10
|
tags: ["autodocs"],
|
|
11
|
+
args: {
|
|
12
|
+
children: "Link text",
|
|
13
|
+
href: "#",
|
|
14
|
+
},
|
|
15
|
+
render: ({ withLayer, layer, ...args }: any) => <Link {...args} />,
|
|
9
16
|
};
|
|
10
17
|
|
|
11
18
|
export default meta;
|
|
12
19
|
|
|
13
20
|
type Story = StoryObj<typeof Link>;
|
|
14
21
|
|
|
15
|
-
export const Default: Story = {
|
|
16
|
-
|
|
22
|
+
export const Default: Story = {};
|
|
23
|
+
|
|
24
|
+
export const WithIcon: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
icon: (
|
|
27
|
+
<svg
|
|
28
|
+
width="24"
|
|
29
|
+
height="24"
|
|
30
|
+
viewBox="0 0 24 24"
|
|
31
|
+
fill="none"
|
|
32
|
+
stroke="currentColor"
|
|
33
|
+
strokeWidth="2"
|
|
34
|
+
strokeLinecap="round"
|
|
35
|
+
strokeLinejoin="round"
|
|
36
|
+
>
|
|
37
|
+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
|
|
38
|
+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
|
|
39
|
+
</svg>
|
|
40
|
+
),
|
|
41
|
+
children: "Link with Icon",
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const Polymorphic: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
component: "button",
|
|
48
|
+
onClick: () => alert("Button clicked!"),
|
|
49
|
+
children: "Rendered as <button>",
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const InlineText: Story = {
|
|
54
|
+
render: () => (
|
|
55
|
+
<Text>
|
|
56
|
+
Here is some text with an <Link href="#">inline link</Link> inside it.
|
|
57
|
+
</Text>
|
|
58
|
+
),
|
|
17
59
|
};
|