From 9dd1d11bc48736d99b067b659148663ce6702697 Mon Sep 17 00:00:00 2001 From: Jay George Date: Fri, 13 Mar 2026 14:00:50 +0000 Subject: [PATCH 1/2] Add a text component --- resources/js/components/ui/Text.vue | 51 ++++++++ resources/js/components/ui/index.js | 1 + resources/js/stories/Text.stories.ts | 170 +++++++++++++++++++++++++++ resources/js/stories/docs/Text.mdx | 27 +++++ 4 files changed, 249 insertions(+) create mode 100644 resources/js/components/ui/Text.vue create mode 100644 resources/js/stories/Text.stories.ts create mode 100644 resources/js/stories/docs/Text.mdx diff --git a/resources/js/components/ui/Text.vue b/resources/js/components/ui/Text.vue new file mode 100644 index 0000000000..ab60621845 --- /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..796bca65d8 --- /dev/null +++ b/resources/js/stories/Text.stories.ts @@ -0,0 +1,170 @@ +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 + From 48107d19ac2564e4a99097bcf0c0f2d4b0d2c8ce Mon Sep 17 00:00:00 2001 From: Jay George Date: Fri, 13 Mar 2026 14:21:22 +0000 Subject: [PATCH 2/2] Tweak and simplify variations --- resources/js/components/ui/Text.vue | 11 +++++------ resources/js/stories/Text.stories.ts | 2 -- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/resources/js/components/ui/Text.vue b/resources/js/components/ui/Text.vue index ab60621845..6f774235c5 100644 --- a/resources/js/components/ui/Text.vue +++ b/resources/js/components/ui/Text.vue @@ -22,17 +22,16 @@ const textClasses = computed(() => { base: 'antialiased', variants: { variant: { - default: 'text-gray-700 dark:text-gray-300', - strong: 'font-semibold text-gray-900 dark:text-white', - subtle: 'text-gray-500 dark:text-gray-400', - code: 'font-mono text-[0.9em] text-gray-700 dark:text-gray-300 bg-gray-600/10 dark:bg-white/10 rounded-sm px-1 py-0.5', + default: 'text-gray-900 dark:text-gray-50', + strong: 'font-semibold text-gray-900 dark:text-gray-50', + subtle: 'text-gray-600 dark:text-gray-600/90', + code: 'font-mono text-[0.9em] text-gray-900 dark:text-gray-50 bg-gray-600/10 dark:bg-white/10 rounded-sm px-1 py-0.5', danger: 'text-red-600 dark:text-red-400', success: 'text-green-600 dark:text-green-400', warning: 'text-amber-600 dark:text-amber-400', }, size: { - xs: 'text-xs', - sm: 'text-sm', + sm: 'text-xs', base: 'text-sm', lg: 'text-base', }, diff --git a/resources/js/stories/Text.stories.ts b/resources/js/stories/Text.stories.ts index 796bca65d8..9cedee9a61 100644 --- a/resources/js/stories/Text.stories.ts +++ b/resources/js/stories/Text.stories.ts @@ -107,7 +107,6 @@ export const Sizes: Story = { - `, }, }, @@ -126,7 +125,6 @@ export const Sizes: Story = { - `, }),