diff --git a/packages/ui/package.json b/packages/ui/package.json index 2ab8cc1f71..c41057aff2 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -74,6 +74,7 @@ "@xterm/xterm": "^6.0.0", "ace-builds": "^1.43.5", "apexcharts": "^4.0.0", + "colord": "^2.9.3", "dayjs": "^1.11.10", "dompurify": "^3.1.7", "es-toolkit": "^1.44.0", diff --git a/packages/ui/src/components/base/index.ts b/packages/ui/src/components/base/index.ts index c789f4e7d8..ca06c2867f 100644 --- a/packages/ui/src/components/base/index.ts +++ b/packages/ui/src/components/base/index.ts @@ -71,7 +71,15 @@ export { default as I18nDebugPanel } from './I18nDebugPanel.vue' export { default as IconSelect } from './IconSelect.vue' export { default as InlineEditableText } from './InlineEditableText.vue' export type { InputAppearance, InputSize } from './inputs' -export { DateInput, DatePicker, Input, InputClearButton, InputFrame, Textarea } from './inputs' +export { + ColorPicker, + DateInput, + DatePicker, + Input, + InputClearButton, + InputFrame, + Textarea, +} from './inputs' export { default as IntlFormatted } from './IntlFormatted.vue' export { default as LoadingBar } from './LoadingBar.vue' export { default as LoadingIndicator } from './LoadingIndicator.vue' diff --git a/packages/ui/src/components/base/inputs/ColorPicker.vue b/packages/ui/src/components/base/inputs/ColorPicker.vue new file mode 100644 index 0000000000..b7ca77e45f --- /dev/null +++ b/packages/ui/src/components/base/inputs/ColorPicker.vue @@ -0,0 +1,346 @@ + + + + + diff --git a/packages/ui/src/components/base/inputs/index.ts b/packages/ui/src/components/base/inputs/index.ts index e396a26cd2..fce0c36a7f 100644 --- a/packages/ui/src/components/base/inputs/index.ts +++ b/packages/ui/src/components/base/inputs/index.ts @@ -1,3 +1,4 @@ +export { default as ColorPicker } from './ColorPicker.vue' export { default as DateInput } from './DateInput.vue' export { default as DatePicker } from './DatePicker.vue' export { default as Input } from './Input.vue' diff --git a/packages/ui/src/components/image-viewer-editor/controls.vue b/packages/ui/src/components/image-viewer-editor/controls.vue index 96527033a5..761593306f 100644 --- a/packages/ui/src/components/image-viewer-editor/controls.vue +++ b/packages/ui/src/components/image-viewer-editor/controls.vue @@ -15,6 +15,7 @@ import IconButton from '#ui/components/base/buttons/IconButton.vue' import SplitButton from '#ui/components/base/buttons/SplitButton.vue' import type { OverflowMenuOption } from '#ui/components/base/buttons/types' import Chips from '#ui/components/base/Chips.vue' +import ColorPicker from '#ui/components/base/inputs/ColorPicker.vue' import { useVIntl } from '#ui/composables/i18n' import { commonMessages } from '#ui/utils/common-messages' @@ -108,10 +109,6 @@ function handlePropertyInput(event: Event) { updatePropertyValue(Number((event.target as HTMLInputElement).value)) } -function handleColorInput(event: Event) { - updateColor((event.target as HTMLInputElement).value) -} - function formatCensorMode(value: ScreenshotCensorMode) { return formatMessage(value === 'blur' ? messages.blur : messages.solid) } @@ -153,27 +150,14 @@ function formatEraserMode(value: ScreenshotEraserMode) { size="small" hide-checkmark-icon /> - + :model-value="color" + :label="formatMessage(messages.colour)" + @update:model-value="updateColor" + @focus="beginPropertyEdit" + @change="commitPropertyEdit" + />
+ +export default meta +type Story = StoryObj + +export const Default: Story = { + render: (args) => ({ + components: { ColorPicker }, + setup() { + const value = ref('#ff6b6b') + return { args, value } + }, + template: /* html */ ` +
+ +

Selected value: {{ value }}

+
+ `, + }), + args: { + label: 'Colour', + }, +} + +export const Small: Story = { + render: () => ({ + components: { ColorPicker }, + setup() { + const value = ref('#3b82f6') + return { value } + }, + template: /* html */ ` +
+ +

Selected value: {{ value }}

+
+ `, + }), +} + +export const Disabled: Story = { + args: { + label: 'Colour', + modelValue: '#22c55e', + disabled: true, + }, +} + +export const FocusAndChangeEvents: Story = { + render: () => ({ + components: { ColorPicker }, + setup() { + const value = ref('#a855f7') + const log = ref([]) + return { value, log } + }, + template: /* html */ ` +
+ +
    +
  • {{ entry }}
  • +
+
+ `, + }), +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c58967540c..1d81ae72f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -185,7 +185,7 @@ importers: devDependencies: '@eslint/compat': specifier: ^1.1.1 - version: 1.4.1(eslint@9.39.2(jiti@1.21.7)) + version: 1.4.1(eslint@9.39.2(jiti@2.6.1)) '@formatjs/cli': specifier: ^6.2.12 version: 6.12.2(@vue/compiler-core@3.5.27)(vue@3.5.27(typescript@5.9.3)) @@ -194,22 +194,22 @@ importers: version: link:../../packages/tooling-config '@nuxt/eslint-config': specifier: ^0.5.6 - version: 0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + version: 0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@taijased/vue-render-tracker': specifier: ^1.0.7 version: 1.0.7(vue@3.5.27(typescript@5.9.3)) '@vitejs/plugin-vue': specifier: ^6.0.3 - version: 6.0.4(vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) + version: 6.0.4(vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) autoprefixer: specifier: ^10.4.19 version: 10.4.24(postcss@8.5.6) eslint: specifier: ^9.9.1 - version: 9.39.2(jiti@1.21.7) + version: 9.39.2(jiti@2.6.1) eslint-plugin-turbo: specifier: ^2.5.4 - version: 2.8.2(eslint@9.39.2(jiti@1.21.7))(turbo@2.8.2) + version: 2.8.2(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.2) postcss: specifier: ^8.4.39 version: 8.5.6 @@ -227,7 +227,7 @@ importers: version: 5.9.3 vite: specifier: ^8.0.0 - version: 8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + version: 8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) vue-component-type-helpers: specifier: ^3.1.8 version: 3.2.4 @@ -712,6 +712,9 @@ importers: apexcharts: specifier: ^4.0.0 version: 4.7.0 + colord: + specifier: ^2.9.3 + version: 2.9.3 dayjs: specifier: ^1.11.10 version: 1.11.19 @@ -721,12 +724,12 @@ importers: es-toolkit: specifier: ^1.44.0 version: 1.44.0 - flatpickr: - specifier: ^4.6.13 - version: 4.6.13 fabric: specifier: ^7.4.0 version: 7.4.0 + flatpickr: + specifier: ^4.6.13 + version: 4.6.13 floating-vue: specifier: ^5.2.2 version: 5.2.2(@nuxt/kit@3.21.0(magicast@0.5.1))(vue@3.5.27(typescript@5.9.3)) @@ -811,7 +814,7 @@ importers: version: 5.2.4(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))(vue@3.5.27(typescript@5.9.3)) eslint-plugin-storybook: specifier: ^10.1.10 - version: 10.2.4(eslint@9.39.2(jiti@2.6.1))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(typescript@5.9.3) + version: 10.2.4(eslint@9.39.2(jiti@1.21.7))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(typescript@5.9.3) storybook: specifier: ^10.1.10 version: 10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -6443,6 +6446,7 @@ packages: eslint@9.39.2: resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true peerDependencies: jiti: '*' @@ -11807,12 +11811,6 @@ snapshots: '@eslint-community/regexpp@4.12.2': {} - '@eslint/compat@1.4.1(eslint@9.39.2(jiti@1.21.7))': - dependencies: - '@eslint/core': 0.17.0 - optionalDependencies: - eslint: 9.39.2(jiti@1.21.7) - '@eslint/compat@1.4.1(eslint@9.39.2(jiti@2.6.1))': dependencies: '@eslint/core': 0.17.0 @@ -12581,31 +12579,6 @@ snapshots: - utf-8-validate - vue - '@nuxt/eslint-config@0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@eslint/js': 9.39.2 - '@nuxt/eslint-plugin': 0.5.7(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@stylistic/eslint-plugin': 2.13.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.2(jiti@1.21.7) - eslint-config-flat-gitignore: 0.3.0(eslint@9.39.2(jiti@1.21.7)) - eslint-flat-config-utils: 0.4.0 - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-jsdoc: 50.8.0(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-regexp: 2.10.0(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-unicorn: 55.0.0(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-vue: 9.33.0(eslint@9.39.2(jiti@1.21.7)) - globals: 15.15.0 - local-pkg: 0.5.1 - pathe: 1.1.2 - vue-eslint-parser: 9.4.3(eslint@9.39.2(jiti@1.21.7)) - transitivePeerDependencies: - - '@typescript-eslint/utils' - - eslint-import-resolver-node - - supports-color - - typescript - '@nuxt/eslint-config@0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint/js': 9.39.2 @@ -12631,15 +12604,6 @@ snapshots: - supports-color - typescript - '@nuxt/eslint-plugin@0.5.7(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.2(jiti@1.21.7) - transitivePeerDependencies: - - supports-color - - typescript - '@nuxt/eslint-plugin@0.5.7(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.54.0 @@ -14132,18 +14096,6 @@ snapshots: '@stripe/stripe-js@7.9.0': {} - '@stylistic/eslint-plugin@2.13.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.2(jiti@1.21.7) - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - estraverse: 5.3.0 - picomatch: 4.0.4 - transitivePeerDependencies: - - supports-color - - typescript - '@stylistic/eslint-plugin@2.13.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) @@ -14558,22 +14510,6 @@ snapshots: dependencies: '@types/node': 24.12.2 - '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 - eslint: 9.39.2(jiti@1.21.7) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -14590,18 +14526,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 - debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.54.0 @@ -14645,18 +14569,6 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.54.0 @@ -14849,12 +14761,6 @@ snapshots: vite: 7.3.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) vue: 3.5.27(typescript@5.9.3) - '@vitejs/plugin-vue@6.0.4(vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': - dependencies: - '@rolldown/pluginutils': 1.0.0-rc.2 - vite: 8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) - vue: 3.5.27(typescript@5.9.3) - '@vitejs/plugin-vue@6.0.4(vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.2 @@ -16471,12 +16377,6 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-flat-gitignore@0.3.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@eslint/compat': 1.4.1(eslint@9.39.2(jiti@1.21.7)) - eslint: 9.39.2(jiti@1.21.7) - find-up-simple: 1.0.1 - eslint-config-flat-gitignore@0.3.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint/compat': 1.4.1(eslint@9.39.2(jiti@2.6.1)) @@ -16498,23 +16398,6 @@ snapshots: optionalDependencies: unrs-resolver: 1.11.1 - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@typescript-eslint/types': 8.54.0 - comment-parser: 1.4.5 - debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) - eslint-import-context: 0.1.9(unrs-resolver@1.11.1) - is-glob: 4.0.3 - minimatch: 10.1.2 - semver: 7.7.4 - stable-hash-x: 0.2.0 - unrs-resolver: 1.11.1 - optionalDependencies: - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): dependencies: '@typescript-eslint/types': 8.54.0 @@ -16532,22 +16415,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-jsdoc@50.8.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@es-joy/jsdoccomment': 0.50.2 - are-docs-informative: 0.0.2 - comment-parser: 1.4.1 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint: 9.39.2(jiti@1.21.7) - espree: 10.4.0 - esquery: 1.7.0 - parse-imports-exports: 0.2.4 - semver: 7.7.4 - spdx-expression-parse: 4.0.0 - transitivePeerDependencies: - - supports-color - eslint-plugin-jsdoc@50.8.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@es-joy/jsdoccomment': 0.50.2 @@ -16573,17 +16440,6 @@ snapshots: optionalDependencies: eslint-config-prettier: 10.1.8(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-regexp@2.10.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) - '@eslint-community/regexpp': 4.12.2 - comment-parser: 1.4.5 - eslint: 9.39.2(jiti@1.21.7) - jsdoc-type-pratt-parser: 4.8.0 - refa: 0.12.1 - regexp-ast-analysis: 0.7.1 - scslre: 0.3.0 - eslint-plugin-regexp@2.10.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) @@ -16599,47 +16455,21 @@ snapshots: dependencies: eslint: 9.39.2(jiti@2.6.1) - eslint-plugin-storybook@10.2.4(eslint@9.39.2(jiti@2.6.1))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(typescript@5.9.3): + eslint-plugin-storybook@10.2.4(eslint@9.39.2(jiti@1.21.7))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint: 9.39.2(jiti@1.21.7) storybook: 10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-turbo@2.8.2(eslint@9.39.2(jiti@1.21.7))(turbo@2.8.2): - dependencies: - dotenv: 16.0.3 - eslint: 9.39.2(jiti@1.21.7) - turbo: 2.8.2 - eslint-plugin-turbo@2.8.2(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.2): dependencies: dotenv: 16.0.3 eslint: 9.39.2(jiti@2.6.1) turbo: 2.8.2 - eslint-plugin-unicorn@55.0.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) - ci-info: 4.4.0 - clean-regexp: 1.0.0 - core-js-compat: 3.48.0 - eslint: 9.39.2(jiti@1.21.7) - esquery: 1.7.0 - globals: 15.15.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.1.0 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.7.4 - strip-indent: 3.0.0 - eslint-plugin-unicorn@55.0.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -16674,20 +16504,6 @@ snapshots: '@stylistic/eslint-plugin': 2.13.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint-plugin-vue@9.33.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) - eslint: 9.39.2(jiti@1.21.7) - globals: 13.24.0 - natural-compare: 1.4.0 - nth-check: 2.1.1 - postcss-selector-parser: 6.1.2 - semver: 7.7.4 - vue-eslint-parser: 9.4.3(eslint@9.39.2(jiti@1.21.7)) - xml-name-validator: 4.0.0 - transitivePeerDependencies: - - supports-color - eslint-plugin-vue@9.33.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) @@ -21399,22 +21215,6 @@ snapshots: yaml: 2.8.2 optional: true - vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.8 - rolldown: 1.0.0-rc.12 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.12.2 - esbuild: 0.27.3 - fsevents: 2.3.3 - jiti: 1.21.7 - sass: 1.97.3 - terser: 5.46.0 - yaml: 2.8.2 - vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): dependencies: lightningcss: 1.32.0 @@ -21591,19 +21391,6 @@ snapshots: transitivePeerDependencies: - supports-color - vue-eslint-parser@9.4.3(eslint@9.39.2(jiti@1.21.7)): - dependencies: - debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.7.0 - lodash: 4.17.23 - semver: 7.7.4 - transitivePeerDependencies: - - supports-color - vue-eslint-parser@9.4.3(eslint@9.39.2(jiti@2.6.1)): dependencies: debug: 4.4.3 diff --git a/standards/frontend/INPUTS.md b/standards/frontend/INPUTS.md index fa5c48fb91..959b063d91 100644 --- a/standards/frontend/INPUTS.md +++ b/standards/frontend/INPUTS.md @@ -12,12 +12,13 @@ into application code. ## Select a component -| Component | Use | -| ------------ | -------------------------------------------------------------------------- | -| `Input` | Single-line text, email, password, number, URL, or search entry | -| `Textarea` | Multi-line text entry | -| `DateInput` | A native browser control for a date or a local date and time | -| `DatePicker` | A styled calendar for ranges, multiple dates, time, or inline presentation | +| Component | Use | +| ------------- | -------------------------------------------------------------------------- | +| `Input` | Single-line text, email, password, number, URL, or search entry | +| `Textarea` | Multi-line text entry | +| `DateInput` | A native browser control for a date or a local date and time | +| `DatePicker` | A styled calendar for ranges, multiple dates, time, or inline presentation | +| `ColorPicker` | A swatch button that opens a hue and saturation picker with a hex field | Use a dedicated component for each other type of control. Do not use `Input` instead of a select, checkbox, radio group, toggle, or file picker. @@ -26,7 +27,7 @@ Import the public input components from `@modrinth/ui`. In `packages/ui`, import from `#ui/components/base/inputs`: ```ts -import { DateInput, DatePicker, Input, Textarea } from '@modrinth/ui' +import { ColorPicker, DateInput, DatePicker, Input, Textarea } from '@modrinth/ui' ``` ## Labels and field descriptions @@ -38,12 +39,7 @@ For a visible label, set the same value for the label `for` and the control `id` ```vue - + ``` An input does not have a `label` prop. Do not use a placeholder as the only label. The @@ -52,13 +48,7 @@ placeholder is not visible after the user enters a value. If a visible label repeats other content, use an accessible name such as `aria-label`: ```vue - + ``` Connect descriptions and validation messages to the control with `aria-describedby`. @@ -66,12 +56,7 @@ The component sends additional attributes to the native control: ```vue - +

Use lowercase letters, numbers, and dashes.

{{ slugError }} @@ -87,22 +72,9 @@ Bind the field value with `v-model`. For text types, the `Input` model is a stri `type="number"`, the model is a number or `undefined`: ```vue - - - + + + ``` An empty number input sets the model to `undefined`. The `clamp` prop keeps the number @@ -117,14 +89,7 @@ the native input type are different. Use `Textarea` for multi-line content: ```vue -