torch-glare 2.5.6 → 2.6.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/README.md +4 -3
- package/dist/bin/index.js +9 -24
- package/dist/bin/index.js.map +1 -1
- package/dist/src/commands/add.d.ts +2 -2
- package/dist/src/commands/add.d.ts.map +1 -1
- package/dist/src/commands/add.js +4 -70
- package/dist/src/commands/add.js.map +1 -1
- package/dist/src/commands/hook.d.ts +5 -4
- package/dist/src/commands/hook.d.ts.map +1 -1
- package/dist/src/commands/hook.js +7 -75
- package/dist/src/commands/hook.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/layout.d.ts +5 -4
- package/dist/src/commands/layout.d.ts.map +1 -1
- package/dist/src/commands/layout.js +7 -75
- package/dist/src/commands/layout.js.map +1 -1
- package/dist/src/commands/provider.d.ts +5 -4
- package/dist/src/commands/provider.d.ts.map +1 -1
- package/dist/src/commands/provider.js +7 -75
- package/dist/src/commands/provider.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +78 -43
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/utils.d.ts +5 -4
- package/dist/src/commands/utils.d.ts.map +1 -1
- package/dist/src/commands/utils.js +7 -80
- package/dist/src/commands/utils.js.map +1 -1
- package/dist/src/shared/addFromRegistry.d.ts +16 -0
- package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
- package/dist/src/shared/addFromRegistry.js +88 -0
- package/dist/src/shared/addFromRegistry.js.map +1 -0
- package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
- package/dist/src/shared/getInstallCommand.js +5 -0
- package/dist/src/shared/getInstallCommand.js.map +1 -1
- package/dist/src/shared/installDependencies.d.ts +0 -10
- package/dist/src/shared/installDependencies.d.ts.map +1 -1
- package/dist/src/shared/installDependencies.js +0 -17
- package/dist/src/shared/installDependencies.js.map +1 -1
- package/dist/src/shared/installFromPlan.d.ts +7 -5
- package/dist/src/shared/installFromPlan.d.ts.map +1 -1
- package/dist/src/shared/installFromPlan.js +103 -36
- package/dist/src/shared/installFromPlan.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +12 -3
- package/dist/src/shared/loadRegistry.d.ts.map +1 -1
- package/dist/src/shared/loadRegistry.js +19 -20
- package/dist/src/shared/loadRegistry.js.map +1 -1
- package/dist/src/shared/registryClient.d.ts +19 -0
- package/dist/src/shared/registryClient.d.ts.map +1 -0
- package/dist/src/shared/registryClient.js +128 -0
- package/dist/src/shared/registryClient.js.map +1 -0
- package/dist/src/shared/resolveEntry.d.ts +10 -7
- package/dist/src/shared/resolveEntry.d.ts.map +1 -1
- package/dist/src/shared/resolveEntry.js +18 -13
- package/dist/src/shared/resolveEntry.js.map +1 -1
- package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
- package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
- package/dist/src/shared/suggestOtherCommand.js +29 -23
- package/dist/src/shared/suggestOtherCommand.js.map +1 -1
- package/dist/src/types/main.d.ts +31 -2
- package/dist/src/types/main.d.ts.map +1 -1
- package/package.json +6 -11
- package/apps/lib/components/ActionButton.tsx +0 -93
- package/apps/lib/components/ActionsGroup.tsx +0 -27
- package/apps/lib/components/AlertDialog.tsx +0 -204
- package/apps/lib/components/Avatar.tsx +0 -46
- package/apps/lib/components/Badge.tsx +0 -250
- package/apps/lib/components/BadgeField.tsx +0 -403
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -325
- package/apps/lib/components/ButtonGroup.tsx +0 -190
- package/apps/lib/components/Calendar.tsx +0 -115
- package/apps/lib/components/Card.tsx +0 -95
- package/apps/lib/components/Checkbox.tsx +0 -42
- package/apps/lib/components/ColorPicker.tsx +0 -441
- package/apps/lib/components/ConclusionHeader.tsx +0 -148
- package/apps/lib/components/ContextMenu.tsx +0 -571
- package/apps/lib/components/CountBadge.tsx +0 -52
- package/apps/lib/components/DataTable.tsx +0 -213
- package/apps/lib/components/DataViews/badge.ts +0 -49
- package/apps/lib/components/DataViews/cell.tsx +0 -324
- package/apps/lib/components/DataViews/context.ts +0 -144
- package/apps/lib/components/DataViews/data-views.tsx +0 -395
- package/apps/lib/components/DataViews/filters/children.tsx +0 -98
- package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
- package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
- package/apps/lib/components/DataViews/filters/index.ts +0 -4
- package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
- package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
- package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
- package/apps/lib/components/DataViews/filters/values.ts +0 -173
- package/apps/lib/components/DataViews/header.tsx +0 -220
- package/apps/lib/components/DataViews/hooks/index.ts +0 -5
- package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
- package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
- package/apps/lib/components/DataViews/index.ts +0 -88
- package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
- package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
- package/apps/lib/components/DataViews/panel/index.ts +0 -3
- package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
- package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
- package/apps/lib/components/DataViews/panel/section.tsx +0 -81
- package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
- package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
- package/apps/lib/components/DataViews/slots.ts +0 -72
- package/apps/lib/components/DataViews/states.tsx +0 -73
- package/apps/lib/components/DataViews/types.ts +0 -510
- package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
- package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
- package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
- package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
- package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
- package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
- package/apps/lib/components/DatePicker.tsx +0 -232
- package/apps/lib/components/Dialog.tsx +0 -116
- package/apps/lib/components/Divider.tsx +0 -28
- package/apps/lib/components/Drawer.tsx +0 -451
- package/apps/lib/components/DropdownMenu.tsx +0 -554
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -85
- package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -168
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -114
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
- package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
- package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
- package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
- package/apps/lib/components/FormBuilder/index.ts +0 -31
- package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
- package/apps/lib/components/FormBuilder/submit.tsx +0 -67
- package/apps/lib/components/FormBuilder/types.ts +0 -316
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -250
- package/apps/lib/components/FormRenderer/detail.tsx +0 -256
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -358
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -17
- package/apps/lib/components/FormRenderer/notch-action.tsx +0 -64
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -393
- package/apps/lib/components/FormRenderer/types.ts +0 -115
- package/apps/lib/components/FormSummary.tsx +0 -282
- package/apps/lib/components/HeaderBar.tsx +0 -117
- package/apps/lib/components/ImageAttachment.tsx +0 -209
- package/apps/lib/components/InnerLabelField.tsx +0 -154
- package/apps/lib/components/Input.tsx +0 -224
- package/apps/lib/components/InputField.tsx +0 -147
- package/apps/lib/components/InputOTP.tsx +0 -84
- package/apps/lib/components/Label.tsx +0 -129
- package/apps/lib/components/LabelField.tsx +0 -76
- package/apps/lib/components/LabeledCheckBox.tsx +0 -51
- package/apps/lib/components/LabeledRadio.tsx +0 -51
- package/apps/lib/components/LinkButton.tsx +0 -94
- package/apps/lib/components/LoginButton.tsx +0 -51
- package/apps/lib/components/PasswordLevel.tsx +0 -58
- package/apps/lib/components/Popover.tsx +0 -312
- package/apps/lib/components/ProfileMenu.tsx +0 -85
- package/apps/lib/components/Radio.tsx +0 -59
- package/apps/lib/components/RadioCard.tsx +0 -50
- package/apps/lib/components/ScrollArea.tsx +0 -54
- package/apps/lib/components/SearchField.tsx +0 -62
- package/apps/lib/components/SearchableSelect.tsx +0 -318
- package/apps/lib/components/SearchableTable.tsx +0 -344
- package/apps/lib/components/SearchableTree.tsx +0 -485
- package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
- package/apps/lib/components/SectionBlock.tsx +0 -168
- package/apps/lib/components/Select.tsx +0 -347
- package/apps/lib/components/SimpleSelect.tsx +0 -225
- package/apps/lib/components/Skeleton.tsx +0 -12
- package/apps/lib/components/SlideDatePicker.tsx +0 -255
- package/apps/lib/components/SpinLoading.tsx +0 -174
- package/apps/lib/components/Stepper.tsx +0 -480
- package/apps/lib/components/Switch.tsx +0 -82
- package/apps/lib/components/TabFormItem.tsx +0 -153
- package/apps/lib/components/TabSwitch.tsx +0 -172
- package/apps/lib/components/Table.tsx +0 -597
- package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
- package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
- package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
- package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
- package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
- package/apps/lib/components/TextEditor/index.ts +0 -7
- package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
- package/apps/lib/components/Textarea.tsx +0 -117
- package/apps/lib/components/Timeline.tsx +0 -263
- package/apps/lib/components/Toast.tsx +0 -87
- package/apps/lib/components/Toggle.tsx +0 -125
- package/apps/lib/components/ToggleButton.tsx +0 -140
- package/apps/lib/components/Tooltip.tsx +0 -116
- package/apps/lib/components/TransparentLabel.tsx +0 -71
- package/apps/lib/components/TreeDropDown.tsx +0 -115
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
- package/apps/lib/components/TreeFolder/icons.tsx +0 -60
- package/apps/lib/components/TreeFolder/index.ts +0 -24
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
- package/apps/lib/components/TreeFolder/types.ts +0 -77
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
- package/apps/lib/hooks/useActiveTreeItem.ts +0 -61
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useHtmlDir.ts +0 -31
- package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
- package/apps/lib/hooks/useIsMobile.ts +0 -21
- package/apps/lib/hooks/useResize.ts +0 -67
- package/apps/lib/hooks/useTagSelection.ts +0 -300
- package/apps/lib/layouts/CNLayout.tsx +0 -372
- package/apps/lib/layouts/DataViewCard.tsx +0 -62
- package/apps/lib/layouts/FieldSection.tsx +0 -91
- package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
- package/apps/lib/providers/ThemeProvider.tsx +0 -84
- package/apps/lib/registry.json +0 -1217
- package/apps/lib/tsconfig.json +0 -9
- package/apps/lib/tsconfig.tsbuildinfo +0 -1
- package/apps/lib/utils/cn.ts +0 -6
- package/apps/lib/utils/color.ts +0 -175
- package/apps/lib/utils/dataViews/path.ts +0 -67
- package/apps/lib/utils/dataViews/query.ts +0 -73
- package/apps/lib/utils/dataViews/types.ts +0 -187
- package/apps/lib/utils/dateFormat.ts +0 -108
- package/apps/lib/utils/resize.ts +0 -31
- package/apps/lib/utils/scroller.ts +0 -26
- package/apps/lib/utils/types.ts +0 -16
- package/docs/BLOCKS.md +0 -129
- package/docs/CHANGELOG-1.1.16.md +0 -108
- package/docs/Cover.png +0 -0
- package/docs/README.md +0 -215
- package/docs/components/action-button.md +0 -638
- package/docs/components/actions-group.md +0 -708
- package/docs/components/alert-dialog.md +0 -920
- package/docs/components/avatar.md +0 -709
- package/docs/components/badge-field.md +0 -738
- package/docs/components/badge.md +0 -301
- package/docs/components/breadcrumb.md +0 -930
- package/docs/components/button-group.md +0 -650
- package/docs/components/button.md +0 -639
- package/docs/components/calendar.md +0 -555
- package/docs/components/card.md +0 -622
- package/docs/components/chart-block-tool.md +0 -129
- package/docs/components/checkbox.md +0 -699
- package/docs/components/cn-layout.md +0 -854
- package/docs/components/color-picker.md +0 -101
- package/docs/components/conclusion-header.md +0 -80
- package/docs/components/context-menu.md +0 -483
- package/docs/components/count-badge.md +0 -560
- package/docs/components/data-table.md +0 -854
- package/docs/components/data-views/backend-response.md +0 -324
- package/docs/components/data-views/examples/a11y-rtl.md +0 -250
- package/docs/components/data-views/examples/api-orders-route.md +0 -130
- package/docs/components/data-views/examples/fields.md +0 -362
- package/docs/components/data-views/examples/filters.md +0 -307
- package/docs/components/data-views/examples/inbox-routing.md +0 -218
- package/docs/components/data-views/examples/index.md +0 -29
- package/docs/components/data-views/examples/overview.md +0 -244
- package/docs/components/data-views/examples/panel.md +0 -212
- package/docs/components/data-views/examples/scale.md +0 -231
- package/docs/components/data-views/examples/server-side.md +0 -210
- package/docs/components/data-views/examples/state.md +0 -250
- package/docs/components/data-views/examples/tree-custom.md +0 -388
- package/docs/components/data-views/examples/view-registry.md +0 -313
- package/docs/components/data-views/examples/views.md +0 -534
- package/docs/components/data-views/guide.md +0 -405
- package/docs/components/data-views/index.md +0 -1521
- package/docs/components/data-views/migration.md +0 -81
- package/docs/components/date-picker.md +0 -857
- package/docs/components/dialog.md +0 -929
- package/docs/components/divider.md +0 -766
- package/docs/components/drawer.md +0 -654
- package/docs/components/dropdown-menu.md +0 -668
- package/docs/components/field-hint.md +0 -898
- package/docs/components/field-section.md +0 -781
- package/docs/components/form-builder.md +0 -284
- package/docs/components/form-renderer.md +0 -396
- package/docs/components/form-summary.md +0 -138
- package/docs/components/form.md +0 -785
- package/docs/components/header-bar.md +0 -188
- package/docs/components/image-attachment.md +0 -906
- package/docs/components/inner-label-field.md +0 -819
- package/docs/components/input-field.md +0 -623
- package/docs/components/input-otp.md +0 -756
- package/docs/components/input.md +0 -634
- package/docs/components/label-field.md +0 -770
- package/docs/components/label.md +0 -761
- package/docs/components/labeled-check-box.md +0 -642
- package/docs/components/labeled-radio.md +0 -796
- package/docs/components/link-button.md +0 -685
- package/docs/components/login-button.md +0 -872
- package/docs/components/password-level.md +0 -803
- package/docs/components/popover.md +0 -649
- package/docs/components/profile-menu.md +0 -656
- package/docs/components/radio-card.md +0 -801
- package/docs/components/radio.md +0 -735
- package/docs/components/scroll-area.md +0 -691
- package/docs/components/search-field.md +0 -702
- package/docs/components/searchable-select.md +0 -368
- package/docs/components/searchable-table.md +0 -438
- package/docs/components/searchable-tree-dialog.md +0 -190
- package/docs/components/searchable-tree.md +0 -200
- package/docs/components/section-block.md +0 -483
- package/docs/components/select.md +0 -709
- package/docs/components/simple-select.md +0 -741
- package/docs/components/skeleton.md +0 -706
- package/docs/components/slide-date-picker.md +0 -837
- package/docs/components/spin-loading.md +0 -696
- package/docs/components/stepper.md +0 -316
- package/docs/components/switch.md +0 -770
- package/docs/components/tab-form-item.md +0 -773
- package/docs/components/tab-switch.md +0 -170
- package/docs/components/table-dnd-wrapper.md +0 -107
- package/docs/components/table.md +0 -1088
- package/docs/components/text-editor.md +0 -735
- package/docs/components/textarea.md +0 -681
- package/docs/components/timeline.md +0 -254
- package/docs/components/toast.md +0 -773
- package/docs/components/toggle-button.md +0 -643
- package/docs/components/toggle.md +0 -882
- package/docs/components/tooltip.md +0 -513
- package/docs/components/transparent-label.md +0 -721
- package/docs/components/tree-drop-down.md +0 -740
- package/docs/components/tree-folder.md +0 -110
- package/docs/components/tree-sub-layout.md +0 -707
- package/docs/explanation/architecture.md +0 -54
- package/docs/explanation/design-system.md +0 -52
- package/docs/how-to/form-and-list-recipes.md +0 -386
- package/docs/how-to/forms-with-form-builder.md +0 -472
- package/docs/how-to/guides.md +0 -1027
- package/docs/migration/changelog.md +0 -60
- package/docs/migration/form-builder-2.5.2.md +0 -113
- package/docs/reference/cli.md +0 -112
- package/docs/reference/components.md +0 -572
- package/docs/reference/hooks.md +0 -1523
- package/docs/reference/providers.md +0 -866
- package/docs/reference/tailwind-plugins.md +0 -942
- package/docs/reference/theme.md +0 -85
- package/docs/reference/types.md +0 -1016
- package/docs/reference/utilities.md +0 -726
- package/docs/tutorials/building-first-form.md +0 -846
- package/docs/tutorials/component-composition.md +0 -882
- package/docs/tutorials/getting-started.md +0 -302
- package/docs/tutorials/theming-basics.md +0 -785
|
@@ -1,685 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: LinkButton
|
|
3
|
-
description: Link-style button with animated arrow indicator for navigation and external links.
|
|
4
|
-
component: true
|
|
5
|
-
group: Buttons & Actions
|
|
6
|
-
keywords: [button, link, navigation, arrow, animated, hover]
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# LinkButton
|
|
10
|
-
|
|
11
|
-
A stylized link button component featuring an animated arrow that appears on hover. Perfect for navigation links, call-to-action elements, and external link indicators.
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
16
|
-
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npx torch-glare@latest init
|
|
20
|
-
npx torch-glare@latest add LinkButton
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
`add` also copies any components, hooks, and utilities that `LinkButton` depends on.
|
|
24
|
-
|
|
25
|
-
## Imports
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { LinkButton } from '@/components/LinkButton'
|
|
29
|
-
import { linkButtonStyles } from '@/components/LinkButton'
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Basic Usage
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
import { LinkButton } from '@/components/LinkButton'
|
|
36
|
-
|
|
37
|
-
export function BasicLinkButton() {
|
|
38
|
-
return (
|
|
39
|
-
<LinkButton size="S" href="/dashboard">
|
|
40
|
-
Go to Dashboard
|
|
41
|
-
</LinkButton>
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Examples
|
|
47
|
-
|
|
48
|
-
### Sizes
|
|
49
|
-
|
|
50
|
-
LinkButton comes in two sizes: S (small) and M (medium).
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
export function LinkButtonSizes() {
|
|
54
|
-
return (
|
|
55
|
-
<div className="flex flex-col gap-4">
|
|
56
|
-
<LinkButton size="S" href="/products">
|
|
57
|
-
Small Link Button
|
|
58
|
-
</LinkButton>
|
|
59
|
-
|
|
60
|
-
<LinkButton size="M" href="/products">
|
|
61
|
-
Medium Link Button
|
|
62
|
-
</LinkButton>
|
|
63
|
-
</div>
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Navigation Links
|
|
69
|
-
|
|
70
|
-
Internal navigation with LinkButton.
|
|
71
|
-
|
|
72
|
-
```tsx
|
|
73
|
-
export function NavigationLinks() {
|
|
74
|
-
return (
|
|
75
|
-
<nav className="flex flex-wrap gap-4">
|
|
76
|
-
<LinkButton size="S" href="/features">
|
|
77
|
-
Features
|
|
78
|
-
</LinkButton>
|
|
79
|
-
|
|
80
|
-
<LinkButton size="S" href="/pricing">
|
|
81
|
-
Pricing Plans
|
|
82
|
-
</LinkButton>
|
|
83
|
-
|
|
84
|
-
<LinkButton size="S" href="/documentation">
|
|
85
|
-
Documentation
|
|
86
|
-
</LinkButton>
|
|
87
|
-
|
|
88
|
-
<LinkButton size="S" href="/support">
|
|
89
|
-
Get Support
|
|
90
|
-
</LinkButton>
|
|
91
|
-
</nav>
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### External Links
|
|
97
|
-
|
|
98
|
-
LinkButton for external URLs with proper attributes.
|
|
99
|
-
|
|
100
|
-
```tsx
|
|
101
|
-
export function ExternalLinks() {
|
|
102
|
-
return (
|
|
103
|
-
<div className="flex flex-col gap-3">
|
|
104
|
-
<LinkButton
|
|
105
|
-
size="M"
|
|
106
|
-
href="https://github.com/your-repo"
|
|
107
|
-
target="_blank"
|
|
108
|
-
rel="noopener noreferrer"
|
|
109
|
-
>
|
|
110
|
-
View on GitHub
|
|
111
|
-
</LinkButton>
|
|
112
|
-
|
|
113
|
-
<LinkButton
|
|
114
|
-
size="M"
|
|
115
|
-
href="https://docs.example.com"
|
|
116
|
-
target="_blank"
|
|
117
|
-
rel="noopener noreferrer"
|
|
118
|
-
>
|
|
119
|
-
Read Documentation
|
|
120
|
-
</LinkButton>
|
|
121
|
-
|
|
122
|
-
<LinkButton
|
|
123
|
-
size="M"
|
|
124
|
-
href="mailto:support@example.com"
|
|
125
|
-
>
|
|
126
|
-
Contact Support
|
|
127
|
-
</LinkButton>
|
|
128
|
-
</div>
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### With React Router
|
|
134
|
-
|
|
135
|
-
Integration with React Router for SPA navigation.
|
|
136
|
-
|
|
137
|
-
```tsx
|
|
138
|
-
import { Link } from 'react-router-dom'
|
|
139
|
-
|
|
140
|
-
export function RouterLinkButton() {
|
|
141
|
-
return (
|
|
142
|
-
<div className="flex gap-4">
|
|
143
|
-
<LinkButton size="S" asChild>
|
|
144
|
-
<Link to="/dashboard">Dashboard</Link>
|
|
145
|
-
</LinkButton>
|
|
146
|
-
|
|
147
|
-
<LinkButton size="S" asChild>
|
|
148
|
-
<Link to="/profile">Profile</Link>
|
|
149
|
-
</LinkButton>
|
|
150
|
-
|
|
151
|
-
<LinkButton size="S" asChild>
|
|
152
|
-
<Link to="/settings">Settings</Link>
|
|
153
|
-
</LinkButton>
|
|
154
|
-
</div>
|
|
155
|
-
)
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### Call-to-Action
|
|
160
|
-
|
|
161
|
-
Prominent CTA implementations.
|
|
162
|
-
|
|
163
|
-
```tsx
|
|
164
|
-
export function CallToAction() {
|
|
165
|
-
return (
|
|
166
|
-
<div className="bg-background-presentation-global-secondary p-8 rounded-lg text-center">
|
|
167
|
-
<h2 className="text-2xl font-bold mb-4">
|
|
168
|
-
Ready to get started?
|
|
169
|
-
</h2>
|
|
170
|
-
<p className="text-content-presentation-global-secondary mb-6">
|
|
171
|
-
Join thousands of developers building with our platform
|
|
172
|
-
</p>
|
|
173
|
-
|
|
174
|
-
<div className="flex justify-center gap-4">
|
|
175
|
-
<LinkButton size="M" href="/signup">
|
|
176
|
-
Start Free Trial
|
|
177
|
-
</LinkButton>
|
|
178
|
-
|
|
179
|
-
<LinkButton size="M" href="/demo">
|
|
180
|
-
View Demo
|
|
181
|
-
</LinkButton>
|
|
182
|
-
</div>
|
|
183
|
-
</div>
|
|
184
|
-
)
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Resource Links
|
|
189
|
-
|
|
190
|
-
Links to downloadable resources.
|
|
191
|
-
|
|
192
|
-
```tsx
|
|
193
|
-
export function ResourceLinks() {
|
|
194
|
-
const resources = [
|
|
195
|
-
{ name: 'API Documentation', href: '/docs/api.pdf', type: 'PDF' },
|
|
196
|
-
{ name: 'Design Guidelines', href: '/docs/design.pdf', type: 'PDF' },
|
|
197
|
-
{ name: 'Sample Code', href: '/downloads/samples.zip', type: 'ZIP' },
|
|
198
|
-
{ name: 'Video Tutorial', href: '/videos/tutorial.mp4', type: 'MP4' },
|
|
199
|
-
]
|
|
200
|
-
|
|
201
|
-
return (
|
|
202
|
-
<div className="grid grid-cols-2 gap-3">
|
|
203
|
-
{resources.map(resource => (
|
|
204
|
-
<LinkButton
|
|
205
|
-
key={resource.name}
|
|
206
|
-
size="S"
|
|
207
|
-
href={resource.href}
|
|
208
|
-
download
|
|
209
|
-
>
|
|
210
|
-
{resource.name}
|
|
211
|
-
<span className="text-xs ml-2 opacity-60">
|
|
212
|
-
({resource.type})
|
|
213
|
-
</span>
|
|
214
|
-
</LinkButton>
|
|
215
|
-
))}
|
|
216
|
-
</div>
|
|
217
|
-
)
|
|
218
|
-
}
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Breadcrumb Navigation
|
|
222
|
-
|
|
223
|
-
LinkButton in breadcrumb trails.
|
|
224
|
-
|
|
225
|
-
```tsx
|
|
226
|
-
export function Breadcrumbs() {
|
|
227
|
-
const path = [
|
|
228
|
-
{ label: 'Home', href: '/' },
|
|
229
|
-
{ label: 'Products', href: '/products' },
|
|
230
|
-
{ label: 'Electronics', href: '/products/electronics' },
|
|
231
|
-
{ label: 'Laptops', href: '/products/electronics/laptops' },
|
|
232
|
-
]
|
|
233
|
-
|
|
234
|
-
return (
|
|
235
|
-
<nav className="flex items-center gap-2">
|
|
236
|
-
{path.map((item, index) => (
|
|
237
|
-
<React.Fragment key={item.href}>
|
|
238
|
-
{index > 0 && (
|
|
239
|
-
<span className="text-content-presentation-global-tertiary">
|
|
240
|
-
/
|
|
241
|
-
</span>
|
|
242
|
-
)}
|
|
243
|
-
{index === path.length - 1 ? (
|
|
244
|
-
<span className="text-content-presentation-global-primary">
|
|
245
|
-
{item.label}
|
|
246
|
-
</span>
|
|
247
|
-
) : (
|
|
248
|
-
<LinkButton size="S" href={item.href}>
|
|
249
|
-
{item.label}
|
|
250
|
-
</LinkButton>
|
|
251
|
-
)}
|
|
252
|
-
</React.Fragment>
|
|
253
|
-
))}
|
|
254
|
-
</nav>
|
|
255
|
-
)
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### Card Actions
|
|
260
|
-
|
|
261
|
-
LinkButtons within card components.
|
|
262
|
-
|
|
263
|
-
```tsx
|
|
264
|
-
export function CardWithLinks() {
|
|
265
|
-
return (
|
|
266
|
-
<div className="border border-border-presentation-global-primary rounded-lg p-6">
|
|
267
|
-
<h3 className="text-lg font-semibold mb-2">
|
|
268
|
-
Premium Features
|
|
269
|
-
</h3>
|
|
270
|
-
<p className="text-content-presentation-global-secondary mb-4">
|
|
271
|
-
Unlock advanced capabilities with our premium plan
|
|
272
|
-
</p>
|
|
273
|
-
|
|
274
|
-
<div className="flex gap-3">
|
|
275
|
-
<LinkButton size="S" href="/features">
|
|
276
|
-
Learn More
|
|
277
|
-
</LinkButton>
|
|
278
|
-
|
|
279
|
-
<LinkButton size="S" href="/pricing">
|
|
280
|
-
View Pricing
|
|
281
|
-
</LinkButton>
|
|
282
|
-
</div>
|
|
283
|
-
</div>
|
|
284
|
-
)
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### Footer Links
|
|
289
|
-
|
|
290
|
-
Organized footer link sections.
|
|
291
|
-
|
|
292
|
-
```tsx
|
|
293
|
-
export function FooterLinks() {
|
|
294
|
-
const sections = [
|
|
295
|
-
{
|
|
296
|
-
title: 'Product',
|
|
297
|
-
links: ['Features', 'Pricing', 'Roadmap', 'Changelog']
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
title: 'Resources',
|
|
301
|
-
links: ['Documentation', 'API Reference', 'Guides', 'Examples']
|
|
302
|
-
},
|
|
303
|
-
{
|
|
304
|
-
title: 'Company',
|
|
305
|
-
links: ['About', 'Blog', 'Careers', 'Contact']
|
|
306
|
-
},
|
|
307
|
-
]
|
|
308
|
-
|
|
309
|
-
return (
|
|
310
|
-
<footer className="grid grid-cols-3 gap-8">
|
|
311
|
-
{sections.map(section => (
|
|
312
|
-
<div key={section.title}>
|
|
313
|
-
<h4 className="font-semibold mb-3">{section.title}</h4>
|
|
314
|
-
<div className="flex flex-col gap-2">
|
|
315
|
-
{section.links.map(link => (
|
|
316
|
-
<LinkButton
|
|
317
|
-
key={link}
|
|
318
|
-
size="S"
|
|
319
|
-
href={`/${link.toLowerCase().replace(' ', '-')}`}
|
|
320
|
-
>
|
|
321
|
-
{link}
|
|
322
|
-
</LinkButton>
|
|
323
|
-
))}
|
|
324
|
-
</div>
|
|
325
|
-
</div>
|
|
326
|
-
))}
|
|
327
|
-
</footer>
|
|
328
|
-
)
|
|
329
|
-
}
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
### Themed LinkButtons
|
|
333
|
-
|
|
334
|
-
Apply different themes to LinkButtons.
|
|
335
|
-
|
|
336
|
-
```tsx
|
|
337
|
-
export function ThemedLinkButtons() {
|
|
338
|
-
return (
|
|
339
|
-
<div className="space-y-4">
|
|
340
|
-
<div className="p-4 bg-white rounded-lg">
|
|
341
|
-
<LinkButton size="M" theme="light" href="/light">
|
|
342
|
-
Light Theme Link
|
|
343
|
-
</LinkButton>
|
|
344
|
-
</div>
|
|
345
|
-
|
|
346
|
-
<div className="p-4 bg-gray-900 rounded-lg">
|
|
347
|
-
<LinkButton size="M" theme="dark" href="/dark">
|
|
348
|
-
Dark Theme Link
|
|
349
|
-
</LinkButton>
|
|
350
|
-
</div>
|
|
351
|
-
|
|
352
|
-
<div className="p-4 bg-gray-100 rounded-lg">
|
|
353
|
-
<LinkButton size="M" theme="default" href="/default">
|
|
354
|
-
Default Theme Link
|
|
355
|
-
</LinkButton>
|
|
356
|
-
</div>
|
|
357
|
-
</div>
|
|
358
|
-
)
|
|
359
|
-
}
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
## API Reference
|
|
363
|
-
|
|
364
|
-
### LinkButton Props
|
|
365
|
-
|
|
366
|
-
| Prop | Type | Default | Description |
|
|
367
|
-
|------|------|---------|-------------|
|
|
368
|
-
| size | `'S' \| 'M'` | `'S'` | Button size |
|
|
369
|
-
| href | `string` | - | Link destination URL |
|
|
370
|
-
| theme | `Themes` | - | Theme variant |
|
|
371
|
-
| asChild | `boolean` | `false` | Merge props with child element |
|
|
372
|
-
| target | `string` | - | Link target attribute |
|
|
373
|
-
| rel | `string` | - | Link rel attribute |
|
|
374
|
-
| download | `boolean \| string` | - | Download attribute |
|
|
375
|
-
| className | `string` | - | Additional CSS classes |
|
|
376
|
-
| children | `ReactNode` | - | Link text content |
|
|
377
|
-
| onClick | `() => void` | - | Click handler |
|
|
378
|
-
|
|
379
|
-
### Size Specifications
|
|
380
|
-
|
|
381
|
-
| Size | Height | Typography | Arrow Size |
|
|
382
|
-
|------|--------|------------|------------|
|
|
383
|
-
| S | 24px | body-small-semibold | 14px × 14px |
|
|
384
|
-
| M | 26px | body-medium-semibold | 16px × 16px |
|
|
385
|
-
|
|
386
|
-
## Styling
|
|
387
|
-
|
|
388
|
-
### Animation Details
|
|
389
|
-
|
|
390
|
-
The LinkButton features a sophisticated hover animation:
|
|
391
|
-
|
|
392
|
-
1. **Arrow Container**: Scales from 0 to full size on hover
|
|
393
|
-
2. **Opacity Transition**: Arrow fades in smoothly
|
|
394
|
-
3. **Padding Animation**: Text padding adjusts for arrow space
|
|
395
|
-
4. **Duration**: 100ms for arrow, 250ms for container
|
|
396
|
-
|
|
397
|
-
### Base Styles
|
|
398
|
-
|
|
399
|
-
```css
|
|
400
|
-
/* Core styles */
|
|
401
|
-
.link-button {
|
|
402
|
-
background: var(--background-presentation-action-link-primary);
|
|
403
|
-
color: var(--content-presentation-action-link);
|
|
404
|
-
border-radius: 6px;
|
|
405
|
-
padding: 2px;
|
|
406
|
-
transition: all 250ms ease-in-out;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/* Arrow animation */
|
|
410
|
-
.arrow-container {
|
|
411
|
-
transition: all 100ms ease-in-out;
|
|
412
|
-
width: 0;
|
|
413
|
-
height: 0;
|
|
414
|
-
opacity: 0;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
.link-button:hover .arrow-container {
|
|
418
|
-
opacity: 1;
|
|
419
|
-
width: 20px; /* S size */
|
|
420
|
-
height: 20px;
|
|
421
|
-
}
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
### Custom Styling
|
|
425
|
-
|
|
426
|
-
```tsx
|
|
427
|
-
// Custom colored link button
|
|
428
|
-
<LinkButton
|
|
429
|
-
size="M"
|
|
430
|
-
className="!bg-purple-100 !text-purple-700 hover:!bg-purple-200"
|
|
431
|
-
href="/custom"
|
|
432
|
-
>
|
|
433
|
-
Custom Styled Link
|
|
434
|
-
</LinkButton>
|
|
435
|
-
|
|
436
|
-
// Inline link style
|
|
437
|
-
<LinkButton
|
|
438
|
-
size="S"
|
|
439
|
-
className="!p-0 !bg-transparent"
|
|
440
|
-
href="/inline"
|
|
441
|
-
>
|
|
442
|
-
Inline Link
|
|
443
|
-
</LinkButton>
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
## TypeScript Types
|
|
447
|
-
|
|
448
|
-
```typescript
|
|
449
|
-
interface LinkButtonProps extends HTMLAttributes<HTMLAnchorElement | HTMLSpanElement> {
|
|
450
|
-
size?: 'S' | 'M'
|
|
451
|
-
theme?: Themes
|
|
452
|
-
asChild?: boolean
|
|
453
|
-
href?: string
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// Exported styles function
|
|
457
|
-
export const linkButtonStyles: (props?: {
|
|
458
|
-
size?: 'S' | 'M'
|
|
459
|
-
}) => string
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
## Common Patterns
|
|
463
|
-
|
|
464
|
-
### Link List Component
|
|
465
|
-
|
|
466
|
-
```tsx
|
|
467
|
-
function LinkList({ links, size = 'S' }) {
|
|
468
|
-
return (
|
|
469
|
-
<ul className="space-y-2">
|
|
470
|
-
{links.map(link => (
|
|
471
|
-
<li key={link.href}>
|
|
472
|
-
<LinkButton size={size} href={link.href}>
|
|
473
|
-
{link.icon && <i className={`${link.icon} mr-2`}></i>}
|
|
474
|
-
{link.label}
|
|
475
|
-
</LinkButton>
|
|
476
|
-
</li>
|
|
477
|
-
))}
|
|
478
|
-
</ul>
|
|
479
|
-
)
|
|
480
|
-
}
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
### Conditional Link Rendering
|
|
484
|
-
|
|
485
|
-
```tsx
|
|
486
|
-
function ConditionalLink({ condition, href, children }) {
|
|
487
|
-
if (!condition) {
|
|
488
|
-
return <span className="text-content-presentation-global-tertiary">
|
|
489
|
-
{children}
|
|
490
|
-
</span>
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
return (
|
|
494
|
-
<LinkButton size="S" href={href}>
|
|
495
|
-
{children}
|
|
496
|
-
</LinkButton>
|
|
497
|
-
)
|
|
498
|
-
}
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
### Link with Badge
|
|
502
|
-
|
|
503
|
-
```tsx
|
|
504
|
-
function LinkWithBadge({ href, label, badge }) {
|
|
505
|
-
return (
|
|
506
|
-
<LinkButton size="M" href={href} className="inline-flex items-center">
|
|
507
|
-
{label}
|
|
508
|
-
{badge && (
|
|
509
|
-
<span className="ml-2 px-1.5 py-0.5 text-xs bg-background-presentation-state-information-primary text-white rounded">
|
|
510
|
-
{badge}
|
|
511
|
-
</span>
|
|
512
|
-
)}
|
|
513
|
-
</LinkButton>
|
|
514
|
-
)
|
|
515
|
-
}
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
## Testing
|
|
519
|
-
|
|
520
|
-
```typescript
|
|
521
|
-
import { render, screen, fireEvent } from '@testing-library/react'
|
|
522
|
-
import { LinkButton } from '@/components/LinkButton'
|
|
523
|
-
|
|
524
|
-
describe('LinkButton', () => {
|
|
525
|
-
it('renders as anchor with href', () => {
|
|
526
|
-
render(
|
|
527
|
-
<LinkButton href="/test">
|
|
528
|
-
Test Link
|
|
529
|
-
</LinkButton>
|
|
530
|
-
)
|
|
531
|
-
|
|
532
|
-
const link = screen.getByText('Test Link')
|
|
533
|
-
expect(link.tagName).toBe('A')
|
|
534
|
-
expect(link).toHaveAttribute('href', '/test')
|
|
535
|
-
})
|
|
536
|
-
|
|
537
|
-
it('renders as span without href', () => {
|
|
538
|
-
render(
|
|
539
|
-
<LinkButton>
|
|
540
|
-
Test Span
|
|
541
|
-
</LinkButton>
|
|
542
|
-
)
|
|
543
|
-
|
|
544
|
-
const element = screen.getByText('Test Span')
|
|
545
|
-
expect(element.tagName).toBe('SPAN')
|
|
546
|
-
})
|
|
547
|
-
|
|
548
|
-
it('applies correct size classes', () => {
|
|
549
|
-
render(
|
|
550
|
-
<LinkButton size="M">
|
|
551
|
-
Medium Link
|
|
552
|
-
</LinkButton>
|
|
553
|
-
)
|
|
554
|
-
|
|
555
|
-
const link = screen.getByText('Medium Link')
|
|
556
|
-
expect(link).toHaveClass('h-[26px]')
|
|
557
|
-
})
|
|
558
|
-
|
|
559
|
-
it('shows arrow on hover', async () => {
|
|
560
|
-
const { container } = render(
|
|
561
|
-
<LinkButton>
|
|
562
|
-
Hover Link
|
|
563
|
-
</LinkButton>
|
|
564
|
-
)
|
|
565
|
-
|
|
566
|
-
const arrow = container.querySelector('svg')
|
|
567
|
-
expect(arrow).toBeInTheDocument()
|
|
568
|
-
})
|
|
569
|
-
|
|
570
|
-
it('supports asChild pattern', () => {
|
|
571
|
-
const CustomLink = ({ children, ...props }) => (
|
|
572
|
-
<a {...props} className="custom-link">
|
|
573
|
-
{children}
|
|
574
|
-
</a>
|
|
575
|
-
)
|
|
576
|
-
|
|
577
|
-
render(
|
|
578
|
-
<LinkButton asChild>
|
|
579
|
-
<CustomLink href="/custom">Custom</CustomLink>
|
|
580
|
-
</LinkButton>
|
|
581
|
-
)
|
|
582
|
-
|
|
583
|
-
const link = screen.getByText('Custom')
|
|
584
|
-
expect(link).toHaveClass('custom-link')
|
|
585
|
-
})
|
|
586
|
-
})
|
|
587
|
-
```
|
|
588
|
-
|
|
589
|
-
## Accessibility
|
|
590
|
-
|
|
591
|
-
- **Semantic HTML**: Uses appropriate anchor or span elements
|
|
592
|
-
- **Keyboard Navigation**: Full keyboard support for links
|
|
593
|
-
- **Focus States**: Clear focus indicators for keyboard users
|
|
594
|
-
- **Screen Reader Support**: Link purpose is clear from text
|
|
595
|
-
- **ARIA Attributes**: Supports all standard ARIA link attributes
|
|
596
|
-
- **External Link Indicators**: Arrow animation provides visual feedback
|
|
597
|
-
|
|
598
|
-
### Accessibility Example
|
|
599
|
-
|
|
600
|
-
```tsx
|
|
601
|
-
<LinkButton
|
|
602
|
-
size="M"
|
|
603
|
-
href="https://external.com"
|
|
604
|
-
target="_blank"
|
|
605
|
-
rel="noopener noreferrer"
|
|
606
|
-
aria-label="Visit external site (opens in new tab)"
|
|
607
|
-
>
|
|
608
|
-
External Resource
|
|
609
|
-
<span className="sr-only">(opens in new tab)</span>
|
|
610
|
-
</LinkButton>
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
## Performance
|
|
614
|
-
|
|
615
|
-
- **CSS Animations**: Hardware-accelerated transitions
|
|
616
|
-
- **Lazy SVG Rendering**: Arrow SVG is always present but hidden
|
|
617
|
-
- **Minimal Re-renders**: Hover state handled via CSS
|
|
618
|
-
- **Optimized Classes**: CVA for efficient class generation
|
|
619
|
-
|
|
620
|
-
### Performance Tips
|
|
621
|
-
|
|
622
|
-
```tsx
|
|
623
|
-
// Memoize link lists
|
|
624
|
-
const MemoizedLinkButton = React.memo(LinkButton)
|
|
625
|
-
|
|
626
|
-
// Use stable href values
|
|
627
|
-
const links = useMemo(() =>
|
|
628
|
-
items.map(item => ({
|
|
629
|
-
href: `/items/${item.id}`,
|
|
630
|
-
label: item.name
|
|
631
|
-
})),
|
|
632
|
-
[items]
|
|
633
|
-
)
|
|
634
|
-
|
|
635
|
-
// Render efficiently
|
|
636
|
-
{links.map(link => (
|
|
637
|
-
<MemoizedLinkButton
|
|
638
|
-
key={link.href}
|
|
639
|
-
size="S"
|
|
640
|
-
href={link.href}
|
|
641
|
-
>
|
|
642
|
-
{link.label}
|
|
643
|
-
</MemoizedLinkButton>
|
|
644
|
-
))}
|
|
645
|
-
```
|
|
646
|
-
|
|
647
|
-
## Migration Guide
|
|
648
|
-
|
|
649
|
-
### From Standard Links
|
|
650
|
-
|
|
651
|
-
```tsx
|
|
652
|
-
// Before: Standard anchor
|
|
653
|
-
<a href="/page" className="text-blue-500 hover:underline">
|
|
654
|
-
Go to page
|
|
655
|
-
</a>
|
|
656
|
-
|
|
657
|
-
// After: LinkButton
|
|
658
|
-
<LinkButton size="S" href="/page">
|
|
659
|
-
Go to page
|
|
660
|
-
</LinkButton>
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
### From Other Libraries
|
|
664
|
-
|
|
665
|
-
```tsx
|
|
666
|
-
// Before: Material-UI Link
|
|
667
|
-
<Link href="/page" underline="hover">
|
|
668
|
-
Link text
|
|
669
|
-
</Link>
|
|
670
|
-
|
|
671
|
-
// After: LinkButton
|
|
672
|
-
<LinkButton size="S" href="/page">
|
|
673
|
-
Link text
|
|
674
|
-
</LinkButton>
|
|
675
|
-
```
|
|
676
|
-
|
|
677
|
-
## Best Practices
|
|
678
|
-
|
|
679
|
-
1. **Use Semantic Sizes**: Choose size based on hierarchy and importance
|
|
680
|
-
2. **External Link Indicators**: Always include target="_blank" and rel attributes
|
|
681
|
-
3. **Descriptive Text**: Link text should clearly indicate destination
|
|
682
|
-
4. **Consistent Styling**: Use the same size for links at the same level
|
|
683
|
-
5. **Accessibility Labels**: Add aria-labels for ambiguous link text
|
|
684
|
-
6. **Keyboard Support**: Ensure all interactive elements are keyboard accessible
|
|
685
|
-
7. **Loading States**: Consider loading states for async navigation
|