@financedistrict/apps-ui 0.1.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/LICENSE +19 -0
- package/README.md +119 -0
- package/dist/Radio-BYWz1n7p.d.cts +32 -0
- package/dist/Radio-BYWz1n7p.d.ts +32 -0
- package/dist/SelectTrigger-By0iPBI3.d.cts +78 -0
- package/dist/SelectTrigger-By0iPBI3.d.ts +78 -0
- package/dist/accordion.cjs +322 -0
- package/dist/accordion.d.cts +156 -0
- package/dist/accordion.d.ts +156 -0
- package/dist/accordion.js +2 -0
- package/dist/apps-ui.umd.js +1 -0
- package/dist/button.cjs +366 -0
- package/dist/button.d.cts +52 -0
- package/dist/button.d.ts +52 -0
- package/dist/button.js +3 -0
- package/dist/checkbox.cjs +74 -0
- package/dist/checkbox.d.cts +63 -0
- package/dist/checkbox.d.ts +63 -0
- package/dist/checkbox.js +2 -0
- package/dist/chunk-3RU7JMFE.js +27 -0
- package/dist/chunk-5TWRK4NW.js +783 -0
- package/dist/chunk-7EOSDFS3.js +9 -0
- package/dist/chunk-AIQ4UOGK.js +142 -0
- package/dist/chunk-B3MMGTPV.js +200 -0
- package/dist/chunk-DAHQYLUI.js +146 -0
- package/dist/chunk-DGBXADSS.js +1 -0
- package/dist/chunk-E6KPNTWW.js +295 -0
- package/dist/chunk-EOAB6G2D.js +149 -0
- package/dist/chunk-FAOVKDVM.js +32 -0
- package/dist/chunk-FV76Z4Z2.js +78 -0
- package/dist/chunk-GLTLBUZ7.js +285 -0
- package/dist/chunk-GTZFV43T.js +154 -0
- package/dist/chunk-HRGZNL4A.js +88 -0
- package/dist/chunk-IEVN3J2F.js +98 -0
- package/dist/chunk-IRS3T6LF.js +352 -0
- package/dist/chunk-IYYHCQXG.js +146 -0
- package/dist/chunk-JIXW3455.js +89 -0
- package/dist/chunk-N4VAP2GB.js +77 -0
- package/dist/chunk-SJ2ZRYVV.js +167 -0
- package/dist/chunk-SNU4YXOR.js +66 -0
- package/dist/chunk-TT6JQATV.js +99 -0
- package/dist/chunk-UPQ3ZPCO.js +66 -0
- package/dist/chunk-UVUSVFOH.js +264 -0
- package/dist/chunk-WJFPGGJB.js +255 -0
- package/dist/chunk-WXEBQA7A.js +371 -0
- package/dist/chunk-Y2O4YYZQ.js +184 -0
- package/dist/cut-corner.cjs +111 -0
- package/dist/cut-corner.d.cts +49 -0
- package/dist/cut-corner.d.ts +49 -0
- package/dist/cut-corner.js +1 -0
- package/dist/dialog.cjs +441 -0
- package/dist/dialog.d.cts +240 -0
- package/dist/dialog.d.ts +240 -0
- package/dist/dialog.js +3 -0
- package/dist/feature-card.cjs +182 -0
- package/dist/feature-card.d.cts +54 -0
- package/dist/feature-card.d.ts +54 -0
- package/dist/feature-card.js +2 -0
- package/dist/filter.cjs +873 -0
- package/dist/filter.d.cts +129 -0
- package/dist/filter.d.ts +129 -0
- package/dist/filter.js +6 -0
- package/dist/index.cjs +4583 -0
- package/dist/index.d.cts +29 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +27 -0
- package/dist/inline-select.cjs +856 -0
- package/dist/inline-select.d.cts +92 -0
- package/dist/inline-select.d.ts +92 -0
- package/dist/inline-select.js +6 -0
- package/dist/input.cjs +263 -0
- package/dist/input.d.cts +157 -0
- package/dist/input.d.ts +157 -0
- package/dist/input.js +4 -0
- package/dist/panel.cjs +185 -0
- package/dist/panel.d.cts +103 -0
- package/dist/panel.d.ts +103 -0
- package/dist/panel.js +2 -0
- package/dist/property-grid.cjs +110 -0
- package/dist/property-grid.d.cts +56 -0
- package/dist/property-grid.d.ts +56 -0
- package/dist/property-grid.js +2 -0
- package/dist/radio.cjs +74 -0
- package/dist/radio.d.cts +39 -0
- package/dist/radio.d.ts +39 -0
- package/dist/radio.js +2 -0
- package/dist/scrollbar.cjs +34 -0
- package/dist/scrollbar.d.cts +35 -0
- package/dist/scrollbar.d.ts +35 -0
- package/dist/scrollbar.js +1 -0
- package/dist/search-bar.cjs +408 -0
- package/dist/search-bar.d.cts +42 -0
- package/dist/search-bar.d.ts +42 -0
- package/dist/search-bar.js +4 -0
- package/dist/select.cjs +998 -0
- package/dist/select.d.cts +357 -0
- package/dist/select.d.ts +357 -0
- package/dist/select.js +5 -0
- package/dist/selectable-feature-card.cjs +159 -0
- package/dist/selectable-feature-card.d.cts +74 -0
- package/dist/selectable-feature-card.d.ts +74 -0
- package/dist/selectable-feature-card.js +3 -0
- package/dist/sidebar-item.cjs +175 -0
- package/dist/sidebar-item.d.cts +75 -0
- package/dist/sidebar-item.d.ts +75 -0
- package/dist/sidebar-item.js +2 -0
- package/dist/switch.cjs +86 -0
- package/dist/switch.d.cts +72 -0
- package/dist/switch.d.ts +72 -0
- package/dist/switch.js +2 -0
- package/dist/table-cell.cjs +196 -0
- package/dist/table-cell.d.cts +76 -0
- package/dist/table-cell.d.ts +76 -0
- package/dist/table-cell.js +2 -0
- package/dist/table-title.cjs +34 -0
- package/dist/table-title.d.cts +16 -0
- package/dist/table-title.d.ts +16 -0
- package/dist/table-title.js +2 -0
- package/dist/tabs.cjs +299 -0
- package/dist/tabs.d.cts +116 -0
- package/dist/tabs.d.ts +116 -0
- package/dist/tabs.js +2 -0
- package/dist/toast.cjs +87 -0
- package/dist/toast.d.cts +48 -0
- package/dist/toast.d.ts +48 -0
- package/dist/toast.js +2 -0
- package/dist/token-input.cjs +415 -0
- package/dist/token-input.d.cts +90 -0
- package/dist/token-input.d.ts +90 -0
- package/dist/token-input.js +3 -0
- package/dist/tooltip.cjs +384 -0
- package/dist/tooltip.d.cts +142 -0
- package/dist/tooltip.d.ts +142 -0
- package/dist/tooltip.js +2 -0
- package/package.json +200 -0
- package/src/fonts.css +33 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { SelectableFeatureCard, selectableFeatureCardBottomVariants, selectableFeatureCardRowVariants, selectableFeatureCardTextVariants, selectableFeatureCardTrailingVariants, selectableFeatureCardVariants } from './chunk-HRGZNL4A.js';
|
|
2
|
+
import './chunk-UPQ3ZPCO.js';
|
|
3
|
+
import './chunk-7EOSDFS3.js';
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var clsx = require('clsx');
|
|
5
|
+
var tailwindMerge = require('tailwind-merge');
|
|
6
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
|
|
9
|
+
function _interopNamespace(e) {
|
|
10
|
+
if (e && e.__esModule) return e;
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
28
|
+
|
|
29
|
+
// src/sidebar-item/SidebarItem.tsx
|
|
30
|
+
function cn(...inputs) {
|
|
31
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
32
|
+
}
|
|
33
|
+
var sidebarItemVariants = classVarianceAuthority.cva(
|
|
34
|
+
[
|
|
35
|
+
"group flex h-9 w-full items-center rounded-xs border-l-2 border-transparent px-3",
|
|
36
|
+
"no-underline transition-colors outline-none"
|
|
37
|
+
],
|
|
38
|
+
{
|
|
39
|
+
variants: {
|
|
40
|
+
active: {
|
|
41
|
+
true: "bg-brand-background border-brand-border",
|
|
42
|
+
false: ""
|
|
43
|
+
},
|
|
44
|
+
interactive: {
|
|
45
|
+
true: [
|
|
46
|
+
"cursor-pointer",
|
|
47
|
+
// Ring only — no fill/text change on focus (see file docstring).
|
|
48
|
+
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus"
|
|
49
|
+
],
|
|
50
|
+
false: ""
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
compoundVariants: [
|
|
54
|
+
// Hover fill only on a non-active, interactive item.
|
|
55
|
+
{ active: false, interactive: true, class: "hover:bg-background" }
|
|
56
|
+
],
|
|
57
|
+
defaultVariants: { active: false, interactive: false }
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
var sidebarItemLabelVariants = classVarianceAuthority.cva(
|
|
61
|
+
["button-01 min-w-0 flex-1 truncate"],
|
|
62
|
+
{
|
|
63
|
+
variants: {
|
|
64
|
+
active: {
|
|
65
|
+
true: "text-brand-foreground",
|
|
66
|
+
false: "text-foreground-muted"
|
|
67
|
+
},
|
|
68
|
+
interactive: { true: "", false: "" }
|
|
69
|
+
},
|
|
70
|
+
compoundVariants: [
|
|
71
|
+
{
|
|
72
|
+
active: false,
|
|
73
|
+
interactive: true,
|
|
74
|
+
class: "group-hover:text-foreground"
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
defaultVariants: { active: false, interactive: false }
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
function setRef(ref, node) {
|
|
81
|
+
if (typeof ref === "function") ref(node);
|
|
82
|
+
else if (ref) ref.current = node;
|
|
83
|
+
}
|
|
84
|
+
function SidebarItem({
|
|
85
|
+
active = false,
|
|
86
|
+
asChild = false,
|
|
87
|
+
href,
|
|
88
|
+
className,
|
|
89
|
+
children,
|
|
90
|
+
ref,
|
|
91
|
+
...props
|
|
92
|
+
}) {
|
|
93
|
+
const interactive = asChild || href != null;
|
|
94
|
+
const rootClassName = cn(
|
|
95
|
+
sidebarItemVariants({ active, interactive }),
|
|
96
|
+
className
|
|
97
|
+
);
|
|
98
|
+
const label = (labelNode) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
99
|
+
"span",
|
|
100
|
+
{
|
|
101
|
+
"data-slot": "sidebar-item-label",
|
|
102
|
+
className: sidebarItemLabelVariants({ active, interactive }),
|
|
103
|
+
children: labelNode
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
const dataState = active ? "active" : void 0;
|
|
107
|
+
const ariaCurrent = active ? "page" : void 0;
|
|
108
|
+
if (asChild) {
|
|
109
|
+
if (!React__namespace.isValidElement(children)) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
"SidebarItem: `asChild` requires a single React element child"
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const child = children;
|
|
115
|
+
const childProps = child.props;
|
|
116
|
+
return React__namespace.cloneElement(
|
|
117
|
+
child,
|
|
118
|
+
{
|
|
119
|
+
...props,
|
|
120
|
+
...childProps,
|
|
121
|
+
"data-slot": "sidebar-item",
|
|
122
|
+
"data-state": dataState,
|
|
123
|
+
"aria-current": ariaCurrent,
|
|
124
|
+
className: cn(
|
|
125
|
+
rootClassName,
|
|
126
|
+
childProps.className
|
|
127
|
+
),
|
|
128
|
+
ref: (node) => {
|
|
129
|
+
setRef(ref, node);
|
|
130
|
+
setRef(childProps.ref, node);
|
|
131
|
+
},
|
|
132
|
+
onClick: (event) => {
|
|
133
|
+
props.onClick?.(event);
|
|
134
|
+
childProps.onClick?.(event);
|
|
135
|
+
},
|
|
136
|
+
style: {
|
|
137
|
+
...props.style,
|
|
138
|
+
...childProps.style
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
label(childProps.children)
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
if (href != null) {
|
|
145
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
146
|
+
"a",
|
|
147
|
+
{
|
|
148
|
+
"data-slot": "sidebar-item",
|
|
149
|
+
"data-state": dataState,
|
|
150
|
+
"aria-current": ariaCurrent,
|
|
151
|
+
href,
|
|
152
|
+
className: rootClassName,
|
|
153
|
+
ref,
|
|
154
|
+
...props,
|
|
155
|
+
children: label(children)
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
160
|
+
"div",
|
|
161
|
+
{
|
|
162
|
+
"data-slot": "sidebar-item",
|
|
163
|
+
"data-state": dataState,
|
|
164
|
+
"aria-current": ariaCurrent,
|
|
165
|
+
className: rootClassName,
|
|
166
|
+
ref,
|
|
167
|
+
...props,
|
|
168
|
+
children: label(children)
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
exports.SidebarItem = SidebarItem;
|
|
174
|
+
exports.sidebarItemLabelVariants = sidebarItemLabelVariants;
|
|
175
|
+
exports.sidebarItemVariants = sidebarItemVariants;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
interface SidebarItemProps extends Omit<React.ComponentProps<"a">, "ref"> {
|
|
6
|
+
/**
|
|
7
|
+
* The current-route item — applies the brand-accent treatment (fill + left
|
|
8
|
+
* indicator + brand label) and sets `aria-current="page"`.
|
|
9
|
+
*/
|
|
10
|
+
active?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Render the single element child as the root (a router `<Link>` / `<a>`),
|
|
13
|
+
* keeping all sidebar-item styling. The child's own children become the
|
|
14
|
+
* label. Requires exactly one valid element child.
|
|
15
|
+
*/
|
|
16
|
+
asChild?: boolean;
|
|
17
|
+
/** Ref forwarded to the root element. */
|
|
18
|
+
ref?: React.Ref<HTMLElement>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A single navigation row for the app sidebar — the Figma `sidebar-item`. A
|
|
22
|
+
* polymorphic navigation control (an `<a>` when `href` is set, `asChild` to
|
|
23
|
+
* compose a router link, otherwise a presentational `<div>`) with a muted,
|
|
24
|
+
* truncating label that recolors on hover. Mark the current route with
|
|
25
|
+
* `active`: it takes the brand fill + left indicator and exposes
|
|
26
|
+
* `aria-current="page"`. Keyboard focus adds only the focus ring and leaves the
|
|
27
|
+
* item's fill and label unchanged.
|
|
28
|
+
*/
|
|
29
|
+
declare function SidebarItem({ active, asChild, href, className, children, ref, ...props }: SidebarItemProps): React.JSX.Element;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* SidebarItem styling — the Figma `sidebar-item` set (node `4949:4240`, states
|
|
33
|
+
* default / hover / focused / active). Binds ONLY to the neutral / brand / focus
|
|
34
|
+
* semantic token layer (never primitives / mode plumbing); theme switching is
|
|
35
|
+
* automatic via `.dark`, so no `dark:` variants.
|
|
36
|
+
*
|
|
37
|
+
* `state` in Figma is a mix of two orthogonal concerns, split here per house
|
|
38
|
+
* style (cf. TableCell): the interaction states (hover / focused) are CSS
|
|
39
|
+
* pseudo-classes on the root, not props; `active` — the item for the current
|
|
40
|
+
* route — is the one real prop.
|
|
41
|
+
*
|
|
42
|
+
* **Focus is ring-only.** `focus-visible` adds ONLY the shared focus ring and
|
|
43
|
+
* changes nothing else — the item's fill and label stay exactly as they are in
|
|
44
|
+
* whatever state it's in (default or `active`), so focusing the current-route
|
|
45
|
+
* item keeps its brand treatment. (This diverges from the Figma `focused`
|
|
46
|
+
* variant, which swapped in a white fill — per product direction the element
|
|
47
|
+
* must not change on focus.)
|
|
48
|
+
*
|
|
49
|
+
* The root is a Tailwind `group`; its own fill recolors on `hover:` and via the
|
|
50
|
+
* `active` variant (never on focus), while the label recolors through the same
|
|
51
|
+
* group (see `sidebarItemLabelVariants`). A 2px left border is reserved
|
|
52
|
+
* transparent in every state so selecting an item never shifts the label —
|
|
53
|
+
* `active` just colors it (`brand/border`).
|
|
54
|
+
*
|
|
55
|
+
* Hover / focus affordances are gated to `interactive: true` (an `<a>` / cloned
|
|
56
|
+
* link) so a presentational `<div>` root stays static, and hover is suppressed
|
|
57
|
+
* while `active` so the brand treatment always wins over the hover fill.
|
|
58
|
+
*/
|
|
59
|
+
declare const sidebarItemVariants: (props?: ({
|
|
60
|
+
active?: boolean | null | undefined;
|
|
61
|
+
interactive?: boolean | null | undefined;
|
|
62
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
63
|
+
/**
|
|
64
|
+
* The label — `button-01` (Archivo Medium 14/20), truncating. Muted by default;
|
|
65
|
+
* recolors to `foreground` on the root's hover (interactive, non-active only)
|
|
66
|
+
* and to `brand/foreground` while `active`. Focus does not recolor the label —
|
|
67
|
+
* the focus ring is the only focus affordance.
|
|
68
|
+
*/
|
|
69
|
+
declare const sidebarItemLabelVariants: (props?: ({
|
|
70
|
+
active?: boolean | null | undefined;
|
|
71
|
+
interactive?: boolean | null | undefined;
|
|
72
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
73
|
+
type SidebarItemVariantsProps = VariantProps<typeof sidebarItemVariants>;
|
|
74
|
+
|
|
75
|
+
export { SidebarItem, type SidebarItemProps, type SidebarItemVariantsProps, sidebarItemLabelVariants, sidebarItemVariants };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
interface SidebarItemProps extends Omit<React.ComponentProps<"a">, "ref"> {
|
|
6
|
+
/**
|
|
7
|
+
* The current-route item — applies the brand-accent treatment (fill + left
|
|
8
|
+
* indicator + brand label) and sets `aria-current="page"`.
|
|
9
|
+
*/
|
|
10
|
+
active?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Render the single element child as the root (a router `<Link>` / `<a>`),
|
|
13
|
+
* keeping all sidebar-item styling. The child's own children become the
|
|
14
|
+
* label. Requires exactly one valid element child.
|
|
15
|
+
*/
|
|
16
|
+
asChild?: boolean;
|
|
17
|
+
/** Ref forwarded to the root element. */
|
|
18
|
+
ref?: React.Ref<HTMLElement>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A single navigation row for the app sidebar — the Figma `sidebar-item`. A
|
|
22
|
+
* polymorphic navigation control (an `<a>` when `href` is set, `asChild` to
|
|
23
|
+
* compose a router link, otherwise a presentational `<div>`) with a muted,
|
|
24
|
+
* truncating label that recolors on hover. Mark the current route with
|
|
25
|
+
* `active`: it takes the brand fill + left indicator and exposes
|
|
26
|
+
* `aria-current="page"`. Keyboard focus adds only the focus ring and leaves the
|
|
27
|
+
* item's fill and label unchanged.
|
|
28
|
+
*/
|
|
29
|
+
declare function SidebarItem({ active, asChild, href, className, children, ref, ...props }: SidebarItemProps): React.JSX.Element;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* SidebarItem styling — the Figma `sidebar-item` set (node `4949:4240`, states
|
|
33
|
+
* default / hover / focused / active). Binds ONLY to the neutral / brand / focus
|
|
34
|
+
* semantic token layer (never primitives / mode plumbing); theme switching is
|
|
35
|
+
* automatic via `.dark`, so no `dark:` variants.
|
|
36
|
+
*
|
|
37
|
+
* `state` in Figma is a mix of two orthogonal concerns, split here per house
|
|
38
|
+
* style (cf. TableCell): the interaction states (hover / focused) are CSS
|
|
39
|
+
* pseudo-classes on the root, not props; `active` — the item for the current
|
|
40
|
+
* route — is the one real prop.
|
|
41
|
+
*
|
|
42
|
+
* **Focus is ring-only.** `focus-visible` adds ONLY the shared focus ring and
|
|
43
|
+
* changes nothing else — the item's fill and label stay exactly as they are in
|
|
44
|
+
* whatever state it's in (default or `active`), so focusing the current-route
|
|
45
|
+
* item keeps its brand treatment. (This diverges from the Figma `focused`
|
|
46
|
+
* variant, which swapped in a white fill — per product direction the element
|
|
47
|
+
* must not change on focus.)
|
|
48
|
+
*
|
|
49
|
+
* The root is a Tailwind `group`; its own fill recolors on `hover:` and via the
|
|
50
|
+
* `active` variant (never on focus), while the label recolors through the same
|
|
51
|
+
* group (see `sidebarItemLabelVariants`). A 2px left border is reserved
|
|
52
|
+
* transparent in every state so selecting an item never shifts the label —
|
|
53
|
+
* `active` just colors it (`brand/border`).
|
|
54
|
+
*
|
|
55
|
+
* Hover / focus affordances are gated to `interactive: true` (an `<a>` / cloned
|
|
56
|
+
* link) so a presentational `<div>` root stays static, and hover is suppressed
|
|
57
|
+
* while `active` so the brand treatment always wins over the hover fill.
|
|
58
|
+
*/
|
|
59
|
+
declare const sidebarItemVariants: (props?: ({
|
|
60
|
+
active?: boolean | null | undefined;
|
|
61
|
+
interactive?: boolean | null | undefined;
|
|
62
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
63
|
+
/**
|
|
64
|
+
* The label — `button-01` (Archivo Medium 14/20), truncating. Muted by default;
|
|
65
|
+
* recolors to `foreground` on the root's hover (interactive, non-active only)
|
|
66
|
+
* and to `brand/foreground` while `active`. Focus does not recolor the label —
|
|
67
|
+
* the focus ring is the only focus affordance.
|
|
68
|
+
*/
|
|
69
|
+
declare const sidebarItemLabelVariants: (props?: ({
|
|
70
|
+
active?: boolean | null | undefined;
|
|
71
|
+
interactive?: boolean | null | undefined;
|
|
72
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
73
|
+
type SidebarItemVariantsProps = VariantProps<typeof sidebarItemVariants>;
|
|
74
|
+
|
|
75
|
+
export { SidebarItem, type SidebarItemProps, type SidebarItemVariantsProps, sidebarItemLabelVariants, sidebarItemVariants };
|
package/dist/switch.cjs
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var clsx = require('clsx');
|
|
4
|
+
var tailwindMerge = require('tailwind-merge');
|
|
5
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
|
|
8
|
+
// src/lib/cn.ts
|
|
9
|
+
function cn(...inputs) {
|
|
10
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
11
|
+
}
|
|
12
|
+
var switchVariants = classVarianceAuthority.cva([
|
|
13
|
+
// Track — 56×24 (`h-6 w-14`), fully round (Figma `radius/full`), 4px inset
|
|
14
|
+
// (`p-1` = Figma `spacing/1`). `appearance-none` strips the native checkbox
|
|
15
|
+
// box; `peer` lets the sibling thumb react to :checked / :disabled.
|
|
16
|
+
"peer inline-flex h-6 w-14 shrink-0 items-center rounded-full border p-1",
|
|
17
|
+
"appearance-none cursor-pointer transition-colors",
|
|
18
|
+
// Off — default
|
|
19
|
+
"bg-button-secondary-background border-button-secondary-border",
|
|
20
|
+
// Off — hover strengthens the border (focused keeps the default border)
|
|
21
|
+
"hover:border-button-secondary-border-accent",
|
|
22
|
+
// Focus ring — suppress the native ring, draw the shared `--focus` ring the
|
|
23
|
+
// same way Checkbox/Radio do: 2px stroke, 2px offset (`outline-solid`
|
|
24
|
+
// restores what `outline-none` zeroed). Circular via the track's rounding.
|
|
25
|
+
"outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus",
|
|
26
|
+
// On — brand fill, border made transparent (kept for a constant box model)
|
|
27
|
+
"checked:bg-brand-primary-background checked:border-transparent",
|
|
28
|
+
"checked:hover:bg-brand-primary-accent",
|
|
29
|
+
// Disabled — off keeps the white track with a muted border; on drops to a
|
|
30
|
+
// neutral muted fill (per Figma). Border transparent when on, muted when off.
|
|
31
|
+
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:border-button-secondary-border-muted",
|
|
32
|
+
"checked:disabled:bg-button-primary-muted checked:disabled:border-transparent"
|
|
33
|
+
]);
|
|
34
|
+
function Switch({
|
|
35
|
+
className,
|
|
36
|
+
wrapperClassName,
|
|
37
|
+
onChange,
|
|
38
|
+
onCheckedChange,
|
|
39
|
+
...props
|
|
40
|
+
}) {
|
|
41
|
+
const handleChange = (event) => {
|
|
42
|
+
onChange?.(event);
|
|
43
|
+
onCheckedChange?.(event.currentTarget.checked);
|
|
44
|
+
};
|
|
45
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
46
|
+
"span",
|
|
47
|
+
{
|
|
48
|
+
className: cn(
|
|
49
|
+
"relative inline-flex shrink-0 items-center",
|
|
50
|
+
wrapperClassName
|
|
51
|
+
),
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
54
|
+
"input",
|
|
55
|
+
{
|
|
56
|
+
type: "checkbox",
|
|
57
|
+
role: "switch",
|
|
58
|
+
"data-slot": "switch",
|
|
59
|
+
className: cn(switchVariants(), className),
|
|
60
|
+
...props,
|
|
61
|
+
onChange: handleChange
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
65
|
+
"span",
|
|
66
|
+
{
|
|
67
|
+
"aria-hidden": "true",
|
|
68
|
+
"data-slot": "switch-thumb",
|
|
69
|
+
className: cn(
|
|
70
|
+
"pointer-events-none absolute left-1 h-4 w-6 rounded-full transition-transform",
|
|
71
|
+
// Off — dark knob at 90% opacity (Figma `opacity/90`)
|
|
72
|
+
"bg-button-secondary-foreground opacity-90",
|
|
73
|
+
"peer-checked:translate-x-5.5 peer-checked:bg-brand-primary-foreground peer-checked:opacity-100",
|
|
74
|
+
// Disabled — muted knob whether on or off (per Figma)
|
|
75
|
+
"peer-disabled:bg-button-secondary-foreground-muted peer-disabled:opacity-100",
|
|
76
|
+
"peer-checked:peer-disabled:bg-button-primary-foreground-muted"
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
exports.Switch = Switch;
|
|
86
|
+
exports.switchVariants = switchVariants;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
interface SwitchProps extends Omit<React.ComponentProps<"input">, "type" | "size"> {
|
|
6
|
+
/**
|
|
7
|
+
* Convenience change callback with the next checked state already
|
|
8
|
+
* extracted. Fires alongside (not instead of) the native `onChange`.
|
|
9
|
+
* Controlled/uncontrolled usage is the standard input contract:
|
|
10
|
+
* `defaultChecked` (uncontrolled, the default) or `checked` + a change
|
|
11
|
+
* handler (controlled).
|
|
12
|
+
*/
|
|
13
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
14
|
+
/** Class names for the outer wrapper span (positions the sliding thumb). */
|
|
15
|
+
wrapperClassName?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Switch control — the Figma `toggle-switch` set (node 5050:2204), rendered as
|
|
19
|
+
* a real `<input type="checkbox" role="switch">`. A toggle switch is a
|
|
20
|
+
* checkbox semantically (on/off), so the platform gives us Space to toggle,
|
|
21
|
+
* form participation (`FormData`), and label association for free; the `switch`
|
|
22
|
+
* ARIA role only refines the announcement ("on/off" instead of
|
|
23
|
+
* "checked/unchecked"). This is the one difference from Checkbox — otherwise it
|
|
24
|
+
* follows the ADR-0010 form-control conventions exactly (on = `:checked`, zero
|
|
25
|
+
* React state, `onCheckedChange` alongside native `onChange`).
|
|
26
|
+
*
|
|
27
|
+
* The visual is a track (the styled input) plus a sliding thumb (a sibling
|
|
28
|
+
* span, since a void `<input>` can't have children); the thumb slides via
|
|
29
|
+
* `peer-checked:` translate. Ships without a label (the Figma set is the bare
|
|
30
|
+
* 56×24 control): associate one by wrapping in a `<label>` or via
|
|
31
|
+
* `htmlFor`/`id`; icon-style usages need an `aria-label`.
|
|
32
|
+
*/
|
|
33
|
+
declare function Switch({ className, wrapperClassName, onChange, onCheckedChange, ...props }: SwitchProps): React.JSX.Element;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Switch styling — mirrors the Figma `toggle-switch` component set
|
|
37
|
+
* (node 5050:2204: `state` default/hover/focused/disabled × `selected` yes/no,
|
|
38
|
+
* one 56×24 size) and binds ONLY to the semantic token layer (never
|
|
39
|
+
* primitives). Theme switching is automatic via the `.dark` class, so no
|
|
40
|
+
* `dark:` variants are needed.
|
|
41
|
+
*
|
|
42
|
+
* As with Checkbox and Radio (ADR-0010), every Figma axis is an *interaction*
|
|
43
|
+
* state, so there is no prop-driven variant table: `selected` maps to the
|
|
44
|
+
* native `:checked` pseudo-class and `state` maps to `:hover` /
|
|
45
|
+
* `:focus-visible` / `:disabled`. This cva styles the TRACK (the `appearance-
|
|
46
|
+
* none` `<input>` itself); the sliding thumb is a sibling element revealed and
|
|
47
|
+
* translated via `peer-checked:` in <Switch>.
|
|
48
|
+
*
|
|
49
|
+
* Track state → token map (from the Figma variants):
|
|
50
|
+
* - off default: `bg-button-secondary-background` + `border-button-secondary-border`
|
|
51
|
+
* - off hover: border strengthens to `button-secondary-border-accent`
|
|
52
|
+
* - off focused: border stays `button-secondary-border` (+ the shared focus ring)
|
|
53
|
+
* - off disabled: border weakens to `button-secondary-border-muted`
|
|
54
|
+
* - on (default/focused): `bg-brand-primary-background`, border removed
|
|
55
|
+
* - on hover: bg strengthens to `brand-primary-accent`
|
|
56
|
+
* - on disabled: neutral `bg-button-primary-muted`, border removed
|
|
57
|
+
*
|
|
58
|
+
* Checked × hover/disabled combinations are compound utilities
|
|
59
|
+
* (`checked:hover:`, `checked:disabled:`) so precedence rides on selector
|
|
60
|
+
* specificity, not Tailwind's stylesheet order. The border is always declared
|
|
61
|
+
* (`border`) so the track's box model is identical on/off — the on states set
|
|
62
|
+
* `border-transparent` rather than removing the border, keeping the 46px inner
|
|
63
|
+
* track width (and therefore the 22px thumb travel) constant across states.
|
|
64
|
+
*
|
|
65
|
+
* Focus ring: the ADR-0010 system standard (2px `--focus` stroke, 2px offset,
|
|
66
|
+
* `:focus-visible` only), following the track's `rounded-full` radius — the
|
|
67
|
+
* same treatment as Checkbox/Radio, overriding whatever the Figma node draws.
|
|
68
|
+
*/
|
|
69
|
+
declare const switchVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
70
|
+
type SwitchVariantsProps = VariantProps<typeof switchVariants>;
|
|
71
|
+
|
|
72
|
+
export { Switch, type SwitchProps, type SwitchVariantsProps, switchVariants };
|
package/dist/switch.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
interface SwitchProps extends Omit<React.ComponentProps<"input">, "type" | "size"> {
|
|
6
|
+
/**
|
|
7
|
+
* Convenience change callback with the next checked state already
|
|
8
|
+
* extracted. Fires alongside (not instead of) the native `onChange`.
|
|
9
|
+
* Controlled/uncontrolled usage is the standard input contract:
|
|
10
|
+
* `defaultChecked` (uncontrolled, the default) or `checked` + a change
|
|
11
|
+
* handler (controlled).
|
|
12
|
+
*/
|
|
13
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
14
|
+
/** Class names for the outer wrapper span (positions the sliding thumb). */
|
|
15
|
+
wrapperClassName?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Switch control — the Figma `toggle-switch` set (node 5050:2204), rendered as
|
|
19
|
+
* a real `<input type="checkbox" role="switch">`. A toggle switch is a
|
|
20
|
+
* checkbox semantically (on/off), so the platform gives us Space to toggle,
|
|
21
|
+
* form participation (`FormData`), and label association for free; the `switch`
|
|
22
|
+
* ARIA role only refines the announcement ("on/off" instead of
|
|
23
|
+
* "checked/unchecked"). This is the one difference from Checkbox — otherwise it
|
|
24
|
+
* follows the ADR-0010 form-control conventions exactly (on = `:checked`, zero
|
|
25
|
+
* React state, `onCheckedChange` alongside native `onChange`).
|
|
26
|
+
*
|
|
27
|
+
* The visual is a track (the styled input) plus a sliding thumb (a sibling
|
|
28
|
+
* span, since a void `<input>` can't have children); the thumb slides via
|
|
29
|
+
* `peer-checked:` translate. Ships without a label (the Figma set is the bare
|
|
30
|
+
* 56×24 control): associate one by wrapping in a `<label>` or via
|
|
31
|
+
* `htmlFor`/`id`; icon-style usages need an `aria-label`.
|
|
32
|
+
*/
|
|
33
|
+
declare function Switch({ className, wrapperClassName, onChange, onCheckedChange, ...props }: SwitchProps): React.JSX.Element;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Switch styling — mirrors the Figma `toggle-switch` component set
|
|
37
|
+
* (node 5050:2204: `state` default/hover/focused/disabled × `selected` yes/no,
|
|
38
|
+
* one 56×24 size) and binds ONLY to the semantic token layer (never
|
|
39
|
+
* primitives). Theme switching is automatic via the `.dark` class, so no
|
|
40
|
+
* `dark:` variants are needed.
|
|
41
|
+
*
|
|
42
|
+
* As with Checkbox and Radio (ADR-0010), every Figma axis is an *interaction*
|
|
43
|
+
* state, so there is no prop-driven variant table: `selected` maps to the
|
|
44
|
+
* native `:checked` pseudo-class and `state` maps to `:hover` /
|
|
45
|
+
* `:focus-visible` / `:disabled`. This cva styles the TRACK (the `appearance-
|
|
46
|
+
* none` `<input>` itself); the sliding thumb is a sibling element revealed and
|
|
47
|
+
* translated via `peer-checked:` in <Switch>.
|
|
48
|
+
*
|
|
49
|
+
* Track state → token map (from the Figma variants):
|
|
50
|
+
* - off default: `bg-button-secondary-background` + `border-button-secondary-border`
|
|
51
|
+
* - off hover: border strengthens to `button-secondary-border-accent`
|
|
52
|
+
* - off focused: border stays `button-secondary-border` (+ the shared focus ring)
|
|
53
|
+
* - off disabled: border weakens to `button-secondary-border-muted`
|
|
54
|
+
* - on (default/focused): `bg-brand-primary-background`, border removed
|
|
55
|
+
* - on hover: bg strengthens to `brand-primary-accent`
|
|
56
|
+
* - on disabled: neutral `bg-button-primary-muted`, border removed
|
|
57
|
+
*
|
|
58
|
+
* Checked × hover/disabled combinations are compound utilities
|
|
59
|
+
* (`checked:hover:`, `checked:disabled:`) so precedence rides on selector
|
|
60
|
+
* specificity, not Tailwind's stylesheet order. The border is always declared
|
|
61
|
+
* (`border`) so the track's box model is identical on/off — the on states set
|
|
62
|
+
* `border-transparent` rather than removing the border, keeping the 46px inner
|
|
63
|
+
* track width (and therefore the 22px thumb travel) constant across states.
|
|
64
|
+
*
|
|
65
|
+
* Focus ring: the ADR-0010 system standard (2px `--focus` stroke, 2px offset,
|
|
66
|
+
* `:focus-visible` only), following the track's `rounded-full` radius — the
|
|
67
|
+
* same treatment as Checkbox/Radio, overriding whatever the Figma node draws.
|
|
68
|
+
*/
|
|
69
|
+
declare const switchVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
70
|
+
type SwitchVariantsProps = VariantProps<typeof switchVariants>;
|
|
71
|
+
|
|
72
|
+
export { Switch, type SwitchProps, type SwitchVariantsProps, switchVariants };
|
package/dist/switch.js
ADDED