diff --git a/.changeset/mean-apples-joke.md b/.changeset/mean-apples-joke.md new file mode 100644 index 0000000000..fae72edb81 --- /dev/null +++ b/.changeset/mean-apples-joke.md @@ -0,0 +1,5 @@ +--- +"@studiocms/ui": patch +--- + +Added a new searchable select component and improved accessibility for normal selects diff --git a/packages/studiocms_ui/src/components.ts b/packages/studiocms_ui/src/components.ts index df22549c85..09998d4fc9 100644 --- a/packages/studiocms_ui/src/components.ts +++ b/packages/studiocms_ui/src/components.ts @@ -11,6 +11,7 @@ export { Toaster, toast } from './components/index'; export { Card } from './components/index'; export { Modal, ModalHelper } from './components/index'; export { Select } from './components/index'; +export { SearchSelect } from './components/index'; export { Dropdown, DropdownHelper } from './components/index'; export { User } from './components/index'; export { ThemeToggle } from './components/index'; diff --git a/packages/studiocms_ui/src/components/Button.astro b/packages/studiocms_ui/src/components/Button.astro index da41519dde..0fe8643fd7 100644 --- a/packages/studiocms_ui/src/components/Button.astro +++ b/packages/studiocms_ui/src/components/Button.astro @@ -36,6 +36,7 @@ const { ]} disabled={disabled} {...props} + tabindex={0} > diff --git a/packages/studiocms_ui/src/components/SearchSelect.astro b/packages/studiocms_ui/src/components/SearchSelect.astro new file mode 100644 index 0000000000..93d3a4fe18 --- /dev/null +++ b/packages/studiocms_ui/src/components/SearchSelect.astro @@ -0,0 +1,430 @@ +--- +import Icon from "../utils/Icon.astro"; +import { generateID } from "../utils/generateID"; +import Input from "./Input.astro"; + +type Option = { + label: string; + value: string; + disabled?: boolean; +}; + +type Props = { + label?: string; + defaultValue?: string; + class?: string; + name?: string; + isRequired?: boolean; + options: Option[]; + disabled?: boolean; + fullWidth?: boolean; +}; + +const { + label, + defaultValue, + class: className, + name = generateID("search-select"), + isRequired, + options = [], + disabled, + fullWidth, +} = Astro.props; +--- + +
+ +
+ x.value === defaultValue)?.label || "Select"} + /> + +
+
    + { + options.map((x, i) => ( +
  • + {x.label} +
  • + )) + } +
+ +
+ + diff --git a/packages/studiocms_ui/src/components/Select.astro b/packages/studiocms_ui/src/components/Select.astro index 62e9b5d75b..36c436fd8f 100644 --- a/packages/studiocms_ui/src/components/Select.astro +++ b/packages/studiocms_ui/src/components/Select.astro @@ -1,292 +1,334 @@ --- -import Icon from '../utils/Icon.astro'; -import { generateID } from '../utils/generateID'; +import Icon from "../utils/Icon.astro"; +import { generateID } from "../utils/generateID"; type Option = { - label: string; - value: string; - disabled?: boolean; + label: string; + value: string; + disabled?: boolean; }; type Props = { - label?: string; - defaultValue?: string; - class?: string; - name?: string; - isRequired?: boolean; - options: Option[]; - disabled?: boolean; - fullWidth?: boolean; + label?: string; + defaultValue?: string; + class?: string; + name?: string; + isRequired?: boolean; + options: Option[]; + disabled?: boolean; + fullWidth?: boolean; }; const { - label, - defaultValue, - class: className, - name = generateID('dropdown'), - isRequired, - options = [], - disabled, - fullWidth, + label, + defaultValue, + class: className, + name = generateID("select"), + isRequired, + options = [], + disabled, + fullWidth, } = Astro.props; --- -
- - -
    - {options.map((x, i) => ( -
  • - {x.label} -
  • - ))} -
- + + { + defaultValue + ? options.find((x) => x.value === defaultValue)?.label + : "Select" + } + + + +
    + { + options.map((x, i) => ( +
  • + {x.label} +
  • + )) + } +
