* add before / after watch events so pro can properly incrementally build
* add events for pro / app
* add extra hooks for non-wa dev
* add old new line
* use package-lock.json from next
* npm install
* prettier
* change to webawesome
* change to webawesome
* update index.md
* whitespace
* add thanks for being a webawesome pro subscriber
* add stub for currentUser
* add source code link
* add source code link
* prettier
* fix raw call
* add pro badge to themer
* add isPro flag to palettes
* show based on currentUser.hasPro
* fix logged out user stuff
---------
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
* progress, components A – C
* left behind tweaks for A – C
* all the rest
* tweaks
* remove 'accent + outlined' appearances and other tweaks
* fix overlooked docs + scouts rule
* re-add `--checked-icon-color` to radio and checkbox
* revert to `--thumb-size`
* fix theme overrides
---------
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
* consolidate theme files
* move dimension to its own layer
* touch up
* fix `.wa-invert`
* fix selectors and missing fonts
* fix selectors (for real this time)
* add button for drawer example
* scaffolding
* building initial page
* loading blank
* committing to pull down changes
* committing to merge
* trying to sync with next
* drawer issue
* added content to drawer
* added checkout page
* added checkout page
* committing to merge
* committing to merge
* made changes to sidebar
* syncing with repo
* syncing with repo
* update sidebar again
---------
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
* use wa-popup in color picker
* remove test
* remove old dropdown, menu, menu item, menu label
* remove old dropdown
* rework dropdown + dropdown item
* update examples
* add hide duration
* update jsdoc
* add event
* add size
* add size
* fix docs
* remove old test; fix types
* add submenu to example
* adapt for <wa-popup>
* remove state
* fix dropdown stuff (#1044)
* fix dropdown stuff
* prettier
* get typescript to give a real error
* remove unnecessary checks
* prettier
* remove old tag
* convert old dropdowns to new syntax
* update example
* update styles
---------
Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
* tidy and touch up content styles
* finish touching up inline text styles
* move styles for docs code blocks from `native.css` to appropriate files
* tidy and touch up list and table styles
* tidy and touch up details styles
* tidy up dialog styles
* fix bloated spacing in dialog and drawer
* add fieldset, refactor radio and checkbox styles
* refactor input, textarea, and select styles
* refactor range styles to match new `<wa-slider>`
* readability improvements
* touch up theme overrides
* fix Matter checkbox and radio hover styles
* visual test setup
* fix improper class placement in visual tests
* add `wa-form-control-*-font-size` and `-wa-form-control-hint-*` custom properties
* use new custom properties
* dump of component sizing improvements
* fix native color picker styles
* update menu with relative sizes
* tidy up menu, select, and tag sizing
* use relative sizing across components
* touch up custom properties
* update docs and comments
* update changelog
* revert changes to visual tests to simplify PR
* revert leftover change to visual tests
* tidy up space doc markdown
* fix default card spacing
* fix card docs
* wrap up new `--tag-max-size` for `<wa-select>`
* change default `--tag-max-size`
* prettier
* touch up
* clean up leftovers
* fix native form control margins
* set default toggle size relative to font size
* correct toggle size in docs
* Konnorrogers/lm form control sizing (#1025)
* try a second updateComplete??
* try a second updateComplete??
* more timeouts?
* try logging
* more logging
gp
* maybe now
* radio group test
* add todo note'
* add workflow dispatch for client tests
---------
Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
* remove redundant styles from template
* rotate arrow based on placement so borders show correctly when applied
* use actual placement, not preferred
* add popover
* update changelog
* update changelog
* use <dialog> for popover
* fix arrow border in FF/Safari
* update content
* add sidebar to plop
* add popover
* remove test value
* remove animation to prevent page-to-page blips
* static sidebar
* manage open sections on page load and with turbo
* cleanup unused scripts
* Remove overlap between Style Utilities and Layout
---------
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
* vertical => orientation="vertical"; fixes#674
* add issue
* Update divider styles and docs to use `orientation='vertical'`
* Update split panel styles and docs to use `orientation='vertical'`
* Update remaining docs and patterns examples to `orientation='vertical'`
---------
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
* Exclude Create link from sidebar, for reals this time
* Fix bug
* Very rough prototype of look & feel
* a11y
* Clean up data files
* Automatically generate theme metadata
* Read look & feel params straight from theme
* First stab at dimensionality icons
* Fix rounding 0 bug
* Add border width slider
* [Image-comparer] Expose wrapper as part
* [Comparer] `pointer-events: none` while dragging
* Dark mode slider
* Adjust increments and ranges for look + feel sliders
* Fix preview
* Fix bug where dark mode was not inverted
* Ability to select panel from URL
* Create mixin for Vue form controls and use it in `<swatch-select>`
* Prototype of slider min/max icon buttons
* Nx tooltip
* Icons
* Prevent failed request
* info-tip: Support passing text as prop
* Clearable
* [Brutalist] Match `--wa-shadow-offset-x-scale` to `--wa-shadow-offset-y-scale`
* Add 'Blocky' dimension (derived from Awesome theme)
* Only show Reset button when `clearable` is set
* Remove `clearable` from Look & Feel sliders
* Add tooltips to min/max buttons
* Remove superfluous `aria-label`
* Do not assume that all hyphens in URLs mean nesting, make it explicit
* Formatting
* Fix bug where styles were not applied on page load
* Update Subtle dimension to maximize compatibility
* `<wa-scoped>`: Do not allow non-template children
* Workaround for card not updating
* Update Glossy dimension to maximize compatibility
* Sync scrolling between regular and inverted preview
* Fix bug
* Make changing the base theme reset customizations
* Fix palette page
* Remove cancel button from editable text
* Don't error in theme pages
* Update Playful dimension to maximize compatibility
* Rename 'Look and Feel' to 'Elements' for better parallel structure
* Hide dimensionality controls
* Make back icon motion more subtle
* Expand spacing slider bounds
* Add `tabindex="-1"` where missing in theme showcase
* Remove extraneous gap from theme headers
* fix edit button bug
* rename comparer => comparison; fix aria-controls
* Always save theme name on blur
* Add changelog for themer and new patterns category
---------
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
* initial commit to this pr
* updated patterns
* category lists
* post headers
* WIP
* made some content updates
* deleted rogue file
* updated descriptions
* ran prettier
* updated padding
* updated prettierignore
* updated element
* swtiched to token
* updated with category list feedback
* updated with category list feedback
* updated with feedback for featurd post
* updated with feedback for footer
* updated with newsletter feedback'
* updated with feedback to the paywall
* updated with updates for post footer
* more footer updates
* updated with feedback for the post header
* updated with feedback for post list
* updated social share
* updated sign up and login
* added logic to elements to prevent them from closing on escape
* Fix typo (incomplete `<h2>` tag)
* Add missing input labels, fix capitalization and punctuation
* Add description to Blog & News index
* ran prettier on markdown files
* ignored the post list file
* changed hierarchy
---------
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
* [Menu-item] Drop `base` wrapper (rel #207)
Also add two states: `has-submenu` and `submenu-expanded`
* Add `checked-icon` and `submenu-icon` slots
* [Menu-label] Drop `base` part
* update changelog
---------
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
* Basic scaffolding
* Generate theme & palette data.js that other JS can import
* Make it possible to include page-card without links
* WIP
* Add `appearance` to details, closes#569
Except `accent` as that's a) far less useful and b) trickier due to the icon color
* Fix broken link
* WIP
* WIP
* Icons icon
* Unify styles for interactive cards
* Prevent focusing inside theme icons
* Fixes
* Action page cards
* Panel scrollables
* scrollable
* Scroll shadows
* Add renaming UI
* UI
* Move styling of heading icons to `ui.css`
* Support permalinks & CRUD
* Make clickable cards more accessible
* Style cards a little better
* Default to styles panel if theme is selected
* Update theme-icons.css
* Custom themes should be saved under Custom
* Get theme code
* Bigger title
* Fixes
* Use theme Vue app for remixing too
* Fix preview jank and make preview script more flexible
* Make radio groups scrollable
* Add affordance to button cards
* Sticky
* `<color-select>`
* Fix theme remixing
* Improve previewing logic
* Fix preview
* Move `domChange()` to separate module
`theme-picker.js` includes side-effects, which may not always be desirable everywhere we may want to import `domChange()`
* Update preview.js
* Panel animation
* Hide Save button if no changes and not saved
* Do not show blank code when no selection has been made
* Use theme slug in filename
* Remove unused component
* Better UI for editing title (and any other text)
* Tweak UI of renaming
* Better indicate default selection
* Fix preview reverting bug
* Fill out app preview with more examples
* Remove `zoom` from theme showcase (yields unexpected/painful results Safari), improve display in wider viewports
* Pending delete
* Make styles panel cards scrollable
* Fix some of the Safari issues
* Update search.css
* Update panel.css
* Select preview UI
* Fix typo
* Frame colors setting as color contrast
* Show dark mode in color mappings
* Brand color
* Swatch styling
* Fix caret icon
* Move Starting theme to the same level as other controls
* Rename typography to Fonts
* Fix bug: Swatch select should show swatches from the selected palette
* Move capitalize to shared utils
* Add utils for handling nested objects
* Icons panel
* Update code.js
* Move utils around
* Add fit and finish to sidebar panels
* Theme card: Move icons to separate data structure
* Move data to dedicated folder since we now have a lot more of it
* Add default icon families and variants to themes
* Data
* Add `deepEntries()`
* Add Duotone
* Spruce up icons preview
* Use theme's icon family in showcase
* Font cards
* Font cards
* Add `max-inline-size` to preview container
* Remove alternate preview options
* Remove theme subtitle
* Support FA kit codes
* Remove Pro badges from theme cards
* Use panagram preview for Fonts
* Consistent heading and label capitalization
* Classes for different icons-card types
* Update data.js.njk
* Variable style on icon family cards
* Fix Sharp Duotone
* Clean up FA kit code hint
* Hide non-functional Icon Library field
* Fix theme icon heights
* icon variant -> style in theme metadata
* Fix bug with icons defaults not being shown
* More convenient theme defaults
* Fix bug with non updating URL
* Fix bug
* Fix multiplying badges
* Custom docs pages
* Add Duotone icons to Mellow theme
* Fix 404
* Remove "Create" from sidebar
* Fix bug
* Move vue components to `/assets/`, move their CSS with them
* Safari/FF compatibility
* Make panels scrollable again
* Fix extra spacing
---------
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
* Reduce build process noise
- Only run 11ty when something has changed within `docs/`
- Only run esbuild if a JS file has changed within
* Update scripts/build.js
Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
---------
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
- Add `:where([class^='wa-theme-'], [class*=' wa-theme-'])` to default `typography.css` since we declare mappings that need to be inherited by other themes.
- Remove declarations that redeclare defaults
- Ensure consistent order
- [Awesome] Switch code font to ui-monospace
Fixes several issues for components using the `display: contents` technique:
- Introduce `--display` CSS property to make it possible to override internal display value of base part.
- Ensure `display: contents` is always applied with `!important` to avoid rendering glitches like the one here
- Ensure non-inherited custom properties are also inherited
- Ensure the `hidden` attribute still works.
* dividing up e-commerce patterns
* started invoice table
* building out the filter
* Initial Commit
* switching machines
* switching machines
* started split image pattern:
* commiting to merge in next
* commiting to switch machines
* upated the product detail patterns
* updated product list patterns
* updated some patterns
* filter work
* added utilities to order history
* added utilities to order-summary
* updated width of container
* switching machines
* switching machines
* fixing conflicts
* editing descriptions
* updated descriptions
* adding some polish
* more filter work
* updated prouct preview
* Revisions to "Product Features"
* "Category Filters" revisions + `wa-placeholder` utility
* cleaned up product list
* tweaked product overview
* tweaked order history
* tweak category preview
* "Checkout Form" revisions
* Re-add `navigation` to "Product Features" carousel
* cleaned up shopping cart
* tweaked order summary
* Add missing file extension
* Fix typo in file name
* Revert checkout form changes in attempt to improve diff
* Reimplement checkout form revisions
* cleaned up checkout form
* Add "What's a Pattern?" and "Using Patterns" to index
* Update category descriptions and headings
* Add docs layout for patterns with stylesheet
* tweaked customer review
* Add checkout form example
* a little more polish
* more tweaks
* switching branches to merge
* created e-commerce index
* unlisted links
* updtated content
* updated content for category preview
* updated order history
* committing to bring branches up to next
* inital commit
* Reorganize app patterns into separate pages
* switching machines
* Add link style utilities
* Refactor product list patterns
* more polish
* Refactor product overview patterns
* switching machines
* Refactor shopping cart patterns
* committing to pull down changes
* updated product preview
* updated image
* updated incentives
* Clean up utility usage and code formatting for category previews
* started updating with style utilities
* Clean up utilities and formatting, replace placeholder text in order history
* updated incentive images
* updated reviews
* added review variant
* more polish
* some heavy duty updates
* removed store navigation
* switching machines
:
* Clean up utility usage and code formatting for order summaries
* Clean up utility usage and code formatting for product previews
* big switchover
* removed old file
* working on sidebar
* updated sidebar
* created info category
* splitting up the old blog page
* a little cleanup and adding detail
* got three done
* updated social share
* Quick formatting adjustment
* initial paywalls
* Use overviews in pattern subcategories (#826)
* Do not error if no pages
* Automatically set parents and tags for patterns
* Update overview.njk
* [WIP] Use overview pages for pattern listings
* Remove explicit parents
---------
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
* some newsletter signups
* added login patterns
* reworked feeds'
* a few more
* added a few more
* add more app patterns
* App pattern tweaks (#827)
* Fix `patterns.css` reference
* Tweaks to action panel patterns
* Tweaks to comments patterns
* Progress on data display patterns
* Progress on empty state patterns
* Use email-related data from recent update in `pattern-main` (altered slightly)
* Tweaks to data display patterns
* Tweaks to empty state patterns
* Tweaks to FAQ patterns
* Tweaks to feed patterns
* Tweaks to grid patterns
* Tweaks to pagination patterns
* Tweaks to pricing patterns
* Tweaks to description list patterns
* Tweaks to leaderboard patterns
* Add and update names and descriptions
* Ensure comments fields have labels
* Tweak recent additions
* switching machines
* catching up with next
* added permissions pattern
* switching machines
* added post articles
* having local browset issues
* a few more app patterns
* took out info patterns
* spiffed up the action panels
* gave the action panels a once over
* added content to data display
* updated a few patterns
* clean up a few e-commerce patterns
* added time componen to reviews
---------
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
Co-authored-by: Lea Verou <lea@verou.me>
Co-authored-by: Lindsay M <126139086+lindsaym-fa@users.noreply.github.com>
* First stab at using the Popover API for PE
* fix popup
* First stab at using the Popover API for PE
* fix popup
* Prettier
* Fix TS error
* Remove workaround
* Default to `strategy = fixed` if Popover API is not supported
* Clear out default UA styles for popovers
* Kill `hoist` with fire 🔥
* Refactor
* Update `@floating-ui/dom`
* Fix flipping and shofting
* Fix autosize
* Use `defaultBoundary` for `flip` too
That way we get the previous behavior for it.
* Remove `strategy`, just use `SUPPORTS_POPOVER` check where relevant
* Remove uses of `strategy`
* Use viewport as the default boundary for shifting and autosizing and add `boundary=scroll` to override
---------
Co-authored-by: konnorrogers <konnor5456@gmail.com>
* Generalize CRUD logic to more easily support themes (and other types of entities)
* Decouple data structures managing saved entities (palettes, themes), sidebar update logic, and palette app (and soon themer) by using events
* Simplify logic (a lot of it carried complexity back from the time we did not use uids and/or was overly general)
* `PersistedArray` class to encapsulate arrays persisted in localStorage
* Remove unused `palette.equals()` function
- Moved fixes to bug fixes section
- Linked `allDefined()` and `.wa-cloak` to their docs
- Grouped related bugfixes together
- Moved docs bugfixes to the end (since they are of least interest to users)
* Fix: Parent URL should be undefined if parent is falsy
* Document `docs.11tydata.js` better
* Move `docs/installation.md` to `docs/`, fixes#585
* Just in case
* Make sure components that only appear within page icons are still detected
* Palette icons
* Update theme-icons.css
* Reduce whitespace between swatches
---------
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
* revert structure and styles to fix WA-A #123
* fix WA-A #201
* update changelog
* fix search dialog position so it doesn't jump around
* remove close watcher; fix dialog/drawer backdrop animations
Instead of raw DSD, use a component that pulls in a child template and then goes over the CSS and extracts font-related rules into the document, just once per rule.
This also fixes theme icons in Vue.
* Fix outline for headings that have links
Previously produced blank items because it assumed any link in a heading is an anchor
* Filter unlisted items from overviews
Previously they were filtered only when the card was rendered, so their heading was still shown
* [Overview] Add id to group headings
* Hide headings from empty groups
Should never happen but you never know
* [Overview] Ensure "Other" is always last even when no sorting
- Sidebar, overview listings, breadcrumbs now based on actual parent-child relationships, rather than increasingly outdated heuristics
- parent properties are now generated automatically from the URL structure, and need only be specified to override that default
- Ability to group by page hierarchy in overview pages, where pages that have >= 2 children become categories
Smaller improvements:
- More flexible syntax for specifying the params of overview pages
- [Overviews] Hide group heading if only one group is present
- parentItem and parentUrl properties that can be used on any page
- Alias a collection as the children of a page (useful for "virtual" parents like Layout)
- Do not error if a page card icon is missing
* Initial comment, based on #768
* Add `neutral` color variables
* Add `success`, `warning`, and `danger` variables
* Theme touch-ups
* Remove unused clamped tokens
* Re-add clamped tokens test page, refactor to be based on hue instead of `brand`
- Add ids, use ids to link copy button. No need for client-side script or updating the copy button manually for dynamic code snippets.
- Add button to link to code block
- Slight refactor on copy plugin to use the 11ty API properly
- General infrastructure to support palette tweaking
- Hue shifts per color scale (UI, permalinks, dynamic code snippets)
- Scale overall chroma up/down (UI, permalinks, dynamic code snippets)
- Update contrast ratio tables (styling for contrast up/down/fail could use improvement, but it's a starting point)
- Make sure it works with Turbo (i.e. things don't break when we navigate to another page)
- Drop `base` part (rel #207)
- Add `hint` slot and attribute (it was the only form control that did not support that)
- Refactor `@watch` calls to `updated()` per @claviska's plan for them
* Add `label` attribute and `defaultLabel` getter to option and menu-item, drop `getTextLabel()`
- Add `label` attribute to option and menu-item, closes#698
- [Option] Add `defaultLabel` cached property to both
- [Option] Remove `getTextLabel()` method from both (people can just set `el.label`)
- Refactor: Merge utils to get text content into one more powerful utility function
- Fixed typo in `slot.ts`
.
Add `label` attribute to menu, remove `getTextLabel`
* Update filename
* Initial progress on visual test suite
* Additional tests and descriptions
* Add native callout, add dividers between tables
* Indicate test failures, improve alignment tests
* Split tests into separate files
* Add table scrolling
* Remove irrelevant icon test cases
* Add test failures
* Shorten "Inline Code" > "Code" to prevent wrapping
* Add horizontal orientation to radio button tests
* add orientation to radio group; fixes#613
* fix timing issue that prevents value from being set sometimes
* gimme a break
* make radio button examples horizontal
---------
Co-authored-by: lindsaym-fa <dev@lindsaym.design>
- Add `default` descriptor
- Do not reflect attributes when equal to their default value
- Patch getter return value to return default value when empty
- Use it in button `appearance`
- Added `part="control", fixes#529
- Removed wrapper div which is no longer needed
- Removed `form-control--has-hint` class which is no longer used anywhere
* Initial glassy theme progress
* Add fallback to slider thumb box shadow
* Remove redundant `wa-dark` styles and refactor shadows
* Rename to 'Glossy' since it fits the vibe better
- Minimize needless swaps
- Centralize logic
- Use an actual `<wa-select>` rather than hacking it with `<wa-dropdown>`
- Move shared includes to shared template
- Rewrite critical theme JS
- Refactor of theme picker code
- Utilize view transitions better and use them for color scheme too
- Do not store default value in localStorage
- Removed unused `*-wide` templates
- Fixed#482
* Presentation improvements
* Change `-webkit-text-size-adjust` to supported value (`none` isn't a supported keyword on iOS)
* Try using `text-size-adjust`
* Throwing caution to the wind
* Give up on `text-size-adjust` and add 1-column view
* tweaked the tag component
* updated based on feedback
* updated to remove span
* changed display to initial
* prettier
---------
Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
* skip broken test
* add middleware to follow new stylesheet imports
* fix avatar tests
* update badge tests
* fix button tests
* skip carousel test
* fix checkbox tests
* fix details test
* update radio button tests
* fix input tests
* fix progress bar tests
* update
* fix range tests
* fix select tests
* restore wrapper div to pass a11y tests
* fix switch tests
* fix tag tests
* fix textarea tests
* fix tooltip tests
* skips
* fix tree item tests
* [DRAFT]: test fixes (#421)
* working on some stuff..
* add a small delay for menu-item
* prettier
* add a small delay for menu-item
* prettier
* add a small delay for menu-item
* add a small delay for menu-item
* add a small delay for menu-item
* prettier
* Empty commit
* add a small delay for menu-item
* always build with alpha
* always build with alpha
* move to alpha builds
---------
Co-authored-by: Konnor Rogers <konnor5456@gmail.com>
- Use hueless color tokens so it can be used with variants (and add example)
- Fix hover effect on zebra rows
- Reduce padding a bit
- Shorten utility class
- CSS nesting
- Simplify styles and DOM
- Add `.wa-text-field` utility class
- Eliminate `--border-color` (except when set by appearance utils), `--border-style`, `--border-radius`
Revert "Replace font-size variable with `1em`"
This reverts commit 1ac70f31abe2bab310bbfbdbb3aa5d4498c5648d.
Replace font-size vars with 1em when calculating form control height
As discussed with @lindsaym-fa last week. Hopefully this will eventually help reduce duplication across themes.
Co-Authored-By: Lindsay M <126139086+lindsaym-fa@users.noreply.github.com>
As discussed with @lindsaym-fa
Still unsure about some of these (especially about whether blockquote & details should be separate) but I figured better go ahead and split and we can fine tune later
Co-Authored-By: Lindsay M <126139086+lindsaym-fa@users.noreply.github.com>
- Removed BEM-style naming (the shadow DOM gives you scoping already!)
- Use new size helper
- Organize styles to keep an element’s styles together, using nesting for modifiers
- Removed unused classes
Turns out `prettier-plugin-organize-imports` sorts imports differently than the old one so this will prevent spreading the change across multiple commits whenever we touch a file (and potentially introducing conflicts)
- Reduce class names by using `:has()`, native pseudo-classes, or `[part~=foo]` selectors
- Remove `hasFocus` property since it’s no longer needed
- Move the icon hiding logic to CSS
Shared styles are now added in the base class, rather than having to be repeated in every component.
In the odd case a component does not want the shared styles, it can define a custom `styles` property of its own.
Rn this means we don't get expand animations at all but that’s fine. I think it's fine to have an animation on close and not on open (different user goals — you open to get to the info, you close to get it out of the way, the opening is more urgent)
* initial progress
* spruce up docs sample page
* clean up and organization
* revert extraneous addition to applied.css
* accidentally reverted the wrong change 😅
* take 2 - revert extraneous addition in applied.css
* more cleanup
* Simplify how list of components is exposed to 11ty
No need for functions or computing multiple times, that's what data is for!
* Add attributes to component data
* Cleanup
* Add slug (tagName without wa-)
* Add component reference / cheatsheet
* initial progress
* testing progress
* play with naming, utility classes
* more tweaking and testing
* progress on 12 column grid
* add layout index, start documenting
* documentation progress
* cleanup and doc progress
* more doc progress
* more progress
* final progress hurdle and cleanup
* refining and editing
* remove sandbox
* refactor extra utility classes
* layout index improvements
* change gap modifiers to utility classes
* change align modifiers to utility classes
* move layout examples above fold
* reduce demo markup
* use standard aspect ratio property for wa-frame
* change border-radius modifier to utility class
* rename wa-grid's 'min-inline-size' to 'min-column-size'
* clean up comments
* rename wa-align-* to wa-align-items-*
* break out style utilities from layout
* clean up
* continued ssr work
* continued ssr work
* prettier
* all components now rendering
* everything finally works
* fix type issues
* working on breadcrumb
* working on breadcrumb
* radio group
* convert all tests to ssr
* prettier
* test suite finally passing
* add layout stuff
* add changelog
* fix TS issue
* fix tests
* fixing deploy stuff
* get QR code displaying
* fix tests
* fix tests
* prettier
* condense hydration stuff
* prettier
* comment out range test
* fixing issues
* use base fixtures
* fixing examples
* dont vendor
* fix import of hydration support
* adding notes
* add notesg
* add ssr loader
* fix build
* prettier
* add notes
* add notes
* prettier
* fixing bundled stuff
* remove cdn
* remove cdn
* prettier
* fiixng tests
* prettier
* split jobs??
* prettier
* fix build stuff
* add reset mouse and await aTimeout
* prettier
* fix improper tests
* prettier
* bail on first
* fix linting
* only test form with client
* redundancy on ssr-loader??
* maybe this will work
* prettier
* try callout now
* fix form.test.ts
* fix form.test.ts
* prettier
* fix forms
* fix forms
* try again
* prettier
* add some awaits
* prettier
* comment out broken SSR tests
* prettier
* comment out broken SSR tests
* prettier
* dont skip in CI
* upgrade playwright to beta
* prettier
* try some trickery
* try some trickery
* await updateComplete
* try to fix form.test.ts
* import hydrateable elements 1 time
* prettier
* fix input defaultValue issues
* fix form controls to behave like their native counterpartS
* add changelog entry
* prettier
* fix unexpected behavior with range / button
* add test for min / maxlength
* prettier
* fix accessibility issue in tab group
* add changelog entry
gp
* fix swatches for things that dont have background colors
* first pass at starlight
* converting to starlight
* working on converting to starlight
* working on data
* watch custom-elements.json
* turn on pagefind
* add component meta data
* fix renderings / overrides.
* fix mdx logo
* continue starlight work
* building site
* get global styles + reloads working
* themer fixes
* adding additional headings
* working on dynamic content
* have TableOfContents.astro push to TOC
* working on code stuff
* remove code preview
* deploy
* add patch package
* patch in build
* patch in build
* remove {% raw %} calls
* convert to starlight...complete
* prettier
* update lockfile
* merge main
* fix index.mdx
* prettier'
* fix small things
* docs updates
* add dark mode shortcut
* prettier
* prettier
* prettier
* remove pagefind from public
* add twitteR
* prettier
* fix tests
* prettier
* remove square, stretch, and squish spacing tokens
* remove units from base tokens
* rename corner tokens with t-shirt size scale
* rename 'font-size' tokens to 'size'
* rename 'neutral' primitives to 'base'
* remove black and white tokens
* improve 'form-controls' tokens
* reintroduce granular focus ring tokens
* fix themer styles
* tweak shadow styles
* improve naming and scope of foundational colors
* overhaul color naming and add new themes
* more classic sl component styles
* make 'chic' theme dark by default
* adjust table row colors
* remove deprecated properties from 'classic' theme
* remove mistakenly committed stylesheets
* revert adjustment to space properties
* delete web-types.json
* revert "rename 'font-size' tokens to 'size'"
* Move custom properties related to shadows and borders to separate stylesheets
* Change base values and themer calculations related to shadows and borders to be unitless
* Add low-level custom properties for alert, button, card, input, select, switch, and textarea
* Add generic guidance for authoring custom properties to the Contributing docs
* [RFC] Proof-of-concept commit for submenu support
This is a Request For Comments to seek directional guidance towards
implementing the submenu slot of menu-item.
Includes:
- SubmenuController to manage event listeners on menu-item.
- Example usage in menu-item documentation.
- Trivial tests to check rendering.
Outstanding questions include:
- Accessibility concerns. E.g. where to handle 'ArrowRight',
'ArrowLeft'?
- Should selection of menu-item denoting submenu be possible or
customizable?
- How to parameterize contained popup?
- Implementation concerns:
- Use of ref / id
- delegation of some rendering to the controller
- What to test
Related to [#620](https://github.com/shoelace-style/shoelace/issues/620).
* Update submenu-controller.ts
Removed extraneous `console.log()`.
* PoC working of ArrowRight to focus on submenu.
* Revert "PoC working of ArrowRight to focus on submenu."
(Didn't mean to publish this.)
This reverts commit be04e9a221.
* [WIP] Submenu WIP continues.
- Submenus now close on change-of-focus, not a timeout.
- Keyboard navigation support added.
- Skidding fix for better alignment.
- Submenu documentation moved to Menu page.
- Tests for accessibility, right and left arrow keys.
* Cleanup: Removed dead code and dead code comments.
* style: Eslint warnings and errors fixed. npm run verify now passes.
* fix: 2 changes to menu / submenu on-click behavior:
1. Close submenu on click explicitly, so this occurs even if the menu is
not inside of an sl-dropdown.
2. In menu, ignore clicks that do not explicitly target a menu-item.
Clicks that were on (e.g. a menu-border) were emitting select events.
* fix: Prevent menu's extraneous Enter / space key propagation.
Menu's handleKeyDown calls item.click (to emit the selection).
Propagating the keyboard event on Enter / space would the cause re-entry
into a submenu, so prevent the needless propagation.
* Submenu tweaks ...
- 100 ms delay when opening submenus on mouseover
- Shadows added
- Distance added to popup to have submenus overlap menu slightly.
* polish up submenu stuff
* stay highlighted when submenu is open
* update changelog
* resolve feedback
---------
Co-authored-by: Bryce Moore <bryce.moore@gmail.com>
* Never select tree items when clicking the chevron
This changes the behaviour of sl-tree so that clicking on the expand/collapse icon will not select/deselect the item, only toggle it's expanded state.
* Refactor: inline SlTree.syncTreeItems
This was only called from 2 places, and they each had different
behaviour anyways.
* SlTree: separate expand/collapse from selection
This makes 'multi' and 'single' mode consistent with each other, and
with native file managers.
* feat(clipboard): add new component sl-clipboard
* using slots
* using a single copyStatus
* feat(clipboard): support inputs/textarea/links and shadow dom
* fix(clipboard): add area-live to announce copied
* feat(clipboard): support any component with a value property
* initial attempt at not auto defining
* add files with -
* continued work on removing auto-define
* fix component definitions
* update with new tag stuff
* fix lots of things
* fix improper scoped elements
* working through side effects
* continued react wrapper work
* update changelog
* formatting
* fixes
* update changelog
* lint / formatting
* fix version injection
* fix version injection, work on test
* fix version injection, work on test
* fix merge conflicts
* fix jsdoc null issue
* fix templates
* use exports
* working on tests
* working on registration mocking
* fix customElements test
* linting
* fix some test stuff
* clean up test
* clean up comment
* rename scopedElements to dependencies
* linting / formatting
* linting / formatting
* mark all packages external and still bundle
* set bundle false
* set bundle true
* dont minify
* fix merge conflicts
* use built shoelace-element
* fix lint errors
* prettier
* appease eslint
* appease eslint gods
* appease eslint gods
* appease eslint gods
* appease eslint gods
* add shoelace-autoloader
* move it all into 1 function
* add exportmaps note
* prettier
* add jsdelivr entrypoint
* read as utf8
* update docs with .component.js importS
* prettier
* Move keydown handler for sl-drawer back to base div
This restores the stacking behaviour of drawers
See: #1457
* Autofocus panel of sl-drawer when it is open on firstUpdate
* Rename SlSlideChange for consistency with other events
* Setup React event types for events used by Shoelace components
Means that consumers of Shoelace via the React wrapper will be able to
use callback methods with the correct event type, instead of having to
rely on casting and friends when using Typescript.
* Add docs demonstrating importing event types for React callbacks
* add modal tab tracking
* prettier
* sort by tabindex
* sort by tabindex
* add a dialog test case for shadow roots
* add a changelog note
* add a changelog note
* prettier + test fixes
* prettier + test fixes
* Add tests for qr-code
* Fix a small bug in qr-code
The background color was not passed to the
qr code
---------
Co-authored-by: Dominikus Hellgartner <dominikus.hellgartner@gmail.com>
The current statement is incorrect and will result in
`Module not found: Package path ./dist/shoelace is not exported from package /your/path/to/node_modules/@shoelace-style/shoelace (see exports field in /your/path/to/node_modules/@shoelace-style/shoelace/package.json)`
* Added tests for sl-split-panel
test for horizontal arrangement
* Added tests for sl-split-panel
tests for vertical arrangement
---------
Co-authored-by: stefanie.hellgartner <stefanie.hellgartner@in-tech.com>
* add regression test for checkbox focusing
* change number of checkboxes / switches
* change max-height to 400px so it fails
* re-add positon: relative;
* Improve performance of sl-icon by caching later
* Fixed error handling
* Don't use requestInclude in sl-icon
* Separate sl-icon errors into cacheable and retryable errors
* Fix acessability issue
* Additionally adapted the test
* Added more accessability tests
* Updated the testing documentation
to take the fact that accessability checks cover only
rendered content into account
---------
Co-authored-by: Dominikus Hellgartner <dominikus.hellgartner@gmail.com>
Did not manage to check
that the properties are correctly passed
to the animation api at this point so this
stays a blackbox test
Co-authored-by: Dominikus Hellgartner <dominikus.hellgartner@gmail.com>
The reason for the problems is that the error event does
not escape from the shadow dom.
Thus it cannot be awaited for in the test
Co-authored-by: Dominikus Hellgartner <dominikus.hellgartner@gmail.com>
* fix(carousel): don't resume autoplay if interacting
* fix(carousel): wrap pagination items
* chore(carousel): add unit tests
* feat(carousel): more reactive pagination dots
* fix(carousel): trigger scrollend when user scroll exactly over a snap point
* Resize observer sometimes throws errors which
are nothing to worry about, see also the corresponding
comment on tab-group.test.ts
* Unfortunately, the web testing library installs an
error event handler which takes precedence before the
event handlers installed in the tests
(see node_modules/@web/browser-logs/dist/logUncaughtErrors.js)
* the only possibility to avoid these null logs is to install
an error event handler at an even earlier place
Co-authored-by: Dominikus Hellgartner <dominikus.hellgartner@gmail.com>
* Improved tests for SlAlert
* added more test for coverage
* Grouped tests in multiple subgroups
* remove executing only one tests
* Fix the now executing tests
---------
Co-authored-by: Dominikus Hellgartner <dominikus.hellgartner@gmail.com>
* #1163 - added read-only properties 'validity' and 'validationMessage' to all nine form controls
* #1163 - added base support for showing form validation messages below the form controls
* #1163 - animated validation errors in demo
* #1181 - Removed all previous changes that have been validation error specific
* Started with 'Inline validation' demo / fixed merge issues / etc.
* #1181 - continued work on missing form validation features
* #1181 - enhanced validation support for SlColorPicker / some cleanup
* #1181 - fixed CSS issues
* #1181 - fixed again CSS issues
* '1181 - added form validation features finally working
* #1181 - bug fixes
* #1181 - fixed open issues / added API doc comments
* #1181 - updated inline validation demos / removed some legacy code
* #1181 - finished invalid form validation example
* #1181 - added tests / several bugfixes
* #1181 - fixed typos etc.
* #1181 - tests
* #1181 - tests
* #1181 - tests
* dropdown filtered menu items
* updated filter, added test
- updated filter to match menu getAllItems private method
- added test
---------
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
* remove duplicate test
* Add tests for sl-tab-group -- initial round of tests
* use individual fixtures for each test
* extract mocks + utility functions in external files
* remove unnecessary internals of intersection observer from the mock
* added first test on scroll buttons
* add scrolling tests
* remove resize observer mock
Resize observer is triggered but waiting for element
to be updated is not enough. You need to free the main thread
with the test for some time
* Also removed intersection observer mock
By waiting long enough for the things to happen automatically
* Fix problems with resize observer
These problems appeared after npm ci but (according
to the sources linked in the comments) unproblematic
* Handle merge request comments
* replace custom wait function with corresponding function
from openwc/testing
* Extracted waitForScrollingToEnd and isElementVisibleFromScrolling into
dedicated files to be reused
* Improve queryByTestId --> make it usable for more complex values
* Add js docs
* run lint fix
* Added tests for selecting a tab by click
* added further tests for tab group selection
* use Promise<void> instead of Promise<any>
to avoid eslint errors
---------
Co-authored-by: Dominikus Hellgartner <dominikus.hellgartner@gmail.com>
* Initial example of a JSON schema and converter for design tokens
* Clean up script and relocate file
* Update token JSON format and finish build process
* removed checked and indeterminate parts from doc
* Revert "removed checked and indeterminate parts from doc"
This reverts commit 5e702387e1ace4e5d6b424f861df8e6a3a1a4fdd.
* control--checked & control--indeterminate parts
* sl-color-picker use lib '@ctrl/tinycolor' instead of 'color'
typescript, esm and smaller
* parseColor adjustments
removed normalizeColorString and other tweaks
* added hsv format
* fixed const
* Fix mapping in exports
Fixes#1019
- Add correct mapping for public entrypoints.
* Remove shoelace.js from from exports list
Should still works fine while importing this way: import { thing } from '@shoelace-style/shoelace';
* added stepUp and stepDown to sl-range
* step function & default props tests for sl-range
* stepUp, stepDown & showPicker functions for input
* step functions & default props tests for sl-input
* made name and placeholder default to empty string
* updated changelog
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
add check to input component if japanese character is chosen by pressing enter key and prevent form submitting
Co-authored-by: VitaliyMaznyi <vitalii.maznyi@fasterthanlight.me>
* Added tests for sl-relative-time
* Solves a blinker which appears only when I run
the full test suite: Chromium and webkit are fine
but sometimes there is this one error on firefox
for the disabled test of the menu item (saying there
was a timeout waiting). Did not happen again after
doing the change.
Co-authored-by: Dominikus Hellgartner <dominikus.hellgartner@gmail.com>
* move component description from docs to component
* use component description in docs
* add style for lead sentence, keep bc for not updated components
* run `npm prettier`
* render summary as part of the header
* add `title` as another custom tag for JSDoc
* render components title in header
* provide possibility to render components "description" into docs with `[component-description:COMPONENT_NAME]`
* the meta summary should be rendered into header too
* Avoid bubbling events for sl-include
I ran into an issue where icons inside of an HTML include were dispatching `sl-load` events, which was causing my `sl-include` event handler to run multiple times. By adding these guards, we ensure only events immediately dispatched by the element itself will be handled.
* Use the correct event variable
The description for the checkbox's value attribute is currently "the checkbox's value attribute." I think we can do better than that, especially considering anyone who hasn't worked with old-school HTML forms that POST to the URL in the `action` attribute is unlikely to know why a checkbox has a value and that value is not boolean.
While I was here I improved a couple of other descriptions. If there's an interest, I can expand this PR to update all of the properties in all controls where the description is tautological.
* Tooltip: Recalculate target after slotchange
The tooltip's positioning breaks after a slotchange, unless the tooltips target is recalculated.
* Update src/components/tooltip/tooltip.test.ts
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
* initial button tests and setup helpers
* fix as many linting errors as I could
* switch back to regular fixtures
* test(button|button-group|divider|format-bytes) add tests for more components
* add tests for format util components
* finish format-number tests
* remove unnecessary ignore
@@ -35,7 +35,7 @@ This Code of Conduct applies within all project spaces, and it also applies when
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at cory@abeautifulsite.net. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@fontawesome.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
# # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name:Client Tests
on:
workflow_dispatch:
push:
branches:[next]
pull_request:
branches:[next]
jobs:
client_test:
runs-on:ubuntu-latest
strategy:
matrix:
node-version:[20.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name:Node.js CI
on:
push:
branches:[next ]
pull_request:
branches:[next ]
jobs:
build:
runs-on:ubuntu-latest
strategy:
matrix:
node-version:[14.x, 16.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name:SSR Tests
on:
# push:
# branches: [next]
workflow_dispatch:
jobs:
ssr_test:
runs-on:ubuntu-latest
strategy:
matrix:
node-version:[20.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Shoemakers, or "Shoelace developers," can use this documentation to learn how to build Shoelace from source. You will need Node >= 14 to build and run the project locally. It is preferred, but not required, to use npm 7.
Developers can use this documentation to learn how to build Web Awesome from source. You will need Node >= 14.17 to build and run the project locally.
**You don't need to do any of this to use Shoelace!** This page is for people who want to contribute to the project, tinker with the source, or create a custom build of Shoelace.
**You don't need to do any of this to use Web Awesome!** This page is for people who want to contribute to the project, tinker with the source, or create a custom build of Web Awesome.
If that's not what you're trying to do, the [documentation website](https://shoelace.style) is where you want to be.
If that's not what you're trying to do, the [documentation website](https://webawesome.com) is where you want to be.
### What are you using to build Shoelace?
### What are you using to build Web Awesome?
Components are built with [LitElement](https://lit-element.polymer-project.org/), a custom elements base class that provides an intuitive API and reactive data binding. The build is a custom script with bundling powered by [esbuild](https://esbuild.github.io/).
### Forking the Repo
### Understanding the Web Awesome monorepo
Start by [forking the repo](https://github.com/shoelace-style/shoelace/fork) on GitHub, then clone it locally and install dependencies.
Web Awesome uses [NPM workspaces](https://docs.npmjs.com/cli/v11/using-npm/workspaces) for its monorepo structure and is fairly minimal in what it provides.
By using a NPM workspaces and a monorepo structure, we can get consistent builds, shared configurations, and reduced duplication across repositories which reduces regressions and forces consistency across `webawesome`, `webawesome-pro`, and `webawesome-app`.
Generally, if you plan to only work with the free version of `webawesome` it is easiest to go to `packages/webawesome` and run all commands from there.
### Where do NPM dependencies go?
Any dependencies intended to be used across all packages (IE: `prettier`, `eslint`) that are _NOT_ used at runtime should be in the root `devDependencies` of `package.json`.
Any dependencies that will be used at runtime by a package should be part of the specific package's `"dependencies"` such as `lit`. This is required because if that dependency is not in the `packages/*/package.json`, it will not be installed when used via NPM.
Individual packages are also free to install devDependencies as needed as long as they are specific to that package only.
To do install a package specific to a package, change your working directory to that package's root
Once you've cloned the repo, run the following command.
Once you've cloned the repo, run the following command from the respective directory within `packages/*`
```bash
cd packages/webawesome
npm start
```
This will spin up the Shoelace dev server. After the initial build, a browser will open automatically. There is currently no hot module reloading (HMR), as browser's don't provide a way to reregister custom elements, but most changes to the source will reload the browser automatically.
The documentation is powered by Docsify, which uses raw markdown files to generate pages. As such, no static files are built for the docs.
This will spin up the dev server. After the initial build, a browser will open automatically. There is currently no hot module reloading (HMR), as browser's don't provide a way to reregister custom elements, but most changes to the source will reload the browser automatically.
### Building
To generate a production build, run the following command.
```bash
cd packages/webawesome
npm run build
```
You can also run `npm run build:serve` to start an [`http-server`](https://www.npmjs.com/package/http-server) instance on `http://localhost:4000` after the build completes, so you can preview the production build.
### Creating New Components
To scaffold a new component, run the following command, replacing `sl-tag-name` with the desired tag name.
To scaffold a new component, run the following command, replacing `wa-tag-name` with the desired tag name.
```bash
npm run create sl-tag-name
cd packages/webawesome
npm run create wa-tag-name
```
This will generate a source file, a stylesheet, and a docs page for you. When you start the dev server, you'll find the new component in the "Components" section of the sidebar.
### Adding additional packages
Right now the only additional packages are in private repositories.
To add additional packages from other repositories, run: `git clone <url> packages/<package-name>` to clone your repo into `packages/`.
Make sure to run `npm install` at the root of the monorepo after adding your package!
### Contributing
Shoelace is an open source project and contributions are encouraged! If you're interesting in contributing, please review the [contribution guidelines](CONTRIBUTING.md) first.
Web Awesome is an open source project and contributions are encouraged! If you're interesting in contributing, please review the [contribution guidelines](CONTRIBUTING.md) first.
## License
Shoelace is designed in New Hampshire by [Cory LaViska](https://twitter.com/claviska). It’s available under the terms of the MIT license.
Designing, developing, and supporting this library requires a lot of time, effort, and skill. I’d like to keep it open source so everyone can use it, but that doesn’t provide me with any income.
**Therefore, if you’re using my software to make a profit,** I respectfully ask that you help [fund its development](https://github.com/sponsors/claviska) by becoming a sponsor. There are multiple tiers to choose from with benefits at every level, including prioritized support, bug fixes, feature requests, and advertising.
👇 Your support is very much appreciated! 👇
- [Become a sponsor](https://github.com/sponsors/claviska)
- [Star on GitHub](https://github.com/shoelace-style/shoelace/stargazers)
- [Follow on Twitter](https://twitter.com/shoelace_style)
Whether you're building Shoelace or building something _with_ Shoelace — have fun creating! 🥾
Web Awesome is available under the terms of the MIT license.
To display an alert as a toast notification, or "toast", create the alert and call its `toast()` method. This will move the alert out of its position in the DOM and into [the toast stack](#the-toast-stack) where it will be shown. Once dismissed, it will be removed from the DOM completely. To reuse a toast, store a reference to it and call `toast()` again later on.
You should always use the `closable` attribute so users can dismiss the notification. It's also common to set a reasonable `duration` when the notification doesn't require acknowledgement.
For convenience, you can create a utility that emits toast notifications with a function call rather than composing them in your HTML. To do this, generate the alert with JavaScript, append it to the body, and call the `toast()` method as shown in the example below.
The toast stack is a fixed position singleton element created and managed internally by the alert component. It will be added and removed from the DOM as needed when toasts are shown. When more than one toast is visible, they will stack vertically in the toast stack.
By default, the toast stack is positioned at the top-right of the viewport. You can change its position by targeting `.sl-toast-stack` in your stylesheet. To make toasts appear at the top-left of the viewport, for example, use the following styles.
```css
.sl-toast-stack {
left: 0;
right: auto;
}
```
?> By design, it is not possible to show toasts in more than one stack simultaneously. Such behavior is confusing and makes for a poor user experience.
When you don't have an image to use, you can set the `initials` attribute to show something more personalized than an icon.
```html preview
<sl-avatar initials="SL"></sl-avatar>
```
### Custom Icons
When no image or initials are set, an icon will be shown. The default avatar shows a generic "user" icon, but you can customize this with the `icon` slot.
```html preview
<sl-avatar>
<sl-icon slot="icon" name="image"></sl-icon>
</sl-avatar>
<sl-avatar>
<sl-icon slot="icon" name="archive"></sl-icon>
</sl-avatar>
<sl-avatar>
<sl-icon slot="icon" name="briefcase"></sl-icon>
</sl-avatar>
```
### Shapes
Avatars can be shaped using the `shape` attribute.
Badges are used to draw attention and display statuses or counts.
```html preview
<sl-badge>Badge</sl-badge>
```
## Examples
### Types
Set the `type` attribute to change the badge's type.
```html preview
<sl-badge type="primary">Primary</sl-badge>
<sl-badge type="success">Success</sl-badge>
<sl-badge type="neutral">Neutral</sl-badge>
<sl-badge type="warning">Warning</sl-badge>
<sl-badge type="danger">Danger</sl-badge>
```
### Pill Badges
Use the `pill` attribute to give badges rounded edges.
```html preview
<sl-badge type="primary" pill>Primary</sl-badge>
<sl-badge type="success" pill>Success</sl-badge>
<sl-badge type="neutral" pill>Neutral</sl-badge>
<sl-badge type="warning" pill>Warning</sl-badge>
<sl-badge type="danger" pill>Danger</sl-badge>
```
### Pulsating Badges
Use the `pulse` attribute to draw attention to the badge with a subtle animation.
```html preview
<div class="badge-pulse">
<sl-badge type="primary" pill pulse>1</sl-badge>
<sl-badge type="success" pill pulse>1</sl-badge>
<sl-badge type="neutral" pill pulse>1</sl-badge>
<sl-badge type="warning" pill pulse>1</sl-badge>
<sl-badge type="danger" pill pulse>1</sl-badge>
</div>
<style>
.badge-pulse sl-badge:not(:last-of-type) {
margin-right: 1rem;
}
</style>
```
### With Buttons
One of the most common use cases for badges is attaching them to buttons. To make this easier, badges will be automatically positioned at the top-right when they're a child of a button.
```html preview
<sl-button>
Requests
<sl-badge pill>30</sl-badge>
</sl-button>
<sl-button style="margin-left: 1rem;">
Warnings
<sl-badge type="warning" pill>8</sl-badge>
</sl-button>
<sl-button style="margin-left: 1rem;">
Errors
<sl-badge type="danger" pill>6</sl-badge>
</sl-button>
```
### With Menu Items
When including badges in menu items, use the `suffix` slot to make sure they're aligned correctly.
Breadcrumbs provide a group of links so users can easily navigate a website's hierarchy.
Breadcrumbs are usually placed before a page's main content with the current page shown last to indicate the user's position in the navigation.
```html preview
<sl-breadcrumb>
<sl-breadcrumb-item>Catalog</sl-breadcrumb-item>
<sl-breadcrumb-item>Clothing</sl-breadcrumb-item>
<sl-breadcrumb-item>Women's</sl-breadcrumb-item>
<sl-breadcrumb-item>Shirts & Tops</sl-breadcrumb-item>
</sl-breadcrumb>
```
## Examples
### Breadcrumb Links
By default, breadcrumb items are rendered as buttons so you can use them to navigate single-page applications. In this case, you'll need to add event listeners to handle clicks.
For websites, you'll probably want to use links instead. You can make any breadcrumb item a link by applying an `href` attribute to it. Now, when the user activates it, they'll be taken to the corresponding page — no event listeners required.
It's often helpful to have a button that works like a link. This is possible by setting the `href` attribute, which will make the component render an `<a>` under the hood. This gives you all the default link behavior the browser provides (e.g. <kbd>CMD/CTRL/SHIFT + CLICK</kbd>) and exposes the `target` and `download` attributes.
?> When a `target` is set, the link will receive `rel="noreferrer noopener"` for [security reasons](https://mathiasbynens.github.io/rel-noopener/).
### Setting a Custom Width
As expected, buttons can be given a custom width by setting its `width`. This is useful for making buttons span the full width of their container on smaller screens.
Use the `caret` attribute to add a dropdown indicator when a button will trigger a dropdown, menu, or popover.
```html preview
<sl-button size="small" caret>Small</sl-button>
<sl-button size="medium" caret>Medium</sl-button>
<sl-button size="large" caret>Large</sl-button>
```
### Loading
Use the `loading` attribute to make a button busy. The width will remain the same as before, preventing adjacent elements from moving around. Clicks will be suppressed until the loading state is removed.
This example demonstrates how to style buttons using a custom class. This is the recommended approach if you need to add additional variations. To customize an existing variation, modify the selector to target the button's type attribute instead of a class (e.g. `sl-button[type="primary"]`).
```html preview
<sl-button class="pink">Pink Button</sl-button>
<style>
sl-button.pink::part(base) {
/* Set design tokens for height and border width */
Use the `opacity` attribute to enable the opacity slider. When this is enabled, the value will be displayed as HEXA, RGBA, or HSLA based on `format`.
```html preview
<sl-color-picker opacity></sl-color-picker>
```
### Formats
Set the color picker's format with the `format` attribute. Valid options include `hex`, `rgb`, and `hsl`. Note that the color picker's input will accept any parsable format (including CSS color names) regardless of this option.
To prevent users from toggling the format themselves, add the `no-format-toggle` attribute.
Context menus offer additional options through a menu that opens at the pointer's location, usually activated by a right-click.
Context menus are designed to work with [menus](/components/menu) and [menu items](/components/menu-item). The menu must include `slot="menu"`. Other content you provide will be part of the context menu's target area.
The [menu component](/components/menu) emits an `sl-select` event when a menu item is selected. You can use this to handle selections. The selected item will be available in `event.detail.item`.
The context menu uses `display: contents`, so it will assume the shape of the content you slot in.
```html preview
<sl-context-menu>
<span style="background: rgb(var(--sl-color-neutral-100)); padding: .5rem 1rem;">
Right-click here
</span>
<sl-menu slot="menu">
<sl-menu-item value="cut">Cut</sl-menu-item>
<sl-menu-item value="copy">Copy</sl-menu-item>
<sl-menu-item value="paste">Paste</sl-menu-item>
</sl-menu>
</sl-context-menu>
```
### Placement
The preferred placement of the context menu can be set with the `placement` attribute. Note that the actual position may vary to ensure the menu remains in the viewport.
Details show a brief summary and expand to show additional content.
```html preview
<sl-details summary="Toggle Me">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</sl-details>
```
## Examples
### Disabled
Use the `disable` attribute to prevent the details from expanding.
```html preview
<sl-details summary="Disabled" disabled>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</sl-details>
```
### Grouping Details
Details are designed to function independently, but you can simulate a group or "accordion" where only one is shown at a time by listening for the `sl-show` event.
```html preview
<div class="details-group-example">
<sl-details summary="First" open>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</sl-details>
<sl-details summary="Second">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</sl-details>
<sl-details summary="Third">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
By design, a dialog's height will never exceed that of the viewport. As such, dialogs will not scroll with the page ensuring the header and footer are always accessible to the user.
By default, dialogs will close when the user clicks the close button, clicks the overlay, or presses the <kbd>Escape</kbd> key. In most cases, the default behavior is the best behavior in terms of UX. However, there are situations where this may be undesirable, such as when data loss will occur.
To keep the dialog open in such cases, you can cancel the `sl-request-close` event. When canceled, the dialog will remain open and pulse briefly to draw the user's attention to it.
By default, the dialog's panel will gain focus when opened. This allows the first tab press to focus on the first tabbable element within the dialog. To set focus on a different element, listen for and cancel the `sl-initial-focus` event.
```html preview
<sl-dialog label="Dialog" class="dialog-focus">
<sl-input placeholder="I will have focus when the dialog is opened"></sl-input>
Add the `vertical` attribute to draw the divider in a vertical orientation. The divider will span the full height of its container. Vertical dividers work especially well inside of a flex container.
By default, the drawer slides out of its [containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#Identifying_the_containing_block), which is usually the viewport. To make the drawer slide out of its parent element, add the `contained` attribute and `position: relative` to the parent.
By design, a drawer's height will never exceed 100% of its container. As such, drawers will not scroll with the page to ensure the header and footer are always accessible to the user.
By default, drawers will close when the user clicks the close button, clicks the overlay, or presses the <kbd>Escape</kbd> key. In most cases, the default behavior is the best behavior in terms of UX. However, there are situations where this may be undesirable, such as when data loss will occur.
To keep the drawer open in such cases, you can cancel the `sl-request-close` event. When canceled, the drawer will remain open and pulse briefly to draw the user's attention to it.
By default, the drawer's panel will gain focus when opened. This allows the first tab press to focus on the first tabbable element within the drawer. To set focus on a different element, listen for and cancel the `sl-initial-focus` event.
```html preview
<sl-drawer label="Drawer" class="drawer-focus">
<sl-input placeholder="I will have focus when the drawer is opened"></sl-input>
Dropdowns expose additional content that "drops down" in a panel.
Dropdowns consist of a trigger and a panel. By default, activating the trigger will expose the panel and interacting outside of the panel will close it.
Dropdowns are designed to work well with [menus](/components/menu) to provide a list of options the user can select from. However, dropdowns can also be used in lower-level applications (e.g. [color picker](/components/color-picker) and [select](/components/select)). The API gives you complete control over showing, hiding, and positioning the panel.
When dropdowns are used with [menus](/components/menu), you can listen for the `sl-select` event to determine which menu item was selected. The menu item element will be exposed in `event.detail.item`. You can set `value` props to make it easier to identify commands.
The preferred placement of the dropdown can be set with the `placement` attribute. Note that the actual position may vary to ensure the panel remains in the viewport.
```html preview
<sl-dropdown placement="top-start">
<sl-button slot="trigger" caret>Edit</sl-button>
<sl-menu>
<sl-menu-item>Cut</sl-menu-item>
<sl-menu-item>Copy</sl-menu-item>
<sl-menu-item>Paste</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item>Find</sl-menu-item>
<sl-menu-item>Replace</sl-menu-item>
</sl-menu>
</sl-dropdown>
```
### Distance
The distance from the panel to the trigger can be customized using the `distance` attribute. This value is specified in pixels.
```html preview
<sl-dropdown distance="30">
<sl-button slot="trigger" caret>Edit</sl-button>
<sl-menu>
<sl-menu-item>Cut</sl-menu-item>
<sl-menu-item>Copy</sl-menu-item>
<sl-menu-item>Paste</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item>Find</sl-menu-item>
<sl-menu-item>Replace</sl-menu-item>
</sl-menu>
</sl-dropdown>
```
### Skidding
The offset of the panel along the trigger can be customized using the `skidding` attribute. This value is specified in pixels.
```html preview
<sl-dropdown skidding="30">
<sl-button slot="trigger" caret>Edit</sl-button>
<sl-menu>
<sl-menu-item>Cut</sl-menu-item>
<sl-menu-item>Copy</sl-menu-item>
<sl-menu-item>Paste</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item>Find</sl-menu-item>
<sl-menu-item>Replace</sl-menu-item>
</sl-menu>
</sl-dropdown>
```
### Hoisting
Dropdown panels will be clipped if they're inside a container that has `overflow: auto|hidden`. The `hoist` attribute forces the panel to use a fixed positioning strategy, allowing it to break out of the container. In this case, the panel will be positioned relative to its containing block, which is usually the viewport unless an ancestor uses a `transform`, `perspective`, or `filter`. [Refer to this page](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed) for more details.
Forms collect data that can easily be processed and sent to a server.
All Shoelace components make use of a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) to encapsulate markup, styles, and behavior. One caveat of this approach is that native `<form>` elements will not recognize Shoelace form controls.
This component solves that problem by serializing _both_ Shoelace form controls and native form controls when the form is submitted. The resulting form data is exposed in the `sl-submit` event as a [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object in `event.detail.formData`. You can also find an array of form controls in `event.detail.formControls`.
Shoelace forms don't make use of `action` and `method` attributes and they don't submit the same way as native forms. To handle submission, you need to listen for the `sl-submit` event as shown in the example below and make an XHR request with the resulting form data.
// Example 2: Output all form control names + values
//
for (const entry of formData.entries()) {
output += `${entry[0]}: ${entry[1]}\n`;
}
alert(output);
//
// Example 3: Get all form controls that were serialized as
// an array of HTML elements
//
console.log(event.detail.formControls);
});
</script>
```
## Form Control Validation
Client-side validation can be enabled through the browser's [Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation) for many form controls. You can enable it using props such as `required`, `pattern`, `minlength`, and `maxlength`. As the user interacts with the form control, the `invalid` attribute will reflect its validity based on its current value and the constraints that have been defined.
When a form control is invalid, the containing form will not be submitted. Instead, the browser will show the user a relevant error message. If you don't want to use client-side validation, you can suppress this behavior by adding `novalidate` to the `<sl-form>` element.
All form controls support validation, but not all validation props are available for every component. Refer to a component's documentation to see which validation props it supports.
!> Client-side validation can be used to improve the UX of forms, but it is not a replacement for server-side validation. **You should always validate and sanitize user input on the server!**
### Required Fields
To make a field required, use the `required` prop. The form will not be submitted if a required form control is empty.
const form = document.querySelector('.input-validation-required');
form.addEventListener('sl-submit', () => alert('All fields are valid!'));
</script>
```
### Input Patterns
To restrict a value to a specific [pattern](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern), use the `pattern` attribute. This example only allows the letters A-Z, so the form will not submit if a number or symbol is entered. This only works with `<sl-input>` elements.
const form = document.querySelector('.input-validation-type');
form.addEventListener('sl-submit', () => alert('All fields are valid!'));
</script>
```
### Custom Validation
To create a custom validation error, use the `setCustomValidity` method. The form will not be submitted when this method is called with anything other than an empty string, and its message will be shown by the browser as the validation error. To make the input valid again, call the method a second time with an empty string as the argument.
const form = document.querySelector('.input-validation-custom');
const input = form.querySelector('sl-input');
form.addEventListener('sl-submit', () => alert('All fields are valid!'));
input.addEventListener('sl-input', () => {
if (input.value === 'shoelace') {
input.setCustomValidity('');
} else {
input.setCustomValidity('Hey, you\'re supposed to type \'shoelace\' before submitting this!');
}
});
</script>
```
### Custom Validation Styles
The `invalid` attribute reflects the form control's validity, so you can style invalid fields using the `[invalid]` selector. The example below demonstrates how you can give erroneous fields a different appearance. Type something other than "shoelace" to demonstrate this.
To opt out of the browser's built-in validation and use your own, add the `novalidate` attribute to the form. This will ignore all constraints and prevent the browser from showing its own warnings when form controls are invalid.
Remember that the `invalid` attribute on form controls reflects validity as defined by the [Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation). You can set it initially, but the `invalid` attribute will update as the user interacts with the form control. As such, you should not rely on it to set invalid styles using a custom validation library.
Instead, toggle a class and target it in your stylesheet as shown below.
Formats a date/time using the specified locale and options.
Localization is handled by the browser's [`Intl.DateTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). No language packs are required.
The `date` attribute determines the date/time to use when formatting. It must be a string that [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) can interpret or a [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object set via JavaScript. If omitted, the current date/time will be assumed.
?> When using strings, avoid ambiguous dates such as `03/04/2020` which can be interpreted as March 4 or April 3 depending on the user's browser and locale. Instead, always use a valid [ISO 8601 date time string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#Date_Time_String_Format) to ensure the date will be parsed properly by all clients.
## Examples
### Date & Time Formatting
Formatting options are based on those found in the [`Intl.DateTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). When formatting options are provided, the date/time will be formatted according to those values. When no formatting options are provided, a localized, numeric date will be displayed instead.
By default, the browser will determine whether to use 12-hour or 24-hour time. To force one or the other, set the `hour-format` attribute to `12` or `24`.
Formats a number using the specified locale and options.
Localization is handled by the browser's [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat). No language packs are required.
To format a number as a monetary value, set the `type` attribute to `currency` and set the `currency` attribute to the desired ISO 4217 currency code. You should also specify `locale` to ensure the the number is formatted correctly for the target locale.
Icon buttons are designed to have a uniform appearance, so their color is not inherited. However, you can still customize them by styling the `base` part.
Icons are symbols that can be used to represent various options within an application.
Shoelace comes bundled with over 1,300 icons courtesy of the [Bootstrap Icons](https://icons.getbootstrap.com/) project. These icons are part of the `default` icon library. If you prefer, you can register [custom icon libraries](#icon-libraries) as well.
Click or tap on an icon below to copy its name and use it like this.
Icons are sized relative to the current font size. To change their size, set the `font-size` property on the icon itself or on a parent element as shown below.
```html preview
<div style="font-size: 32px;">
<sl-icon name="exclamation-triangle"></sl-icon>
<sl-icon name="archive"></sl-icon>
<sl-icon name="battery-charging"></sl-icon>
<sl-icon name="bell"></sl-icon>
<sl-icon name="clock"></sl-icon>
<sl-icon name="download"></sl-icon>
<sl-icon name="file-earmark"></sl-icon>
<sl-icon name="flag"></sl-icon>
<sl-icon name="heart"></sl-icon>
<sl-icon name="image"></sl-icon>
<sl-icon name="lightning"></sl-icon>
<sl-icon name="mic"></sl-icon>
<sl-icon name="search"></sl-icon>
<sl-icon name="star"></sl-icon>
<sl-icon name="trash"></sl-icon>
<sl-icon name="x-circle"></sl-icon>
</div>
```
### Custom Icons
Custom icons can be loaded individually with the `src` attribute. Only SVGs on a local or CORS-enabled endpoint are supported. If you're using more than one custom icon, it might make sense to register a [custom icon library](#icon-libraries).
You can register additional icons to use with the `<sl-icon>` component through icon libraries. Icon files can exist locally or on a CORS-enabled endpoint (e.g. a CDN). There is no limit to how many icon libraries you can register and there is no cost associated with registering them, as individual icons are only requested when they're used.
Shoelace ships with two built-in icon libraries, `default` and `system`. The [default icon library](#customizing-the-default-library) contains all of the icons in the Bootstrap Icons project. The [system icon library](#customizing-the-system-library) contains only a small subset of icons that are used internally by Shoelace components.
To register an additional icon library, use the `registerIconLibrary()` function that's exported from `utilities/icon-library.js`. At a minimum, you must provide a name and a resolver function. The resolver function translates an icon name to a URL where the corresponding SVG file exists. Refer to the examples below to better understand how it works.
If necessary, a mutator function can be used to mutate the SVG element before rendering. This is necessary for some libraries due to the many possible ways SVGs are crafted. For example, icons should ideally inherit the current text color via `currentColor`, so you may need to apply `fill="currentColor` or `stroke="currentColor"` to the SVG element using this function.
Here's an example that registers an icon library located in the `/assets/icons` directory.
```html
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
If an icon is used before registration occurs, it will be empty initially but shown when registered.
The following examples demonstrate how to register a number of popular, open source icon libraries via CDN. Feel free to adapt the code as you see fit to use your own origin or naming conventions.
### Boxicons
This will register the [Boxicons](https://boxicons.com/) library using the jsDelivr CDN. This library has three variations: regular (`bx-*`), solid (`bxs-*`), and logos (`bxl-*`). A mutator function is required to set the SVG's `fill` to `currentColor`.
Icons in this library are licensed under the [Creative Commons 4.0 License](https://github.com/atisawd/boxicons#license).
```html preview
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
registerIconLibrary('boxicons', {
resolver: name => {
let folder = 'regular';
if (name.substring(0, 4) === 'bxs-') folder = 'solid';
if (name.substring(0, 4) === 'bxl-') folder = 'logos';
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
registerIconLibrary('feather', {
resolver: name => `https://cdn.jsdelivr.net/npm/feather-icons@4.28.0/dist/icons/${name}.svg`
});
</script>
```
### Font Awesome
This will register the [Font Awesome Free](https://fontawesome.com/) library using the jsDelivr CDN. This library has three variations: regular (`far-*`), solid (`fas-*`), and brands (`fab-*`). A mutator function is required to set the SVG's `fill` to `currentColor`.
Icons in this library are licensed under the [Font Awesome Free License](https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt). Some of the icons that appear on the Font Awesome website require a license and are therefore not available in the CDN.
```html preview
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
registerIconLibrary('fa', {
resolver: name => {
const filename = name.replace(/^fa[rbs]-/, '');
let folder = 'regular';
if (name.substring(0, 4) === 'fas-') folder = 'solid';
if (name.substring(0, 4) === 'fab-') folder = 'brands';
This will register the [Ionicons](https://ionicons.com/) library using the jsDelivr CDN. This library has three variations: outline (default), filled (`*-filled`), and sharp (`*-sharp`). A mutator function is required to polyfill a handful of styles we're not including.
Icons in this library are licensed under the [MIT License](https://github.com/ionic-team/ionicons/blob/master/LICENSE).
```html preview
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
registerIconLibrary('ionicons', {
resolver: name => `https://cdn.jsdelivr.net/npm/ionicons@5.1.2/dist/ionicons/svg/${name}.svg`,
This will register the [Jam Icons](https://jam-icons.com/) library using the jsDelivr CDN. This library has two variations: regular (default) and filled (`*-f`). A mutator function is required to set the SVG's `fill` to `currentColor`.
Icons in this library are licensed under the [MIT License](https://github.com/michaelampr/jam/blob/master/LICENSE).
```html preview
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
registerIconLibrary('jam', {
resolver: name => `https://cdn.jsdelivr.net/npm/jam-icons@2.0.0/svg/${name}.svg`,
This will register the [Material Icons](https://material.io/resources/icons/?style=baseline) library using the jsDelivr CDN. This library has three variations: outline (default), round (`*_round`), and sharp (`*_sharp`). A mutator function is required to set the SVG's `fill` to `currentColor`.
Icons in this library are licensed under the [Apache 2.0 License](https://github.com/google/material-design-icons/blob/master/LICENSE).
```html preview
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
registerIconLibrary('material', {
resolver: name => {
const match = name.match(/^(.*?)(_(round|sharp))?$/);
This will register the [Remix Icon](https://remixicon.com/) library using the jsDelivr CDN. This library groups icons by categories, so the name must include the category and icon separated by a slash, as well as the `-line` or `-fill` suffix as needed. A mutator function is required to set the SVG's `fill` to `currentColor`.
Icons in this library are licensed under the [Apache 2.0 License](https://github.com/Remix-Design/RemixIcon/blob/master/License).
```html preview
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
This will register the [Unicons](https://iconscout.com/unicons) library using the jsDelivr CDN. This library has two variations: line (default) and solid (`*-s`). A mutator function is required to set the SVG's `fill` to `currentColor`.
Icons in this library are licensed under the [Apache 2.0 License](https://github.com/Iconscout/unicons/blob/master/LICENSE). Some of the icons that appear on the Unicons website, particularly many of the solid variations, require a license and are therefore not available in the CDN.
```html preview
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
The default icon library contains over 1,300 icons courtesy of the [Bootstrap Icons](https://icons.getbootstrap.com/) project. These are the icons that display when you use `<sl-icon>` without the `library` attribute. If you prefer to have these icons resolve elsewhere or to a different icon library, register an icon library using the `default` name and a custom resolver.
This example will load the same set of icons from the jsDelivr CDN instead of your local assets folder.
```html
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
registerIconLibrary('default', {
resolver: name => `https://cdn.jsdelivr.net/npm/bootstrap-icons@1.0.0/icons/${name}.svg`
});
</script>
```
### Customizing the System Library
The system library contains only the icons used internally by Shoelace components. Unlike the default icon library, the system library does not rely on physical assets. Instead, its icons are hard-coded as data URIs into the resolver to ensure their availability.
If you want to change the icons Shoelace uses internally, you can register an icon library using the `system` name and a custom resolver. If you choose to do this, it's your responsibility to provide all of the icons that are required by components. You can reference `src/components/library.system.ts` for a complete list of system icons used by Shoelace.
```html
<script type="module">
import { registerIconLibrary } from '/dist/utilities/icon-library.js';
registerIconLibrary('system', {
resolver: name => `/path/to/custom/icons/${name}.svg`
});
</script>
```
<!-- Supporting scripts and styles for the search utility -->
Compare visual differences between similar photos with a sliding panel.
For best results, use images that share the same dimensions. The slider can be controlled by dragging or pressing the left and right arrow keys. (Tip: press shift + arrows to move the slider in larger intervals, or home + end to jump to the beginning or end.)
```html preview
<sl-image-comparer>
<img slot="before" src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80&sat=-100&bri=-5" alt="Grayscale version of kittens in a basket looking around.">
<img slot="after" src="https://images.unsplash.com/photo-1517331156700-3c241d2b4d83?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80" alt="Color version of kittens in a basket looking around.">
</sl-image-comparer>
```
## Examples
### Initial Position
Use the `position` attribute to set the initial position of the slider. This is a percentage from `0` to `100`.
```html preview
<sl-image-comparer position="25">
<img slot="before" src="https://images.unsplash.com/photo-1520903074185-8eca362b3dce?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1200&q=80" alt="A person sitting on bricks wearing untied boots.">
<img slot="after" src="https://images.unsplash.com/photo-1520640023173-50a135e35804?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2250&q=80" alt="A person sitting on a yellow curb tying shoelaces on a boot.">
Includes give you the power to embed external HTML files into the page.
Included files are asynchronously requested using `window.fetch()`. Requests are cached, so the same file can be included multiple times, but only one request will be made.
The included content will be inserted into the `<sl-include>` element's default slot so it can be easily accessed and styled through the light DOM.
When an include file loads successfully, the `sl-load` event will be emitted. You can listen for this event to add custom loading logic to your includes.
If the request fails, the `sl-error` event will be emitted. In this case, `event.detail.status` will contain the resulting HTTP status code of the request, e.g. 404 (not found).
The `value` attribute can be used to assign a hidden value, such as a unique identifier, to a menu item. When an item is selected, the `sl-select` event will be emitted and a reference to the item will be available at `event.detail.item`. You can use this reference to access the selected item's value, its checked state, and more.
Menus provide a list of options for the user to choose from.
You can use [menu items](/components/menu-item), [menu labels](/components/menu-label), and [dividers](/components/divider) to compose a menu. Menus support keyboard interactions, including type-to-select an option.
?> Menus are intended for system menus (dropdown menus, select menus, context menus, etc.). They should not be mistaken for navigation menus which serve a different purpose and have a different semantic meaning. If you're building navigation, use `<nav>` and `<a>` elements instead.
The Mutation Observer component offers a thin, declarative interface to the [`MutationObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
The mutation observer will report changes to the content it wraps through the `sl-mutation` event. When emitted, a collection of [MutationRecord](https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord) objects will be attached to `event.detail` that contains information about how it changed.
```html preview
<div class="mutation-overview">
<sl-mutation-observer attr>
<sl-button type="primary">Click to mutate</sl-button>
?> When you create a mutation observer, you must indicate what changes it should respond to by including at least one of `attr`, `child-list`, or `char-data`. If you don't specify at least one of these attributes, no mutation events will be emitted.
## Examples
### Child List
Use the `child-list` attribute to watch for new child elements that are added or removed.
const value = Math.min(100, progressBar.value + 10);
progressBar.value = value;
progressBar.textContent = `${value}%`;
});
subtractButton.addEventListener('click', () => {
const value = Math.max(0, progressBar.value - 10)
progressBar.value = value;
progressBar.textContent = `${value}%`;
});
</script>
```
### Indeterminate
The `indeterminate` attribute can be used to inform the user that the operation is pending, but its status cannot currently be determined. In this state, `value` is ignored and the label, if present, will not be shown.
Generates a [QR code](https://www.qrcode.com/) and renders it using the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API).
QR codes are useful for providing small pieces of information to users who can quickly scan them with a smartphone. Most smartphones have built-in QR code scanners, so simply pointing the camera at a QR code will decode it and allow the user to visit a website, dial a phone number, read a message, etc.
```html preview
<div class="qr-overview">
<sl-qr-code value="https://shoelace.style/" label="Scan this code to visit Shoelace on the web!"></sl-qr-code>
Use the `fill` and `background` attributes to modify the QR code's colors. You should always ensure good contrast for optimal compatibility with QR code scanners.
QR codes can be rendered with various levels of [error correction](https://www.qrcode.com/en/about/error_correction.html) that can be set using the `error-correction` attribute. This example generates four codes with the same value using different error correction levels.
Radios allow the user to select one option from a group of many.
Radios are designed to be used with [radio groups](/components/radio-group). As such, all of the examples on this page utilize them to demonstrate their correct usage.
```html preview
<sl-radio-group label="Select an option" no-fieldset>
<sl-radio value="1" checked>Option 1</sl-radio>
<sl-radio value="2">Option 2</sl-radio>
<sl-radio value="3">Option 3</sl-radio>
</sl-radio-group>
```
?> This component doesn't work with standard forms. Use [`<sl-form>`](/components/form) instead.
## Examples
### Disabled
Use the `disabled` attribute to disable a radio.
```html preview
<sl-radio-group label="Select an option" no-fieldset>
Outputs a localized time phrase relative to the current date and time.
Localization is handled by the browser's [`Intl.RelativeTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat). No language packs are required.
The `date` attribute determines when the date/time is calculated from. It must be a string that [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) can interpret or a [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object set via JavaScript.
?> When using strings, avoid ambiguous dates such as `03/04/2020` which can be interpreted as March 4 or April 3 depending on the user's browser and locale. Instead, always use a valid [ISO 8601 date time string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#Date_Time_String_Format) to ensure the date will be parsed properly by all clients.
!> The `Intl.RelativeTimeFormat` API is available [in all major browsers](https://caniuse.com/mdn-javascript_builtins_intl_relativetimeformat), but it only became available to Safari in version 14. If you need to support Safari 13, you'll need to [use a polyfill](https://github.com/catamphetamine/relative-time-format).
## Examples
### Keeping Time in Sync
Use the `sync` attribute to update the displayed value automatically as time passes.
relativeTime.date = new Date(new Date().getTime() - 60000);
</script>
```
### Formatting Styles
You can change how the time is displayed using the `format` attribute. Note that some locales may display the same values for `narrow` and `short` formats.
The Resize Observer component offers a thin, declarative interface to the [`ResizeObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
The resize observer will report changes to the dimensions of the elements it wraps through the `sl-resize` event. When emitted, a collection of [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry) objects will be attached to `event.detail` that contains the target element and information about its dimensions.
You can slot in any [replaced element](https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element), including `<iframe>`, `<img>`, and `<video>`. As the element's width changes, its height will resize proportionally. Only one element should be slotted into the container. The default aspect ratio is `16:9`.
```html preview
<sl-responsive-media>
<img src="https://images.unsplash.com/photo-1541427468627-a89a96e5ca1d?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1800&q=80" alt="A train riding through autumn foliage with mountains in the distance.">
</sl-responsive-media>
```
## Examples
### Responsive Images
The following image maintains a `4:3` aspect ratio as its container is resized.
```html preview
<sl-responsive-media aspect-ratio="4:3">
<img src="https://images.unsplash.com/photo-1473186578172-c141e6798cf4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1800&q=80" alt="Two blue chairs on a sandy beach.">
</sl-responsive-media>
```
### Responsive Videos
The following video is embedded using an `iframe` and maintains a `16:9` aspect ratio as its container is resized.
To allow multiple options to be selected, use the `multiple` attribute. It's a good practice to use `clearable` when this option is enabled. When using this option, `value` will be an array instead of a string.
```html preview
<sl-select placeholder="Select a few" multiple clearable>
The `value` property is bound to the current selection. As the selection changes, so will the value. To programmatically manage the selection, update the `value` property.
Skeletons are used to show where content will eventually be drawn.
These are simple containers for scaffolding layouts that mimic what users will see when content has finished loading. This prevents large areas of empty space during asynchronous operations.
Skeletons try not to be opinionated, as there are endless possibilities for designing layouts. Therefore, you'll likely use more than one skeleton to create the effect you want. If you find yourself using them frequently, consider creating a template that renders them with the desired arrangement and styles.
There are two built-in effects, `sheen` and `pulse`. Effects are intentionally subtle, as they can be distracting when used extensively. The default is `none`, which displays a static, non-animated skeleton.
```html preview
<div class="skeleton-effects">
<sl-skeleton effect="none"></sl-skeleton>
None
<sl-skeleton effect="sheen"></sl-skeleton>
Sheen
<sl-skeleton effect="pulse"></sl-skeleton>
Pulse
</div>
<style>
.skeleton-effects {
font-size: var(--sl-font-size-small);
}
.skeleton-effects sl-skeleton:not(:first-child) {
margin-top: 1rem;
}
</style>
```
### Paragraphs
Use multiple skeletons and some clever styles to simulate paragraphs.
```html preview
<div class="skeleton-paragraphs">
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
</div>
<style>
.skeleton-paragraphs sl-skeleton {
margin-bottom: 1rem;
}
.skeleton-paragraphs sl-skeleton:nth-child(2) {
width: 95%;
}
.skeleton-paragraphs sl-skeleton:nth-child(4) {
width: 90%;
}
.skeleton-paragraphs sl-skeleton:last-child {
width: 50%;
}
</style>
```
### Avatars
Set a matching width and height to make a circle, square, or rounded avatar skeleton.
```html preview
<div class="skeleton-avatars">
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
</div>
<style>
.skeleton-avatars sl-skeleton {
display: inline-block;
width: 3rem;
height: 3rem;
margin-right: .5rem;
}
.skeleton-avatars sl-skeleton:nth-child(1) {
--border-radius: 0;
}
.skeleton-avatars sl-skeleton:nth-child(2) {
--border-radius: var(--sl-border-radius-medium);
}
</style>
```
### Custom Shapes
Use the `--border-radius` custom property to make circles, squares, and rectangles. For more complex shapes, you can apply `clip-path` to the `indicator` part. [Try Clippy](https://bennettfeely.com/clippy/) if you need help generating custom shapes.
Spinners are used to show the progress of an indeterminate operation.
```html preview
<sl-spinner></sl-spinner>
```
## Examples
### Size
Spinners are sized based on the current font size. To change their size, set the `font-size` property on the spinner itself or on a parent element as shown below.
Tab groups organize content into a container that shows one section at a time.
Tab groups make use of [tabs](/components/tab) and [tab panels](/components/tab-panel). Each tab must be slotted into the `nav` slot and its `panel` must refer to a tab panel of the same name.
<sl-tab-panel name="general">This is the general tab panel.</sl-tab-panel>
<sl-tab-panel name="custom">This is the custom tab panel.</sl-tab-panel>
<sl-tab-panel name="advanced">This is the advanced tab panel.</sl-tab-panel>
<sl-tab-panel name="disabled">This is a disabled tab panel.</sl-tab-panel>
</sl-tab-group>
```
### Closable Tabs
Add the `closable` attribute to a tab to show a close button. This example shows how you can dynamically remove tabs from the DOM when the close button is activated.
When focused, keyboard users can press <kbd>Left</kbd> or <kbd>Right</kbd> to select the desired tab. By default, the corresponding tab panel will be shown immediately (automatic activation). You can change this behavior by setting `activation="manual"` which will require the user to press <kbd>Space</kbd> or <kbd>Enter</kbd> before showing the tab panel (manual activation).
Tooltips display additional information based on a specific action.
A tooltip's target is its _first child element_, so you should only wrap one element inside of the tooltip. If you need the tooltip to show up for multiple elements, nest them inside a container first.
Tooltips use `display: contents` so they won't interfere with how elements are positioned in a flex or grid layout.
```html preview
<sl-tooltip content="This is a tooltip">
<sl-button>Hover Me</sl-button>
</sl-tooltip>
```
## Examples
### Placement
Use the `placement` attribute to set the preferred placement of the tooltip.
Set the `trigger` attribute to `click` to toggle the tooltip on click instead of hover.
```html preview
<sl-tooltip content="Click again to dismiss" trigger="click">
<sl-button>Click to Toggle</sl-button>
</sl-tooltip>
```
### Manual Trigger
Tooltips can be controller programmatically by setting the `trigger` attribute to `manual`. Use the `open` attribute to control when the tooltip is shown.
You can control the size of tooltip arrows by overriding the `--sl-tooltip-arrow-size` design token.
```html preview
<div style="--sl-tooltip-arrow-size: 0;">
<sl-tooltip content="This is a tooltip">
<sl-button>Above</sl-button>
</sl-tooltip>
<sl-tooltip content="This is a tooltip" placement="bottom">
<sl-button>Below</sl-button>
</sl-tooltip>
</div>
```
To override it globally, set it in a root block in your stylesheet after the Shoelace stylesheet is loaded.
```css
:root {
--sl-tooltip-arrow-size: 0;
}
```
### HTML in Tooltips
Use the `content` slot to create tooltips with HTML content. Tooltips are designed only for text and presentational elements. Avoid placing interactive content, such as buttons, links, and form controls, in a tooltip.
```html preview
<sl-tooltip>
<div slot="content">I'm not <strong>just</strong> a tooltip, I'm a <em>tooltip</em> with HTML!</div>
<sl-button>Hover me</sl-button>
</sl-tooltip>
```
### Hoisting
Tooltips will be clipped if they're inside a container that has `overflow: auto|hidden|scroll`. The `hoist` attribute forces the tooltip to use a fixed positioning strategy, allowing it to break out of the container. In this case, the tooltip will be positioned relative to its containing block, which is usually the viewport unless an ancestor uses a `transform`, `perspective`, or `filter`. [Refer to this page](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed) for more details.
Shoelace components can be customized at a high level through design tokens. This gives you control over theme colors and general styling. For more advanced customizations, you can make use of component parts and custom properties to target individual components.
## Design Tokens
Shoelace makes use of several design tokens to provide a consistent appearance across components. You can customize them and use them in your own application with pure CSS — no preprocessor required.
Design tokens offer a high-level way to customize the library with minimal effort. There are no component-specific variables, however, as design tokens are intended to be generic and highly reusable. To customize an individual component, refer to the section entitled [Component Parts](#component-parts).
Design tokens are accessed through CSS custom properties that are defined in your theme. Because design tokens live at the page level, they're prefixed with `--sl-` to avoid collisions with other libraries.
To customize a design token, simply override it in your stylesheet using a `:root` block. Here's an example that changes the primary theme to purple based on existing [color primitives](/tokens/color#primitives).
```css
:root{
/* Changes the primary theme color to purple using primitives */
Many design tokens are described further along in this documentation. For a complete list, refer to `src/themes/light.styles.ts` in the project's [source code](https://github.com/shoelace-style/shoelace/blob/current/src/themes/light.styles.ts).
## Component Parts
Whereas design tokens offer a high-level way to customize the library, component parts offer a low-level way to customize individual components. Again, this is done with pure CSS — no preprocessor required.
Shoelace components use a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) to encapsulate their styles and behaviors. As a result, you can't simply target their internals with the usual CSS selectors. Instead, components expose "parts" that can be targeted with the [CSS part selector](https://developer.mozilla.org/en-US/docs/Web/CSS/::part), or `::part()`.
Here's an example that modifies buttons with the `tomato-button` class.
```html preview
<sl-button class="tomato-button">
Tomato Button
</sl-button>
<style>
.tomato-button::part(base) {
background: rgb(var(--sl-color-neutral-0));
border: solid 1px tomato;
}
.tomato-button::part(base):hover {
background: rgba(255, 99, 71, .1);
}
.tomato-button::part(base):active {
background: rgba(255, 99, 71, .2);
}
.tomato-button::part(base):focus {
box-shadow: 0 0 0 3px rgba(255, 99, 71, .33);
}
.tomato-button::part(label) {
color: tomato;
}
</style>
```
At first glance, this approach might seem a bit verbose or even limiting, but it comes with a few important advantages:
- Customizations can be made to components with explicit selectors, such as `::part(icon)`, rather than implicit selectors, such as `.button > div > span + .icon`, that are much more fragile.
- The internal structure of a component will likely change as it evolves. By exposing component parts through an API, the internals can be reworked without fear of breaking customizations as long as its parts remain intact.
- It encourages us to think more about how components are designed and how customizations should be allowed before userscan take advantage of them. Once we opt a part into the component's API, it's guaranteed to be supported and can't be removed until a major version of the library is released.
Most (but not all) components expose parts. You can find them in each component's API documention under the "CSS Parts" section.
## Custom Properties
For convenience, some components expose CSS custom properties you can override. These are not design tokens, nor do they have the same `--sl-` prefix since they're scoped to a component.
You can set custom properties on a component in your stylesheet.
```css
sl-avatar {
--size: 6rem;
}
```
This will also work if you need to target a subset of components with a specific class.
```css
sl-avatar.your-class {
--size: 6rem;
}
```
Alternatively, you can set them inline directly on the element.
```html
<sl-avatar style="--size: 6rem;"></sl-avatar>
```
Not all components expose CSS custom properties. For those that do, they can be found in the component's API documentation.
## Animations
Some components use animation, such as when a dialog is shown or hidden. Animations are performed using the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API) rather than CSS. However, you can still customize them through Shoelace's animation registry. If a component has customizable animations, they'll be listed in the "Animation" section of its documentation.
To customize a default animation, use the `setDefaultAnimation()` method. The function accepts an animation name (found in the component's docs) and an object with `keyframes` and `options` or `null` to disable the animation.
This example will make all dialogs use a custom show animation.
```js
import { setDefaultAnimation } from '@shoelace-style/shoelace/dist/utilities/animation-registry.js';
If you only want to target a single component, use the `setAnimation()` method instead. This function accepts an element, an animation name, and an object comprised of animation `keyframes` and `options`.
In this example, only the target dialog will use a custom show animation.
```js
import { setAnimation } from '@shoelace-style/shoelace/dist/utilities/animation-registry.js';
To learn more about creating Web Animations, refer to the documentation for [`Element.animate()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate).
?> Animations respect the users `prefers-reduced-motion` setting. When this setting is enabled, animations will not be played. To disable animations for all users, pass in `null` instead of a keyframes/options object.
If you prefer to use the dark theme instead, use this. Note the `sl-theme-dark` class on the `<html>` element. [Learn more about the Dark Theme.](/getting-started/themes#dark-theme)
If you want to load the light or dark theme based on the user's `prefers-color-scheme` setting, use this. The `media` attributes ensure that only the user's preferred theme stylesheet loads and the `onload` attribute sets the appropriate [theme class](/getting-started/themes) on the `<html>` element.
Now you can [start using Shoelace!](/getting-started/usage)
## Local Installation
If you don't want to use the CDN, you can install Shoelace locally with the following command.
```bash
npm install @shoelace-style/shoelace
```
It's up to you to make the source files available to your app. One way to do this is to create a route in your app called `/shoelace` that serves static files from `node_modules/@shoelace-style/shoelace`.
Once you've done that, add the following tags to your page. Make sure to update `href` and `src` so they point to the route you created.
Alternatively, [you can use a bundler](#bundling).
?> For clarity, the docs will usually show imports from `@shoelace-style/shoelace`. If you're not using a module resolver or bundler, you'll need to adjust these paths to point to the folder Shoelace is in.
## Setting the Base Path
Some components rely on assets (icons, images, etc.) and Shoelace needs to know where they're located. For convenience, Shoelace will try to auto-detect the correct location based on the script you've loaded it from. This assumes assets are colocated with `shoelace.js` and will "just work" for most users.
However, if you're [cherry picking](#cherry-picking) or [bundling](#bundling) Shoelace, you'll need to set the base path. You can do this one of two ways.
?> The library also exports a `getBasePath()` method you can use to reference assets.
## Cherry Picking
The previous approach is the _easiest_ way to load Shoelace, but easy isn't always efficient. You'll incur the full size of the library even if you only use a handful of components. This is convenient for prototyping, but may result in longer load times in production. To improve this, you can cherry pick the components you need.
Cherry picking can be done from your local install or [directly from the CDN](https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/). This will limit the number of files the browser has to download and reduce the amount of bytes being transferred. The disadvantage is that you need to load component manually.
Here's an example that loads only the button component. Again, if you're not using a module resolver, you'll need to adjust the path to point to the folder Shoelace is in.
You can copy and paste the code to import a component from the "Importing" section of the component's documentation. Note that some components have dependencies that are automatically imported when you cherry pick. If a component has dependencies, they will be listed in the "Dependencies" section of its docs.
!> Never cherry pick components or utilities from `shoelace.js` as this will cause the browser to load the entire library. Instead, cherry pick from specific modules as shown above.
!> You will see files named `chunk.[hash].js` in the `chunks` directory. Never import these files directly, as they are generated and change from version to version.
## Bundling
Shoelace is distributed as a collection of standard ES modules that [all modern browsers can understand](https://caniuse.com/es6-module). However, importing a lot of modules can result in a lot of HTTP requests and potentially longer load times. Using a CDN can alleviate this, but some users may wish to further optimize their imports with a bundler.
To use Shoelace with a bundler, first install Shoelace along with your bundler of choice.
```bash
npm install @shoelace-style/shoelace
```
Now it's time to configure your bundler. Configurations vary for each tool, but here are some examples to help you get started.
// Set the base path to the folder you copied Shoelace's assets to
setBasePath('/dist/shoelace');
// <sl-button>, <sl-icon>, <sl-input>, and <sl-rating> are ready to use!
```
!> Component modules include side effects for registration purposes. Because of this, importing directly from `@shoelace-style/shoelace` may result in a larger bundle size than necessary. For optimal tree shaking, always cherry pick, i.e. import components and utilities from their respective files, as shown above.
Designed in New Hampshire by [Cory LaViska](https://twitter.com/claviska).
</div>
<div class="splash-end">
<img class="splash-image" src="/assets/images/undraw-content-team.svg" alt="Cartoon of people assembling components while standing on a giant laptop.">
Now you have access to all of Shoelace's components! Try adding a button:
```html
<sl-button>Click me</sl-button>
```
See the [installation instructions](getting-started/installation) for more details and other ways to install Shoelace.
## New to Web Components?
**TL;DR**–we finally have a way to create [our own HTML elements](https://html.spec.whatwg.org/multipage/custom-elements.html) and use them in any framework we want!
Thanks to the popularity of frameworks such as Angular, Vue, and React, component-driven development has become a part of our every day lives. Components help us encapsulate styles and behaviors into reusable building blocks. They make a lot of sense in terms of design, development, and testing.
Unfortunately, _framework-specific_ components fail us in a number of ways:
- You can only use them in the framework they're designed for 🔒
- Their lifespan is limited to that of the framework's ⏳
- New frameworks/versions can lead to breaking changes, requiring substantial effort to update components 😭
Web components solve these problems. They're [supported by all modern browsers](https://caniuse.com/#feat=custom-elementsv1), they're framework-agnostic, and they're [part of the standard](https://developer.mozilla.org/en-US/docs/Web/Web_Components), so we know they'll be supported for many years to come.
This is the technology that Shoelace is built on.
## What Problem Does This Solve?
Shoelace provides a collection of professionally designed, every day UI components built on a framework-agnostic technology. Why spend hundreds of hours (or more) building a design system from scratch? Why make a component library that only works with one framework?
With Shoelace, you can:
- Start building things faster (no need to roll your own buttons)
- Build multiple apps with different frameworks that all share the same UI
- Skip having to learn a new component library every time you switch frameworks
If your organization is looking to build a design system, [Shoelace will save you thousands of dollars](https://medium.com/eightshapes-llc/and-you-thought-buttons-were-easy-26eb5b5c1871).* All the foundational components you need are right here, ready to be customized for your brand. And since it's built on web standards, browsers will continue to support it for many years to come.
Whether you use Shoelace as a starting point for your organization's design system or for a fun personal project, there's no limit to what you can do with it.
<small>*Please consider giving back some of what you save by [supporting this project with a sponsorship](https://github.com/sponsors/claviska).</small>
## Browser Support
Shoelace is tested in the latest two versions of the following browsers.
Critical bug fixes in earlier versions will be addressed based on their severity and impact.
If you need to support IE11 or pre-Chromium Edge, this library isn't for you. Although web components can (to some degree) be polyfilled for legacy browsers, supporting them is outside the scope of this project. If you're using Shoelace in such a browser, you're gonna have a bad time. ⛷
## License
Shoelace is designed in New Hampshire by [Cory LaViska](https://twitter.com/claviska). It's available under the terms of the MIT license.
Designing, developing, and supporting this library requires a lot of time, effort, and skill. If you're using this software to make a profit, I respectfully ask that you help [fund its development](https://github.com/sponsors/claviska) by becoming a sponsor.
Shoelace is designed to be highly customizable through pure CSS. Out of the box, you can choose from a light or dark theme. Alternatively, you can design your own theme from scratch.
A theme is nothing more than a stylesheet that uses the Shoelace API to define design tokens and apply custom styles to components. To create a theme, you will need a decent understanding of CSS, including [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) and the [`::part` selector](https://developer.mozilla.org/en-US/docs/Web/CSS/::part).
For developers, built-in themes are also available as JavaScript modules that export [Lit CSSResult](https://lit.dev/docs/api/styles/#CSSResult) objects. You can find them in `dist/themes/*.styles.js`.
## Theme Basics
All themes are scoped to classes using the `sl-theme-{name}` convention, where `{name}` is a lowercase, hyphen-delimited value representing the name of the theme. The included light and dark themes use `sl-theme-light` and `sl-theme-dark`, respectively. A custom theme called "Purple Power", for example, would use the `sl-theme-purple-power` class.
Every selector must be scoped to the theme's class to ensure interoperability with other themes. You should also scope them to `:host` so they can be imported and applied to custom element shadow roots.
```css
:host,
.sl-theme-purple-power{
/* ... */
}
```
### Activating Themes
To activate a theme, import it and apply the theme's class to the `<html>` element. This example imports and activates the dark theme, or "dark mode."
?> There is one exception to this rule — the light theme _does not_ need to be activated. For convenience, the light theme is scoped to `:root` and will be activated by default when imported.
### Using Multiple Themes
You can activate themes on various containers throughout the page. This example uses the light theme with a dark-themed sidebar.
There are two ways to create themes. The easiest way is to customize a built-in theme. The advanced way is to create a new theme from scratch. Which method you choose depends on your project's requirements and the amount of effort you're willing to commit to.
### Customizing a Built-in Theme
The easiest way to customize Shoelace is to override one of the built-in themes. You can do this by importing the light or dark theme as-is, then creating a separate stylesheet that overrides the [design tokens](/getting-started/customizing#design-tokens) and adds [component styles](/getting-started/customizing#component-parts) to your liking. You must import your theme _after_ the built-in theme.
If you're customizing the light theme, you should scope your styles to the following selectors.
```css
:root,
:host,
.sl-theme-light{
/* your custom styles here */
}
```
If you're customizing the dark theme, you should scope your styles to the following selectors.
```css
:host,
.sl-theme-dark{
/* your custom styles here */
}
```
By customizing a built-in theme, you'll maintain a smaller stylesheet containing only the changes you've made. Contrast this to [creating a new theme](#creating-a-new-theme), where you need to explicitly define every design token required by the library. This approach is more "future-proof," as new design tokens that emerge in subsequent versions of Shoelace will be accounted for by the built-in theme.
While this may be easier to maintain, the drawback is that your theme modifies a built-in theme and thus can't be activated independently.
### Creating a New Theme
Creating a new theme is more of an undertaking than [customizing an existing one](#customizing-a-built-in-theme). At a minimum, you must implement all of the required design tokens. The easiest way to do this is by "forking" one of the built-in themes and modifying it from there.
Start by changing the selector to match your theme's name. Assuming your new theme is called "Purple Power", your theme should be scoped like this.
```css
:host,
.sl-theme-purple-power{
/* your custom styles here */
}
```
By creating a new theme, you won't be relying on a built-in theme as a foundation. Because the theme is decoupled from the built-ins, you can activate it independently as an alternative to the built-ins. This is the recommended approach if you're looking to open source your theme for others to use.
You will, however, need to maintain your theme more carefully, as new versions of Shoelace may introduce new design tokens that your theme won't have accounted for. Because of this, it's recommended that you clearly specify which version(s) of Shoelace your theme is designed to work with and keep it up to date as new versions of Shoelace are released.
## Dark Theme
The built-in dark theme uses an inverted + shifted color scale so, if you're using design tokens as intended, you'll get a decent dark mode for free. While this isn't the same as a professionally curated dark theme, it provides an excellent baseline for one and you're encouraged to customize it depending on your needs.
This was achieved by taking the light theme's [color tokens](/tokens/color) and "flipping" the scale so 100 becomes 900, 200 becomes 800, 300 becomes 700, etc. Next, the luminance of each primitive was increased slightly to avoid true black, a color that is typically undesirable in dark themes. The result is a custom palette that complements the light theme well and makes it easy to offer light and dark variations with minimal effort.
To install the dark theme, add the following to the `<head>` section of your page.
To activate the theme, apply the `sl-theme-dark` class to the `<html>` element.
```html
<htmlclass="sl-theme-dark">
...
</html>
```
### Detecting the User's Color Scheme Preference
Shoelace doesn't try to auto-detect the user's light/dark mode preference. This should be done at the application level. As a best practice, to provide a dark theme in your app, you should:
- Check for [`prefers-color-scheme`](https://stackoverflow.com/a/57795495/567486) and use its value by default
- Allow the user to override the setting in your app
- Remember the user's preference and restore it on subsequent logins
Shoelace avoids using the `prefers-color-scheme` media query because not all apps support dark mode, and it would break things for the ones that don't.
Shoelace components are just regular HTML elements, or "custom elements" to be precise. You can use them like any other element. Each component has detailed documentation that describes its full API, including properties, events, methods, and more.
## Web Component Basics
### Properties
Many components have properties that can be set using attributes. For example, buttons accept a `size` attribute that maps to the `size` property which dictates the button's size.
```html
<sl-buttonsize="small">Click me</sl-button>
```
Some properties are boolean, so they only have true/false values. To activate a boolean property, add the corresponding attribute without a value.
```html
<sl-buttondisabled>Click me</sl-button>
```
In rare cases, a property may require an array, an object, or a function. For example, to customize the color picker's list of preset swatches, you set the `swatches` property to an array of colors. This can be done with JavaScript.
Refer to a component's documentation for a complete list of its properties.
### Events
You can listen for standard events such as `click`, `mouseover`, etc. as you normally would. In addition, some components emit custom events. These work the same way as standard events, but are prefixed with `sl-` to prevent collisions with standard events and other libraries.
Refer to a component's documentation for a complete list of its custom events.
### Methods
Some components have methods you can call to trigger various behaviors. For example, you can set focus on a Shoelace input using the `focus()` method.
```html
<sl-input></sl-input>
<script>
constinput=document.querySelector('sl-input');
input.focus();
</script>
```
Refer to a component's documentation for a complete list of its methods and their arguments.
### Slots
Many components use slots to accept content inside of them. The most common slot is the _default_ slot, which includes any content inside the component that doesn't have a `slot` attribute.
For example, a button's default slot is used to populate its label.
```html
<sl-button>Click me</sl-button>
```
Some components also have _named_ slots. A named slot can be populated by adding a child element with the appropriate `slot` attribute. Notice how the icon below has the `slot="prefix"` attribute? This tells the component to place the icon into its `prefix` slot.
```html
<sl-button>
<sl-iconslot="prefix"name="gear"></sl-icon>
Settings
</sl-button>
```
The location of a named slot doesn't matter. You can put it anywhere inside the component and the browser will move it to the right place automatically!
Refer to a component's documentation for a complete list of available slots.
### Don't Use Self-closing Tags
Custom elements cannot have self-closing tags. Similar to `<script>` and `<textarea>`, you must always include the full closing tag.
```html
<!-- Don't do this -->
<sl-input/>
<!-- Always do this -->
<sl-input></sl-input>
```
### Differences from Native Elements
You might expect similarly named elements to share the same API as native HTML elements. This is not always the case. Shoelace components **are not** designed to be one-to-one replacements for their HTML counterparts.
For example, `<button>` and `<sl-button>` both have a `type` attribute, but it does different things. The former controls whether the button submits a form and the latter controls the button's appearance.
?> **Don't make assumptions about a component's API!** To prevent unexpected behaviors, please take the time to review the documentation and make sure you understand what each attribute, property, method, and event is intended to do.
## Code Completion
### VS Code
Shoelace ships with a file called `vscode.html-custom-data.json` that can be used to describe its components to Visual Studio Code. This enables code completion for Shoelace components (also known as "code hinting" or "IntelliSense"). To enable it, you need to tell VS Code where the file is.
If `settings.json` already exists, simply add the above line to the root of the object. Note that you may need to restart VS Code for the changes to take affect.
### Other Editors
Most popular editors support custom code completion with a bit of configuration. Please [submit a feature request](https://github.com/shoelace-style/shoelace/issues/new/choose) for your editor of choice. PRs are also welcome!
## React
React [doesn't play nice](https://custom-elements-everywhere.com/#react) with custom elements —it's a bit finicky about props.
> React passes all data to Custom Elements in the form of HTML attributes. For primitive data this is fine, but the system breaks down when passing rich data, like objects or arrays. In these instances you end up with stringified values like `some-attr="[object Object]"` which can't actually be used.
Event handling can also be cumbersome.
> Because React implements its own synthetic event system, it cannot listen for DOM events coming from Custom Elements without the use of a workaround. Developers will need to reference their Custom Elements using a ref and manually attach event listeners with addEventListener. This makes working with Custom Elements cumbersome.
Fortunately, there's a package called [@shoelace-style/react](https://www.npmjs.com/package/@shoelace-style/react) that will let you use Shoelace components as if they were React components. You can install it using this command.
```bash
npm install @shoelace-style/react
```
Include the default theme and any components you want to use in your app.
Vue [plays nice](https://custom-elements-everywhere.com/#vue) with custom elements. You just have to tell it to ignore Shoelace components. This is pretty easy because they all start with `sl-`.
When binding complex data such as objects and arrays, use the `.prop` modifier to make Vue bind them as a property instead of an attribute.
```html
<sl-color-picker:swatches.prop="mySwatches"/>
```
### Two-way Binding
One caveat is there's currently [no support for v-model on custom elements](https://github.com/vuejs/vue/issues/7830), but you can still achieve two-way binding manually.
If that's too verbose, you can use a custom directive instead.
### Using a Custom Directive
You can use [this utility](https://www.npmjs.com/package/@shoelace-style/vue-sl-model) to add a custom directive that will work just like `v-model` but for Shoelace components. To install it, use this command.
```bash
npm install @shoelace-style/vue-sl-model
```
Next, import the directive and enable it like this.
Now you can use the `v-sl-model` directive to keep your data in sync!
```html
<sl-inputv-sl-model="name">
```
## Angular
Angular [plays nice](https://custom-elements-everywhere.com/#angular) with custom elements. Just make sure to apply the custom elements schema as shown below.
Shoelace follows [Semantic Versioning](https://semver.org/). Breaking changes in components with the <sl-badge type="primary" pill>Stable</sl-badge> badge will not be accepted until the next major version. As such, all contributions must consider the project's roadmap and take this into consideration. Features that are deemed no longer necessary will be deprecated but not removed.
Components with the <sl-badge type="warning" pill>Experimental</sl-badge> badge should not be used in production. They are made available as release candidates for development and testing purposes. As such, changes to experimental components will not be subject to semantic versioning.
_During the beta period, these restrictions may be relaxed in the event of a mission-critical bug._ 🐛
- Added eye dropper to `<sl-color-picker>` when the browser supports the [EyeDropper API](https://wicg.github.io/eyedropper-api/)
- Fixed a bug in `<sl-button-group>` where buttons groups with only one button would have an incorrect border radius
- Improved the `<sl-color-picker>` trigger's border in dark mode
- Refactored positioning logic in `<sl-dropdown>` so Popper is only active when the menu is open
- Updated to Lit 2.0.2
## 2.0.0-beta.58
This version once again restores the bundled distribution because the unbundled + CDN approach is currently confusing and [not working properly](https://github.com/shoelace-style/shoelace/issues/559#issuecomment-949662331). Unbundling the few dependencies Shoelace has is still a goal of the project, but [this jsDelivr bug](https://github.com/jsdelivr/jsdelivr/issues/18337) needs to be resolved before we can achieve it.
I sincerely apologize for the instability of the last few beta releases as a result of this effort.
- Added `label` attribute to `<sl-progress-bar>` and `<sl-progress-ring>` to improve a11y
- Fixed a bug where the tooltip would show briefly when clicking a disabled `<sl-range>`
- Fixed a bug that caused a console error when `<sl-range>` was used
- Fixed a bug where the `nav` part in `<sl-tab-group>` was on the incorrect element [#563](https://github.com/shoelace-style/shoelace/pull/563)
- Fixed a bug where non-integer aspect ratios were calculated incorrectly in `<sl-responsive-media>`
- Fixed a bug in `<sl-range>` where setting `value` wouldn't update the active and inactive portion of the track [#572](https://github.com/shoelace-style/shoelace/pull/572)
- Reverted to publishing the bundled dist and removed `/+esm` links from the docs
- Updated to Bootstrap Icons to 1.6.1
## 2.0.0-beta.57
- Fix CodePen links and CDN links
## 2.0.0-beta.56
This release is the second attempt at unbundling dependencies. This will be a breaking change only if your configuration _does not_ support bare module specifiers. CDN users and bundler users will be unaffected, but note the URLs for modules on the CDN must have the `/+esm` now.
- Added the `hoist` attribute to `<sl-tooltip>` [#564](https://github.com/shoelace-style/shoelace/issues/564)
- Unbundled dependencies and configured external imports to be packaged with bare module specifiers
## 2.0.0-beta.55
- Revert unbundling due to issues with the CDN not handling bare module specifiers as expected
## 2.0.0-beta.54
Shoelace doesn't have a lot of dependencies, but this release unbundles most of them so you can potentially save some extra kilobytes. This will be a breaking change only if your configuration _does not_ support bare module specifiers. CDN users and bundler users will be unaffected.
- 🚨 BREAKING: renamed the `sl-clear` event to `sl-remove`, the `clear-button` part to `remove-button`, and the `clearable` property to `removable` in `<sl-tag>`
- Added the `disabled` prop to `<sl-resize-observer>`
- Fixed a bug in `<sl-mutation-observer>` where setting `disabled` initially didn't work
- Unbundled dependencies and configured external imports to be packaged with bare module specifiers
- 🚨 BREAKING: removed `percentage` attribute from `<sl-progress-bar>` and `<sl-progress-ring>` (use `value`) instead
- 🚨 BREAKING: switched the default `type` of `<sl-tag>` from `primary` to `neutral`
- Added the experimental `<sl-mutation-observer>` component
- Added the `<sl-divider>` component
- Added `--sl-surface-base` and `--sl-surface-base-alt` as early surface tokens to improve the appearance of alert, card, and panels in dark mode
- Added the `--sl-panel-border-width` design token
- Added missing background color to `<sl-details>`
- Added the `--padding` custom property to `<sl-tab-panel>`
- Added the `outline` variation to `<sl-button>` [#522](https://github.com/shoelace-style/shoelace/issues/522)
- Added the `filled` variation to `<sl-input>`, `<sl-textarea>`, and `<sl-select>` and supporting design tokens
- Added the `control` part to `<sl-select>` so you can target the main control with CSS [#538](https://github.com/shoelace-style/shoelace/issues/538)
- Added a border to `<sl-badge>` to improve contrast when drawn on various background colors
- Added `--track-color-active` and `--track-color-inactive` custom properties to `<sl-range>` [#550](https://github.com/shoelace-style/shoelace/issues/550)
- Added the undocumented custom properties `--thumb-size`, `--tooltip-offset`, `--track-height` on `<sl-range>`
- Changed the default `distance` in `<sl-dropdown>` from `2` to `0` [#538](https://github.com/shoelace-style/shoelace/issues/538)
- Fixed a bug where `<sl-select>` would be larger than the viewport when it had lots of options [#544](https://github.com/shoelace-style/shoelace/issues/544)
- Fixed a bug where `<sl-progress-ring>` wouldn't animate in Safari
- Updated the default height of `<sl-progress-bar>` from `16px` to `1rem` and added a subtle shadow to indicate depth
- Removed the `lit-html` dependency and moved corresponding imports to `lit` [#546](https://github.com/shoelace-style/shoelace/issues/546)
## 2.0.0-beta.52
- 🚨 BREAKING: changed the `--stroke-width` custom property of `<sl-spinner>` to `--track-width` for consistency
- 🚨 BREAKING: removed the `size` and `stroke-width` attributes from `<sl-progress-ring>` so it's fully customizable with CSS (use the `--size` and `--track-width` custom properties instead)
- Added the `--speed` custom property to `<sl-spinner>`
- Added the `--size` and `--track-width` custom properties to `<sl-progress-ring>`
- Added tests for `<sl-badge>` [#530](https://github.com/shoelace-style/shoelace/pull/530)
- Fixed a bug where `<sl-tab>` wasn't using a border radius token [#523](https://github.com/shoelace-style/shoelace/issues/523)
- Fixed a bug in the Remix Icons example where some icons would 404 [#528](https://github.com/shoelace-style/shoelace/issues/528)
- Updated `<sl-progress-ring>` to use only CSS for styling
- Updated `<sl-spinner>` to use an SVG and improved the indicator animation
- Updated to Lit 2.0 and lit-html 2.0 🔥
## 2.0.0-beta.51
A number of users had trouble counting characters that repeat, so this release improves design token patterns so that "t-shirt sizes" are more accessible. For example, `--sl-font-size-xxx-large` has become `--sl-font-size-3x-large`. This change applies to all design tokens that use this scale.
- 🚨 BREAKING: all t-shirt size design tokens now use `2x`, `3x`, `4x` instead of `xx`, `xxx`, `xxxx`
- Added missing `--sl-focus-ring-*` tokens to dark theme
- Added an "Importing" section to all components with copy/paste code to make cherry picking easier
- Improved the documentation search with a custom plugin powered by [Lunr](https://lunrjs.com/)
- Improved the `--sl-shadow-x-small` elevation
- Improved visibility of elevations and overlays in dark theme
- Reduced the size of `<sl-color-picker>` slightly to better accommodate mobile devices
- Removed `<sl-icon>` dependency from `<sl-color-picker>` and improved the copy animation
## 2.0.0-beta.50
- Added `<sl-breadcrumb>` and `<sl-breadcrumb-item>` components
- Added `--sl-letter-spacing-denser`, `--sl-letter-spacing-looser`, `--sl-line-height-denser`, and `--sl-line-height-looser` design tokens
- Fixed a bug where form controls would error out when the value was set to `undefined` [#513](https://github.com/shoelace-style/shoelace/pull/513)
## 2.0.0-beta.49
This release changes the way focus states are applied to elements. In browsers that support [`:focus-visible`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible), it will be used. In unsupportive browsers ([currently only Safari](https://caniuse.com/mdn-css_selectors_focus-visible)), `:focus` will be used instead. This means the browser will determine whether a focus ring should be shown based on how the user interacts with the page.
This release also fixes a critical bug in the color scale where `--sl-color-neutral-0` and `--sl-color-neutral-1000` were reversed.
- 🚨 BREAKING: fixed a bug where `--sl-color-neutral-0` and `--sl-color-neutral-1000` were inverted (swap them to update)
- 🚨 BREAKING: removed the `no-fieldset` property from `<sl-radio-group>` (fieldsets are now hidden by default; use `fieldset` to show them)
- 🚨 BREAKING: removed `--focus-ring` custom property from `<sl-input>`, `<sl-select>`, `<sl-tab>` for consistency with other form controls
- Added `--swatch-size` custom property to `<sl-color-picker>`
- Added `date` to `<sl-input>` as a supported `type`
- Added the `--sl-focus-ring` design token for a more convenient way to apply focus ring styles
- Adjusted elevation tokens to use neutral in light mode and black in dark mode
- Adjusted `--sl-overlay-background-color` in dark theme to be black instead of gray
- Fixed a bug in `<sl-color-picker>` where the opacity slider wasn't showing the current color
- Fixed a bug where Edge in Windows would show the native password toggle next to the custom password toggle [#508](https://github.com/shoelace-style/shoelace/issues/508)
- Fixed a bug where pressing up/down in `<sl-tab-group>` didn't select the next/previous tab in vertical placements
- Improved size of `<sl-color-picker>`
- Improved icon contrast in `<sl-input>`
- Improved contrast of `<sl-switch>`
- Improved `:focus-visible` behavior in many components
- Removed elevation from `<sl-color-picker>` when rendered inline
- Removed custom `:focus-visible` logic in favor of a directive that outputs `:focus-visible` or `:focus` depending on browser support
- Updated to Lit 2.0.0-rc.3
- Updated to lit-html 2.0.0-rc.4
## 2.0.0-beta.48
This release improves theming by offering both light and dark themes that can be used autonomously. It also improves contrast in most components, adds a variety of new color primitives, and changes the way color tokens are consumed.
Previously, color tokens were in hexidecimal format. Now, Shoelace now uses an `R G B` format that requires you to use the `rgb()` function in your CSS.
```css
.example{
/* rgb() is required now */
color:rgb(var(--sl-color-neutral-500));
}
```
This is more verbose than previous versions, but it has the advantage of letting you set the alpha channel of any color token.
```css
.example-with-alpha{
/* easily adjust opacity for any color token */
color:rgb(var(--sl-color-neutral-500)/50%);
}
```
This change applies to all design tokens that implement a color. Refer to the [color tokens](/tokens/color) page for more details.
- 🚨 BREAKING: all design tokens that implement colors have been converted to `R G B` and must be used with the `rgb()` function
- 🚨 BREAKING: removed `--sl-color-black|white` color tokens (use `--sl-color-neutral-0|1000` instead)
- 🚨 BREAKING: renamed `dist/themes/base.css` to `dist/themes/light.css`
- 🚨 BREAKING: removed `--sl-focus-ring-color-primary` tokens (use color tokens and `--sl-focus-ring-width|alpha` instead)
- 🚨 BREAKING: removed `--tabs-border-color` from `<sl-tab-group>` (use `--track-color` instead)
- 🚨 BREAKING: changed the default value for `effect` to `none` in `<sl-skeleton>` (use `sheen` to restore the original behavior)
- Added new color primitives to the base set of design tokens
- Added `--sl-color-*-950` swatches to all color palettes
- Added a console error that appears when menu items have duplicate values in `<sl-select>`
- Added CodePen link to code examples
- Added `prefix` and `suffix` slots to `<sl-select>` [#501](https://github.com/shoelace-style/shoelace/pull/501)
- Added `--indicator-color` custom property to `<sl-tab-group>`
- Exposed base and dark stylesheets so they can be imported via JavaScript [#438](https://github.com/shoelace-style/shoelace/issues/438)
- Fixed a bug in `<sl-menu>` where pressing <kbd>Enter</kbd> after using type to select would result in the wrong value
- Fixed a bug in `<sl-radio-group>` where clicking a radio button would cause the wrong control to be focused
- Fixed a bug in `<sl-button>` and `<sl-icon-button>` where an unintended `ref` attribute was present
- Fixed a bug in the focus-visible utility that failed to respond to mouseup events
- Fixed a bug where clicking on a menu item would persist its hover/focus state
- Fixed a bug in `<sl-select>` where it would erroneously intercept important keyboard shortcuts [#504](https://github.com/shoelace-style/shoelace/issues/504)
- Improved contrast throughout all components [#128](https://github.com/shoelace-style/shoelace/issues/128)
- Refactored thumb position logic in `<sl-switch>` [#490](https://github.com/shoelace-style/shoelace/pull/490)
- Reworked the dark theme to use an inverted + shifted design token approach instead of component-specific selectors
## 2.0.0-beta.47
This release improves how component dependencies are imported. If you've been cherry picking, you no longer need to import component dependencies manually. This significantly improves developer experience, making Shoelace even easier to use. For transparency, component dependencies will continue to be listed in the docs.
- Added "Reflects" column to the properties table
- Dependencies are now automatically imported for all components
- Fixed a bug where tabbing into `<sl-radio-group>` would not always focus the checked radio
- Fixed a bug in component styles that prevented the box sizing reset from being applied
- Fixed a regression in `<sl-color-picker>` where dragging the grid handle wasn't smooth
- Fixed a bug where slot detection could incorrecly match against slots of child elements [#481](https://github.com/shoelace-style/shoelace/pull/481)
- Fixed a bug in `<sl-input>` where focus would move to the end of the input when typing in Safari [#480](https://github.com/shoelace-style/shoelace/issues/480)
- Improved base path utility logic
## 2.0.0-beta.46
This release improves the developer experience of `<sl-animation>`. Previously, an animation was assumed to be playing unless the `pause` attribute was set. This behavior has been reversed and `pause` has been removed. Now, animations will not play until the new `play` attribute is applied.
This is a lot more intuitive and makes it easier to activate animations imperatively. In addition, the `play` attribute is automatically removed automatically when the animation finishes or cancels, making it easier to restart finite animations. Lastly, the animation's timing is now accessible through the new `currentTime` property instead of `getCurrentTime()` and `setCurrentTime()`.
In addition, Shoelace no longer uses Sass. Component styles now use Lit's template literal styles and theme files use pure CSS.
- 🚨 BREAKING: removed the `pause` attribute from `<sl-animation>` (use `play` to start and stop the animation instead)
- 🚨 BREAKING: removed `getCurrentTime()` and `setCurrentTime()` from `<sl-animation>` (use the `currentTime` property instead)
- 🚨 BREAKING: removed the `close-on-select` attribute from `<sl-dropdown>` (use `stay-open-on-select` instead)
- Added the `currentTime` property to `<sl-animation>` to control the current time without methods
- Fixed a bug in `<sl-range>` where the tooltip wasn't showing in Safari [#477](https://github.com/shoelace-style/shoelace/issues/477)
- Fixed a bug in `<sl-menu>` where pressing <kbd>Enter</kbd> in a menu didn't work with click handlers
- Reworked `<sl-menu>` and `<sl-menu-item>` to use a roving tab index and improve keyboard accessibility
- Reworked tabbable logic to be more performant [#466](https://github.com/shoelace-style/shoelace/issues/466)
- Switched component stylesheets from Sass to Lit's template literal styles
- Switched theme stylesheets from Sass to CSS
## 2.0.0-beta.45
This release changes the way component metadata is generated. Previously, the project used TypeDoc to analyze components and generate a very large file with type data. The data was then parsed and converted to an easier-to-consume file called `metadata.json`. Alas, TypeDoc is expensive to run and the metadata format wasn't standard.
Thanks to an amazing effort by [Pascal Schilp](https://twitter.com/passle_), the world has a simpler, faster way to gather metadata using the [Custom Elements Manifest Analyzer](https://github.com/open-wc/custom-elements-manifest). Not only is this tool faster, but the data follows the evolving `custom-elements.json` format. This is exciting because a standard format for custom elements opens the door for many potential uses, including documentation generation, framework adapters, IDE integrations, third-party uses, and more. [Check out Pascal's great article](https://dev.to/open-wc/introducing-custom-elements-manifest-gkk) for more info about `custom-elements.json` and the new analyzer.
The docs have been updated to use the new `custom-elements.json` file. If you're relying on the old `metadata.json` file for any purpose, this will be a breaking change for you.
- 🚨 BREAKING: removed the `sl-overlay-click` event from `<sl-dialog>` and `<sl-drawer>` (use `sl-request-close` instead) [#471](https://github.com/shoelace-style/shoelace/discussions/471)
- Added `custom-elements.json` for component metadata
- Added `sl-request-close` event to `<sl-dialog>` and `<sl-drawer>`
- Added `dialog.denyClose` and `drawer.denyClose` animations
- Fixed a bug in `<sl-color-picker>` where setting `value` immediately wouldn't trigger an update
- Fixed a bug in `<sl-dialog>` and `<sl-drawer>` where setting `open` intially didn't set a focus trap
- Fixed a bug that resulted in form controls having incorrect validity when `disabled` was initially set [#473](https://github.com/shoelace-style/shoelace/issues/473)
- Fixed a bug in the docs that caused the metadata file to be requested twice
- Fixed a bug where tabbing out of a modal would cause the browser to lag [#466](https://github.com/shoelace-style/shoelace/issues/466)
- Updated the docs to use the new `custom-elements.json` for component metadata
## 2.0.0-beta.44
- 🚨 BREAKING: all `invalid` props on form controls now reflect validity before interaction [#455](https://github.com/shoelace-style/shoelace/issues/455)
- Allow `null` to be passed to disable animations in `setDefaultAnimation()` and `setAnimation()`
- Converted build scripts to ESM
- Fixed a bug in `<sl-checkbox>` where `invalid` did not update properly
- Fixed a bug in `<sl-dropdown>` where a `keydown` listener wasn't cleaned up properly
- Fixed a bug in `<sl-select>` where `sl-blur` was emitted prematurely [#456](https://github.com/shoelace-style/shoelace/issues/456)
- Fixed a bug in `<sl-select>` where no selection with `multiple` resulted in an incorrect value [#457](https://github.com/shoelace-style/shoelace/issues/457)
- Fixed a bug in `<sl-select>` where `sl-change` was emitted immediately after connecting to the DOM [#458](https://github.com/shoelace-style/shoelace/issues/458)
- Fixed a bug in `<sl-select>` where non-printable keys would cause the menu to open
- Fixed a bug in `<sl-select>` where `invalid` was not always updated properly
- Reworked the `@watch` decorator to use `update` instead of `updated` resulting in better performance and flexibility
## 2.0.0-beta.43
- Added `?` to optional arguments in methods tables in the docs
- Added the `scrollPosition()` method to `<sl-textarea>` to get/set scroll position
- Added intial tests for `<sl-dialog>`, `<sl-drawer>`, `<sl-dropdown>`, and `<sl-tooltip>`
- Fixed a bug in `<sl-tab-group>` where scrollable tab icons were not displaying correctly
- Fixed a bug in `<sl-dialog>` and `<sl-drawer>` where preventing clicks on the overlay no longer worked as described [#452](https://github.com/shoelace-style/shoelace/issues/452)
- Fixed a bug in `<sl-dialog>` and `<sl-drawer>` where setting initial focus no longer worked as described [#453](https://github.com/shoelace-style/shoelace/issues/453)
- Fixed a bug in `<sl-card>` where the `slotchange` listener wasn't attached correctly [#454](https://github.com/shoelace-style/shoelace/issues/454)
- Fixed lifecycle bugs in a number of components [#451](https://github.com/shoelace-style/shoelace/issues/451)
- Removed `fill: both` from internal animate utility so styles won't "stick" by default [#450](https://github.com/shoelace-style/shoelace/issues/450)
## 2.0.0-beta.42
This release addresses an issue with the `open` attribute no longer working in a number of components, as a result of the changes in beta.41. It also removes a small but controversial feature that complicated show/hide logic and led to a poor experience for developers and end users.
There are two ways to show/hide affected components: by calling `show() | hide()` and by toggling the `open` prop. Previously, it was possible to call `event.preventDefault()` in an `sl-show | sl-hide ` handler to stop the component from showing/hiding. The problem becomes obvious when you set `el.open = false`, the event gets canceled, and in the next cycle `el.open` has reverted to `true`. Not only is this unexpected, but it also doesn't play nicely with frameworks. Additionally, this made it impossible to await `show() | hide()` since there was a chance they'd never resolve.
Technical reasons aside, canceling these events seldom led to a good user experience, so the decision was made to no longer allow `sl-show | sl-hide` to be cancelable.
- 🚨 BREAKING: `sl-show` and `sl-hide` events are no longer cancelable
- Added Iconoir example to the icon docs
- Added Web Test Runner
- Added intial tests for `<sl-alert>` and `<sl-details>`
- Changed the `cancelable` default to `false` for the internal `@event` decorator
- Fixed a bug where toggling `open` stopped working in `<sl-alert>`, `<sl-dialog>`, `<sl-drawer>`, `<sl-dropdown>`, and `<sl-tooltip>`
- Fixed a bug in `<sl-range>` where setting a value outside the default `min` or `max` would clamp the value [#448](https://github.com/shoelace-style/shoelace/issues/448)
- Fixed a bug in `<sl-dropdown>` where placement wouldn't adjust properly when shown [#447](https://github.com/shoelace-style/shoelace/issues/447)
- Fixed a bug in the internal `shimKeyframesHeightAuto` utility that caused `<sl-details>` to measure heights incorrectly [#445](https://github.com/shoelace-style/shoelace/issues/445)
- Fixed a number of imports that should have been type imports
- Updated Lit to 2.0.0-rc.2
- Updated esbuild to 0.12.4
## 2.0.0-beta.41
This release changes how components animate. In previous versions, CSS transitions were used for most show/hide animations. Transitions are problematic due to the way `transitionend` works. This event fires once _per transition_, and it's impossible to know which transition to look for when users can customize any possible CSS property. Because of this, components previously required the `opacity` property to transition. If a user were to prevent `opacity` from transitioning, the component wouldn't hide properly and the `sl-after-show|hide` events would never emit.
CSS animations, on the other hand, have a more reliable `animationend` event. Alas, `@keyframes` don't cascade and can't be injected into a shadow DOM via CSS, so there would be no good way to customize them.
The most elegant solution I found was to use the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API), which offers more control over animations at the expense of customizations being done in JavaScript. Fortunately, through the [Animation Registry](/getting-started/customizing#animations), you can customize animations globally and/or per component with a minimal amount of code.
- 🚨 BREAKING: changed `left` and `right` placements to `start` and `end` in `<sl-drawer>`
- 🚨 BREAKING: changed `left` and `right` placements to `start` and `end` in `<sl-tab-group>`
- 🚨 BREAKING: removed `--hide-duration`, `--hide-timing-function`, `--show-duration`, and `--show-timing-function` custom properties from `<sl-tooltip>` (use the Animation Registry instead)
- Added the Animation Registry
- Fixed a bug where removing `<sl-dropdown>` from the DOM and adding it back destroyed the popover reference [#443](https://github.com/shoelace-style/shoelace/issues/443)
- Updated animations for `<sl-alert>`, `<sl-dialog>`, `<sl-drawer>`, `<sl-dropdown>`, and `<sl-tooltip>` to use the Animation Registry instead of CSS transitions
- Improved a11y by respecting `prefers-reduced-motion` for all show/hide animations
- Improved `--show-delay` and `--hide-delay` behavior in `<sl-tooltip>` so they only apply on hover
- Removed the internal popover utility
## 2.0.0-beta.40
- 🚨 BREAKING: renamed `<sl-responsive-embed>` to `<sl-responsive-media>` and added support for images and videos [#436](https://github.com/shoelace-style/shoelace/issues/436)
- Fixed a bug where setting properties before an element was defined would render incorrectly [#425](https://github.com/shoelace-style/shoelace/issues/425)
- Fixed a bug that caused all modules to be imported when cherry picking certain components [#439](https://github.com/shoelace-style/shoelace/issues/439)
- Fixed a bug where the scrollbar would reposition `<sl-dialog>` on hide causing it to jump [#424](https://github.com/shoelace-style/shoelace/issues/424)
- Fixed a bug that prevented the project from being built in a Windows environment
- Improved a11y in `<sl-progress-ring>`
- Removed `src/utilities/index.ts` to prevent tree-shaking confusion (please import utilities directly from their respective modules)
- Removed global `[hidden]` styles so they don't affect anything outside of components
- Updated to Bootstrap Icons 1.5.0
- Updated React docs to use [`@shoelace-style/react`](https://github.com/shoelace-style/react)
- Added `system` icon library and updated all components to use this instead of the default icon library [#420](https://github.com/shoelace-style/shoelace/issues/420)
- Updated to esbuild 0.8.57
- Updated to Lit 2.0.0-rc.1 and lit-html 2.0.0-rc.2
## 2.0.0-beta.38
- 🚨 BREAKING: `<sl-radio>` components must be located inside an `<sl-radio-group>` for proper accessibility [#218](https://github.com/shoelace-style/shoelace/issues/218)
- Added `--header-spacing`, `--body-spacing`, and `--footer-spacing` custom properties to `<sl-drawer>` and `<sl-dialog>` [#409](https://github.com/shoelace-style/shoelace/issues/409)
- Fixed a bug where `<sl-menu-item>` prefix and suffix slots wouldn't always receive the correct spacing
- Fixed a bug where `<sl-badge>` used `--sl-color-white` instead of the correct design tokens [#407](https://github.com/shoelace-style/shoelace/issues/407)
- Fixed a bug in `<sl-dialog>` and `<sl-drawer>` where the escape key would cause parent components to close
- Fixed a race condition bug in `<sl-icon>` [#410](https://github.com/shoelace-style/shoelace/issues/410)
- Improved focus trap behavior in `<sl-dialog>` and `<sl-drawer>`
- Improved a11y in `<sl-dialog>` and `<sl-drawer>` by restoring focus to trigger on close
- Improved a11y in `<sl-radio>` with Windows high contrast mode [#215](https://github.com/shoelace-style/shoelace/issues/215)
- Improved a11y in `<sl-select>` by preventing the chevron icon from being announced
- Internal: removed the `options` argument from the modal utility as focus trapping is now handled internally
## 2.0.0-beta.37
- Added `click()` method to `<sl-checkbox>`, `<sl-radio>`, and `<sl-switch>`
- Added the `activation` attribute to `<sl-tab-group>` to allow for automatic and manual tab activation
- Added `npm run create <tag>` script to scaffold new components faster
- Fixed a bug in `<sl-tooltip>` where events weren't properly cleaned up on disconnect
- Fixed a bug in `<sl-tooltip>` where they wouldn't display after toggling `disabled` off and on again [#391](https://github.com/shoelace-style/shoelace/issues/391)
- Fixed a bug in `<sl-details>` where `show()` and `hide()` would toggle the control when disabled
- Fixed a bug in `<sl-color-picker>` where setting `value` wouldn't update the control
- Fixed a bug in `<sl-tab-group>` where tabs that are initially disabled wouldn't receive the indicator on activation [#403](https://github.com/shoelace-style/shoelace/issues/403)
- Fixed incorrect event names for `sl-after-show` and `sl-after-hide` in `<sl-details>`
- Improved a11y for disabled buttons that are rendered as links
- Improved a11y for `<sl-button-group>` by adding the correct `role` attribute
- Improved a11y for `<sl-input>`, `<sl-range>`, `<sl-select>`, and `<sl-textarea>` so labels and helper text are read properly by screen readers
- Removed `sl-show`, `sl-hide`, `sl-after-show`, `sl-after-hide` events from `<sl-color-picker>` (the color picker's visibility cannot be controlled programmatically so these shouldn't have been exposed; the dropdown events now bubble up so you can listen for those instead)
- Reworked `<sl-button-group>` so it doesn't require light DOM styles
## 2.0.0-beta.36
- 🚨 BREAKING: renamed `setFocus()` to `focus()` in button, checkbox, input, menu item, radio, range, rating, select, switch, and tab
- 🚨 BREAKING: renamed `removeFocus()` to `blur()` in button, checkbox, input, menu item, radio, range, rating, select, switch, and tab
- Added `click()` method to `<sl-button>`
- Fixed a bug where toggling `open` on `<sl-drawer>` would skip the transition
- Fixed a bug where `<sl-color-picker>` could be opened when disabled
- Fixed a bug in `<sl-color-picker>` that caused erratic slider behaviors [#388](https://github.com/shoelace-style/shoelace/issues/388) [#389](https://github.com/shoelace-style/shoelace/issues/389)
- Fixed a bug where `<sl-details>` wouldn't always render the correct height when open initially [#357](https://github.com/shoelace-style/shoelace/issues/357)
- Renamed `components.json` to `metadata.json`
- Updated to the prerelease versions of LitElement and lit-html
- Updated to Bootstrap Icons 1.4.1
## 2.0.0-beta.35
- Fixed a bug in `<sl-animation>` where `sl-cancel` and `sl-finish` events would never fire
- Fixed a bug where `<sl-alert>` wouldn't always transition properly
- Fixed a bug where using `<sl-menu>` inside a shadow root would break keyboard selections [#382](https://github.com/shoelace-style/shoelace/issues/382)
- Fixed a bug where toggling `multiple` in `<sl-select>` would lead to a stale display label
- Fixed a bug in `<sl-tab-group>` where changing `placement` could result in the active tab indicator being drawn a few pixels off
- Fixed a bug in `<sl-button>` where link buttons threw an error on focus, blur, and click
- Improved `@watch` decorator to run after update instead of during
- Updated `<sl-menu-item>` checked icon to `check` instead of `check2`
- Upgraded the status of `<sl-resize-observer>` from experimental to stable
## 2.0.0-beta.34
This release changes the way components are registered if you're [cherry picking](/getting-started/installation?id=cherry-picking) or [using a bundler](/getting-started/installation?id=bundling). This recommendation came from the LitElement team and simplifies Shoelace's dependency graph. It also eliminates the need to call a `register()` function before using each component.
From now on, importing a component will register it automatically. The caveat is that bundlers may not tree shake the library properly if you import from `@shoelace-style/shoelace`, so the recommendation is to import components and utilities from their corresponding files instead.
- 🚨 BREAKING: component modules now have a side effect, so bundlers may not tree shake properly when importing from `@shoelace-style/shoelace` (see the [installation page](/getting-started/installation?id=bundling) for more details and how to update)
- Added `sl-clear` event to `<sl-select>`
- Fixed a bug where dynamically changing menu items in `<sl-select>` would cause the display label to be blank [#374](https://github.com/shoelace-style/shoelace/discussions/374)
- Fixed a bug where setting the `value` attribute or property on `<sl-input>` and `<sl-textarea>` would trigger validation too soon
- Fixed the margin in `<sl-menu-label>` to align with menu items
- Fixed `autofocus` attributes in `<sl-input>` and `<sl-textarea>`
- Improved types for `autocapitalize` in `<sl-input>` and `<sl-textarea>`
- Reverted the custom `@tag` decorator in favor of `@customElement` to enable auto-registration
## 2.0.0-beta.33
- Fixed a bug where link buttons could have incorrect `target`, `download`, and `rel` props
- Fixed `aria-label` and `aria-labelledby` props in `<sl-dialog>` and `<sl-drawer>`
- Fixed `tabindex` attribute in `<sl-menu>`
- Fixed a bug in `<sl-select>` where tags would always render as pills
- Fixed a bug in `<sl-button>` where calling `setFocus()` would throw an error
## 2.0.0-beta.32
- Added tag name maps so TypeScript can identify Shoelace elements [#371](https://github.com/shoelace-style/shoelace/pull/371)
- Fixed a bug where the active tab indicator wouldn't render properly on tabs styled with `flex-end` [#355](https://github.com/shoelace-style/shoelace/issues/355)
- Fixed a bug where `sl-change` wasn't emitted by `<sl-checkbox>` or `<sl-switch>` [#370](https://github.com/shoelace-style/shoelace/issues/370)
- Fixed a bug where some props weren't being watched correctly in `<sl-alert>` and `<sl-color-picker>`
- Improved `@watch` decorator so watch handlers don't run before the first render
- Removed guards that were added due to previous watch handler behavior
## 2.0.0-beta.31
- Add touch support to `<sl-rating>` [#362](https://github.com/shoelace-style/shoelace/pull/362)
- Fixed a bug where the `open` attribute on `<sl-details>` would prevent it from opening [#357](https://github.com/shoelace-style/shoelace/issues/357)
- Fixed event detail type parsing so component class names are shown instead of `default`
## 2.0.0-beta.30
- Fix default exports for all components so cherry picking works again [#365](https://github.com/shoelace-style/shoelace/issues/365)
- Revert FOUC base style because it interferes with some framework and custom element use cases
## 2.0.0-beta.29
**This release migrates component implementations from Shoemaker to LitElement.** Due to feedback from the community, Shoelace will rely on a more heavily tested library for component implementations. This gives you a more solid foundation and reduces my maintenance burden. Thank you for all your comments, concerns, and encouragement! Aside from that, everything else from beta.28 still applies plus the following.
- 🚨 BREAKING: removed the `symbol` property from `<sl-rating>` and reverted to `getSymbol` for optimal flexibility
- Added `vscode.html-custom-data.json` to the build to support IntelliSense (see [the usage section](/getting-started/usage#code-completion) for details)
- Added a base style to prevent FOUC before components are defined
- Fixed bug where TypeScript types weren't being generated [#364](https://github.com/shoelace-style/shoelace/pull/364)
- Improved vertical padding in `<sl-tooltip>`
- Moved chunk files into a separate folder
- Reverted menu item active styles
- Updated esbuild to 0.8.54
## 2.0.0-beta.28
**This release includes a major under the hood overhaul of the library and how it's distributed.** Until now, Shoelace was developed with Stencil. This release moves to a lightweight tool called Shoemaker, a homegrown utility that provides declarative templating and data binding while reducing the boilerplate required for said features.
This change in tooling addresses a number of longstanding bugs and limitations. It also gives us more control over the library and build process while streamlining development and maintenance. Instead of two different distributions, Shoelace now offers a single, standards-compliant collection of ES modules. This may affect how you install and use the library, so please refer to the [installation page](/getting-started/installation) for details.
!> Due to the large number of internal changes, I would consider this update to be less stable than previous ones. If you're using Shoelace in a production app, consider holding off until the next beta to allow for more exhaustive testing from the community. Please report any bugs you find on the [issue tracker](https://github.com/shoelace-style/shoelace/issues).
The component API remains the same except for the changes noted below. Thanks for your patience as I work diligently to make Shoelace more stable and future-proof. 🙌
- 🚨 BREAKING: removed the custom elements bundle (you can import ES modules directly)
- 🚨 BREAKING: removed `getAnimationNames()` and `getEasingNames()` methods from `<sl-animation>` (you can import them from `utilities/animation.js` instead)
- 🚨 BREAKING: removed the `<sl-icon-library>` component since it required imperative initialization (you can import the `registerIconLibrary()` function from `utilities/icon-library.js` instead)
- 🚨 BREAKING: removed the experimental `<sl-theme>` component due to technical limitations (you should set the `sl-theme-{name}` class on the `<body>` instead)
- 🚨 BREAKING: moved the base stylesheet from `dist/shoelace.css` to `dist/themes/base.css`
- 🚨 BREAKING: moved `icons` into `assets/icons` to make future assets easier to colocate
- 🚨 BREAKING: changed `getSymbol` property in `<sl-rating>` to `symbol` (it now accepts a string or a function that returns an icon name)
- 🚨 BREAKING: renamed `setAssetPath()` to `setBasePath()` and added the ability to set the library's base path with a `data-shoelace` attribute (`setBasePath()` is exported from `utilities/base-path.js`)
- Fixed `min` and `max` types in `<sl-input>` to allow numbers and strings [#330](https://github.com/shoelace-style/shoelace/issues/330)
- Fixed a bug where `<sl-checkbox>`, `<sl-radio>`, and `<sl-switch>` controls would shrink with long labels [#325](https://github.com/shoelace-style/shoelace/issues/325)
- Fixed a bug in `<sl-select>` where the dropdown menu wouldn't reposition when the box resized [#340](https://github.com/shoelace-style/shoelace/issues/340)
- Fixed a bug where ignoring clicks and clicking the overlay would prevent the escape key from closing the dialog/drawer [#344](https://github.com/shoelace-style/shoelace/pull/344)
- Removed the lazy loading dist (importing `shoelace.js` will load and register all components now)
- Switched from Stencil to Shoemaker
- Switched to a custom build powered by [esbuild](https://esbuild.github.io/)
- Updated to Bootstrap Icons 1.4.0
## 2.0.0-beta.27
- Added `handle-icon` slot to `<sl-image-comparer>` [#311](https://github.com/shoelace-style/shoelace/issues/311)
- Added `label` and `helpText` props and slots to `<sl-range>` [#318](https://github.com/shoelace-style/shoelace/issues/318)
- Added "Integrating with NextJS" tutorial to the docs, courtesy of [crutchcorn](https://github.com/crutchcorn)
- Added `content` slot to `<sl-tooltip>` [#322](https://github.com/shoelace-style/shoelace/pull/322)
- Fixed a bug in `<sl-select>` where removing a tag would toggle the dropdown
- Fixed a bug in `<sl-input>` and `<sl-textarea>` where the input might not exist when the value watcher is called [#313](https://github.com/shoelace-style/shoelace/issues/313)
- Fixed a bug in `<sl-details>` where hidden elements would receive focus when tabbing [#323](https://github.com/shoelace-style/shoelace/issues/323)
- Fixed a bug in `<sl-icon>` where `sl-error` would only be emitted for network failures [#326](https://github.com/shoelace-style/shoelace/pull/326)
- Reduced the default line-height for `<sl-tooltip>`
- Updated `<sl-menu-item>` focus styles
- Updated `<sl-select>` so tags will wrap when `multiple` is true
- Updated to Stencil 2.4.0
## 2.0.0-beta.26
- 🚨 BREAKING: Fixed animations bloat
- Removed ~400 baked-in Animista animations because they were causing ~200KB of bloat (they can still be used with custom keyframes)
- Reworked animations into a separate module ([`@shoelace-style/animations`](https://github.com/shoelace-style/animations)) so it's more maintainable and animations are sync with the latest version of animate.css
- Animation and easing names are now camelcase (e.g. `easeInOut` instead of `ease-in-out`)
- Added the `FocusOptions` argument to all components that have a `setFocus()` method
- Added `sl-initial-focus` event to `<sl-dialog>` and `<sl-drawer>` so focus can be customized to a specific element
- Added `close-button` part to `<sl-tab>` so the close button can be customized
- Added `scroll-button` part to `<sl-tab-group>` so the scroll buttons can be customized
- Fixed a bug where `sl-hide` would be emitted twice when closing an alert with `hide()`
- Fixed a bug in `<sl-color-picker>` where the toggle button was smaller than the preview button in Safari
- Fixed a bug in `<sl-tab-group>` where activating a nested tab group didn't work properly [#299](https://github.com/shoelace-style/shoelace/issues/299)
- Fixed a bug in `<sl-tab-group>` where removing tabs would throw an error
- Fixed a bug in `<sl-alert>`, `<sl-dialog>`, `<sl-drawer>`, `<sl-select>`, and `<sl-tag>` where the close button's base wasn't exported so it couldn't be styled
- Removed `text` type from `<sl-badge>` as it was erroneously copied and never had styles
- Updated `<sl-tab-group>` so the `active` property is reflected to its attribute
- Updated the docs to show dependencies instead of dependents which is much more useful when working with the custom elements bundle
- Updated to Bootstrap Icons 1.3.0
## 2.0.0-beta.25
- 🚨 BREAKING: Reworked color tokens
- Theme colors are now inspired by Tailwind's professionally-designed color palette
- Color token variations now range from 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950
- Color token variations were inverted, e.g. 50 is lightest and 950 is darkest
- All component styles were adapted to use the new color tokens, but visual changes are subtle
- The dark theme was adapted use the new color tokens
- HSL is no longer used because it is not perceptually uniform (this may be revisited when all browsers support [LCH colors](https://lea.verou.me/2020/04/lch-colors-in-css-what-why-and-how/))
- 🚨 BREAKING: Refactored `<sl-select>` to improve accessibility [#216](https://github.com/shoelace-style/shoelace/issues/216)
- Removed the internal `<sl-input>` because it was causing problems with a11y and virtual keyboards
- Removed `input`, `prefix` and `suffix` parts
- 🚨 BREAKING: Removed `copy-button` part from `<sl-color-picker>` since copying is now done by clicking the preview
- Added `getFormattedValue()` method to `<sl-color-picker>` so you can retrieve the current value in any format
- Added visual separators between solid buttons in `<sl-button-group>`
- Added `help-text` attribute to `<sl-input>`, `<sl-textarea>`, and `<sl-select>`
- Fixed a bug where moving the mouse while `<sl-dropdown>` is closing would remove focus from the trigger
- Fixed a bug where `<sl-menu-item>` didn't set a default color in the dark theme
- Fixed a bug where `<sl-color-picker>` preview wouldn't update in Safari
- Fixed a bug where removing an icon's `name` or `src` wouldn't remove the previously rendered SVG [#285](https://github.com/shoelace-style/shoelace/issues/285)
- Fixed a bug where disabled link buttons didn't appear disabled
- Improved button spacings and added split button example
- Improved elevation tokens in dark theme
- Improved accessibility in `<sl-tooltip>` by allowing escape to dismiss it [#219](https://github.com/shoelace-style/shoelace/issues/219)
- Improved slot detection in `<sl-card>`, `<sl-dialog>`, and `<sl-drawer>`
- Made `@types/resize-observer-browser` a dependency so users don't have to install it manually
- Refactored internal label + help text logic into a functional component used by `<sl-input>`, `<sl-textarea>`, and `<sl-select>`
- Removed `sl-blur` and `sl-focus` events from `<sl-menu>` since menus can't have focus as of 2.0.0-beta.22
- Updated `<sl-spinner>` so the indicator is more obvious
- Updated to Bootstrap Icons 1.2.2
## 2.0.0-beta.24
- Added `<sl-format-date>` component
- Added `indeterminate` state to `<sl-progress-bar>` [#274](https://github.com/shoelace-style/shoelace/issues/274)
- Added `--track-color`, `--indicator-color`, and `--label-color` to `<sl-progress-bar>` [#276](https://github.com/shoelace-style/shoelace/issues/276)
- Added `allow-scripts` attribute to `<sl-include>` [#280](https://github.com/shoelace-style/shoelace/issues/280)
- Fixed a bug where `<sl-menu-item>` color variable was incorrect [#272](https://github.com/shoelace-style/shoelace/issues/272)
- Fixed a bug where `<sl-dialog>` and `<sl-drawer>` would emit the `sl-hide` event twice [#275](https://github.com/shoelace-style/shoelace/issues/275)
- Fixed a bug where calling `event.preventDefault()` on certain form elements wouldn't prevent `<sl-form>` from submitting [#277](https://github.com/shoelace-style/shoelace/issues/277)
- Fixed drag handle orientation in `<sl-image-comparer>`
- Restyled `<sl-spinner>` so the track is visible and the indicator is smaller.
- Removed `resize-observer-polyfill` in favor of `@types/resize-observer-browser` since all target browsers support `ResizeObserver`
- Upgraded the status of `<sl-form>`, `<sl-image-comparer>`, and `<sl-include>` from experimental to stable
- Added experimental `<sl-theme>` utility and updated theming documentation
- Fixed a bug where `<sl-menu-item>` wouldn't render properly in the dark theme
- Fixed a bug where `<sl-select>` would show an autocomplete menu
- Improved placeholder contrast in dark theme
- Updated to Boostrap Icons 1.1.0
- Updated to Stencil 2.3.0
## 2.0.0-beta.22
- 🚨 BREAKING: Refactored `<sl-menu>` and `<sl-menu-item>` to improve accessibility by using proper focus states [#217](https://github.com/shoelace-style/shoelace/issues/217)
- Moved `tabindex` from `<sl-menu>` to `<sl-menu-item>`
- Removed the `active` attribute from `<sl-menu-item>` because synthetic focus states are bad for accessibility
- Removed the `sl-activate` and `sl-deactivate` events from `<sl-menu-item>` (listen for `focus` and `blur` instead)
- Updated `<sl-select>` so keyboard navigation still works
- Added `no-scroll-controls` attribute to `<sl-tab-group>` [#253](https://github.com/shoelace-style/shoelace/issues/253)
- Fixed a bug where setting `open` initially wouldn't show `<sl-dialog>` or `<sl-drawer>` [#255](https://github.com/shoelace-style/shoelace/issues/255)
- Fixed a bug where `disabled` could be set when buttons are rendered as links
- Fixed a bug where hoisted dropdowns would render in the wrong position when placed inside `<sl-dialog>` [#252](https://github.com/shoelace-style/shoelace/issues/252)
- Fixed a bug where boolean aria attributes didn't explicitly set `true|false` string values in the DOM
- Fixed a bug where `aria-describedby` was never set on tooltip targets in `<sl-tooltip>`
- Fixed a bug where setting `position` on `<sl-image-comparer>` wouldn't update the divider's position
- Fixed a bug where the check icon was announced to screen readers in `<sl-menu-item>`
- Improved `<sl-icon-button>` accessibility by encouraging proper use of `label` and hiding the internal icon from screen readers [#220](https://github.com/shoelace-style/shoelace/issues/220)
- Improved `<sl-dropdown>` accessibility by attaching `aria-haspopup` and `aria-expanded` to the slotted trigger
- Refactored position logic to remove an unnecessary state variable in `<sl-image-comparer>`
- Refactored design tokens to use `rem` instead of `px` for input height and spacing [#221](https://github.com/shoelace-style/shoelace/issues/221)
- Removed `console.log` from modal utility
- Updated to Stencil 2.2.0
## 2.0.0-beta.21
- Added `label` slot to `<sl-input>`, `<sl-select>`, and `<sl-textarea>` [#248](https://github.com/shoelace-style/shoelace/issues/248)
- Added `label` slot to `<sl-dialog>` and `<sl-drawer>`
- Added experimental `<sl-include>` component
- Added status code to the `sl-error` event in `<sl-icon>`
- Fixed a bug where initial transitions didn't show in `<sl-dialog>` and `<sl-drawer>` [#247](https://github.com/shoelace-style/shoelace/issues/247)
- Fixed a bug where indeterminate checkboxes would maintain the indeterminate state when toggled
- Fixed a bug where concurrent active modals (i.e. dialog, drawer) would try to steal focus from each other
- Improved `<sl-color-picker>` grid and slider handles [#246](https://github.com/shoelace-style/shoelace/issues/246)
- Refactored `<sl-icon>` request logic and removed unused cache map
- Reworked show/hide logic in `<sl-alert>`, `<sl-dialog>`, and `<sl-drawer>` to not use reflow hacks and the `hidden` attribute
- Reworked slot logic in `<sl-card>`, `<sl-dialog>`, and `<sl-drawer>`
- Updated to Popper 2.5.3 to address a fixed position bug in Firefox
## 2.0.0-beta.20
- 🚨 BREAKING: Transformed all Shoelace events to lowercase ([details](#why-did-event-names-change))
- Added support for dropdowns and non-icon elements to `<sl-input>`
- Added `spellcheck` attribute to `<sl-input>`
- Added `<sl-icon-library>` to allow custom icon library registration
- Added `library` attribute to `<sl-icon>` and `<sl-icon-button>`
- Added "Integrating with Rails" tutorial to the docs, courtesy of [ParamagicDev](https://github.com/ParamagicDev)
- Fixed a bug where `<sl-progress-ring>` rendered incorrectly when zoomed in Safari [#227](https://github.com/shoelace-style/shoelace/issues/227>)
- Fixed a bug where tabbing into slotted elements closes `<sl-dropdown>` when used in a shadow root [#223](https://github.com/shoelace-style/shoelace/issues/223)
- Fixed a bug where scroll anchoring caused undesirable scrolling when `<sl-details>` are grouped
### Why did event names change?
Shoelace events were updated to use a lowercase, kebab-style naming convention. Instead of event names such as `slChange` and `slAfterShow`, you'll need to use `sl-change` and `sl-after-show` now.
This change was necessary to address a critical issue in frameworks that use DOM templates with declarative event bindings such as `<sl-button @slChange="handler">`. Due to HTML's case-insensitivity, browsers translate attribute names to lowercase, turning `@slChange` into `@slchange`, making it impossible to listen to `slChange`.
While declarative event binding is a non-standard feature, not supporting it would make Shoelace much harder to use in popular frameworks. To accommodate those users and provide a better developer experience, we decided to change the naming convention while Shoelace is still in beta.
The following pages demonstrate why this change was necessary.
- [This Polymer FAQ from Custom Elements Everywhere](https://custom-elements-everywhere.com/#faq-polymer)
- Added `input`, `label`, `prefix`, `clear-button`, `suffix`, `help-text` exported parts to `<sl-select>` to make the input customizable
- Added toast notifications through the `toast()` method on `<sl-alert>`
- Fixed a bug where mouse events would bubble up when `<sl-button>` was disabled, causing tooltips to erroneously appear
- Fixed a bug where pressing space would open and immediately close `<sl-dropdown>` panels in Firefox
- Fixed a bug where `<sl-tooltip>` would throw an error on init
- Fixed a bug in custom keyframes animation example
- Refactored clear logic in `<sl-input>`
## 2.0.0-beta.18
- Added `name` and `invalid` attribute to `<sl-color-picker>`
- Added support for form submission and validation to `<sl-color-picker>`
- Added touch support to demo resizers in the docs
- Added `<sl-responsive-embed>` component
- Fixed a bug where swapping an animated element wouldn't restart the animation in `<sl-animation>`
- Fixed a bug where the cursor was incorrect when `<sl-select>` was disabled
- Fixed a bug where `slblur` and `slfocus` were emitted twice in `<sl-select>`
- Fixed a bug where clicking on `<sl-menu>` wouldn't focus it
- Fixed a bug in the popover utility where `onAfterShow` would fire too soon
- Fixed a bug where `bottom` and `right` placements didn't render properly in `<sl-tab-group>`
- Improved keyboard logic in `<sl-dropdown>`, `<sl-menu>`, and `<sl-select>`
- Updated `<sl-animation>` to stable
- Updated to Stencil 2.0 (you may need to purge `node_modules` and run `npm install` after pulling)
- Updated entry points in `package.json` to reflect new filenames generated by Stencil 2
## 2.0.0-beta.17
- Added `minlength` and `spellcheck` attributes to `<sl-textarea>`
- Fixed a bug where clicking a tag in `<sl-select>` wouldn't toggle the menu
- Fixed a bug where options where `<sl-select>` options weren't always visible or scrollable
- Fixed a bug where setting `null` on `<sl-input>`, `<sl-textarea>`, or `<sl-select>` would throw an error
- Fixed a bug where `role` was on the wrong element and aria attribute weren't explicit in `<sl-checkbox>`, `<sl-switch>`, and `<sl-radio>`
- Fixed a bug where dynamically adding/removing a slot wouldn't work as expected in `<sl-card>`, `<sl-dialog>`, and `<sl-drawer>`
- Fixed a bug where the value wasn't updated and events weren't emitted when using `setRangeText` in `<sl-input>` and `<sl-textarea>`
- Optimized `hasSlot` utility by using a simpler selector
- Updated Bootstrap Icons to 1.0.0 with many icons redrawn and improved
- Updated contribution guidelines
**Form validation has been reworked and is much more powerful now!**
- The `invalid` attribute now reflects the control's validity as determined by the browser's constraint validation API
- Added `required` to `<sl-checkbox>`, `<sl-select>`, and `<sl-switch>`
- Added `reportValidity()` and `setCustomValidity()` methods to all form controls
- Added validation checking for custom and native form controls to `<sl-form>`
- Added `novalidate` attribute to `<sl-form>` to disable validation
- Removed the `valid` attribute from all form controls
- Removed valid and invalid design tokens and related styles (you can use your own custom styles to achieve this)
## 2.0.0-beta.16
- Added `hoist` attribute to `<sl-color-picker>`, `<sl-dropdown>`, and `<sl-select>` to work around panel clipping
- Added `<sl-format-bytes>` utility component
- Added `clearable` and `required` props to `<sl-select>`
- Added `slclear` event to `<sl-input>`
- Added keyboard support to the preview resizer in the docs
- Fixed a bug where the `aria-selected` state was incorrect in `<sl-menu-item>`
- Fixed a bug where custom properties applied to `<sl-tooltip>` didn't affect show/hide transitions
- Fixed a bug where `--sl-input-color-*` custom properties had no effect on `<sl-input>` and `<sl-textarea>`
- Refactored `<sl-dropdown>` and `<sl-tooltip>` to use positioner elements so panels/tooltips can be customized easier
## 2.0.0-beta.15
- Added `image-comparer` component
- Added `--width`, `--height`, and `--thumb-size` custom props to `<sl-switch>`
- Fixed an `aria-labelledby` attribute typo in a number of components
- Fixed a bug where the `change` event wasn't updating the value in `<sl-input>`
- Fixed a bug where `<sl-color-picker>` had the wrong border color in the dark theme
- Fixed a bug where `<sl-menu-item>` had the wrong color in dark mode when disabled
- Fixed a bug where WebKit's autocomplete styles made inputs looks broken
- Fixed a bug where aria labels were wrong in `<sl-select>`
- Fixed a bug where clicking the label wouldn't focus the control in `<sl-select>`
## 2.0.0-beta.14
- Added dark theme
- Added `--sl-panel-background-color` and `--sl-panel-border-color` tokens
- Added `--tabs-border-color` custom property to `<sl-tab-group>`
- Added `--track-color` custom property to `<sl-range>`
- Added `tag` part to `<sl-select>`
- Updated `package.json` so custom elements imports can be consumed from the root
- Fixed a bug where scrolling dialogs didn't resize properly in Safari
- Fixed a bug where `slshow` and `slhide` would be emitted twice in some components
- Fixed a bug where `custom-elements/index.d.ts` was broken due to an unclosed comment (fixed in Stencil 1.17.3)
- Fixed bug where inputs were not using border radius tokens
- Fixed a bug where the text color was being erroneously set in `<sl-progress-ring>`
- Fixed a bug where `<sl-progress-bar>` used the wrong part name internally for `indicator`
- Removed background color from `<sl-menu>`
- Updated to Stencil 1.17.3
## 2.0.0-beta.13
- Added `slactivate` and `sldeactivate` events to `<sl-menu-item>`
- Added experimental `<sl-animation>` component
- Added shields to documentation
- Fixed a bug where link buttons would have `type="button"`
- Fixed a bug where button groups with tooltips experienced an odd spacing issue in Safari
- Fixed a bug where scrolling in dropdowns/selects didn't work properly on Windows (special thanks to [Trendy](http://github.com/trendy) for helping troubleshoot!)
- Fixed a bug where selecting a menu item in a dropdown would cause Safari to scroll
- Fixed a bug where type to select wouldn't accept symbols
- Moved scrolling logic from `<sl-menu>` to `<sl-dropdown>`
## 2.0.0-beta.12
- Added support for `href`, `target`, and `download` to buttons
- Fixed a bug where buttons would have horizontal spacing in Safari
- Fixed a bug that caused an import resolution error when using Shoelace in a Stencil app
## 2.0.0-beta.11
- Added button group component
- Fixed icon button alignment
- Fixed a bug where focus visible observer wasn't removed from `<sl-details>`
- Replaced the deprecated `componentDidUnload` lifecycle method with `disconnectedCallback` to prevent issues with frameworks
## 2.0.0-beta.10
- Added community page to the docs
- Fixed a bug where many components would erroneously receive an `id` when using the custom elements bundle
- Fixed a bug where tab groups weren't scrollable with the mouse
## 2.0.0-beta.9
- Added the icon button component
- Added the skeleton component
- Added the `typeToSelect` method to menu so type-to-select behavior can be controlled externally
- Added the `pulse` attribute to badge
- Fixed a bug where hovering over select showed the wrong cursor
- Fixed a bug where tabbing into a select control would highlight the label
- Fixed a bug where tabbing out of a select control wouldn't close it
- Fixed a bug where closing dropdowns wouldn't give focus back to the trigger
- Fixed a bug where type-to-select wasn't working after the first letter
- Fixed a bug where clicking on menu items and dividers would steal focus from the menu
- Fixed a bug where the color picker wouldn't parse uppercase values
- Removed the `no-footer` attribute from dialog and drawer (slot detection is automatic, so the attribute is not required)
- Removed `close-icon` slot from alert
- Replaced make-shift icon buttons with `<sl-icon-button>` in alert, dialog, drawer, and tag
- Updated Stencil to 1.17.1
- Switched to jsDelivr for better CDN performance
## 2.0.0-beta.8
- Added the card component
- Added `--focus-ring` custom property to tab
- Fixed a bug where range tooltips didn't appear on iOS
- Fixed constructor bindings so they don't break the custom elements bundle
- Fixed tag color contrast to be AA compliant
- Fixed a bug that made it difficult to vertically align rating
- Fixed a bug where dropdowns would always close on mousedown when inside a shadow root
- Made tag text colors AA compliant
- Promoted badge to stable
- Refactored `:host` variables and moved non-display props to base elements
- Refactored event handler bindings to occur in `connectedCallback` instead of the constructor
- Refactored scroll locking logic to use `Set` instead of an array
- Updated the custom elements bundle documentation and added bundler examples
- Upgraded Stencil to 1.17.0-0 (next) to fix custom elements bundle
## 2.0.0-beta.7
- Added links to version 1 resources to the docs
- Added rating component
- Fixed a bug where some build files were missing
- Fixed clearable tags demo
- Fixed touch icon size in docs
## 2.0.0-beta.6
- Enabled the `dist-custom-elements-bundle` output target
- Fixed a bug where nested form controls were ignored in `<sl-form>`
## 2.0.0-beta.5
- Fixed bug where `npm install` would fail due to postinstall script
- Removed unused dependency
## 2.0.0-beta.4
- Added `pill` variation to badges
- Fixed a bug where all badges had `pointer-events: none`
- Fixed `@since` props to show 2.0 instead of 1.0
- Fixed giant cursors in inputs in Safari
- Fixed color picker input width in Safari
- Fixed initial transitions for drawer, dialog, and popover consumers
- Fixed a bug where dialog, dropdown, and drawer would sometimes not transition in on the first open
Shoelace has a growing community of designers and developers that are building amazing things with web components. We'd love for you to become a part of it!
Please be respectful of other users and remember that Shoelace is an open source project. We'll try to help when we can, but there's no guarantee we'll be able solve your problem. Please manage your expectations and don't forget to contribute back to the conversation when you can!
## Discussion Forum
The [discussion forum](https://github.com/shoelace-style/shoelace/discussions) is open to anyone with a GitHub account. This is the best place to:
- Ask for help
- Share ideas and get feedback
- Show the community what you're working on
- Learn more about the project, its values, and its roadmap
You can post questions on Stack Overflow using [the "shoelace" tag](https://stackoverflow.com/questions/tagged/shoelace). This is a public forum where talented developers answer questions. It's a great way to get help, but it is not maintained or actively monitored by the Shoelace author.
Follow [@shoelace_style](https://twitter.com/shoelace_style) on Twitter for general updates and announcements about Shoelace. This is a great place to say "hi" or to share something you're working on. You're also welcome to follow [@claviska](https://twitter.com/claviska), the creator, for tweets about web components, web development, and life.
**Please avoid using Twitter for support questions.** The [discussion forum](https://github.com/shoelace-style/shoelace/discussions) is a much better place to share code snippets, screenshots, and other troubleshooting info. You'll have much better luck there, as more users will have a chance to help you.
Shoelace is an open source project, meaning everyone can use it and contribute to its development. When you join our community, you'll find a friendly group of enthusiasts at all experience levels who are willing to chat about anything and everything related to Shoelace.
The easiest way to get started contributing is to join the [community chat](https://discord.gg/mg8f26C). This is where we hang out, discuss new ideas, ask for feedback, and more!
A common misconception about contributing to an open source project is that you need to know how to code. This simply isn't true. In fact, there are _many_ ways to contribute, and some of the most important contributions come from those who never write a single line of code. Here's a list of ways you can make a meaningful contribution to the project:
- Submitting well-written bug reports
- Submitting feature requests that are within the scope of the project
- Improving the documentation
- Responding to users that need help in the community chat or discussion forum
- Triaging issues on GitHub
- Being a developer advocate for the project
- Sponsoring the project financially
- Writing tests
- Sharing ideas
- And, of course, contributing code!
Please take a moment to review these guidelines to make the contribution process as easy as possible for both yourself and the project's maintainers.
## Using the Issue Tracker
The [issue tracker](https://github.com/shoelace-style/shoelace/issues) is for bug reports, feature requests, and pull requests.
- Please **do not** use the issue tracker for personal support requests. Use [the discussion forum](https://github.com/shoelace-style/shoelace/discussions/categories/help) instead.
- Please **do not** derail, hijack, or troll issues. Keep the discussion on topic and be respectful of others.
- Please **do not** post comments with "+1" or "👍". Use [reactions](https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) instead.
- Please **do** use the issue tracker for feature requests, bug reports, and pull requests.
Issues that do not follow these guidelines are subject to closure. There simply aren't enough resources for the author and contributors to troubleshoot personal support requests.
### Feature Requests
Feature requests can be added using the issue tracker.
- Please **do** search for an existing request before suggesting a new feature.
- Please **do** use the "👍" reaction to vote for a feature.
- Please **do** share substantial use cases and perspective that support new features if they haven't already been mentioned.
- Please **do not** bump, spam, or ping contributors to prioritize your own feature.
If you would like your feature prioritized, please consider [sponsoring the project](https://github.com/sponsors/claviska).
### Bug Reports
A bug is _a demonstrable problem_ caused by code in the library. Bug reports are an important contribution to the quality of the project. When submitting a bug report, there are a few steps you can take to make sure your issues gets attention quickly.
- Please **do not** paste in large blocks of irrelevant code
- Please **do** search for an existing issue before creating a new one
- Please **do** explain the bug clearly
- Please **do** provide a minimal test case that demonstrates the bug (e.g. [jsfiddle.net](https://jsfiddle.net/) or [CodePen](https://codepen.io/))
- Please **do** provide additional information, when necessary, to replicate the bug
**A minimal test case is critical to a successful bug report.** It demonstrates that the bug exists in the library and not in surrounding code. Contributors should be able to understand the bug without studying your code, otherwise they'll probably move on to another bug.
If you would like your bug prioritized, please consider [sponsoring the project](https://github.com/sponsors/claviska).
### Pull Requests
To keep the project on track, please consider the following guidelines before submitting a PR.
- Please **do not** submit a PR without opening an issue first, especially for non-trivial changes. This may prevent you from doing work that won't be accepted for various reasons (e.g. someone is already working on it, it's not a good fit for the project, it needs additional planning, etc.)
- Please **do** make sure your PR clearly defines what you're changing. Even if you feel your changes are obvious, please explain them so other contributors can more easily review your works. PRs without detailed descriptions are subject to closure pending more details.
- Please **do** open your PR against the `next` branch.
- Please **do not** edit anything in `dist/`. These files are generated automatically, so you need to edit the source files instead.
The author reserves the right to reject any PR that's outside the scope of the project or doesn't meet code quality standards.
### Branches
`current` - This branch reflects the latest release and powers [shoelace.style](https://shoelace.style/).
`next` - This is the branch you should submit pull requests against. It reflects what's coming in the _next_ release, which can be previewed at [next.shoelace.style](https://next.shoelace.style/).
## Developing
To set up a local dev environment, [fork the repo](https://github.com/shoelace-style/shoelace/fork) on GitHub, clone it locally, and install its dependencies.
Once you've cloned the repo, run the following command to spin up the Shoelace dev server.
```bash
npm start
```
After the initial build, a browser will open automatically to a local version of the docs. The documentation is powered by Docsify, which uses raw markdown files to generate pages on the fly.
### Creating New Components
To scaffold a new component, run the following command, replacing `sl-tag-name` with the desired tag name.
```bash
npm run create sl-tag-name
```
This will generate a source file, a stylesheet, and a docs page for you. When you start the dev server, you'll find the new component in the "Components" section of the sidebar.
### Dev Sandbox
Component development occurs _within_ the local docs site. I've found that offering common variations _in the docs_ is more beneficial for users than segmenting demos and code examples into separate tools such as Storybook. This encourages more thorough documentation, streamlines development for maintainers, and simplifies how the project is built. It also reduces installation and startup times significantly.
There is currently no hot module reloading (HMR), as browsers don't provide a way to unregister custom elements. However, most changes to the source will reload the browser automatically.
For more information about running and building the project locally, refer to `README.md` in the project's root.
### Testing
Shoelace uses [Web Test Runner](https://modern-web.dev/guides/test-runner/getting-started/) for testing. To launch the test runner during development, open a terminal and launch the dev server.
```bash
npm start
```
In a second terminal window, launch the test runner.
```bash
npm run test:watch
```
Follow the on-screen instructions to work with the test runner. Tests will automatically re-run as you make changes.
To run tests only once, make sure to build the project first.
```bash
npm run build
npm run test
```
## Best Practices
The following is a non-exhaustive list of conventions, patterns, and best practices we try to follow. As a contributor, we ask that you make a good faith effort to follow them as well. This ensures consistency and maintainability throughout the project.
If in doubt, use your best judgment and the maintainers will be happy to guide you during the code review process. If you'd like clarification on something before submitting a PR, feel free to reach out on the [community chat](https://discord.gg/mg8f26C).
?> This section can be a lot to digest in one sitting, so don't feel like you need to take it all in right now. Most contributors will be better off skimming this section and reviewing the relevant content as needed.
### Accessibility
Shoelace is built with accessibility in mind. Creating generic components that are fully accessible to users with varying capabilities across a multitude of circumstances is a daunting challenge. Oftentimes, the solution to an a11y problem is not written in black and white and, therefore, we may not get it right the first time around. There are, however, guidelines we can follow in our effort to make Shoelace an accessible foundation from which applications and websites can be built.
We take this commitment seriously, so please ensure your contributions have this goal in mind. If you need help with anything a11y-related, please [reach out to the community](/resources/community) for assistance. If you discover an accessibility concern within the library, please file a bug on the [issue tracker](https://github.com/shoelace-style/shoelace/issues).
It's important to remember that, although accessibility starts with foundational components, it doesn't end with them. It everyone's responsibility to encourage best practices and ensure we're providing an optimal experience for all of our users.
### Documentation
Maintaining good documentation can be a painstaking task, but poor documentation leads to frustration and makes the project less appealing to users. Fortunately, writing documentation for Shoelace is fast and easy!
Most of Shoelace's technical documentation is generated with JSDoc comments and TypeScript metadata from the source code. Every property, method, event, etc. is documented this way. In-code comments encourage contributors to keep the documentation up to date as changes occur so the docs are less likely to become stale. Refer to an existing component to see how JSDoc comments are used in Shoelace.
Instructions, code examples, and interactive demos are hand-curated to give users the best possible experience. Typically, the most relevant information is shown first and less common examples are shown towards the bottom. Edge cases and gotchas should be called out in context with tips or warnings.
The docs are powered by [Docsify](https://docsify.now.sh/). Check out `docs/_sidebar.md` and `docs/components/` to get an idea of how pages are structured and formatted. If you're creating a new component, it may help to use an existing component's markdown file as a template.
If you need help with documentation, feel free to reach out on the [community chat](https://discord.gg/mg8f26C).
### Code Formatting
Most code formatting is handled automatically by [Prettier](https://prettier.io/) via commit hooks. However, for the best experience, you should [install it in your editor](https://prettier.io/docs/en/editors.html) and enable format on save.
Please do not make any changes to `prettier.config.cjs` without consulting the maintainers.
### Composability
Components should be composable, meaning you can easily reuse them with and within other components. This reduces the overall size of the library, expedites feature development, and maintains a consistent user experience.
The `<sl-select>` component, for example, makes use of the dropdown, input, menu, and menu item components. Because it's offloading most of its functionality and styles to lower-level components, the select component remains lightweight and its appearance is consistent with other form controls and menus.
### Component Stucture
All components have a host element, which is a reference to the `<sl-*>` element itself. Make sure to always set the host element's `display` property to the appropriate value depending on your needs, as the default is `inline` per the custom element spec.
```css
:host{
display:block;
}
```
Aside from `display`, avoid setting styles on the host element when possible. The reason for this is that styles applied to the host element are not encapsulated. Instead, create a base element that wraps the component's internals and style that instead. This convention also makes it easier to use BEM in components, as the base element can serve as the "block" entity.
### Class Names
All components use a [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM), so styles are completely encapsulated from the rest of the document. As a result, class names used _inside_ a component won't conflict with class names _outside_ the component, so we're free to name them anything we want.
Internally, each component uses the [BEM methodology](http://getbem.com/) for class names. There is no technical requirement to do this — it's purely the preference of the author to enforce consistency and clarity throughout components. As such, all contributions are expected to follow this pattern.
### Boolean Props
Boolean props should _always_ default to `false`, otherwise there's no way for the user to unset the, without JavaScript. To keep the API as friendly and consistent as possible, use a name like `noHeader` with a default value of `false` instead of `header` with a default value of `true`.
### Conditional Slots
When a component relies on the presence of slotted content to do something, don't assume its initial state is permanent. Slotted content can be added or removed any time and components must be aware of this. A good practice to manage this is:
- Add `@slotchange={this.handleSlotChange}` to the slots you want to watch
- Add a `handleSlotChange` method and use the `hasSlot` utility to update state variables for the the respective slot(s)
- Never conditionally render `<slot>` elements in a component — always use `hidden` so the slot remains in the DOM and the `slotchange` event can be captured
See the source of card, dialog, or drawer for examples.
### Custom Events
Components must only emit custom events, and all custom events must start with `sl-` as a namespace. For compatibility with frameworks that utilize DOM templates, custom events must have lowercase, kebab-style names. For example, use `sl-change` instead of `slChange`.
This convention avoids the problem of browsers lowercasing attributes, causing some frameworks to be unable to listen to them. This problem isn't specific to one framework, but [Vue's documentation](https://vuejs.org/v2/guide/components-custom-events.html#Event-Names) provides a good explanation of the problem.
### CSS Custom Properties
To expose custom properties as part of a component's API, scope them to the `:host` block.
Then use the following syntax for comments so they appear in the generated docs. Do not use the `--sl-` prefix, as that is reserved for design tokens that live in the global scope.
```js
/**
* @cssproperty --color: The component's text color.
* @cssproperty --background-color: The component's background color.
*/
@customElement('sl-example')
exportdefaultclassSlExample{
// ...
}
```
### When to use a property vs. a CSS custom property
When designing a component's API, standard properties are generally used to change the _behavior_ of a component, whereas CSS custom properties ("CSS variables") are used to change the _appearance_ of a component. Remember that properties can't respond to media queries, but CSS variables can.
There are some exceptions to this (e.g. when it significantly improves developer experience), but a good rule of thumbs is "will this need to change based on screen size?" If so, you probably want to use a CSS variable.
### When to use a CSS custom property vs. a CSS part
There are two ways to enable customizations for components. One way is with CSS custom properties ("CSS variables"), the other is with CSS parts ("parts").
CSS variables are scoped to the host element and can be reused throughout the component. A good example of a CSS variable would be `--border-width`, which might get reused throughout a component to ensure borders share the same width for all internal elements.
Parts let you target a specific element inside the component's shadow DOM but, by design, you can't target a part's children or siblings. You can _only_ customize the part itself. Use a part when you need to allow a single element inside the component to accept styles.
This convention can be relaxed when the developer experience is greatly improved by not following these suggestions.
### Design Token Color Values
All design tokens that implement a color value must do so in the following `R G B` format for consistency.
```css
:root{
--sl-color-sky-500:14165233;
}
```
This format requires the consumer to use the `rgb()` function in their stylesheets, but it also lets them control each token's alpha channel.
Border radius tokens are used to give sharp edges a more subtle, rounded effect. They use rem units so they scale with the base font size. The pixel values displayed are based on a 16px font size.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.