diff --git a/packages/cms/src/ui.js b/packages/cms/src/ui.js index 4063a97f6d..a06c3dd795 100644 --- a/packages/cms/src/ui.js +++ b/packages/cms/src/ui.js @@ -114,6 +114,7 @@ export const { TabProvider, Tabs, TabTrigger, + Text, Textarea, TimePicker, ToggleGroup, diff --git a/resources/js/bootstrap/cms/ui.js b/resources/js/bootstrap/cms/ui.js index 28803da78b..010b54d241 100644 --- a/resources/js/bootstrap/cms/ui.js +++ b/resources/js/bootstrap/cms/ui.js @@ -114,6 +114,7 @@ export { TabProvider, Tabs, TabTrigger, + Text, Textarea, TimePicker, ToggleGroup, diff --git a/resources/js/components/ui/Text.vue b/resources/js/components/ui/Text.vue new file mode 100644 index 0000000000..80efa653cf --- /dev/null +++ b/resources/js/components/ui/Text.vue @@ -0,0 +1,51 @@ + + + diff --git a/resources/js/components/ui/index.js b/resources/js/components/ui/index.js index 4f4909880e..8021a93cd6 100644 --- a/resources/js/components/ui/index.js +++ b/resources/js/components/ui/index.js @@ -82,6 +82,7 @@ export { default as TableRows } from './Table/Rows.vue'; export { default as TabList } from './Tabs/List.vue'; export { default as Tabs } from './Tabs/Tabs.vue'; export { default as TabTrigger } from './Tabs/Trigger.vue'; +export { default as Text } from './Text.vue'; export { default as Textarea } from './Textarea.vue'; export { default as TimePicker } from './TimePicker/TimePicker.vue'; export { default as ToggleGroup } from './Toggle/Group.vue'; diff --git a/resources/js/stories/Text.stories.ts b/resources/js/stories/Text.stories.ts new file mode 100644 index 0000000000..9cedee9a61 --- /dev/null +++ b/resources/js/stories/Text.stories.ts @@ -0,0 +1,168 @@ +import type {Meta, StoryObj} from '@storybook/vue3'; +import {Text} from '@ui'; +import {computed} from 'vue'; + +const meta = { + title: 'Components/Text', + component: Text, + argTypes: { + size: { + control: 'select', + options: ['xs', 'sm', 'base', 'lg'], + }, + variant: { + control: 'select', + options: ['default', 'strong', 'subtle', 'code', 'danger', 'success', 'warning'], + }, + as: { + control: 'select', + options: ['span', 'p', 'div'], + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + text: 'The quick brown fox jumps over the lazy dog.', + }, +}; + +const introCode = ` +
+ + + + +
+`; + +export const _DocsIntro: Story = { + tags: ['!dev'], + parameters: { + docs: { + source: { code: introCode }, + }, + }, + render: () => ({ + components: { Text }, + template: introCode, + }), +}; + +export const Variants: Story = { + argTypes: { + variant: { control: { disable: true } }, + text: { control: { disable: true } }, + }, + parameters: { + docs: { + source: { + code: ` + + + + + + + + `, + }, + }, + }, + render: (args) => ({ + components: { Text }, + setup() { + const sharedProps = computed(() => { + const { variant, text, ...rest } = args; + return rest; + }); + return { sharedProps }; + }, + template: ` +
+ + + + + + + +
+ `, + }), +}; + +export const Sizes: Story = { + argTypes: { + size: { control: { disable: true } }, + text: { control: { disable: true } }, + }, + parameters: { + docs: { + source: { + code: ` + + + + `, + }, + }, + }, + render: (args) => ({ + components: { Text }, + setup() { + const sharedProps = computed(() => { + const { size, text, ...rest } = args; + return rest; + }); + return { sharedProps }; + }, + template: ` +
+ + + +
+ `, + }), +}; + +const inlineCode = ` +Default with strong and subtle inline +`; + +export const _InlineDocs: Story = { + tags: ['!dev'], + parameters: { + docs: { + source: { code: inlineCode }, + }, + }, + render: () => ({ + components: { Text }, + template: inlineCode, + }), +}; + +const paragraphCode = ` +
+ This is a paragraph of default text that could appear inside a widget or table description. + This is a subtle paragraph, useful for secondary information or metadata. +
+`; + +export const _AsParagraph: Story = { + tags: ['!dev'], + parameters: { + docs: { + source: { code: paragraphCode }, + }, + }, + render: () => ({ + components: { Text }, + template: paragraphCode, + }), +}; diff --git a/resources/js/stories/docs/Text.mdx b/resources/js/stories/docs/Text.mdx new file mode 100644 index 0000000000..62235424cd --- /dev/null +++ b/resources/js/stories/docs/Text.mdx @@ -0,0 +1,27 @@ +import { Canvas, Meta, ArgTypes } from '@storybook/addon-docs/blocks'; +import * as TextStories from '../Text.stories'; + + + +# Text +A utility component for styling inline and block text with consistent variants and sizes. Useful inside tables, widgets, cards, and anywhere you need to quickly apply text styles without reaching for utility classes. + + +## Variants +Use the `variant` prop to control the visual style of the text. + + +## Sizes +Use the `size` prop to control the text size. + + +## Inline Composition +Since `Text` renders as a `span` by default, you can nest variants inline. + + +## As Paragraph +Use the `as` prop to render as a `p` or any other element. + + +## Arguments + diff --git a/resources/js/tests/Package.test.js b/resources/js/tests/Package.test.js index 5d43ccfb22..a87dcd9a43 100644 --- a/resources/js/tests/Package.test.js +++ b/resources/js/tests/Package.test.js @@ -190,6 +190,7 @@ it('exports ui', async () => { 'TabContent', 'TabList', 'TabTrigger', + 'Text', 'Stack', 'StackClose', 'StackContent',