From 76006fca5242c829ecb915c465da3f99de7a5d6e Mon Sep 17 00:00:00 2001 From: Dante Date: Wed, 11 Mar 2026 08:34:57 +0900 Subject: [PATCH] feat: add text widget stories and Number input stories (#9527) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 스크린샷 2026-03-07 오후 9 39 20 ## Summary - Add Storybook stories for WidgetInputText, WidgetTextarea, and ScrubableNumberInput - Reorganize story titles under `Components/Input/` to align with Figma design system - Fix PrimeIcons not rendering in Storybook (caused by `[&_*]:!font-inter` override) - Fix knip unused export warnings (dead code removal + workspace config) ## Test plan - [ ] Run `pnpm storybook` and verify Components/Input/InputText stories render - [ ] Verify Components/Input/TextArea stories render with label and copy button - [ ] Verify Components/Input/Number stories render with -/+ icons - [ ] Toggle Storybook theme between Light/Dark and confirm Number story adapts - [ ] Verify existing Button stories still render correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9527-feat-add-text-widget-stories-and-Number-input-stories-31c6d73d3650817ba351cdef26a356c8) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude Opus 4.6 --- .storybook/preview.ts | 2 +- knip.config.ts | 12 +- .../common/ScrubableNumberInput.stories.ts | 160 ++++++++++++++++++ .../components/WidgetInputText.stories.ts | 2 +- .../components/WidgetTextarea.stories.ts | 2 +- 5 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 src/components/common/ScrubableNumberInput.stories.ts diff --git a/.storybook/preview.ts b/.storybook/preview.ts index e22c896fa2..54eca1d76c 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -58,7 +58,7 @@ export const withTheme = (Story: StoryFn, context: StoryContext) => { document.documentElement.classList.remove('dark-theme') document.body.classList.remove('dark-theme') } - document.body.classList.add('[&_*]:!font-inter') + document.body.classList.add('font-inter') return Story(context.args, context) } diff --git a/knip.config.ts b/knip.config.ts index 7c3ae13ced..23379bb0e6 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -20,6 +20,10 @@ const config: KnipConfig = { 'packages/tailwind-utils': { project: ['src/**/*.{js,ts}'] }, + 'packages/shared-frontend-utils': { + project: ['src/**/*.{js,ts}'], + entry: ['src/formatUtil.ts', 'src/networkUtil.ts'] + }, 'packages/registry-types': { project: ['src/**/*.{js,ts}'] } @@ -32,7 +36,9 @@ const config: KnipConfig = { '@primeuix/forms', '@primeuix/styled', '@primeuix/utils', - '@primevue/icons' + '@primevue/icons', + // Used by lucideStrokePlugin.js (CSS @plugin) + '@iconify/utils' ], ignore: [ // Auto generated manager types @@ -47,7 +53,9 @@ const config: KnipConfig = { // Pending integration in stacked PR 'src/components/sidebar/tabs/nodeLibrary/CustomNodesPanel.vue', // Agent review check config, not part of the build - '.agents/checks/eslint.strict.config.js' + '.agents/checks/eslint.strict.config.js', + // Loaded via @plugin directive in CSS, not detected by knip + 'packages/design-system/src/css/lucideStrokePlugin.js' ], compilers: { // https://github.com/webpro-nl/knip/issues/1008#issuecomment-3207756199 diff --git a/src/components/common/ScrubableNumberInput.stories.ts b/src/components/common/ScrubableNumberInput.stories.ts new file mode 100644 index 0000000000..b70a23ca07 --- /dev/null +++ b/src/components/common/ScrubableNumberInput.stories.ts @@ -0,0 +1,160 @@ +import type { + ComponentPropsAndSlots, + Meta, + StoryObj +} from '@storybook/vue3-vite' +import { ref, toRefs } from 'vue' + +import Button from '@/components/ui/button/Button.vue' +import Popover from '@/components/ui/Popover.vue' + +import ScrubableNumberInput from './ScrubableNumberInput.vue' + +type StoryArgs = ComponentPropsAndSlots + +const meta: Meta = { + title: 'Components/Input/Number', + component: ScrubableNumberInput, + tags: ['autodocs'], + parameters: { layout: 'centered' }, + argTypes: { + min: { control: 'number' }, + max: { control: 'number' }, + step: { control: 'number' }, + disabled: { control: 'boolean' }, + hideButtons: { control: 'boolean' } + }, + args: { + min: 0, + max: 100, + step: 1, + disabled: false, + hideButtons: false + }, + decorators: [ + (story) => ({ + components: { story }, + template: '
' + }) + ] +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: (args) => ({ + components: { ScrubableNumberInput }, + setup() { + const { min, max, step, disabled, hideButtons } = toRefs(args) + const value = ref(42) + return { value, min, max, step, disabled, hideButtons } + }, + template: + '' + }) +} + +export const Disabled: Story = { + args: { disabled: true }, + render: (args) => ({ + components: { ScrubableNumberInput }, + setup() { + const { disabled } = toRefs(args) + const value = ref(50) + return { value, disabled } + }, + template: + '' + }) +} + +export const AtMinimum: Story = { + render: () => ({ + components: { ScrubableNumberInput }, + setup() { + const value = ref(0) + return { value } + }, + template: + '' + }) +} + +export const AtMaximum: Story = { + render: () => ({ + components: { ScrubableNumberInput }, + setup() { + const value = ref(100) + return { value } + }, + template: + '' + }) +} + +export const FloatPrecision: Story = { + args: { min: 0, max: 1, step: 0.01 }, + render: (args) => ({ + components: { ScrubableNumberInput }, + setup() { + const { min, max, step } = toRefs(args) + const value = ref(0.75) + return { value, min, max, step } + }, + template: + '' + }) +} + +export const LargeNumber: Story = { + render: () => ({ + components: { ScrubableNumberInput }, + setup() { + const value = ref(1809000312992) + return { value } + }, + template: + '' + }) +} + +export const HiddenButtons: Story = { + args: { hideButtons: true }, + render: (args) => ({ + components: { ScrubableNumberInput }, + setup() { + const { hideButtons } = toRefs(args) + const value = ref(42) + return { value, hideButtons } + }, + template: + '' + }) +} + +export const WithControlButton: Story = { + render: () => ({ + components: { ScrubableNumberInput, Button, Popover }, + setup() { + const value = ref(1809000312992) + return { value } + }, + template: ` + + + +
Control popover content
+
+
+ ` + }) +} diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetInputText.stories.ts b/src/renderer/extensions/vueNodes/widgets/components/WidgetInputText.stories.ts index 6e15ece0dc..82075ca785 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetInputText.stories.ts +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetInputText.stories.ts @@ -17,7 +17,7 @@ interface StoryArgs extends ComponentPropsAndSlots { } const meta: Meta = { - title: 'Widgets/WidgetInputText', + title: 'Components/Input/InputText', component: WidgetInputText, tags: ['autodocs'], parameters: { layout: 'centered' }, diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.stories.ts b/src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.stories.ts index b0e8916396..646c5d6719 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.stories.ts +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.stories.ts @@ -16,7 +16,7 @@ interface StoryArgs extends ComponentPropsAndSlots { } const meta: Meta = { - title: 'Widgets/WidgetTextarea', + title: 'Components/Input/TextArea', component: WidgetTextarea, tags: ['autodocs'], parameters: {