torch-glare-mcp 1.6.0 → 1.6.2
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/README.md +81 -0
- package/apps/lib/components/ActionButton.tsx +60 -0
- package/apps/lib/components/ActionsGroup.tsx +27 -0
- package/apps/lib/components/AlertDialog.tsx +204 -0
- package/apps/lib/components/Avatar.tsx +46 -0
- package/apps/lib/components/Badge.tsx +247 -0
- package/apps/lib/components/BadgeField.tsx +334 -0
- package/apps/lib/components/Breadcrumb.tsx +280 -0
- package/apps/lib/components/Button.tsx +317 -0
- package/apps/lib/components/ButtonGroup.tsx +190 -0
- package/apps/lib/components/Calendar.tsx +125 -0
- package/apps/lib/components/Card.tsx +94 -0
- package/apps/lib/components/Checkbox.tsx +42 -0
- package/apps/lib/components/ColorPicker.tsx +441 -0
- package/apps/lib/components/ConclusionHeader.tsx +148 -0
- package/apps/lib/components/ContextMenu.tsx +528 -0
- package/apps/lib/components/CountBadge.tsx +52 -0
- package/apps/lib/components/DataTable.tsx +213 -0
- package/apps/lib/components/DataViews/DataViewRadio.tsx +49 -0
- package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +393 -0
- package/apps/lib/components/DataViews/DataViewsHeader.tsx +207 -0
- package/apps/lib/components/DataViews/DataViewsLayout.tsx +332 -0
- package/apps/lib/components/DataViews/FilterPanel.tsx +493 -0
- package/apps/lib/components/DataViews/HeaderSearch.tsx +93 -0
- package/apps/lib/components/DataViews/InboxView.tsx +463 -0
- package/apps/lib/components/DataViews/InboxViewCard.tsx +127 -0
- package/apps/lib/components/DataViews/KanbanView.tsx +336 -0
- package/apps/lib/components/DataViews/PanelControls.tsx +39 -0
- package/apps/lib/components/DataViews/SettingsPanel.tsx +279 -0
- package/apps/lib/components/DataViews/TableView.tsx +212 -0
- package/apps/lib/components/DataViews/TreeView.tsx +364 -0
- package/apps/lib/components/DataViews/badgeAdapter.ts +49 -0
- package/apps/lib/components/DataViews/fieldRenderers.tsx +299 -0
- package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +87 -0
- package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +120 -0
- package/apps/lib/components/DataViews/filters/PresetChips.tsx +45 -0
- package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +165 -0
- package/apps/lib/components/DataViews/index.ts +36 -0
- package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +50 -0
- package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +74 -0
- package/apps/lib/components/DataViews/types.ts +203 -0
- package/apps/lib/components/DatePicker.tsx +232 -0
- package/apps/lib/components/Dialog.tsx +116 -0
- package/apps/lib/components/Divider.tsx +28 -0
- package/apps/lib/components/Drawer.tsx +403 -0
- package/apps/lib/components/DropdownMenu.tsx +497 -0
- package/apps/lib/components/FieldHint.tsx +69 -0
- package/apps/lib/components/Form.tsx +182 -0
- package/apps/lib/components/FormBuilder/DisplayField.tsx +40 -0
- package/apps/lib/components/FormBuilder/context.ts +71 -0
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +65 -0
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +76 -0
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +16 -0
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +34 -0
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +79 -0
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +174 -0
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +40 -0
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +139 -0
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +32 -0
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +82 -0
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +37 -0
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +101 -0
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +175 -0
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +72 -0
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +42 -0
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +312 -0
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +222 -0
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +49 -0
- package/apps/lib/components/FormBuilder/fields/countries.ts +303 -0
- package/apps/lib/components/FormBuilder/fields/index.ts +25 -0
- package/apps/lib/components/FormBuilder/form-builder.tsx +292 -0
- package/apps/lib/components/FormBuilder/header.tsx +105 -0
- package/apps/lib/components/FormBuilder/index.ts +37 -0
- package/apps/lib/components/FormBuilder/numberFormat.ts +16 -0
- package/apps/lib/components/FormBuilder/stepper.tsx +217 -0
- package/apps/lib/components/FormBuilder/submit.tsx +41 -0
- package/apps/lib/components/FormBuilder/types.ts +264 -0
- package/apps/lib/components/FormBuilder/viewFormat.tsx +137 -0
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +121 -0
- package/apps/lib/components/FormRenderer/form-renderer.tsx +113 -0
- package/apps/lib/components/FormRenderer/index.ts +9 -0
- package/apps/lib/components/FormRenderer/types.ts +79 -0
- package/apps/lib/components/FormStepper.tsx +272 -0
- package/apps/lib/components/FormSummary.tsx +282 -0
- package/apps/lib/components/HeaderBar.tsx +119 -0
- package/apps/lib/components/ImageAttachment.tsx +209 -0
- package/apps/lib/components/InnerLabelField.tsx +154 -0
- package/apps/lib/components/Input.tsx +206 -0
- package/apps/lib/components/InputField.tsx +148 -0
- package/apps/lib/components/InputOTP.tsx +84 -0
- package/apps/lib/components/Label.tsx +129 -0
- package/apps/lib/components/LabelField.tsx +76 -0
- package/apps/lib/components/LabeledCheckBox.tsx +51 -0
- package/apps/lib/components/LabeledRadio.tsx +51 -0
- package/apps/lib/components/LinkButton.tsx +94 -0
- package/apps/lib/components/LoginButton.tsx +51 -0
- package/apps/lib/components/PasswordLevel.tsx +58 -0
- package/apps/lib/components/Popover.tsx +256 -0
- package/apps/lib/components/ProfileMenu.tsx +85 -0
- package/apps/lib/components/Radio.tsx +59 -0
- package/apps/lib/components/RadioCard.tsx +50 -0
- package/apps/lib/components/ScrollArea.tsx +54 -0
- package/apps/lib/components/SearchField.tsx +62 -0
- package/apps/lib/components/SearchableSelect.tsx +308 -0
- package/apps/lib/components/SearchableTable.tsx +343 -0
- package/apps/lib/components/SearchableTree.tsx +469 -0
- package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
- package/apps/lib/components/SectionBlock.tsx +88 -0
- package/apps/lib/components/Select.tsx +313 -0
- package/apps/lib/components/SimpleSelect.tsx +225 -0
- package/apps/lib/components/Skeleton.tsx +12 -0
- package/apps/lib/components/SlideDatePicker.tsx +242 -0
- package/apps/lib/components/SpinLoading.tsx +174 -0
- package/apps/lib/components/Stepper.tsx +331 -0
- package/apps/lib/components/Switch.tsx +82 -0
- package/apps/lib/components/TabFormItem.tsx +153 -0
- package/apps/lib/components/TabSwitch.tsx +154 -0
- package/apps/lib/components/Table.tsx +387 -0
- package/apps/lib/components/TextEditor/ChartBlockTool.ts +676 -0
- package/apps/lib/components/TextEditor/RichTextField.tsx +46 -0
- package/apps/lib/components/TextEditor/TableDnDWrapper.ts +462 -0
- package/apps/lib/components/TextEditor/TextEditor.tsx +1164 -0
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +429 -0
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +70 -0
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +50 -0
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +48 -0
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +98 -0
- package/apps/lib/components/TextEditor/editorjs.d.ts +60 -0
- package/apps/lib/components/TextEditor/index.ts +7 -0
- package/apps/lib/components/TextEditor/markdownParser.ts +346 -0
- package/apps/lib/components/Textarea.tsx +92 -0
- package/apps/lib/components/Timeline.tsx +263 -0
- package/apps/lib/components/Toast.tsx +87 -0
- package/apps/lib/components/Toggle.tsx +125 -0
- package/apps/lib/components/ToggleButton.tsx +140 -0
- package/apps/lib/components/Tooltip.tsx +116 -0
- package/apps/lib/components/TransparentLabel.tsx +71 -0
- package/apps/lib/components/TreeDropDown.tsx +103 -0
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +377 -0
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +75 -0
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +352 -0
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +60 -0
- package/apps/lib/components/TreeFolder/icons.tsx +60 -0
- package/apps/lib/components/TreeFolder/index.ts +24 -0
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +109 -0
- package/apps/lib/components/TreeFolder/types.ts +77 -0
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +255 -0
- package/apps/lib/hooks/useActiveTreeItem.ts +58 -0
- package/apps/lib/hooks/useClickOutside.ts +27 -0
- package/apps/lib/hooks/useDataViewsState.ts +175 -0
- package/apps/lib/hooks/useIsMobile.ts +21 -0
- package/apps/lib/hooks/useResize.ts +67 -0
- package/apps/lib/hooks/useTagSelection.ts +214 -0
- package/apps/lib/layouts/CNLayout.tsx +372 -0
- package/apps/lib/layouts/DataViewCard.tsx +62 -0
- package/apps/lib/layouts/FieldSection.tsx +62 -0
- package/apps/lib/layouts/TreeSubLayout.tsx +173 -0
- package/apps/lib/providers/ThemeProvider.tsx +84 -0
- package/apps/lib/utils/cn.ts +6 -0
- package/apps/lib/utils/color.ts +175 -0
- package/apps/lib/utils/dataViews/columnUtils.ts +132 -0
- package/apps/lib/utils/dataViews/fieldUtils.ts +197 -0
- package/apps/lib/utils/dataViews/nestedDataUtils.tsx +371 -0
- package/apps/lib/utils/dataViews/pathUtils.ts +139 -0
- package/apps/lib/utils/dataViews/rangeUtils.ts +234 -0
- package/apps/lib/utils/dataViews/treeUtils.ts +396 -0
- package/apps/lib/utils/dateFormat.ts +108 -0
- package/apps/lib/utils/resize.ts +31 -0
- package/apps/lib/utils/types.ts +16 -0
- package/dist/component-registry.d.ts +18 -2
- package/dist/component-registry.js +140 -30
- package/dist/component-registry.js.map +1 -1
- package/dist/docs-loader.d.ts +28 -2
- package/dist/docs-loader.js +109 -40
- package/dist/docs-loader.js.map +1 -1
- package/dist/form-fields.d.ts +75 -0
- package/dist/form-fields.js +488 -0
- package/dist/form-fields.js.map +1 -0
- package/dist/index.js +520 -52
- package/dist/index.js.map +1 -1
- package/dist/markdown-utils.d.ts +6 -0
- package/dist/markdown-utils.js +19 -0
- package/dist/markdown-utils.js.map +1 -1
- package/dist/registry-loader.d.ts +78 -0
- package/dist/registry-loader.js +199 -0
- package/dist/registry-loader.js.map +1 -0
- package/dist/server.test.d.ts +9 -0
- package/dist/server.test.js +245 -0
- package/dist/server.test.js.map +1 -0
- package/docs/components/action-button.md +30 -24
- package/docs/components/actions-group.md +26 -20
- package/docs/components/alert-dialog.md +45 -45
- package/docs/components/avatar.md +6 -2
- package/docs/components/badge-field.md +6 -2
- package/docs/components/badge.md +7 -1
- package/docs/components/breadcrumb.md +15 -40
- package/docs/components/button-group.md +13 -10
- package/docs/components/button.md +58 -33
- package/docs/components/calendar.md +26 -19
- package/docs/components/card.md +23 -18
- package/docs/components/chart-block-tool.md +129 -0
- package/docs/components/checkbox.md +16 -8
- package/docs/components/cn-layout.md +7 -1
- package/docs/components/color-picker.md +101 -0
- package/docs/components/conclusion-header.md +80 -0
- package/docs/components/context-menu.md +18 -25
- package/docs/components/count-badge.md +7 -1
- package/docs/components/data-table.md +45 -33
- package/docs/components/data-views-config-panel.md +15 -11
- package/docs/components/data-views-layout.md +13 -16
- package/docs/components/date-picker.md +30 -23
- package/docs/components/dialog.md +43 -42
- package/docs/components/divider.md +10 -4
- package/docs/components/drawer.md +161 -135
- package/docs/components/dropdown-menu.md +25 -34
- package/docs/components/field-hint.md +37 -25
- package/docs/components/field-section.md +9 -3
- package/docs/components/form-builder.md +270 -0
- package/docs/components/form-renderer.md +228 -0
- package/docs/components/form-stepper.md +6 -0
- package/docs/components/form-summary.md +123 -0
- package/docs/components/form.md +17 -20
- package/docs/components/header-bar.md +6 -0
- package/docs/components/image-attachment.md +43 -45
- package/docs/components/inbox-view.md +16 -5
- package/docs/components/inner-label-field.md +34 -24
- package/docs/components/input-field.md +18 -10
- package/docs/components/input-otp.md +14 -11
- package/docs/components/input.md +22 -16
- package/docs/components/kanban-view.md +15 -5
- package/docs/components/label-field.md +32 -22
- package/docs/components/label.md +43 -32
- package/docs/components/labeled-check-box.md +16 -8
- package/docs/components/labeled-radio.md +18 -11
- package/docs/components/link-button.md +7 -1
- package/docs/components/login-button.md +8 -2
- package/docs/components/password-level.md +37 -24
- package/docs/components/popover.md +26 -23
- package/docs/components/profile-menu.md +38 -27
- package/docs/components/radio-card.md +16 -9
- package/docs/components/radio.md +16 -8
- package/docs/components/scroll-area.md +6 -2
- package/docs/components/search-field.md +14 -6
- package/docs/components/searchable-select.md +19 -14
- package/docs/components/searchable-table.md +18 -13
- package/docs/components/searchable-tree-dialog.md +190 -0
- package/docs/components/searchable-tree.md +200 -0
- package/docs/components/section-block.md +12 -4
- package/docs/components/select.md +23 -18
- package/docs/components/simple-select.md +14 -10
- package/docs/components/skeleton.md +43 -33
- package/docs/components/slide-date-picker.md +37 -29
- package/docs/components/spin-loading.md +32 -23
- package/docs/components/stepper.md +6 -0
- package/docs/components/switch.md +14 -6
- package/docs/components/tab-form-item.md +7 -1
- package/docs/components/tab-switch.md +13 -6
- package/docs/components/table-dnd-wrapper.md +107 -0
- package/docs/components/table-view.md +15 -5
- package/docs/components/table.md +28 -28
- package/docs/components/text-editor.md +37 -13
- package/docs/components/textarea.md +15 -7
- package/docs/components/timeline.md +6 -0
- package/docs/components/toast.md +35 -26
- package/docs/components/toggle-button.md +24 -21
- package/docs/components/toggle.md +23 -15
- package/docs/components/tooltip.md +42 -30
- package/docs/components/transparent-label.md +29 -20
- package/docs/components/tree-drop-down.md +31 -23
- package/docs/components/tree-sub-layout.md +6 -2
- package/docs/components/tree-view.md +16 -5
- package/docs/explanation/architecture.md +54 -0
- package/docs/explanation/design-system.md +52 -0
- package/docs/how-to/data-views-from-backend-response.md +6 -4
- package/docs/how-to/form-and-list-recipes.md +26 -19
- package/docs/how-to/forms-with-form-builder.md +408 -0
- package/docs/how-to/guides.md +177 -197
- package/docs/migration/changelog.md +38 -0
- package/docs/reference/cli.md +87 -0
- package/docs/reference/components.md +11 -12
- package/docs/reference/hooks.md +8 -8
- package/docs/reference/providers.md +22 -22
- package/docs/reference/tailwind-plugins.md +2 -2
- package/docs/reference/theme.md +85 -0
- package/docs/reference/types.md +4 -4
- package/docs/reference/utilities.md +19 -26
- package/docs/tutorials/building-first-form.md +170 -172
- package/docs/tutorials/component-composition.md +34 -50
- package/docs/tutorials/getting-started.md +2 -2
- package/docs/tutorials/theming-basics.md +13 -10
- package/package.json +5 -2
- package/registry.json +997 -0
- package/docs/llms-manifest.json +0 -554
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# torch-glare-mcp
|
|
2
|
+
|
|
3
|
+
An [MCP](https://modelcontextprotocol.io) server that gives AI assistants full access to the
|
|
4
|
+
**TORCH Glare** component library — component docs, API references, code examples, design-system
|
|
5
|
+
info, **install commands + dependency graphs**, and the **actual source** the CLI copies.
|
|
6
|
+
|
|
7
|
+
TORCH Glare is a _copy-in_ library (like shadcn/ui): the `torch-glare` CLI copies component source
|
|
8
|
+
directly into your project. This server lets an assistant go from "which component?" all the way to
|
|
9
|
+
"here's how to install it and here's the code."
|
|
10
|
+
|
|
11
|
+
## Install into an AI client
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx torch-glare mcp
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This interactively adds the server to Claude Code (`.mcp.json`), Claude Desktop, and/or Cursor.
|
|
18
|
+
Or add it manually:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"mcpServers": {
|
|
23
|
+
"torch-glare-docs": { "command": "npx", "args": ["-y", "torch-glare-mcp"] }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Tools
|
|
29
|
+
|
|
30
|
+
| Tool | Purpose |
|
|
31
|
+
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
32
|
+
| `list-components` | List all components, optionally filtered by category (`buttons`, `forms`, `layout`, `dataDisplay`, `overlays`, `dateTime`, `feedback`, `labels`, `navigation`, `advanced`). |
|
|
33
|
+
| `search-components` | Scored search by name, description, or tags. |
|
|
34
|
+
| `get-component-docs` | Full markdown docs for one component. |
|
|
35
|
+
| `get-component-api` | Just the props table + TypeScript types. |
|
|
36
|
+
| `get-usage-examples` | Code examples, optionally filtered by keyword. |
|
|
37
|
+
| `get-design-system-info` | Theming, typography, colors, plugins, hooks, providers, utilities, installation. |
|
|
38
|
+
| `get-install-info` | The `torch-glare` install command, import statement (from the file's real exports), npm deps, and the full transitive set of internal deps the CLI copies. |
|
|
39
|
+
| `get-component-source` | The exact `.tsx`/`.ts` source the CLI copies into a project. |
|
|
40
|
+
| `get-guide` | A tutorial or how-to guide by name (call with no name to list them). |
|
|
41
|
+
| `create-form` | Turn a list of fields into a form: the right `FormBuilder.*` per field, install commands, and a complete `FormRenderer`-based starting point (optionally a stepper, a drawer, and a live `FormSummary` totals panel). |
|
|
42
|
+
| `get-related-components` | What an item copies in and what other items compose it. |
|
|
43
|
+
|
|
44
|
+
`list-components` / `search-components` also cover installable hooks, utils, layouts, and providers.
|
|
45
|
+
`get-component-docs` returns a compact overview + table of contents by default — pass `section`
|
|
46
|
+
(e.g. `"examples"`, `"api"`) or `section:"full"` to drill in. Search is token- and synonym-aware
|
|
47
|
+
(e.g. `"modal"` → `Dialog`).
|
|
48
|
+
|
|
49
|
+
## Resources
|
|
50
|
+
|
|
51
|
+
- `torch-glare://component-index` — categorized component index
|
|
52
|
+
- `torch-glare://getting-started` — installation + first-component tutorial
|
|
53
|
+
- `torch-glare://design-system` — theming, typography, colors, plugins
|
|
54
|
+
- `torch-glare://component/{name}` — full docs for one component (templated)
|
|
55
|
+
|
|
56
|
+
The library's hard rule — never emit `system` color tokens or the `SystemStyle` variant, always use
|
|
57
|
+
the `presentation` equivalents — is sent once via the server's **`instructions`** (at connect), with
|
|
58
|
+
a short reminder on the code-emitting tools.
|
|
59
|
+
|
|
60
|
+
> When iterating on docs or component source in this repo, run `pnpm run build` (or
|
|
61
|
+
> `pnpm run mcp:build` from the repo root) so the server picks up your changes — it reads the bundled
|
|
62
|
+
> copies produced by `sync-docs`.
|
|
63
|
+
|
|
64
|
+
## Development
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pnpm install
|
|
68
|
+
pnpm run build # runs sync-docs (prebuild) then tsc
|
|
69
|
+
pnpm run dev # tsc --watch
|
|
70
|
+
pnpm test # unit tests
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
In the monorepo the server reads docs and source directly from `../docs` and `../apps/lib`. On
|
|
74
|
+
`build`, `scripts/sync-docs.mjs` bundles `docs/`, `registry.json`, and the `apps/lib` source into
|
|
75
|
+
the package so the published server is self-contained.
|
|
76
|
+
|
|
77
|
+
Inspect it interactively:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npx @modelcontextprotocol/inspector node dist/index.js
|
|
81
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React, { ButtonHTMLAttributes } from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { Button } from "./Button";
|
|
4
|
+
import { cn } from "../utils/cn";
|
|
5
|
+
import { ButtonVariant, Themes } from "../utils/types";
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva("!rounded-[4px]", {
|
|
8
|
+
variants: {
|
|
9
|
+
size: {
|
|
10
|
+
XS: "h-[18px] w-[18px] text-[12px]",
|
|
11
|
+
S: "h-[22px] w-[22px] text-[12px]",
|
|
12
|
+
M: "h-[32px] w-[32px] text-[18px]",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
size: "M",
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
interface Props
|
|
21
|
+
extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
22
|
+
is_loading?: boolean;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
asChild?: boolean;
|
|
25
|
+
as?: React.ElementType;
|
|
26
|
+
theme?: Themes;
|
|
27
|
+
variant?: ButtonVariant;
|
|
28
|
+
}
|
|
29
|
+
export const ActionButton = function ({
|
|
30
|
+
size,
|
|
31
|
+
asChild,
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- excluded from {...props} spread
|
|
33
|
+
as: Tag = "button",
|
|
34
|
+
className,
|
|
35
|
+
variant,
|
|
36
|
+
type = "button",
|
|
37
|
+
children,
|
|
38
|
+
theme,
|
|
39
|
+
...props
|
|
40
|
+
}: Props) {
|
|
41
|
+
return (
|
|
42
|
+
<Button
|
|
43
|
+
theme={theme}
|
|
44
|
+
asChild={asChild}
|
|
45
|
+
buttonType="icon"
|
|
46
|
+
type={type}
|
|
47
|
+
size={size == "XS" ? "S" : size == "S" ? "M" : size == "M" ? "L" : "S"}
|
|
48
|
+
variant={variant}
|
|
49
|
+
className={cn(
|
|
50
|
+
buttonVariants({
|
|
51
|
+
size,
|
|
52
|
+
}),
|
|
53
|
+
className,
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
>
|
|
57
|
+
{children}
|
|
58
|
+
</Button>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React, { HTMLAttributes } from "react";
|
|
2
|
+
import { cn } from "../utils/cn";
|
|
3
|
+
import { Themes } from "../utils/types";
|
|
4
|
+
import { Divider } from "./Divider";
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
|
+
withDivider?: boolean; // to display the divider line if you pass it see on figma design file
|
|
8
|
+
theme?: Themes;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const ActionsGroup: React.FC<Props> = ({ withDivider, className, children, theme, ...props }) => {
|
|
12
|
+
return (
|
|
13
|
+
<section
|
|
14
|
+
{...props}
|
|
15
|
+
data-theme={theme}
|
|
16
|
+
className={cn("flex items-center gap-2 w-full", className)}
|
|
17
|
+
>
|
|
18
|
+
{withDivider && <Divider />}
|
|
19
|
+
{children}
|
|
20
|
+
{withDivider && <Divider />}
|
|
21
|
+
</section>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// <div className="flex border-t border-solid border-border-presentation-global-primary flex-1 px-2" />
|
|
26
|
+
|
|
27
|
+
export default ActionsGroup;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../utils/cn";
|
|
7
|
+
import { Button, buttonVariants } from "./Button";
|
|
8
|
+
import { ButtonVariant } from "../utils/types";
|
|
9
|
+
import { cva } from "class-variance-authority";
|
|
10
|
+
|
|
11
|
+
const StatusTextStyle = cva("", {
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
default:
|
|
15
|
+
"[&_strong]:text-content-presentation-global-primary [&_[data-description]]:text-content-presentation-global-primary",
|
|
16
|
+
info: "[&_strong]:text-content-presentation-state-information [&_[data-description]]:text-content-presentation-state-information",
|
|
17
|
+
success:
|
|
18
|
+
"[&_strong]:text-content-presentation-state-success [&_[data-description]]:text-content-presentation-state-success",
|
|
19
|
+
warning:
|
|
20
|
+
"[&_strong]:text-content-presentation-state-warning [&_[data-description]]:text-content-presentation-state-warning",
|
|
21
|
+
error:
|
|
22
|
+
"[&_strong]:text-content-presentation-state-negative [&_[data-description]]:text-content-presentation-state-negative",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
variant: "default",
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const AlertDialog = AlertDialogPrimitive.Root;
|
|
31
|
+
|
|
32
|
+
const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
|
33
|
+
|
|
34
|
+
const AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
35
|
+
|
|
36
|
+
const AlertDialogOverlay = React.forwardRef<
|
|
37
|
+
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
|
|
38
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
|
|
39
|
+
>(({ className, ...props }, ref) => (
|
|
40
|
+
<AlertDialogPrimitive.Overlay
|
|
41
|
+
className={cn(
|
|
42
|
+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
ref={ref}
|
|
47
|
+
/>
|
|
48
|
+
));
|
|
49
|
+
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
|
|
50
|
+
|
|
51
|
+
const AlertDialogContent = React.forwardRef<
|
|
52
|
+
React.ElementRef<typeof AlertDialogPrimitive.Content>,
|
|
53
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> & {
|
|
54
|
+
variant?: "info" | "success" | "warning" | "error" | "default";
|
|
55
|
+
}
|
|
56
|
+
>(({ className, variant = "default", ...props }, ref) => (
|
|
57
|
+
<AlertDialogPortal>
|
|
58
|
+
<AlertDialogOverlay />
|
|
59
|
+
<AlertDialogPrimitive.Content
|
|
60
|
+
ref={ref}
|
|
61
|
+
className={cn(
|
|
62
|
+
StatusTextStyle({ variant }),
|
|
63
|
+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-[800px] translate-x-[-50%] translate-y-[-50%]",
|
|
64
|
+
"gap-2 rounded-[16px] border-2 border-border-presentation-global-primary",
|
|
65
|
+
"bg-background-presentation-body-overlay-primary p-[12px]",
|
|
66
|
+
"text-content-presentation-global-primary",
|
|
67
|
+
"shadow-lg duration-200",
|
|
68
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
69
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
70
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
71
|
+
"data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
|
|
72
|
+
"data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
|
|
73
|
+
className,
|
|
74
|
+
)}
|
|
75
|
+
{...props}
|
|
76
|
+
/>
|
|
77
|
+
</AlertDialogPortal>
|
|
78
|
+
));
|
|
79
|
+
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
|
|
80
|
+
|
|
81
|
+
const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
82
|
+
<div className={cn("flex justify-between space-x-2 text-left", className)} {...props} />
|
|
83
|
+
);
|
|
84
|
+
AlertDialogHeader.displayName = "AlertDialogHeader";
|
|
85
|
+
|
|
86
|
+
const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
87
|
+
<div
|
|
88
|
+
className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
);
|
|
92
|
+
AlertDialogFooter.displayName = "AlertDialogFooter";
|
|
93
|
+
|
|
94
|
+
const AlertDialogTitle = React.forwardRef<
|
|
95
|
+
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
|
96
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
|
|
97
|
+
>(({ className, ...props }, ref) => (
|
|
98
|
+
<AlertDialogPrimitive.Title
|
|
99
|
+
ref={ref}
|
|
100
|
+
className={cn("typography-display-medium-semibold", className)}
|
|
101
|
+
{...props}
|
|
102
|
+
/>
|
|
103
|
+
));
|
|
104
|
+
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
|
|
105
|
+
|
|
106
|
+
const AlertDialogLabel = React.forwardRef<
|
|
107
|
+
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
|
108
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title> & {
|
|
109
|
+
title: string;
|
|
110
|
+
}
|
|
111
|
+
>(({ className, title, ...props }, ref) => {
|
|
112
|
+
const words = title.split(" ");
|
|
113
|
+
const firstWord = words[0];
|
|
114
|
+
const restOfTitle = words.slice(1).join(" ");
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<AlertDialogPrimitive.Title
|
|
118
|
+
ref={ref}
|
|
119
|
+
className={cn("typography-display-medium-semibold", className)}
|
|
120
|
+
{...props}
|
|
121
|
+
>
|
|
122
|
+
<p className="first-letter:uppercase typography-display-medium-semibold">
|
|
123
|
+
<strong className="typography-display-medium-semibold">{firstWord}</strong>
|
|
124
|
+
{restOfTitle.length > 0 && " " + restOfTitle}
|
|
125
|
+
</p>
|
|
126
|
+
</AlertDialogPrimitive.Title>
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
AlertDialogLabel.displayName = "AlertDialogLabel";
|
|
130
|
+
|
|
131
|
+
const AlertDialogDescription = React.forwardRef<
|
|
132
|
+
React.ElementRef<typeof AlertDialogPrimitive.Description>,
|
|
133
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
|
|
134
|
+
>(({ className, ...props }, ref) => (
|
|
135
|
+
<AlertDialogPrimitive.Description
|
|
136
|
+
data-description=""
|
|
137
|
+
ref={ref}
|
|
138
|
+
className={cn(
|
|
139
|
+
"typography-body-large-medium",
|
|
140
|
+
"bg-background-presentation-form-base",
|
|
141
|
+
"border border-border-presentation-global-primary",
|
|
142
|
+
"rounded-[8px] p-[24px_48px_48px_48px]",
|
|
143
|
+
className,
|
|
144
|
+
)}
|
|
145
|
+
{...props}
|
|
146
|
+
/>
|
|
147
|
+
));
|
|
148
|
+
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
|
|
149
|
+
|
|
150
|
+
const AlertDialogAction = React.forwardRef<
|
|
151
|
+
React.ElementRef<typeof AlertDialogPrimitive.Action>,
|
|
152
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> & {
|
|
153
|
+
size?: "M" | "S" | "L" | "XL";
|
|
154
|
+
variant?: ButtonVariant;
|
|
155
|
+
buttonType?: "button" | "icon";
|
|
156
|
+
}
|
|
157
|
+
>(({ className, size = "M", variant = "BorderStyle", buttonType = "button", ...props }, ref) => (
|
|
158
|
+
<AlertDialogPrimitive.Action
|
|
159
|
+
ref={ref}
|
|
160
|
+
className={cn(
|
|
161
|
+
buttonVariants({ variant: variant, size: size, buttonType: buttonType }),
|
|
162
|
+
className,
|
|
163
|
+
)}
|
|
164
|
+
asChild
|
|
165
|
+
>
|
|
166
|
+
<Button size={size} variant={variant} buttonType={buttonType} {...props} />
|
|
167
|
+
</AlertDialogPrimitive.Action>
|
|
168
|
+
));
|
|
169
|
+
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
|
|
170
|
+
|
|
171
|
+
const AlertDialogCancel = React.forwardRef<
|
|
172
|
+
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
|
|
173
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel> & {
|
|
174
|
+
size?: "M" | "S" | "L" | "XL";
|
|
175
|
+
variant?: ButtonVariant;
|
|
176
|
+
buttonType?: "button" | "icon";
|
|
177
|
+
}
|
|
178
|
+
>(({ className, size = "M", variant = "RedSecStyle", buttonType = "icon", ...props }, ref) => (
|
|
179
|
+
<AlertDialogPrimitive.Cancel
|
|
180
|
+
ref={ref}
|
|
181
|
+
className={cn(
|
|
182
|
+
buttonVariants({ variant: variant, size: size, buttonType: buttonType }),
|
|
183
|
+
"",
|
|
184
|
+
className,
|
|
185
|
+
)}
|
|
186
|
+
{...props}
|
|
187
|
+
/>
|
|
188
|
+
));
|
|
189
|
+
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
|
|
190
|
+
|
|
191
|
+
export {
|
|
192
|
+
AlertDialog,
|
|
193
|
+
AlertDialogPortal,
|
|
194
|
+
AlertDialogOverlay,
|
|
195
|
+
AlertDialogTrigger,
|
|
196
|
+
AlertDialogContent,
|
|
197
|
+
AlertDialogHeader,
|
|
198
|
+
AlertDialogFooter,
|
|
199
|
+
AlertDialogTitle,
|
|
200
|
+
AlertDialogLabel,
|
|
201
|
+
AlertDialogDescription,
|
|
202
|
+
AlertDialogAction,
|
|
203
|
+
AlertDialogCancel,
|
|
204
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
5
|
+
import { cn } from "../utils/cn";
|
|
6
|
+
|
|
7
|
+
const Avatar = React.forwardRef<
|
|
8
|
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
9
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
10
|
+
>(({ className, ...props }, ref) => (
|
|
11
|
+
<AvatarPrimitive.Root
|
|
12
|
+
ref={ref}
|
|
13
|
+
className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
));
|
|
17
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
18
|
+
|
|
19
|
+
const AvatarImage = React.forwardRef<
|
|
20
|
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
21
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
22
|
+
>(({ className, ...props }, ref) => (
|
|
23
|
+
<AvatarPrimitive.Image
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={cn("aspect-square h-full w-full object-cover", className)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
));
|
|
29
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
30
|
+
|
|
31
|
+
const AvatarFallback = React.forwardRef<
|
|
32
|
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
33
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
34
|
+
>(({ className, ...props }, ref) => (
|
|
35
|
+
<AvatarPrimitive.Fallback
|
|
36
|
+
ref={ref}
|
|
37
|
+
className={cn(
|
|
38
|
+
"flex h-full w-full items-center justify-center rounded-full bg-background-presentation-action-disabled text-content-presentation-global-primary",
|
|
39
|
+
className,
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
));
|
|
44
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
45
|
+
|
|
46
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { ReactNode, HTMLAttributes } from "react";
|
|
2
|
+
import { cva, VariantProps } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../utils/cn";
|
|
4
|
+
import { Themes } from "../utils/types";
|
|
5
|
+
|
|
6
|
+
const SOLID_TEXT =
|
|
7
|
+
"text-content-presentation-global-primary-light [&_i]:text-content-presentation-global-primary-light";
|
|
8
|
+
|
|
9
|
+
const solidCompoundVariants = [
|
|
10
|
+
{
|
|
11
|
+
badgeStyle: "solid" as const,
|
|
12
|
+
color: "gray" as const,
|
|
13
|
+
className: `bg-background-presentation-badge-gray-solid ${SOLID_TEXT}`,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
badgeStyle: "solid" as const,
|
|
17
|
+
color: "slate" as const,
|
|
18
|
+
className: `bg-background-presentation-badge-slate-solid ${SOLID_TEXT}`,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
badgeStyle: "solid" as const,
|
|
22
|
+
color: "red" as const,
|
|
23
|
+
className: `bg-background-presentation-badge-red-solid ${SOLID_TEXT}`,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
badgeStyle: "solid" as const,
|
|
27
|
+
color: "orange" as const,
|
|
28
|
+
className: `bg-background-presentation-badge-orange-solid ${SOLID_TEXT}`,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
badgeStyle: "solid" as const,
|
|
32
|
+
color: "yellow" as const,
|
|
33
|
+
className: `bg-background-presentation-badge-yellow-solid ${SOLID_TEXT}`,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
badgeStyle: "solid" as const,
|
|
37
|
+
color: "green" as const,
|
|
38
|
+
className: `bg-background-presentation-badge-green-solid ${SOLID_TEXT}`,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
badgeStyle: "solid" as const,
|
|
42
|
+
color: "ocean" as const,
|
|
43
|
+
className: `bg-background-presentation-badge-ocean-solid ${SOLID_TEXT}`,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
badgeStyle: "solid" as const,
|
|
47
|
+
color: "blue" as const,
|
|
48
|
+
className: `bg-background-presentation-badge-blue-solid ${SOLID_TEXT}`,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
badgeStyle: "solid" as const,
|
|
52
|
+
color: "purple" as const,
|
|
53
|
+
className: `bg-background-presentation-badge-purple-solid ${SOLID_TEXT}`,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
badgeStyle: "solid" as const,
|
|
57
|
+
color: "rose" as const,
|
|
58
|
+
className: `bg-background-presentation-badge-rose-solid ${SOLID_TEXT}`,
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const SUBTLE_TEXT =
|
|
63
|
+
"text-content-presentation-global-subtle [&>div]:mix-blend-luminosity [&_i]:text-content-presentation-global-subtle [&_i]:mix-blend-luminosity [&>button]:mix-blend-luminosity";
|
|
64
|
+
|
|
65
|
+
const subtleCompoundVariants = [
|
|
66
|
+
{
|
|
67
|
+
badgeStyle: "subtle" as const,
|
|
68
|
+
color: "gray" as const,
|
|
69
|
+
className: `bg-background-presentation-badge-gray-subtle ${SUBTLE_TEXT}`,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
badgeStyle: "subtle" as const,
|
|
73
|
+
color: "slate" as const,
|
|
74
|
+
className: `bg-background-presentation-badge-slate-subtle ${SUBTLE_TEXT}`,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
badgeStyle: "subtle" as const,
|
|
78
|
+
color: "red" as const,
|
|
79
|
+
className: `bg-background-presentation-badge-red-subtle ${SUBTLE_TEXT}`,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
badgeStyle: "subtle" as const,
|
|
83
|
+
color: "orange" as const,
|
|
84
|
+
className: `bg-background-presentation-badge-orange-subtle ${SUBTLE_TEXT}`,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
badgeStyle: "subtle" as const,
|
|
88
|
+
color: "yellow" as const,
|
|
89
|
+
className: `bg-background-presentation-badge-yellow-subtle ${SUBTLE_TEXT}`,
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
badgeStyle: "subtle" as const,
|
|
93
|
+
color: "green" as const,
|
|
94
|
+
className: `bg-background-presentation-badge-green-subtle ${SUBTLE_TEXT}`,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
badgeStyle: "subtle" as const,
|
|
98
|
+
color: "ocean" as const,
|
|
99
|
+
className: `bg-background-presentation-badge-ocean-subtle ${SUBTLE_TEXT}`,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
badgeStyle: "subtle" as const,
|
|
103
|
+
color: "blue" as const,
|
|
104
|
+
className: `bg-background-presentation-badge-blue-subtle ${SUBTLE_TEXT}`,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
badgeStyle: "subtle" as const,
|
|
108
|
+
color: "purple" as const,
|
|
109
|
+
className: `bg-background-presentation-badge-purple-subtle ${SUBTLE_TEXT}`,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
badgeStyle: "subtle" as const,
|
|
113
|
+
color: "rose" as const,
|
|
114
|
+
className: `bg-background-presentation-badge-rose-subtle ${SUBTLE_TEXT}`,
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
export const badgeStyles = cva(
|
|
119
|
+
[
|
|
120
|
+
"inline-flex items-center justify-center w-fit",
|
|
121
|
+
"rounded-[6px]",
|
|
122
|
+
"transition-all duration-200 ease-in-out",
|
|
123
|
+
"whitespace-nowrap",
|
|
124
|
+
"[&_i]:!leading-none",
|
|
125
|
+
// The subtle variants blend their label/icon with `mix-blend-luminosity`.
|
|
126
|
+
// `isolate` opens a new stacking context so that blend only composites
|
|
127
|
+
// against the badge's own background — not against arbitrary page layers
|
|
128
|
+
// behind it (semi-transparent rows, gradients, masks), which otherwise
|
|
129
|
+
// ghosts/double-strokes the text in "random" places.
|
|
130
|
+
"isolate",
|
|
131
|
+
],
|
|
132
|
+
{
|
|
133
|
+
variants: {
|
|
134
|
+
badgeStyle: {
|
|
135
|
+
solid: "",
|
|
136
|
+
subtle: "",
|
|
137
|
+
},
|
|
138
|
+
color: {
|
|
139
|
+
gray: "",
|
|
140
|
+
slate: "",
|
|
141
|
+
red: "",
|
|
142
|
+
orange: "",
|
|
143
|
+
yellow: "",
|
|
144
|
+
green: "",
|
|
145
|
+
ocean: "",
|
|
146
|
+
blue: "",
|
|
147
|
+
purple: "",
|
|
148
|
+
rose: "",
|
|
149
|
+
},
|
|
150
|
+
size: {
|
|
151
|
+
XS: "h-[18px] px-[6px] py-0 [&_i]:text-[12px] [&>div]:typography-body-small-medium",
|
|
152
|
+
S: "h-[22px] px-[6px] py-[2px] [&_i]:text-[12px] [&>div]:typography-body-small-medium",
|
|
153
|
+
M: "h-[26px] px-[8px] py-[2px] [&_i]:text-[16px] [&>div]:typography-body-medium-medium",
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
compoundVariants: [...solidCompoundVariants, ...subtleCompoundVariants],
|
|
157
|
+
defaultVariants: {
|
|
158
|
+
badgeStyle: "subtle",
|
|
159
|
+
color: "gray",
|
|
160
|
+
size: "S",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
interface BadgeProps
|
|
166
|
+
extends Omit<HTMLAttributes<HTMLSpanElement>, "color">, VariantProps<typeof badgeStyles> {
|
|
167
|
+
label?: string;
|
|
168
|
+
badgeIcon?: ReactNode;
|
|
169
|
+
showIcon?: boolean;
|
|
170
|
+
isClosable?: boolean;
|
|
171
|
+
onClose?: () => void;
|
|
172
|
+
theme?: Themes;
|
|
173
|
+
className?: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export const Badge: React.FC<BadgeProps> = ({
|
|
177
|
+
label,
|
|
178
|
+
badgeIcon,
|
|
179
|
+
showIcon = true,
|
|
180
|
+
isClosable,
|
|
181
|
+
onClose,
|
|
182
|
+
theme,
|
|
183
|
+
badgeStyle,
|
|
184
|
+
color,
|
|
185
|
+
size,
|
|
186
|
+
className,
|
|
187
|
+
...props
|
|
188
|
+
}) => {
|
|
189
|
+
return (
|
|
190
|
+
<span
|
|
191
|
+
{...props}
|
|
192
|
+
data-theme={theme}
|
|
193
|
+
className={cn(
|
|
194
|
+
badgeStyles({ badgeStyle, color, size }),
|
|
195
|
+
{ "cursor-default": isClosable },
|
|
196
|
+
className,
|
|
197
|
+
)}
|
|
198
|
+
>
|
|
199
|
+
{showIcon && (
|
|
200
|
+
<div className="flex items-center justify-center">
|
|
201
|
+
{badgeIcon ?? <i className="ri-circle-fill !text-[8px]" />}
|
|
202
|
+
</div>
|
|
203
|
+
)}
|
|
204
|
+
|
|
205
|
+
{label && <div className="px-[3px]">{label}</div>}
|
|
206
|
+
|
|
207
|
+
{isClosable && (
|
|
208
|
+
<button
|
|
209
|
+
type="button"
|
|
210
|
+
onClick={onClose}
|
|
211
|
+
onKeyDown={(e) => {
|
|
212
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
213
|
+
e.preventDefault();
|
|
214
|
+
onClose?.();
|
|
215
|
+
}
|
|
216
|
+
}}
|
|
217
|
+
className={cn(
|
|
218
|
+
"rounded-[4px]",
|
|
219
|
+
"flex items-center justify-center cursor-pointer",
|
|
220
|
+
"hover:bg-background-presentation-action-secondary",
|
|
221
|
+
"transition-colors duration-150",
|
|
222
|
+
size === "M"
|
|
223
|
+
? "w-[16px] h-[16px]"
|
|
224
|
+
: size === "S"
|
|
225
|
+
? "w-[14px] h-[14px]"
|
|
226
|
+
: "w-[12px] h-[12px]",
|
|
227
|
+
)}
|
|
228
|
+
aria-label="Remove badge"
|
|
229
|
+
>
|
|
230
|
+
<svg
|
|
231
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
232
|
+
width="100%"
|
|
233
|
+
height="100%"
|
|
234
|
+
viewBox="0 0 12 12"
|
|
235
|
+
fill="none"
|
|
236
|
+
aria-hidden="true"
|
|
237
|
+
>
|
|
238
|
+
<path
|
|
239
|
+
d="M6.00002 5.33336L8.33334 3L9 3.66667L6.66668 6.00002L9 8.33334L8.33334 9L6.00002 6.66668L3.66667 9L3 8.33334L5.33336 6.00002L3 3.66667L3.66667 3L6.00002 5.33336Z"
|
|
240
|
+
fill="currentColor"
|
|
241
|
+
/>
|
|
242
|
+
</svg>
|
|
243
|
+
</button>
|
|
244
|
+
)}
|
|
245
|
+
</span>
|
|
246
|
+
);
|
|
247
|
+
};
|