+
+ diff --git a/packages/studiocms_ui/src/components/index.ts b/packages/studiocms_ui/src/components/index.ts index cc28e543eb..46bf1c7e1a 100644 --- a/packages/studiocms_ui/src/components/index.ts +++ b/packages/studiocms_ui/src/components/index.ts @@ -1,24 +1,25 @@ -export { default as Button } from './Button.astro'; -export { default as Divider } from './Divider.astro'; -export { default as Input } from './Input.astro'; -export { default as Row } from './Row.astro'; -export { default as Center } from './Center.astro'; -export { default as Textarea } from './Textarea.astro'; -export { default as Checkbox } from './Checkbox.astro'; -export { default as Toggle } from './Toggle.astro'; -export { default as RadioGroup } from './RadioGroup.astro'; -export { default as Toaster } from './Toast/Toaster.astro'; -export { default as Card } from './Card.astro'; -export { default as Modal } from './Modal/Modal.astro'; -export { default as Select } from './Select.astro'; -export { default as Dropdown } from './Dropdown/Dropdown.astro'; -export { default as User } from './User.astro'; +export { default as Button } from "./Button.astro"; +export { default as Divider } from "./Divider.astro"; +export { default as Input } from "./Input.astro"; +export { default as Row } from "./Row.astro"; +export { default as Center } from "./Center.astro"; +export { default as Textarea } from "./Textarea.astro"; +export { default as Checkbox } from "./Checkbox.astro"; +export { default as Toggle } from "./Toggle.astro"; +export { default as RadioGroup } from "./RadioGroup.astro"; +export { default as Toaster } from "./Toast/Toaster.astro"; +export { default as Card } from "./Card.astro"; +export { default as Modal } from "./Modal/Modal.astro"; +export { default as Select } from "./Select.astro"; +export { default as SearchSelect } from "./SearchSelect.astro"; +export { default as Dropdown } from "./Dropdown/Dropdown.astro"; +export { default as User } from "./User.astro"; export { default as ThemeToggle } from './ThemeToggle.astro'; -export { default as Sidebar } from './Sidebar/Single.astro'; -export { default as DoubleSidebar } from './Sidebar/Double.astro'; -export { SingleSidebarHelper, DoubleSidebarHelper } from './Sidebar/helpers'; +export { default as Sidebar } from "./Sidebar/Single.astro"; +export { default as DoubleSidebar } from "./Sidebar/Double.astro"; +export { SingleSidebarHelper, DoubleSidebarHelper } from "./Sidebar/helpers"; -export { toast } from './Toast/toast'; -export { ModalHelper } from './Modal/modal'; -export { DropdownHelper } from './Dropdown/dropdown'; +export { toast } from "./Toast/toast"; +export { ModalHelper } from "./Modal/modal"; +export { DropdownHelper } from "./Dropdown/dropdown"; diff --git a/packages/studiocms_ui/src/css/global.css b/packages/studiocms_ui/src/css/global.css index a3ab334447..db1e321a53 100644 --- a/packages/studiocms_ui/src/css/global.css +++ b/packages/studiocms_ui/src/css/global.css @@ -1,4 +1,2 @@ @import url("./colors.css"); -@import url("./sizes.css"); @import url("./resets.css"); -@import url("./spacings.css"); diff --git a/packages/studiocms_ui/src/css/sizes.css b/packages/studiocms_ui/src/css/sizes.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/studiocms_ui/src/css/spacings.css b/packages/studiocms_ui/src/css/spacings.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/playgrounds/ui/src/components/SearchSelectTests.astro b/playgrounds/ui/src/components/SearchSelectTests.astro new file mode 100644 index 0000000000..dfa2261809 --- /dev/null +++ b/playgrounds/ui/src/components/SearchSelectTests.astro @@ -0,0 +1,50 @@ +--- +import { Row, SearchSelect } from '@studiocms/ui/components'; +--- + + + + + + + diff --git a/playgrounds/ui/src/pages/index.astro b/playgrounds/ui/src/pages/index.astro index 620dfa6bb2..54d8fb163f 100644 --- a/playgrounds/ui/src/pages/index.astro +++ b/playgrounds/ui/src/pages/index.astro @@ -9,6 +9,7 @@ import CheckboxTests from '@/components/CheckboxTests.astro'; import DropdownTests from '@/components/DropdownTests.astro'; import ModalTests from '@/components/ModalTests.astro'; import RadioGroupTests from '@/components/RadioGroupTests.astro'; +import SearchSelectTests from '@/components/SearchSelectTests.astro'; import SelectTests from '@/components/SelectTests.astro'; import ToastTests from '@/components/ToastTests.astro'; import ToggleTests from '@/components/ToggleTests.astro'; @@ -100,6 +101,8 @@ import ButtonTests from '../components/ButtonTests.astro';

Select

+

Search Select

+

Dropdown

User

@@ -178,4 +181,4 @@ import ButtonTests from '../components/ButtonTests.astro'; sunIcon.classList.remove('hidden'); } }); - \ No newline at end of file + diff --git a/www/docs/src/content/docs/customizing/studiocms-ui/components/select-searchable.mdx b/www/docs/src/content/docs/customizing/studiocms-ui/components/select-searchable.mdx new file mode 100644 index 0000000000..4b4542c502 --- /dev/null +++ b/www/docs/src/content/docs/customizing/studiocms-ui/components/select-searchable.mdx @@ -0,0 +1,159 @@ +--- +title: Select (Searchable) +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import PreviewCard from '~/components/PreviewCard.astro'; +import { SearchSelect } from '@studiocms/ui/components'; + +A variation of the ` + + + + ```astro + --- + import { Select } from '@studiocms/ui/components'; + --- + + + + + + ```astro + --- + import { Select } from '@studiocms/ui/components'; + --- + + +``` + + +### Full Width + +Normally, the input has a minimum width and extends as needed. You can force it to take up +the entire width of its parent container by setting the `fullWidth` prop to true: + + + + + + ``` + + + +:::note[About Accessibility] +The select element's dropdown can be navigated via tabbing and elements can be selected by hitting the +`Enter` key. +::: diff --git a/www/docs/src/content/docs/customizing/studiocms-ui/index.mdx b/www/docs/src/content/docs/customizing/studiocms-ui/index.mdx index 6e754a4e66..d578c46a2a 100644 --- a/www/docs/src/content/docs/customizing/studiocms-ui/index.mdx +++ b/www/docs/src/content/docs/customizing/studiocms-ui/index.mdx @@ -28,11 +28,11 @@ import { Button } from '@studiocms/ui/components';