banhatten-ui 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "Slider",
3
+ "description": "Range slider supporting single-handle and double-handle (range) modes. Uses ProgressBar track styling and SliderHandle for thumb.",
4
+
5
+ "base": {
6
+ "display": "flex",
7
+ "flexDirection": "column",
8
+ "width": "100%"
9
+ },
10
+
11
+ "track": {
12
+ "height": "8px",
13
+ "borderRadius": "{radius.full}",
14
+ "bg": "{alias.bg-tertiary}"
15
+ },
16
+
17
+ "fill": {
18
+ "bg": "{alias.bg-brand}",
19
+ "borderRadius": "{radius.full}"
20
+ },
21
+
22
+ "variants": {
23
+ "single": {
24
+ "description": "One handle. Fill from 0 to value."
25
+ },
26
+ "double": {
27
+ "description": "Two handles. Fill between start and end values."
28
+ }
29
+ },
30
+
31
+ "states": {
32
+ "disabled": {
33
+ "pointerEvents": "none",
34
+ "cursor": "default"
35
+ }
36
+ },
37
+
38
+ "props": {
39
+ "variant": { "type": "enum", "values": ["single", "double"], "default": "single" },
40
+ "value": { "type": "number | [number, number]", "description": "Current value. Number for single, tuple for double." },
41
+ "min": { "type": "number", "default": 0 },
42
+ "max": { "type": "number", "default": 100 },
43
+ "step": { "type": "number", "default": 1 },
44
+ "label": { "type": "ReactNode", "description": "Label text above the slider." },
45
+ "showLabelInfoIcon": { "type": "boolean", "default": false },
46
+ "helperText": { "type": "ReactNode", "description": "Helper text below the slider." },
47
+ "valueLabelVariant": { "type": "enum", "values": ["tooltip", "label"], "description": "How to display the value on the handle." },
48
+ "valueLabelPosition": { "type": "enum", "values": ["above", "below"], "default": "below" },
49
+ "formatValue": { "type": "function", "description": "(value: number) => string. Formats the displayed value." },
50
+ "disabled": { "type": "boolean", "default": false }
51
+ },
52
+
53
+ "slots": {
54
+ "label": { "position": "above", "fontSize": "14px", "fontWeight": 500, "color": "{alias.text-primary}", "marginBottom": "{spacing.sm}" },
55
+ "helperText": { "position": "below", "fontSize": "14px", "color": "{alias.text-secondary}", "marginTop": "{spacing.sm}" },
56
+ "infoIcon": { "element": "Icon", "name": "info", "size": "xs", "color": "{alias.icon-tertiary}" }
57
+ },
58
+
59
+ "subComponents": {
60
+ "SliderHandle": {
61
+ "description": "Draggable handle positioned on the track. Fixed 24x24px circle.",
62
+ "base": {
63
+ "size": "24px",
64
+ "borderRadius": "{radius.full}",
65
+ "border": { "width": "1px", "color": "{alias.border-brand}" },
66
+ "bg": "{alias.bg-primary}",
67
+ "shadow": "{shadow.sm}",
68
+ "cursor": "grab",
69
+ "transition": "background-color"
70
+ },
71
+ "states": {
72
+ "hover": { "bg": "{alias.bg-brand-tertiary}" },
73
+ "active": { "bg": "{alias.bg-brand-secondary}", "cursor": "grabbing" }
74
+ },
75
+ "props": {
76
+ "valueLabel": { "type": "ReactNode", "description": "Value to display as tooltip or label." },
77
+ "labelVariant": { "type": "enum", "values": ["tooltip", "label"] },
78
+ "labelPosition": { "type": "enum", "values": ["above", "below"], "default": "below" }
79
+ },
80
+ "valueLabelStyles": {
81
+ "tooltip": { "uses": "Tooltip component", "variant": "light", "offset": "8px" },
82
+ "label": { "fontSize": "12px", "color": "{alias.text-primary}", "offset": "8px" }
83
+ }
84
+ }
85
+ },
86
+
87
+ "accessibility": {
88
+ "role": "group",
89
+ "notes": "Hidden range input(s) for keyboard navigation. aria-valuenow, aria-valuemin, aria-valuemax, aria-valuetext on inputs. Double variant labels inputs as 'start' and 'end'."
90
+ }
91
+ }
@@ -0,0 +1,104 @@
1
+ {
2
+ "name": "Tag",
3
+ "description": "Interactive label chip supporting simple text, dot indicator, and icon variants. Selectable with optional close action.",
4
+
5
+ "base": {
6
+ "display": "inline-flex",
7
+ "alignItems": "center",
8
+ "justifyContent": "center",
9
+ "borderRadius": "{radius.sm}",
10
+ "fontWeight": 400,
11
+ "flexShrink": 0,
12
+ "gap": "4px",
13
+ "border": { "width": "1px" },
14
+ "transition": "background-color, border-color, color"
15
+ },
16
+
17
+ "variants": {
18
+ "simple": {},
19
+ "with-dot": {},
20
+ "with-icon": {}
21
+ },
22
+
23
+ "sizes": {
24
+ "small": { "height": "24px", "paddingX": "{spacing.sm}", "fontSize": "12px", "lineHeight": "16px" },
25
+ "large": { "height": "28px", "paddingX": "{spacing.md}", "fontSize": "14px", "lineHeight": "20px" }
26
+ },
27
+
28
+ "states": {
29
+ "default": {
30
+ "bg": "{alias.bg-primary}",
31
+ "border": { "color": "{alias.border-strong}" },
32
+ "text": "{alias.text-primary}",
33
+ "hover": { "bg": "{alias.highlight-hover}" }
34
+ },
35
+ "focus": {
36
+ "bg": "{alias.bg-primary}",
37
+ "border": { "color": "{alias.border-brand}" },
38
+ "text": "{alias.text-brand}"
39
+ },
40
+ "active": {
41
+ "bg": "{alias.bg-brand-tertiary}",
42
+ "border": { "color": "{alias.border-brand}" },
43
+ "text": "{alias.text-primary}",
44
+ "hover": { "bg": "{alias.bg-brand-tertiary}" }
45
+ },
46
+ "disabled": {
47
+ "bg": "{alias.bg-secondary}",
48
+ "border": { "color": "{alias.border-inactive-subtle}" },
49
+ "text": "{alias.text-inactive}",
50
+ "pointerEvents": "none"
51
+ }
52
+ },
53
+
54
+ "props": {
55
+ "type": { "type": "enum", "values": ["simple", "with-dot", "with-icon"], "default": "simple" },
56
+ "state": { "type": "enum", "values": ["default", "focus", "active", "disabled"], "default": "default" },
57
+ "size": { "type": "enum", "values": ["small", "large"], "default": "small" },
58
+ "leftIcon": { "type": "string", "default": "calendar_month", "description": "Material Symbol name for leading icon (type='with-icon')." },
59
+ "iconVariant": { "type": "enum", "values": ["outlined", "rounded", "sharp"], "default": "outlined" },
60
+ "iconFilled": { "type": "boolean", "default": false },
61
+ "close": { "type": "boolean", "default": false, "description": "Whether to show a close button on the right." },
62
+ "onClose": { "type": "function", "description": "Callback fired when the close button is clicked." }
63
+ },
64
+
65
+ "slots": {
66
+ "dot": {
67
+ "position": "start",
68
+ "size": "6px",
69
+ "borderRadius": "{radius.full}",
70
+ "defaultColor": "{alias.bg-success}",
71
+ "disabledColor": "currentColor"
72
+ },
73
+ "leftIcon": {
74
+ "position": "start",
75
+ "element": "Icon",
76
+ "iconSizeByTagSize": { "small": "xs", "large": "sm" },
77
+ "colorByState": {
78
+ "default": "{alias.text-primary}",
79
+ "focus": "{alias.text-brand}",
80
+ "active": "{alias.text-brand}",
81
+ "disabled": "{alias.text-inactive}"
82
+ }
83
+ },
84
+ "closeButton": {
85
+ "position": "end",
86
+ "element": "CloseButton",
87
+ "variant": "ghost",
88
+ "size": "sm",
89
+ "colorByState": {
90
+ "default": "{alias.text-primary}",
91
+ "focus": "{alias.text-brand}",
92
+ "active": "{alias.text-brand}",
93
+ "disabled": "{alias.text-inactive}"
94
+ }
95
+ }
96
+ },
97
+
98
+ "defaults": { "type": "simple", "state": "default", "size": "small" },
99
+
100
+ "accessibility": {
101
+ "role": "status",
102
+ "notes": "Rendered as a <span>. Dot and icon are aria-hidden. Close button has aria-label='Remove tag'."
103
+ }
104
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "TextArea",
3
+ "description": "Multi-line text input with label, helper text, error state, and character counter.",
4
+
5
+ "base": {
6
+ "display": "flex",
7
+ "width": "100%",
8
+ "alignItems": "flex-start",
9
+ "bg": "{alias.component-input-bg}",
10
+ "border": { "width": "1px", "color": "{alias.border-strong}" },
11
+ "borderRadius": "{radius.sm}",
12
+ "shadow": "{shadow.xs}",
13
+ "transition": "border-color",
14
+ "minHeight": "88px",
15
+ "paddingX": "{spacing.sm}",
16
+ "paddingY": "{spacing.sm}",
17
+ "fontSize": "14px",
18
+ "lineHeight": "20px"
19
+ },
20
+
21
+ "states": {
22
+ "disabled": {
23
+ "bg": "{alias.bg-secondary}",
24
+ "border": { "color": "{alias.border-inactive}" },
25
+ "shadow": "none",
26
+ "pointerEvents": "none",
27
+ "text": "{alias.text-inactive}"
28
+ },
29
+ "error": {
30
+ "border": { "color": "{alias.border-danger-secondary}" }
31
+ },
32
+ "focused": {
33
+ "border": { "color": "{alias.border-brand}" },
34
+ "focusRing": { "width": "4px", "color": "{alias.border-focused}", "inset": "-1px", "borderRadius": "{radius.sm}" }
35
+ },
36
+ "focused+error": {
37
+ "border": { "color": "{alias.border-danger}" },
38
+ "focusRing": { "width": "4px", "color": "{alias.border-focused-danger}", "inset": "-1px", "borderRadius": "{radius.sm}" }
39
+ }
40
+ },
41
+
42
+ "props": {
43
+ "label": { "type": "string", "description": "Label text above the textarea." },
44
+ "optional": { "type": "boolean", "default": false, "description": "Displays (Optional) + info icon next to label." },
45
+ "helperText": { "type": "string", "description": "Helper text below the textarea." },
46
+ "helperTextIcon": { "type": "string", "description": "Material Symbol name for helper text icon." },
47
+ "errorMessage": { "type": "string", "description": "Error message below the textarea. Overrides helperText." },
48
+ "maxLength": { "type": "number", "description": "Shows character counter beside the textarea." },
49
+ "rows": { "type": "number", "default": 4 },
50
+ "disabled": { "type": "boolean", "default": false }
51
+ },
52
+
53
+ "slots": {
54
+ "label": { "position": "above", "fontSize": "14px", "fontWeight": 500, "color": "{alias.text-primary}", "marginBottom": "{spacing.sm}" },
55
+ "helperText": { "position": "below", "fontSize": "14px", "color": "{alias.text-secondary}", "errorColor": "{alias.text-error}", "marginTop": "{spacing.sm}" },
56
+ "characterCounter": { "position": "end-outside", "fontSize": "14px", "color": "{alias.text-tertiary}", "errorColor": "{alias.text-error}" }
57
+ },
58
+
59
+ "accessibility": {
60
+ "role": "textbox",
61
+ "notes": "aria-invalid set when error. aria-describedby links to helperText or errorMessage."
62
+ }
63
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "Toggle",
3
+ "description": "Switch/toggle control with optional label and support text. Supports icon mode showing check/close on the thumb.",
4
+
5
+ "base": {
6
+ "display": "inline-flex",
7
+ "gap": "{spacing.md}",
8
+ "cursor": "pointer"
9
+ },
10
+
11
+ "track": {
12
+ "borderRadius": "{radius.full}",
13
+ "padding": "2px",
14
+ "transition": "background-color",
15
+ "off": {
16
+ "bg": "{alias.bg-quarterary}",
17
+ "hover": { "bg": "rgba(from {alias.bg-quarterary} r g b / 0.8)" }
18
+ },
19
+ "on": {
20
+ "bg": "{alias.component-toggle-brand-bg}",
21
+ "hover": { "bg": "{alias.component-toggle-brand-bg-hover}" }
22
+ }
23
+ },
24
+
25
+ "thumb": {
26
+ "borderRadius": "{radius.full}",
27
+ "bg": "{alias.bg-primary}",
28
+ "shadow": "{shadow.md}",
29
+ "transition": "transform"
30
+ },
31
+
32
+ "sizes": {
33
+ "sm": {
34
+ "track": { "height": "20px", "width": "32px" },
35
+ "thumb": { "size": "14px", "translateX": "12px" }
36
+ },
37
+ "md": {
38
+ "track": { "height": "24px", "width": "40px" },
39
+ "thumb": { "size": "20px", "translateX": "16px" }
40
+ }
41
+ },
42
+
43
+ "states": {
44
+ "disabled": {
45
+ "cursor": "default",
46
+ "track": { "bg": "{alias.bg-inactive-subtle}" },
47
+ "thumb": { "bg": "{alias.bg-quarterary}", "shadow": "none" },
48
+ "labelColor": "{alias.text-inactive}"
49
+ },
50
+ "focus": {
51
+ "ring": "2px",
52
+ "ringColor": "{alias.border-brand}",
53
+ "ringOffset": "2px"
54
+ }
55
+ },
56
+
57
+ "props": {
58
+ "size": { "type": "enum", "values": ["sm", "md"], "default": "md" },
59
+ "label": { "type": "string", "description": "Label text next to the toggle." },
60
+ "supportText": { "type": "string", "description": "Support text below the label." },
61
+ "togglePosition": { "type": "enum", "values": ["leading", "trailing"], "default": "trailing" },
62
+ "withIcon": { "type": "boolean", "default": false, "description": "Show check icon when on, close icon when off." },
63
+ "checked": { "type": "boolean" },
64
+ "disabled": { "type": "boolean", "default": false }
65
+ },
66
+
67
+ "slots": {
68
+ "label": { "fontSize": "14px", "fontWeight": 500, "lineHeight": "16px", "color": "{alias.text-primary}" },
69
+ "supportText": { "fontSize": "14px", "lineHeight": "20px", "color": "{alias.text-secondary}", "gap": "{spacing.xxs}" },
70
+ "thumbIcon": { "element": "Icon", "size": "xs", "onIcon": "check", "offIcon": "close" }
71
+ },
72
+
73
+ "defaults": { "size": "md" },
74
+
75
+ "accessibility": {
76
+ "role": "switch",
77
+ "notes": "aria-checked reflects on/off state. Native checkbox input is visually hidden."
78
+ }
79
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "Tooltip",
3
+ "description": "Floating overlay that surfaces contextual information on hover/focus. Supports single-line (small) and title+subtitle (large) layouts with dark and light color schemes.",
4
+
5
+ "base": {
6
+ "borderRadius": "{radius.sm}",
7
+ "fontSize": "12px",
8
+ "lineHeight": "20px",
9
+ "maxWidth": "var(--radix-tooltip-content-available-width)",
10
+ "zIndex": 50,
11
+ "transition": "opacity 150ms ease-out"
12
+ },
13
+
14
+ "variants": {
15
+ "dark": {
16
+ "bg": "{alias.bg-always-dark}",
17
+ "text": "{alias.text-on-color}",
18
+ "subtitleColor": "{alias.text-on-color}",
19
+ "arrowFill": "{alias.bg-primary-inverse}"
20
+ },
21
+ "light": {
22
+ "bg": "{alias.bg-primary}",
23
+ "text": "{alias.text-primary}",
24
+ "subtitleColor": "{alias.text-on-color-inverse}",
25
+ "border": { "width": "1px", "color": "{alias.border-default}" },
26
+ "shadow": "{shadow.lg}",
27
+ "arrowFill": "#ffffff"
28
+ }
29
+ },
30
+
31
+ "sizes": {
32
+ "small": { "paddingX": "{spacing.md}", "paddingY": "{spacing.sm}" },
33
+ "large": { "paddingX": "{spacing.md}", "paddingY": "{spacing.md}", "display": "flex", "flexDirection": "column", "gap": "{spacing.xs}" }
34
+ },
35
+
36
+ "states": {
37
+ "open": { "opacity": 1 },
38
+ "closed": { "opacity": 0 }
39
+ },
40
+
41
+ "props": {
42
+ "content": { "type": "ReactNode", "description": "Single-line content (size='small')." },
43
+ "title": { "type": "string", "description": "Title text (size='large'). Auto-infers size='large' when provided." },
44
+ "subtitle": { "type": "string", "description": "Subtitle text (size='large'). Auto-infers size='large' when provided." },
45
+ "size": { "type": "enum", "values": ["small", "large"], "default": "small", "description": "Small: single text line. Large: title + subtitle. Auto-inferred from title/subtitle when omitted." },
46
+ "variant": { "type": "enum", "values": ["dark", "light"], "default": "dark" },
47
+ "side": { "type": "enum", "values": ["top", "bottom", "left", "right"], "default": "bottom" },
48
+ "sideOffset": { "type": "number", "default": 8, "description": "Distance in px between the tooltip and the trigger." },
49
+ "delayDuration": { "type": "number", "default": 200, "description": "Delay in ms before showing." },
50
+ "showArrow": { "type": "boolean", "default": true, "description": "When false, the arrow/pointer is not rendered." }
51
+ },
52
+
53
+ "slots": {
54
+ "title": {
55
+ "fontWeight": 500
56
+ },
57
+ "subtitle": {
58
+ "fontWeight": 400
59
+ },
60
+ "arrow": {
61
+ "width": "12px",
62
+ "height": "6px"
63
+ }
64
+ },
65
+
66
+ "subComponents": {
67
+ "TooltipProvider": { "description": "Context provider for shared tooltip delay configuration." },
68
+ "TooltipTrigger": { "description": "Wraps the trigger element. Uses asChild pattern." },
69
+ "TooltipContent": { "description": "The tooltip popup content. Accepts size, variant, title, subtitle, showArrow props." }
70
+ },
71
+
72
+ "defaults": { "variant": "dark", "size": "small", "side": "bottom", "sideOffset": 8, "delayDuration": 200, "showArrow": true },
73
+
74
+ "accessibility": {
75
+ "role": "tooltip",
76
+ "notes": "Built on Radix UI Tooltip primitives. Trigger uses asChild. Content is portaled. Keyboard accessible via focus."
77
+ }
78
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "banhatten-ui",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Banhatten Design System - React component library with token-based theming",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -21,7 +21,9 @@
21
21
  "types": "./dist/tokens/tailwind.config.d.ts",
22
22
  "import": "./dist/tokens/tailwind.config.mjs",
23
23
  "require": "./dist/tokens/tailwind.config.js"
24
- }
24
+ },
25
+ "./specs/*": "./dist/specs/*.json",
26
+ "./CURSOR_RULE.md": "./dist/CURSOR_RULE.md"
25
27
  },
26
28
  "files": [
27
29
  "dist",