diff --git a/.changeset/stupid-ads-tap.md b/.changeset/stupid-ads-tap.md new file mode 100644 index 00000000..625719c8 --- /dev/null +++ b/.changeset/stupid-ads-tap.md @@ -0,0 +1,7 @@ +--- +'@ldn-viz/ui': major +--- + +CHANGED - the select component is now based on the `svelte-select` library +ADDED - a new `Tooltip` component allows the display of help tooltips when an icon is hovered over +ADDED - an `InputWrapper` provides consisten chrome (such as help text or error messages) around input elements diff --git a/apps/docs/.storybook/preview-head.html b/apps/docs/.storybook/preview-head.html index 0cf9fa9d..29b5f20a 100644 --- a/apps/docs/.storybook/preview-head.html +++ b/apps/docs/.storybook/preview-head.html @@ -1,2 +1,7 @@ - + + + diff --git a/package-lock.json b/package-lock.json index 3c5306e0..7f58d552 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "packages/*" ], "dependencies": { - "@changesets/cli": "^2.26.1" + "@changesets/cli": "^2.26.1", + "svelte-select": "^5.7.0" }, "devDependencies": { "eslint": "^8.0.0", @@ -17050,6 +17051,15 @@ "node": ">=4.0" } }, + "node_modules/svelte-floating-ui": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-1.5.3.tgz", + "integrity": "sha512-yjLeRQ4SNcICbMabp5S2cXc5ubBd2eua+swfTqqGBeg8ZrUvotZYK8jsRWETl/3RgLQsaZbEYKx8OmLA3wL/yw==", + "dependencies": { + "@floating-ui/core": "^1.2.4", + "@floating-ui/dom": "^1.2.4" + } + }, "node_modules/svelte-hmr": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz", @@ -17165,6 +17175,24 @@ "node": ">=12" } }, + "node_modules/svelte-select": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/svelte-select/-/svelte-select-5.7.0.tgz", + "integrity": "sha512-oClK1exjcWDj2817+0djGhK04t5CSZbuP0oh7gz+3dEcn/G+QqRsfI2/dvIyOSHILqNzlj+Ztp2z1pMtE7Wf8Q==", + "dependencies": { + "@floating-ui/dom": "^1.2.1", + "svelte-floating-ui": "1.2.8" + } + }, + "node_modules/svelte-select/node_modules/svelte-floating-ui": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-1.2.8.tgz", + "integrity": "sha512-8Ifi5CD2Ui7FX7NjJRmutFtXjrB8T/FMNoS2H8P81t5LHK4I9G4NIs007rLWG/nRl7y+zJUXa3tWuTjYXw/O5A==", + "dependencies": { + "@floating-ui/core": "^1.1.0", + "@floating-ui/dom": "^1.1.0" + } + }, "node_modules/svelte/node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", @@ -19432,7 +19460,8 @@ "@types/d3-dsv": "^3.0.1", "d3-dsv": "^3.0.1", "postcss-cli": "^10.1.0", - "postcss-discard-comments": "^6.0.0" + "postcss-discard-comments": "^6.0.0", + "svelte-floating-ui": "^1.5.3" }, "devDependencies": { "@playwright/test": "^1.28.1", diff --git a/package.json b/package.json index 7a925c24..c565b5d5 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "packages/*" ], "dependencies": { - "@changesets/cli": "^2.26.1" + "@changesets/cli": "^2.26.1", + "svelte-select": "^5.7.0" }, "overrides": { "@rgossiaux/svelte-headlessui": { diff --git a/packages/themes/ldn-theme.js b/packages/themes/ldn-theme.js index 310eefef..3e65bc4c 100644 --- a/packages/themes/ldn-theme.js +++ b/packages/themes/ldn-theme.js @@ -29,7 +29,7 @@ const config = { 'border-color': ldnColors.core.grey[300], '&:disabled': { - 'background-color': ldnColors.core.grey[200] + 'background-color': ldnColors.core.grey[100] } }, '.form-input, .form-textarea, .form-select, .form-multiselect': { @@ -38,6 +38,9 @@ const config = { 'border-color': ldnColors.core.blue[600] } }, + '.form-input::placeholder, .form-textarea::placeholder': { + color: ldnColors.core.grey[300] + }, '.form-checkbox, .form-radio': { color: ldnColors.core.blue[600], '&:focus': { @@ -45,7 +48,8 @@ const config = { } }, '.form-label': { - color: ldnColors.core.grey[700] + color: ldnColors.core.grey[700], + 'font-weight': '500' }, '.form-select': { 'background-image': `url("${svgToDataUri( @@ -55,7 +59,7 @@ const config = { '.dark': { '.form-input, .form-textarea, .form-select, .form-multiselect, .form-checkbox, .form-radio': { - 'border-color': ldnColors.core.grey[400], + 'border-color': ldnColors.core.grey[600], 'background-color': ldnColors.core.grey[600], color: ldnColors.core.grey[50], '&:focus': { @@ -63,11 +67,11 @@ const config = { }, '&:disabled, &:disabled::placeholder': { 'background-color': ldnColors.core.grey[400], - color: ldnColors.core.grey[600] + color: ldnColors.core.grey[300] } }, '.form-input::placeholder, .form-textarea::placeholder': { - color: ldnColors.core.grey[200] + color: ldnColors.core.grey[300] }, '.form-checkbox, .form-radio': { color: ldnColors.core.blue[600] diff --git a/packages/ui/package.json b/packages/ui/package.json index 666d85d8..6f819c2b 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -67,7 +67,8 @@ "@types/d3-dsv": "^3.0.1", "d3-dsv": "^3.0.1", "postcss-cli": "^10.1.0", - "postcss-discard-comments": "^6.0.0" + "postcss-discard-comments": "^6.0.0", + "svelte-floating-ui": "^1.5.3" }, "overrides": { "@rgossiaux/svelte-headlessui": { diff --git a/packages/ui/src/lib/button/Button.svelte b/packages/ui/src/lib/button/Button.svelte index e3cdd8a9..af259f8a 100644 --- a/packages/ui/src/lib/button/Button.svelte +++ b/packages/ui/src/lib/button/Button.svelte @@ -157,6 +157,8 @@ on:touchcancel on:mouseenter on:mouseleave + role="button" + tabindex="0" > diff --git a/packages/ui/src/lib/index.js b/packages/ui/src/lib/index.js index 6d7877c1..cc40edca 100644 --- a/packages/ui/src/lib/index.js +++ b/packages/ui/src/lib/index.js @@ -1,40 +1,33 @@ // Reexport your entry components here export { default as Button } from './button/Button.svelte'; - export { default as Checkbox } from './checkBox/Checkbox.svelte'; export { default as CheckboxGroup } from './checkBox/CheckboxGroup.svelte'; - export { default as DataDownloadButton } from './dataDownloadButton/DataDownloadButton.svelte'; +export { default as Header } from './header/Header.svelte'; +export { default as HeaderItem } from './header/HeaderItem.svelte'; +export { default as HeaderRight } from './header/HeaderRight.svelte'; +export { default as HeaderTitle } from './header/HeaderTitle.svelte'; +export { default as NavLink } from './header/NavLink.svelte'; +export { default as NavLinks } from './header/NavLinks.svelte'; export { default as ImageDownloadButton } from './imageDownloadButton/ImageDownloadButton.svelte'; export { default as LogoByCIU } from './logos/LogoByCIU.svelte'; export { default as LogoCIU } from './logos/LogoCIU.svelte'; export { default as LogoLOTI } from './logos/LogoLOTI.svelte'; export { default as LogoMayor } from './logos/LogoMayor.svelte'; - export { default as Modal } from './modal/Modal.svelte'; -export { default as Header } from './header/Header.svelte'; -export { default as HeaderItem } from './header/HeaderItem.svelte'; -export { default as HeaderRight } from './header/HeaderRight.svelte'; -export { default as HeaderTitle } from './header/HeaderTitle.svelte'; -export { default as NavLink } from './header/NavLink.svelte'; -export { default as NavLinks } from './header/NavLinks.svelte'; - export { default as PlacardButton } from './placardButton/PlacardButton.svelte'; export { default as RadioButton } from './radioButton/RadioButton.svelte'; export { default as RadioButtonGroup } from './radioButton/RadioButtonGroup.svelte'; - export { default as RadioButtonGroupSolid } from './radioButtonSolid/RadioButtonGroupSolid.svelte'; export { default as RadioButtonSolid } from './radioButtonSolid/RadioButtonSolid.svelte'; - export { default as Select } from './select/Select.svelte'; export { default as Spinner } from './spinners/Spinner.svelte'; export { default as TabbedSidebar } from './tabbedSidebar/TabbedSidebar.svelte'; export { default as TabbedSidebarTabLabel } from './tabbedSidebar/TabbedSidebarTabLabel.svelte'; export { default as TabbedSidebarTabList } from './tabbedSidebar/TabbedSidebarTabList.svelte'; export { default as TabbedSidebarWrapper } from './tabbedSidebar/TabbedSidebarWrapper.svelte'; - export { default as TabLabel } from './tabs/TabLabel.svelte'; export { default as TabList } from './tabs/TabList.svelte'; diff --git a/packages/ui/src/lib/input/Input.stories.svelte b/packages/ui/src/lib/input/Input.stories.svelte new file mode 100644 index 00000000..77e4b444 --- /dev/null +++ b/packages/ui/src/lib/input/Input.stories.svelte @@ -0,0 +1,83 @@ + + + + + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
diff --git a/packages/ui/src/lib/input/Input.svelte b/packages/ui/src/lib/input/Input.svelte new file mode 100644 index 00000000..6b3ca7ea --- /dev/null +++ b/packages/ui/src/lib/input/Input.svelte @@ -0,0 +1,25 @@ + + + + + diff --git a/packages/ui/src/lib/input/InputWrapper.svelte b/packages/ui/src/lib/input/InputWrapper.svelte new file mode 100644 index 00000000..189af813 --- /dev/null +++ b/packages/ui/src/lib/input/InputWrapper.svelte @@ -0,0 +1,65 @@ + + +
+
+ {#if label} + + {/if} + + {#if hint} + + {hintTooltipContent} + + {/if} +
+ + + + {#if description && !errorMessage} + {description} + {:else if errorMessage} + {errorMessage} + {/if} +
+ diff --git a/packages/ui/src/lib/select/Introduction.mdx b/packages/ui/src/lib/select/Introduction.mdx index 6fbb376f..34c6b301 100644 --- a/packages/ui/src/lib/select/Introduction.mdx +++ b/packages/ui/src/lib/select/Introduction.mdx @@ -6,6 +6,5 @@ import { Meta } from '@storybook/blocks'; The `Select` component allows users to select an option form a drop-down list of alternatives. -It may [have a label](./?path=/story/ui-select--with-label), -[have an initially value/initially selected item](./?path=/story/ui-select--with-initial-value) or -[be disabled](./?path=/story/ui-select--disabled). +Our select element is a wrapper around ['Svelte Select'](https://github.com/rob-balfre/svelte-select) +Check the documentation for advanced usage and a full list of props, events, slots etc. diff --git a/packages/ui/src/lib/select/Select.stories.svelte b/packages/ui/src/lib/select/Select.stories.svelte index 595210e8..2089de91 100644 --- a/packages/ui/src/lib/select/Select.stories.svelte +++ b/packages/ui/src/lib/select/Select.stories.svelte @@ -1,14 +1,15 @@ - @@ -18,12 +19,122 @@ + + + + +
+ +
+
+ + +
+ +
+
- + +
+ +
+
+ + +
+ +
+
- - + diff --git a/packages/ui/src/lib/select/Select.svelte b/packages/ui/src/lib/select/Select.svelte index 2b8c2539..9af74698 100644 --- a/packages/ui/src/lib/select/Select.svelte +++ b/packages/ui/src/lib/select/Select.svelte @@ -1,93 +1,145 @@ - dispatch('change', ev.detail)} {disabled} class="relative"> - {#if label !== undefined} - - classNames( - disabled - ? 'text-gray-700 dark:text-core-grey-400' - : 'text-gray-700 dark:text-core-grey-50', - 'block text-sm font-medium' - )} - >{label} - - {/if} -
- - classNames( - disabled - ? 'bg-gray-200 dark:bg-core-grey-600 dark:text-core-grey-400' - : 'bg-white dark:bg-core-grey-600 dark:text-core-grey-50', - 'relative w-full cursor-default border border-gray-300 dark:border-gray-700 py-2 pl-3 pr-10 text-left shadow-sm focus:border-core-blue-500 focus:outline-none focus:ring-1 focus:ring-core-blue-500 sm:text-sm' - )} - > - - {!(value === undefined || value === null) && !disabled && options.length > 0 - ? options.filter((d) => d.id === value)[0]?.label - : 'Select option'} - - - - - - + +
+