@ternent/core 0.0.1
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/.changeset/README.md +8 -0
- package/.changeset/config.json +17 -0
- package/.github/workflows/deploy-armour.yml +42 -0
- package/.github/workflows/deploy-identity.yml +42 -0
- package/.github/workflows/deploy-seal.yml +42 -0
- package/.github/workflows/deploy-ui.yml +42 -0
- package/.github/workflows/deploy-utils.yml +42 -0
- package/.github/workflows/release-create.yml +59 -0
- package/.github/workflows/release-publish.yml +54 -0
- package/.nvmrc +1 -0
- package/.ops/publish.mjs +31 -0
- package/package.json +16 -0
- package/packages/README.md +0 -0
- package/packages/armour/CHANGELOG.md +66 -0
- package/packages/armour/CLAUDE.md +8 -0
- package/packages/armour/README.md +103 -0
- package/packages/armour/SPEC.md +92 -0
- package/packages/armour/package.json +45 -0
- package/packages/armour/src/constants.ts +5 -0
- package/packages/armour/src/deps.d.ts +56 -0
- package/packages/armour/src/errors.ts +172 -0
- package/packages/armour/src/files.ts +73 -0
- package/packages/armour/src/identity.ts +72 -0
- package/packages/armour/src/index.ts +56 -0
- package/packages/armour/src/init.ts +10 -0
- package/packages/armour/src/passphrase.ts +33 -0
- package/packages/armour/src/recipients.ts +73 -0
- package/packages/armour/src/text.ts +68 -0
- package/packages/armour/src/types.ts +93 -0
- package/packages/armour/test/armour.test.ts +270 -0
- package/packages/armour/tsconfig.build.json +12 -0
- package/packages/armour/tsconfig.json +12 -0
- package/packages/armour/vite.config.ts +29 -0
- package/packages/concord/CHANGELOG.md +83 -0
- package/packages/concord/CLAUDE.md +9 -0
- package/packages/concord/README.md +146 -0
- package/packages/concord/SPEC.md +287 -0
- package/packages/concord/package.json +51 -0
- package/packages/concord/src/app.ts +717 -0
- package/packages/concord/src/errors.ts +9 -0
- package/packages/concord/src/index.ts +20 -0
- package/packages/concord/src/types.ts +127 -0
- package/packages/concord/test/concord.test.ts +978 -0
- package/packages/concord/tsconfig.json +12 -0
- package/packages/concord/vite.browser.config.ts +27 -0
- package/packages/concord/vite.config.ts +35 -0
- package/packages/concord/vite.config.ts.timestamp-1774262297922-ffd76e35ea668.mjs +83 -0
- package/packages/identity/CHANGELOG.md +47 -0
- package/packages/identity/README.md +236 -0
- package/packages/identity/package.json +41 -0
- package/packages/identity/src/index.ts +538 -0
- package/packages/identity/test/identity.test.ts +172 -0
- package/packages/identity/tsconfig.build.json +12 -0
- package/packages/identity/vite.config.ts +17 -0
- package/packages/ledger/CHANGELOG.md +69 -0
- package/packages/ledger/CLAUDE.md +9 -0
- package/packages/ledger/SPEC.md +304 -0
- package/packages/ledger/package.json +48 -0
- package/packages/ledger/src/index.ts +2 -0
- package/packages/ledger/src/ledger.ts +1286 -0
- package/packages/ledger/src/seal-cli.d.ts +25 -0
- package/packages/ledger/src/types.ts +294 -0
- package/packages/ledger/test/ledger.test.ts +838 -0
- package/packages/ledger/tsconfig.json +12 -0
- package/packages/ledger/vite.browser.config.ts +27 -0
- package/packages/ledger/vite.config.ts +39 -0
- package/packages/seal/CHANGELOG.md +137 -0
- package/packages/seal/CLAUDE.md +8 -0
- package/packages/seal/README.md +258 -0
- package/packages/seal/bin/seal +6 -0
- package/packages/seal/package.json +59 -0
- package/packages/seal/src/artifact.ts +380 -0
- package/packages/seal/src/cli.ts +372 -0
- package/packages/seal/src/commands/identity.ts +52 -0
- package/packages/seal/src/commands/manifest.ts +71 -0
- package/packages/seal/src/commands/publicKey.ts +7 -0
- package/packages/seal/src/commands/sign.ts +56 -0
- package/packages/seal/src/commands/verify.ts +54 -0
- package/packages/seal/src/crypto.ts +85 -0
- package/packages/seal/src/errors.ts +88 -0
- package/packages/seal/src/index.ts +5 -0
- package/packages/seal/src/manifest.ts +114 -0
- package/packages/seal/src/node.ts +18 -0
- package/packages/seal/src/proof.ts +344 -0
- package/packages/seal/test/artifact.test.ts +86 -0
- package/packages/seal/test/cli.test.ts +208 -0
- package/packages/seal/test/crypto.test.ts +21 -0
- package/packages/seal/test/manifest.test.ts +32 -0
- package/packages/seal/test/proof.test.ts +60 -0
- package/packages/seal/tsconfig.json +12 -0
- package/packages/seal/vite.config.ts +54 -0
- package/packages/ui/CHANGELOG.md +393 -0
- package/packages/ui/README.md +57 -0
- package/packages/ui/jsconfig.json +19 -0
- package/packages/ui/package.json +64 -0
- package/packages/ui/scripts/check-tokens.js +56 -0
- package/packages/ui/scripts/generate-theme-css.mjs +85 -0
- package/packages/ui/src/design-system/base.css +8 -0
- package/packages/ui/src/design-system/docs/ACCESSIBILITY_RULES.md +186 -0
- package/packages/ui/src/design-system/docs/AI_SYSTEM.md +281 -0
- package/packages/ui/src/design-system/docs/PATTERN_RULES.md +83 -0
- package/packages/ui/src/design-system/docs/PRIMITIVE_RULES.md +258 -0
- package/packages/ui/src/design-system/docs/TOKEN_RULES.md +235 -0
- package/packages/ui/src/design-system/docs/VISUAL_DIRECTION.md +68 -0
- package/packages/ui/src/design-system/foundation.js +420 -0
- package/packages/ui/src/design-system/tokens.css +140 -0
- package/packages/ui/src/design-system/tokens.js +327 -0
- package/packages/ui/src/design-system/utils.js +246 -0
- package/packages/ui/src/main.js +4 -0
- package/packages/ui/src/patterns/FeatureCard/FeatureCard.spec.md +24 -0
- package/packages/ui/src/patterns/FeatureCard/FeatureCard.types.ts +8 -0
- package/packages/ui/src/patterns/FeatureCard/FeatureCard.vue +175 -0
- package/packages/ui/src/patterns/FormField/FormField.spec.md +65 -0
- package/packages/ui/src/patterns/FormField/FormField.types.ts +11 -0
- package/packages/ui/src/patterns/FormField/FormField.vue +87 -0
- package/packages/ui/src/patterns/IdentityGlyph/IdentityGlyph.vue +61 -0
- package/packages/ui/src/patterns/IdentityGlyph/IdentityHandle.vue +58 -0
- package/packages/ui/src/patterns/IdentityGlyph/identityGlyph.types.ts +36 -0
- package/packages/ui/src/patterns/IdentityGlyph/identityGlyph.utils.ts +585 -0
- package/packages/ui/src/patterns/IdentityGlyph/index.ts +5 -0
- package/packages/ui/src/patterns/KeyValueList/KeyValueList.spec.md +28 -0
- package/packages/ui/src/patterns/KeyValueList/KeyValueList.types.ts +16 -0
- package/packages/ui/src/patterns/KeyValueList/KeyValueList.vue +50 -0
- package/packages/ui/src/patterns/LandingPage/LandingIcon.vue +90 -0
- package/packages/ui/src/patterns/LandingPage/LandingPage.spec.md +24 -0
- package/packages/ui/src/patterns/LandingPage/LandingPage.types.ts +212 -0
- package/packages/ui/src/patterns/LandingPage/LandingPage.vue +599 -0
- package/packages/ui/src/patterns/ListWorkspaceLayout/ListWorkspaceLayout.test.ts +33 -0
- package/packages/ui/src/patterns/ListWorkspaceLayout/ListWorkspaceLayout.vue +44 -0
- package/packages/ui/src/patterns/Logo/Logo.spec.md +22 -0
- package/packages/ui/src/patterns/Logo/Logo.vue +160 -0
- package/packages/ui/src/patterns/PageSurface/PageSurface.spec.md +15 -0
- package/packages/ui/src/patterns/PageSurface/PageSurface.vue +85 -0
- package/packages/ui/src/patterns/PanelChrome/PanelChrome.spec.md +39 -0
- package/packages/ui/src/patterns/PanelChrome/PanelChrome.types.ts +1 -0
- package/packages/ui/src/patterns/PanelChrome/PanelChrome.vue +187 -0
- package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.spec.md +31 -0
- package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.types.ts +23 -0
- package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.vue +354 -0
- package/packages/ui/src/patterns/RecordList/RecordList.spec.md +35 -0
- package/packages/ui/src/patterns/RecordList/RecordList.test.ts +42 -0
- package/packages/ui/src/patterns/RecordList/RecordList.types.ts +9 -0
- package/packages/ui/src/patterns/RecordList/RecordList.utils.ts +5 -0
- package/packages/ui/src/patterns/RecordList/RecordList.vue +134 -0
- package/packages/ui/src/patterns/SectionClarifier/SectionClarifier.vue +85 -0
- package/packages/ui/src/patterns/SectionIntro/SectionIntro.spec.md +25 -0
- package/packages/ui/src/patterns/SectionIntro/SectionIntro.types.ts +7 -0
- package/packages/ui/src/patterns/SectionIntro/SectionIntro.vue +141 -0
- package/packages/ui/src/patterns/SidebarNav/SidebarNav.spec.md +34 -0
- package/packages/ui/src/patterns/SidebarNav/SidebarNav.types.ts +17 -0
- package/packages/ui/src/patterns/SidebarNav/SidebarNav.vue +110 -0
- package/packages/ui/src/patterns/SplitView/SplitView.spec.md +28 -0
- package/packages/ui/src/patterns/SplitView/SplitView.test.ts +22 -0
- package/packages/ui/src/patterns/SplitView/SplitView.types.ts +3 -0
- package/packages/ui/src/patterns/SplitView/SplitView.utils.ts +13 -0
- package/packages/ui/src/patterns/SplitView/SplitView.vue +39 -0
- package/packages/ui/src/patterns/StepList/StepList.spec.md +15 -0
- package/packages/ui/src/patterns/StepList/StepList.types.ts +4 -0
- package/packages/ui/src/patterns/StepList/StepList.vue +91 -0
- package/packages/ui/src/patterns/Verification/VerificationBadge.vue +97 -0
- package/packages/ui/src/patterns/Verification/VerificationComponents.test.ts +153 -0
- package/packages/ui/src/patterns/Verification/VerificationDetailsPanel.vue +270 -0
- package/packages/ui/src/patterns/Verification/VerificationSummary.vue +171 -0
- package/packages/ui/src/patterns/Verification/index.ts +6 -0
- package/packages/ui/src/patterns/Verification/verification.types.ts +8 -0
- package/packages/ui/src/patterns/Verification/verification.utils.test.ts +37 -0
- package/packages/ui/src/patterns/Verification/verification.utils.ts +75 -0
- package/packages/ui/src/patterns/index.ts +25 -0
- package/packages/ui/src/primitives/Accordian/Accordian.vue +11 -0
- package/packages/ui/src/primitives/Accordian/AccordianItem.vue +14 -0
- package/packages/ui/src/primitives/Accordion/Accordion.props.ts +21 -0
- package/packages/ui/src/primitives/Accordion/Accordion.spec.md +50 -0
- package/packages/ui/src/primitives/Accordion/Accordion.types.ts +4 -0
- package/packages/ui/src/primitives/Accordion/Accordion.variants.ts +12 -0
- package/packages/ui/src/primitives/Accordion/Accordion.vue +71 -0
- package/packages/ui/src/primitives/Accordion/AccordionItem.props.ts +14 -0
- package/packages/ui/src/primitives/Accordion/AccordionItem.vue +40 -0
- package/packages/ui/src/primitives/Badge/Badge.props.ts +17 -0
- package/packages/ui/src/primitives/Badge/Badge.spec.md +17 -0
- package/packages/ui/src/primitives/Badge/Badge.types.ts +15 -0
- package/packages/ui/src/primitives/Badge/Badge.variants.ts +48 -0
- package/packages/ui/src/primitives/Badge/Badge.vue +31 -0
- package/packages/ui/src/primitives/Button/Button.props.ts +29 -0
- package/packages/ui/src/primitives/Button/Button.spec.md +139 -0
- package/packages/ui/src/primitives/Button/Button.types.ts +19 -0
- package/packages/ui/src/primitives/Button/Button.variants.ts +72 -0
- package/packages/ui/src/primitives/Button/Button.vue +90 -0
- package/packages/ui/src/primitives/Card/Card.props.ts +17 -0
- package/packages/ui/src/primitives/Card/Card.spec.md +29 -0
- package/packages/ui/src/primitives/Card/Card.types.ts +12 -0
- package/packages/ui/src/primitives/Card/Card.variants.ts +27 -0
- package/packages/ui/src/primitives/Card/Card.vue +37 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.props.ts +21 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.spec.md +51 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.types.ts +4 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.variants.ts +34 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.vue +92 -0
- package/packages/ui/src/primitives/Dialog/Dialog.props.ts +29 -0
- package/packages/ui/src/primitives/Dialog/Dialog.spec.md +52 -0
- package/packages/ui/src/primitives/Dialog/Dialog.types.ts +3 -0
- package/packages/ui/src/primitives/Dialog/Dialog.variants.ts +27 -0
- package/packages/ui/src/primitives/Dialog/Dialog.vue +78 -0
- package/packages/ui/src/primitives/Drawer/Drawer.props.ts +33 -0
- package/packages/ui/src/primitives/Drawer/Drawer.spec.md +50 -0
- package/packages/ui/src/primitives/Drawer/Drawer.types.ts +5 -0
- package/packages/ui/src/primitives/Drawer/Drawer.variants.ts +35 -0
- package/packages/ui/src/primitives/Drawer/Drawer.vue +88 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.props.ts +17 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.spec.md +35 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.types.ts +5 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.variants.ts +14 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.vue +40 -0
- package/packages/ui/src/primitives/FileInput/FileInput.props.ts +41 -0
- package/packages/ui/src/primitives/FileInput/FileInput.types.ts +6 -0
- package/packages/ui/src/primitives/FileInput/FileInput.variants.ts +46 -0
- package/packages/ui/src/primitives/FileInput/FileInput.vue +163 -0
- package/packages/ui/src/primitives/Input/Input.props.ts +29 -0
- package/packages/ui/src/primitives/Input/Input.spec.md +79 -0
- package/packages/ui/src/primitives/Input/Input.types.ts +13 -0
- package/packages/ui/src/primitives/Input/Input.variants.ts +54 -0
- package/packages/ui/src/primitives/Input/Input.vue +99 -0
- package/packages/ui/src/primitives/Label/Label.props.ts +25 -0
- package/packages/ui/src/primitives/Label/Label.spec.md +31 -0
- package/packages/ui/src/primitives/Label/Label.types.ts +3 -0
- package/packages/ui/src/primitives/Label/Label.variants.ts +17 -0
- package/packages/ui/src/primitives/Label/Label.vue +38 -0
- package/packages/ui/src/primitives/Menu/Menu.props.ts +17 -0
- package/packages/ui/src/primitives/Menu/Menu.spec.md +38 -0
- package/packages/ui/src/primitives/Menu/Menu.types.ts +10 -0
- package/packages/ui/src/primitives/Menu/Menu.variants.ts +10 -0
- package/packages/ui/src/primitives/Menu/Menu.vue +57 -0
- package/packages/ui/src/primitives/Popover/Popover.props.ts +25 -0
- package/packages/ui/src/primitives/Popover/Popover.spec.md +49 -0
- package/packages/ui/src/primitives/Popover/Popover.types.ts +3 -0
- package/packages/ui/src/primitives/Popover/Popover.variants.ts +18 -0
- package/packages/ui/src/primitives/Popover/Popover.vue +74 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.props.ts +29 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.spec.md +50 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.types.ts +12 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.variants.ts +48 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.vue +87 -0
- package/packages/ui/src/primitives/Separator/Separator.props.ts +9 -0
- package/packages/ui/src/primitives/Separator/Separator.spec.md +15 -0
- package/packages/ui/src/primitives/Separator/Separator.types.ts +3 -0
- package/packages/ui/src/primitives/Separator/Separator.variants.ts +8 -0
- package/packages/ui/src/primitives/Separator/Separator.vue +23 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.props.ts +21 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.spec.md +18 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.types.ts +5 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.variants.ts +18 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.vue +37 -0
- package/packages/ui/src/primitives/Spinner/Spinner.props.ts +13 -0
- package/packages/ui/src/primitives/Spinner/Spinner.spec.md +16 -0
- package/packages/ui/src/primitives/Spinner/Spinner.types.ts +5 -0
- package/packages/ui/src/primitives/Spinner/Spinner.variants.ts +15 -0
- package/packages/ui/src/primitives/Spinner/Spinner.vue +33 -0
- package/packages/ui/src/primitives/SplitButton/SplitButton.vue +108 -0
- package/packages/ui/src/primitives/Switch/Switch.props.ts +21 -0
- package/packages/ui/src/primitives/Switch/Switch.spec.md +49 -0
- package/packages/ui/src/primitives/Switch/Switch.types.ts +3 -0
- package/packages/ui/src/primitives/Switch/Switch.variants.ts +34 -0
- package/packages/ui/src/primitives/Switch/Switch.vue +71 -0
- package/packages/ui/src/primitives/Tabs/Tabs.props.ts +25 -0
- package/packages/ui/src/primitives/Tabs/Tabs.spec.md +48 -0
- package/packages/ui/src/primitives/Tabs/Tabs.types.ts +11 -0
- package/packages/ui/src/primitives/Tabs/Tabs.variants.ts +28 -0
- package/packages/ui/src/primitives/Tabs/Tabs.vue +59 -0
- package/packages/ui/src/primitives/Textarea/Textarea.props.ts +33 -0
- package/packages/ui/src/primitives/Textarea/Textarea.spec.md +59 -0
- package/packages/ui/src/primitives/Textarea/Textarea.types.ts +5 -0
- package/packages/ui/src/primitives/Textarea/Textarea.variants.ts +27 -0
- package/packages/ui/src/primitives/Textarea/Textarea.vue +74 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.props.ts +21 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.spec.md +45 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.types.ts +3 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.variants.ts +4 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.vue +31 -0
- package/packages/ui/src/primitives/TreeView/TreeView.types.ts +10 -0
- package/packages/ui/src/primitives/TreeView/TreeView.vue +113 -0
- package/packages/ui/src/primitives/TreeView/TreeViewNode.vue +190 -0
- package/packages/ui/src/primitives/index.ts +29 -0
- package/packages/ui/src/style.css +7 -0
- package/packages/ui/src/style.js +1 -0
- package/packages/ui/src/themes/armour.css +147 -0
- package/packages/ui/src/themes/aurora.css +147 -0
- package/packages/ui/src/themes/citrine-ash.css +147 -0
- package/packages/ui/src/themes/concord.css +147 -0
- package/packages/ui/src/themes/garnet-honey.css +147 -0
- package/packages/ui/src/themes/harbor-rose.css +147 -0
- package/packages/ui/src/themes/ledger.css +147 -0
- package/packages/ui/src/themes/neon-noir.css +74 -0
- package/packages/ui/src/themes/obsidian-iris.css +147 -0
- package/packages/ui/src/themes/pixpax.css +147 -0
- package/packages/ui/src/themes/print.css +147 -0
- package/packages/ui/src/themes/prism.css +147 -0
- package/packages/ui/src/themes/proof.css +145 -0
- package/packages/ui/src/themes/semanticThemeContract.js +2256 -0
- package/packages/ui/src/themes/spruce-ink.css +147 -0
- package/packages/ui/src/themes/sunset.css +147 -0
- package/packages/ui/tailwind.config.js +64 -0
- package/packages/ui/vite.config.js +35 -0
- package/packages/ui/vite.config.js.timestamp-1780697224943-89fbc929987bc.mjs +38 -0
- package/packages/utils/CHANGELOG.md +111 -0
- package/packages/utils/README.md +3 -0
- package/packages/utils/package.json +46 -0
- package/packages/utils/src/index.test.js +39 -0
- package/packages/utils/src/index.ts +289 -0
- package/packages/utils/tsconfig.build.json +12 -0
- package/packages/utils/vite.config.js +28 -0
- package/pnpm-workspace.yaml +8 -0
- package/scripts/vite/package-lib-config.ts +59 -0
- package/tsconfig.json +24 -0
- package/tsconfig.node.json +9 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PropType } from "vue";
|
|
2
|
+
import type { SwitchSize } from "./Switch.types";
|
|
3
|
+
|
|
4
|
+
export const switchProps = {
|
|
5
|
+
modelValue: {
|
|
6
|
+
type: Boolean,
|
|
7
|
+
default: false,
|
|
8
|
+
},
|
|
9
|
+
size: {
|
|
10
|
+
type: String as PropType<SwitchSize>,
|
|
11
|
+
default: "md",
|
|
12
|
+
},
|
|
13
|
+
disabled: {
|
|
14
|
+
type: Boolean,
|
|
15
|
+
default: false,
|
|
16
|
+
},
|
|
17
|
+
invalid: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Switch
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Binary on/off control primitive built on Ark UI.
|
|
6
|
+
|
|
7
|
+
## Category
|
|
8
|
+
|
|
9
|
+
Primitive
|
|
10
|
+
|
|
11
|
+
## Public API
|
|
12
|
+
|
|
13
|
+
Props:
|
|
14
|
+
|
|
15
|
+
- `modelValue`: boolean
|
|
16
|
+
- `size`: `sm | md`
|
|
17
|
+
- `disabled`: boolean
|
|
18
|
+
- `invalid`: boolean
|
|
19
|
+
|
|
20
|
+
Slots:
|
|
21
|
+
|
|
22
|
+
- default: inline label
|
|
23
|
+
- `description`: supporting text below the label
|
|
24
|
+
|
|
25
|
+
Events:
|
|
26
|
+
|
|
27
|
+
- `update:modelValue`
|
|
28
|
+
|
|
29
|
+
## States
|
|
30
|
+
|
|
31
|
+
- unchecked
|
|
32
|
+
- checked
|
|
33
|
+
- focus-visible
|
|
34
|
+
- disabled
|
|
35
|
+
- invalid
|
|
36
|
+
|
|
37
|
+
## Accessibility
|
|
38
|
+
|
|
39
|
+
- built on Ark `Switch.Root`
|
|
40
|
+
- includes hidden input for form participation
|
|
41
|
+
- focus treatment is applied at the wrapper level with `focus-within`
|
|
42
|
+
|
|
43
|
+
## Example
|
|
44
|
+
|
|
45
|
+
```vue
|
|
46
|
+
<Switch v-model="enabled">
|
|
47
|
+
Email notifications
|
|
48
|
+
</Switch>
|
|
49
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SwitchSize } from "./Switch.types";
|
|
2
|
+
|
|
3
|
+
export const switchRootClass =
|
|
4
|
+
"group inline-flex w-fit items-start gap-3 rounded-[var(--ui-radius-md)] " +
|
|
5
|
+
"focus-within:ring-2 focus-within:ring-[var(--ui-ring)]";
|
|
6
|
+
|
|
7
|
+
export const switchControlBaseClass =
|
|
8
|
+
"relative inline-flex shrink-0 rounded-full border border-[var(--ui-border)] bg-[var(--ui-tonal-secondary)] " +
|
|
9
|
+
"transition-[background-color,border-color,box-shadow] duration-[var(--ui-duration-normal)] ease-[var(--ui-ease-out)] " +
|
|
10
|
+
"group-hover:border-[var(--ui-primary-muted)] data-[state=checked]:border-[var(--ui-primary)] data-[state=checked]:bg-[var(--ui-primary)]";
|
|
11
|
+
|
|
12
|
+
export const switchControlStateClasses = {
|
|
13
|
+
default: "",
|
|
14
|
+
invalid:
|
|
15
|
+
"border-[var(--ui-critical)] data-[state=checked]:border-[var(--ui-critical)] data-[state=checked]:bg-[var(--ui-critical)]",
|
|
16
|
+
disabled: "opacity-50",
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
export const switchControlSizeClasses: Record<SwitchSize, string> = {
|
|
20
|
+
sm: "h-5 w-9",
|
|
21
|
+
md: "h-6 w-10",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const switchThumbBaseClass =
|
|
25
|
+
"absolute left-0.5 top-1/2 -translate-y-1/2 rounded-full bg-[var(--ui-bg)] shadow-[var(--ui-shadow-sm)] " +
|
|
26
|
+
"transition-transform duration-[var(--ui-duration-normal)] ease-[var(--ui-ease-out)]";
|
|
27
|
+
|
|
28
|
+
export const switchThumbSizeClasses: Record<SwitchSize, string> = {
|
|
29
|
+
sm: "size-4 data-[state=checked]:translate-x-4",
|
|
30
|
+
md: "size-5 data-[state=checked]:translate-x-4",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const switchLabelClass = "text-[var(--ui-fg)]";
|
|
34
|
+
export const switchDescriptionClass = "text-sm text-[var(--ui-fg-muted)]";
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Switch } from "@ark-ui/vue/switch";
|
|
3
|
+
import { computed, normalizeClass, useAttrs, useSlots } from "vue";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
5
|
+
import { switchProps } from "./Switch.props";
|
|
6
|
+
import {
|
|
7
|
+
switchControlBaseClass,
|
|
8
|
+
switchControlSizeClasses,
|
|
9
|
+
switchControlStateClasses,
|
|
10
|
+
switchDescriptionClass,
|
|
11
|
+
switchLabelClass,
|
|
12
|
+
switchRootClass,
|
|
13
|
+
switchThumbBaseClass,
|
|
14
|
+
switchThumbSizeClasses,
|
|
15
|
+
} from "./Switch.variants";
|
|
16
|
+
|
|
17
|
+
defineOptions({ inheritAttrs: false });
|
|
18
|
+
|
|
19
|
+
const emit = defineEmits<{
|
|
20
|
+
"update:modelValue": [value: boolean];
|
|
21
|
+
}>();
|
|
22
|
+
|
|
23
|
+
const attrs = useAttrs();
|
|
24
|
+
const slots = useSlots();
|
|
25
|
+
const props = defineProps(switchProps);
|
|
26
|
+
|
|
27
|
+
const rootClass = computed(() => twMerge(switchRootClass, normalizeClass(attrs.class)));
|
|
28
|
+
|
|
29
|
+
const controlClass = computed(() =>
|
|
30
|
+
twMerge(
|
|
31
|
+
switchControlBaseClass,
|
|
32
|
+
switchControlSizeClasses[props.size],
|
|
33
|
+
props.invalid ? switchControlStateClasses.invalid : switchControlStateClasses.default,
|
|
34
|
+
props.disabled ? switchControlStateClasses.disabled : "",
|
|
35
|
+
),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const thumbClass = computed(() =>
|
|
39
|
+
twMerge(switchThumbBaseClass, switchThumbSizeClasses[props.size]),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const rootAttrs = computed(() => {
|
|
43
|
+
const { class: _class, ...rest } = attrs;
|
|
44
|
+
return rest;
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<Switch.Root
|
|
50
|
+
:checked="props.modelValue"
|
|
51
|
+
:disabled="props.disabled"
|
|
52
|
+
:invalid="props.invalid"
|
|
53
|
+
:class="rootClass"
|
|
54
|
+
v-bind="rootAttrs"
|
|
55
|
+
@update:checked="emit('update:modelValue', $event)"
|
|
56
|
+
>
|
|
57
|
+
<Switch.HiddenInput />
|
|
58
|
+
<Switch.Control :class="controlClass">
|
|
59
|
+
<Switch.Thumb :class="thumbClass" />
|
|
60
|
+
</Switch.Control>
|
|
61
|
+
|
|
62
|
+
<div v-if="slots.default || slots.description" class="flex flex-col gap-1">
|
|
63
|
+
<Switch.Label v-if="slots.default" :class="switchLabelClass">
|
|
64
|
+
<slot />
|
|
65
|
+
</Switch.Label>
|
|
66
|
+
<div v-if="slots.description" :class="switchDescriptionClass">
|
|
67
|
+
<slot name="description" />
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</Switch.Root>
|
|
71
|
+
</template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PropType } from "vue";
|
|
2
|
+
import type { TabItem, TabsSize, TabsVariant } from "./Tabs.types";
|
|
3
|
+
|
|
4
|
+
export const tabsProps = {
|
|
5
|
+
modelValue: {
|
|
6
|
+
type: String,
|
|
7
|
+
default: undefined,
|
|
8
|
+
},
|
|
9
|
+
items: {
|
|
10
|
+
type: Array as PropType<TabItem[]>,
|
|
11
|
+
default: () => [],
|
|
12
|
+
},
|
|
13
|
+
size: {
|
|
14
|
+
type: String as PropType<TabsSize>,
|
|
15
|
+
default: "md",
|
|
16
|
+
},
|
|
17
|
+
variant: {
|
|
18
|
+
type: String as PropType<TabsVariant>,
|
|
19
|
+
default: "underline",
|
|
20
|
+
},
|
|
21
|
+
lazyMount: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: true,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Tabs
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Single-selection navigation primitive for switching between related panels.
|
|
6
|
+
|
|
7
|
+
## Category
|
|
8
|
+
|
|
9
|
+
Primitive
|
|
10
|
+
|
|
11
|
+
## Public API
|
|
12
|
+
|
|
13
|
+
Props:
|
|
14
|
+
|
|
15
|
+
- `modelValue`
|
|
16
|
+
- `items`: `{ value, label, disabled? }[]`
|
|
17
|
+
- `size`: `sm | md`
|
|
18
|
+
- `variant`: `underline | pill`
|
|
19
|
+
- `lazyMount`
|
|
20
|
+
|
|
21
|
+
Slots:
|
|
22
|
+
|
|
23
|
+
- dynamic panel slots named `panel-{value}`
|
|
24
|
+
|
|
25
|
+
## Accessibility
|
|
26
|
+
|
|
27
|
+
- built on Ark tabs semantics
|
|
28
|
+
- keyboard roving focus and active tab semantics come from Ark
|
|
29
|
+
|
|
30
|
+
## Keyboard behavior
|
|
31
|
+
|
|
32
|
+
- arrow keys move focus between tabs
|
|
33
|
+
- Enter/Space activate the focused tab
|
|
34
|
+
|
|
35
|
+
## Example
|
|
36
|
+
|
|
37
|
+
```vue
|
|
38
|
+
<Tabs
|
|
39
|
+
v-model="tab"
|
|
40
|
+
:items="[
|
|
41
|
+
{ value: 'overview', label: 'Overview' },
|
|
42
|
+
{ value: 'activity', label: 'Activity' },
|
|
43
|
+
]"
|
|
44
|
+
>
|
|
45
|
+
<template #panel-overview>Overview content</template>
|
|
46
|
+
<template #panel-activity>Activity content</template>
|
|
47
|
+
</Tabs>
|
|
48
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const tabsSizeValues = ["sm", "md"] as const;
|
|
2
|
+
export const tabsVariantValues = ["underline", "pill"] as const;
|
|
3
|
+
|
|
4
|
+
export type TabsSize = (typeof tabsSizeValues)[number];
|
|
5
|
+
export type TabsVariant = (typeof tabsVariantValues)[number];
|
|
6
|
+
|
|
7
|
+
export type TabItem = {
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
label: string;
|
|
10
|
+
value: string;
|
|
11
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TabsSize, TabsVariant } from "./Tabs.types";
|
|
2
|
+
|
|
3
|
+
export const tabsRootClass = "w-full";
|
|
4
|
+
export const tabsListBaseClass =
|
|
5
|
+
"relative flex w-full items-center gap-1 border-b border-[color-mix(in_srgb,var(--ui-border)_82%,transparent)]";
|
|
6
|
+
export const tabsListVariantClasses: Record<TabsVariant, string> = {
|
|
7
|
+
underline: "",
|
|
8
|
+
pill: "rounded-[var(--ui-radius-md)] border border-[color-mix(in_srgb,var(--ui-border)_82%,transparent)] border-b bg-[var(--ui-tonal-tertiary)] p-1",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const tabsTriggerBaseClass =
|
|
12
|
+
"inline-flex items-center justify-center rounded-[var(--ui-radius-sm)] font-medium transition-[background-color,color,box-shadow] " +
|
|
13
|
+
"duration-[var(--ui-duration-normal)] ease-[var(--ui-ease-out)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-ring)] " +
|
|
14
|
+
"disabled:pointer-events-none disabled:opacity-50";
|
|
15
|
+
|
|
16
|
+
export const tabsTriggerSizeClasses: Record<TabsSize, string> = {
|
|
17
|
+
sm: "px-3 py-2 text-sm",
|
|
18
|
+
md: "px-4 py-2.5 text-sm",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const tabsTriggerVariantClasses: Record<TabsVariant, string> = {
|
|
22
|
+
underline:
|
|
23
|
+
"rounded-none border-b-2 border-transparent text-[var(--ui-fg-muted)] hover:text-[var(--ui-fg)] " +
|
|
24
|
+
"data-[selected]:border-[var(--ui-primary)] data-[selected]:text-[var(--ui-fg)]",
|
|
25
|
+
pill: "text-[var(--ui-fg-muted)] hover:text-[var(--ui-fg)] data-[selected]:bg-[var(--ui-surface)] data-[selected]:text-[var(--ui-fg)] data-[selected]:shadow-[var(--ui-shadow-sm)] data-[selected]:border data-[selected]:border-[color-mix(in_srgb,var(--ui-border)_86%,transparent)]",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const tabsContentClass = "pt-5 text-[var(--ui-fg)]";
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Tabs as ArkTabs } from "@ark-ui/vue/tabs";
|
|
3
|
+
import { computed } from "vue";
|
|
4
|
+
import { tabsProps } from "./Tabs.props";
|
|
5
|
+
import {
|
|
6
|
+
tabsContentClass,
|
|
7
|
+
tabsListBaseClass,
|
|
8
|
+
tabsListVariantClasses,
|
|
9
|
+
tabsRootClass,
|
|
10
|
+
tabsTriggerBaseClass,
|
|
11
|
+
tabsTriggerSizeClasses,
|
|
12
|
+
tabsTriggerVariantClasses,
|
|
13
|
+
} from "./Tabs.variants";
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits<{
|
|
16
|
+
"update:modelValue": [value: string];
|
|
17
|
+
}>();
|
|
18
|
+
|
|
19
|
+
const props = defineProps(tabsProps);
|
|
20
|
+
|
|
21
|
+
const model = computed({
|
|
22
|
+
get: () => props.modelValue ?? props.items[0]?.value,
|
|
23
|
+
set: (value: string) => emit("update:modelValue", value),
|
|
24
|
+
});
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<ArkTabs.Root
|
|
29
|
+
v-model="model"
|
|
30
|
+
:lazy-mount="props.lazyMount"
|
|
31
|
+
unmount-on-exit
|
|
32
|
+
:class="tabsRootClass"
|
|
33
|
+
>
|
|
34
|
+
<ArkTabs.List :class="[tabsListBaseClass, tabsListVariantClasses[props.variant]]">
|
|
35
|
+
<ArkTabs.Trigger
|
|
36
|
+
v-for="item in props.items"
|
|
37
|
+
:key="item.value"
|
|
38
|
+
:value="item.value"
|
|
39
|
+
:disabled="item.disabled"
|
|
40
|
+
:class="[
|
|
41
|
+
tabsTriggerBaseClass,
|
|
42
|
+
tabsTriggerSizeClasses[props.size],
|
|
43
|
+
tabsTriggerVariantClasses[props.variant],
|
|
44
|
+
]"
|
|
45
|
+
>
|
|
46
|
+
{{ item.label }}
|
|
47
|
+
</ArkTabs.Trigger>
|
|
48
|
+
</ArkTabs.List>
|
|
49
|
+
|
|
50
|
+
<ArkTabs.Content
|
|
51
|
+
v-for="item in props.items"
|
|
52
|
+
:key="`panel-${item.value}`"
|
|
53
|
+
:value="item.value"
|
|
54
|
+
:class="tabsContentClass"
|
|
55
|
+
>
|
|
56
|
+
<slot :name="`panel-${item.value}`" :item="item" />
|
|
57
|
+
</ArkTabs.Content>
|
|
58
|
+
</ArkTabs.Root>
|
|
59
|
+
</template>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { PropType } from "vue";
|
|
2
|
+
import type { TextareaResize, TextareaSize } from "./Textarea.types";
|
|
3
|
+
|
|
4
|
+
export const textareaProps = {
|
|
5
|
+
modelValue: {
|
|
6
|
+
type: String,
|
|
7
|
+
default: "",
|
|
8
|
+
},
|
|
9
|
+
size: {
|
|
10
|
+
type: String as PropType<TextareaSize>,
|
|
11
|
+
default: "md",
|
|
12
|
+
},
|
|
13
|
+
rows: {
|
|
14
|
+
type: Number,
|
|
15
|
+
default: 4,
|
|
16
|
+
},
|
|
17
|
+
disabled: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false,
|
|
20
|
+
},
|
|
21
|
+
invalid: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: false,
|
|
24
|
+
},
|
|
25
|
+
readonly: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: false,
|
|
28
|
+
},
|
|
29
|
+
resize: {
|
|
30
|
+
type: String as PropType<TextareaResize>,
|
|
31
|
+
default: "vertical",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Textarea
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Multiline text entry primitive for the v2 form system.
|
|
6
|
+
|
|
7
|
+
## Category
|
|
8
|
+
|
|
9
|
+
Primitive
|
|
10
|
+
|
|
11
|
+
## Public API
|
|
12
|
+
|
|
13
|
+
Props:
|
|
14
|
+
|
|
15
|
+
- `modelValue`: string
|
|
16
|
+
- `size`: `sm | md | lg`
|
|
17
|
+
- `rows`: number
|
|
18
|
+
- `disabled`: boolean
|
|
19
|
+
- `invalid`: boolean
|
|
20
|
+
- `readonly`: boolean
|
|
21
|
+
- `resize`: `vertical | none`
|
|
22
|
+
|
|
23
|
+
Events:
|
|
24
|
+
|
|
25
|
+
- `update:modelValue`
|
|
26
|
+
- `focus`
|
|
27
|
+
- `blur`
|
|
28
|
+
|
|
29
|
+
## States
|
|
30
|
+
|
|
31
|
+
- default
|
|
32
|
+
- hover
|
|
33
|
+
- focus-visible
|
|
34
|
+
- disabled
|
|
35
|
+
- invalid
|
|
36
|
+
- readonly
|
|
37
|
+
|
|
38
|
+
## Accessibility
|
|
39
|
+
|
|
40
|
+
- uses native `<textarea>` semantics
|
|
41
|
+
- supports `aria-invalid` when invalid
|
|
42
|
+
- relies on external labels and descriptions through attrs such as `id` and `aria-describedby`
|
|
43
|
+
|
|
44
|
+
## Token usage
|
|
45
|
+
|
|
46
|
+
- `--ui-surface`
|
|
47
|
+
- `--ui-fg`
|
|
48
|
+
- `--ui-fg-muted`
|
|
49
|
+
- `--ui-border`
|
|
50
|
+
- `--ui-primary`
|
|
51
|
+
- `--ui-critical`
|
|
52
|
+
- `--ui-ring`
|
|
53
|
+
- `--ui-radius-md`
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
```vue
|
|
58
|
+
<Textarea v-model="notes" rows="6" />
|
|
59
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TextareaResize, TextareaSize } from "./Textarea.types";
|
|
2
|
+
|
|
3
|
+
export const textareaBaseClass =
|
|
4
|
+
"flex w-full appearance-none border bg-[var(--ui-surface)] text-[var(--ui-fg)] " +
|
|
5
|
+
"placeholder:text-[var(--ui-fg-muted)] rounded-[var(--ui-radius-md)] border-[var(--ui-border)] " +
|
|
6
|
+
"transition-[box-shadow,border-color,background-color,color] duration-[var(--ui-duration-normal)] ease-[var(--ui-ease-out)] " +
|
|
7
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-ring)] focus-visible:border-[var(--ui-primary)] " +
|
|
8
|
+
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 " +
|
|
9
|
+
"read-only:cursor-default read-only:bg-[var(--ui-tonal-tertiary)]";
|
|
10
|
+
|
|
11
|
+
export const textareaStateClasses = {
|
|
12
|
+
default: "hover:border-[var(--ui-primary-muted)]",
|
|
13
|
+
invalid:
|
|
14
|
+
"border-[var(--ui-critical)] text-[var(--ui-fg)] " +
|
|
15
|
+
"focus-visible:border-[var(--ui-critical)] focus-visible:ring-[var(--ui-critical-muted)]",
|
|
16
|
+
} as const;
|
|
17
|
+
|
|
18
|
+
export const textareaSizeClasses: Record<TextareaSize, string> = {
|
|
19
|
+
sm: "px-3 py-2 text-sm",
|
|
20
|
+
md: "px-4 py-3 text-sm",
|
|
21
|
+
lg: "px-4 py-3 text-base",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const textareaResizeClasses: Record<TextareaResize, string> = {
|
|
25
|
+
vertical: "resize-y",
|
|
26
|
+
none: "resize-none",
|
|
27
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, normalizeClass, useAttrs } from "vue";
|
|
3
|
+
import { twMerge } from "tailwind-merge";
|
|
4
|
+
import { textareaProps } from "./Textarea.props";
|
|
5
|
+
import {
|
|
6
|
+
textareaBaseClass,
|
|
7
|
+
textareaResizeClasses,
|
|
8
|
+
textareaSizeClasses,
|
|
9
|
+
textareaStateClasses,
|
|
10
|
+
} from "./Textarea.variants";
|
|
11
|
+
|
|
12
|
+
defineOptions({ inheritAttrs: false });
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits<{
|
|
15
|
+
"update:modelValue": [value: string];
|
|
16
|
+
blur: [event: FocusEvent];
|
|
17
|
+
focus: [event: FocusEvent];
|
|
18
|
+
}>();
|
|
19
|
+
|
|
20
|
+
const attrs = useAttrs();
|
|
21
|
+
const props = defineProps(textareaProps);
|
|
22
|
+
|
|
23
|
+
const classes = computed(() =>
|
|
24
|
+
twMerge(
|
|
25
|
+
textareaBaseClass,
|
|
26
|
+
textareaSizeClasses[props.size],
|
|
27
|
+
textareaResizeClasses[props.resize],
|
|
28
|
+
props.invalid ? textareaStateClasses.invalid : textareaStateClasses.default,
|
|
29
|
+
normalizeClass(attrs.class),
|
|
30
|
+
),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const textareaAttrs = computed(() => {
|
|
34
|
+
const {
|
|
35
|
+
class: _class,
|
|
36
|
+
value: _value,
|
|
37
|
+
modelValue: _modelValue,
|
|
38
|
+
disabled: _disabled,
|
|
39
|
+
readonly: _readonly,
|
|
40
|
+
rows: _rows,
|
|
41
|
+
...rest
|
|
42
|
+
} = attrs;
|
|
43
|
+
|
|
44
|
+
return rest;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
function handleInput(event: Event) {
|
|
48
|
+
emit("update:modelValue", (event.target as HTMLTextAreaElement).value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function handleFocus(event: FocusEvent) {
|
|
52
|
+
emit("focus", event);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function handleBlur(event: FocusEvent) {
|
|
56
|
+
emit("blur", event);
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<template>
|
|
61
|
+
<textarea
|
|
62
|
+
:value="props.modelValue"
|
|
63
|
+
:rows="props.rows"
|
|
64
|
+
:class="classes"
|
|
65
|
+
:disabled="props.disabled"
|
|
66
|
+
:readonly="props.readonly"
|
|
67
|
+
:aria-invalid="props.invalid ? 'true' : undefined"
|
|
68
|
+
:data-invalid="props.invalid ? 'true' : 'false'"
|
|
69
|
+
v-bind="textareaAttrs"
|
|
70
|
+
@input="handleInput"
|
|
71
|
+
@focus="handleFocus"
|
|
72
|
+
@blur="handleBlur"
|
|
73
|
+
/>
|
|
74
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PropType } from "vue";
|
|
2
|
+
import type { TooltipPlacement } from "./Tooltip.types";
|
|
3
|
+
|
|
4
|
+
export const tooltipProps = {
|
|
5
|
+
placement: {
|
|
6
|
+
type: String as PropType<TooltipPlacement>,
|
|
7
|
+
default: "top",
|
|
8
|
+
},
|
|
9
|
+
openDelay: {
|
|
10
|
+
type: Number,
|
|
11
|
+
default: 200,
|
|
12
|
+
},
|
|
13
|
+
closeDelay: {
|
|
14
|
+
type: Number,
|
|
15
|
+
default: 100,
|
|
16
|
+
},
|
|
17
|
+
showArrow: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: true,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Tooltip
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Lightweight non-interactive hint overlay for short explanatory text.
|
|
6
|
+
|
|
7
|
+
## Category
|
|
8
|
+
|
|
9
|
+
Primitive
|
|
10
|
+
|
|
11
|
+
## Public API
|
|
12
|
+
|
|
13
|
+
Props:
|
|
14
|
+
|
|
15
|
+
- `open` via `v-model:open`
|
|
16
|
+
- `placement`: `top | bottom | left | right`
|
|
17
|
+
- `openDelay`
|
|
18
|
+
- `closeDelay`
|
|
19
|
+
- `showArrow`
|
|
20
|
+
|
|
21
|
+
Slots:
|
|
22
|
+
|
|
23
|
+
- `trigger`
|
|
24
|
+
- default tooltip content
|
|
25
|
+
|
|
26
|
+
## Accessibility
|
|
27
|
+
|
|
28
|
+
- built on Ark tooltip semantics
|
|
29
|
+
- intended for short supplemental text, not complex interactive content
|
|
30
|
+
|
|
31
|
+
## Keyboard behavior
|
|
32
|
+
|
|
33
|
+
- opens on focus and hover via Ark behavior
|
|
34
|
+
- closes on blur, pointer leave, or Escape
|
|
35
|
+
|
|
36
|
+
## Example
|
|
37
|
+
|
|
38
|
+
```vue
|
|
39
|
+
<Tooltip>
|
|
40
|
+
<template #trigger>
|
|
41
|
+
<Button variant="plain-secondary">?</Button>
|
|
42
|
+
</template>
|
|
43
|
+
Helpful context
|
|
44
|
+
</Tooltip>
|
|
45
|
+
```
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export const tooltipPositionerClass = "z-50 px-2";
|
|
2
|
+
export const tooltipContentClass =
|
|
3
|
+
"max-w-xs rounded-[var(--ui-radius-md)] border border-[var(--ui-border)] bg-[var(--ui-fg)] px-3 py-2 text-sm text-[var(--ui-bg)] shadow-[var(--ui-shadow-md)]";
|
|
4
|
+
export const tooltipArrowClass = "fill-[var(--ui-fg)] stroke-[var(--ui-fg)]";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Tooltip as ArkTooltip } from "@ark-ui/vue/tooltip";
|
|
3
|
+
import { tooltipProps } from "./Tooltip.props";
|
|
4
|
+
import { tooltipArrowClass, tooltipContentClass, tooltipPositionerClass } from "./Tooltip.variants";
|
|
5
|
+
|
|
6
|
+
const open = defineModel<boolean>("open", { default: false });
|
|
7
|
+
const props = defineProps(tooltipProps);
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<ArkTooltip.Root
|
|
12
|
+
v-model:open="open"
|
|
13
|
+
:open-delay="props.openDelay"
|
|
14
|
+
:close-delay="props.closeDelay"
|
|
15
|
+
:positioning="{ placement: props.placement }"
|
|
16
|
+
lazy-mount
|
|
17
|
+
unmount-on-exit
|
|
18
|
+
>
|
|
19
|
+
<ArkTooltip.Trigger v-if="$slots.trigger" as-child>
|
|
20
|
+
<slot name="trigger" />
|
|
21
|
+
</ArkTooltip.Trigger>
|
|
22
|
+
<ArkTooltip.Positioner :class="tooltipPositionerClass">
|
|
23
|
+
<ArkTooltip.Content :class="tooltipContentClass">
|
|
24
|
+
<slot />
|
|
25
|
+
<ArkTooltip.Arrow v-if="props.showArrow" :class="tooltipArrowClass">
|
|
26
|
+
<ArkTooltip.ArrowTip />
|
|
27
|
+
</ArkTooltip.Arrow>
|
|
28
|
+
</ArkTooltip.Content>
|
|
29
|
+
</ArkTooltip.Positioner>
|
|
30
|
+
</ArkTooltip.Root>
|
|
31
|
+
</template>
|