diff --git a/.claude/hooks/naglint.sh b/.claude/hooks/naglint.sh index dd0601e..3871d37 100755 --- a/.claude/hooks/naglint.sh +++ b/.claude/hooks/naglint.sh @@ -1,6 +1,5 @@ #!/bin/bash -# NagLint PostToolUse hook — runs after Write/Edit on .ts/.tsx/.js/.jsx files -# Reads tool_use JSON from stdin, extracts file_path, runs nag --agent-json +# NagLint PostToolUse hook — runs after Write/Edit on source files NAG=/Users/matsbosson/Documents/StayThree/NagLint/target/release/nag @@ -16,9 +15,8 @@ if [ -z "$FILE" ]; then exit 0 fi -# Only lint source files — skip config, json, yaml, md, etc. case "$FILE" in - *.ts|*.tsx|*.js|*.jsx) ;; + *.ts|*.tsx|*.js|*.jsx|*.mjs|*.cjs|*.mts|*.cts|*.rs) ;; *) echo "{}"; exit 0 ;; esac @@ -35,7 +33,6 @@ if [ "$RAW" = "{}" ] || [ -z "$RAW" ]; then fi # For .tsx/.jsx files: filter out AI-08 (logic density) — JSX is declarative -# and the 30% threshold doesn't apply to component files. case "$FILE" in *.tsx|*.jsx) FILTERED=$(echo "$RAW" | python3 -c " diff --git a/.claude/settings.json b/.claude/settings.json index b80df20..2c63c08 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,28 +1,2 @@ { - "hooks": { - "PreToolUse": [ - { - "matcher": "Write|Edit", - "hooks": [ - { - "type": "command", - "command": "jq -r '.tool_input.file_path // \"\"' | { read -r f; case \"$f\" in *.rs|*.js|*.jsx|*.mjs|*.cjs|*.ts|*.tsx|*.mts|*.cts) /Users/matsbosson/Documents/StayThree/NagLint/target/release/nag --rules-summary | jq -Rs '{hookSpecificOutput: {hookEventName: \"PreToolUse\", additionalContext: .}}';; *) echo '{}';; esac; }", - "statusMessage": "NagLint rules..." - } - ] - } - ], - "PostToolUse": [ - { - "matcher": "Write|Edit", - "hooks": [ - { - "type": "command", - "command": "/Users/matsbosson/Documents/StayThree/PettyUI/.claude/hooks/naglint.sh", - "statusMessage": "NagLint checking..." - } - ] - } - ] - } } diff --git a/.firecrawl/apis-for-ai.md b/.firecrawl/apis-for-ai.md deleted file mode 100644 index 3e9ff2a..0000000 --- a/.firecrawl/apis-for-ai.md +++ /dev/null @@ -1,2154 +0,0 @@ -![Revisit consent button](https://cdn-cookieyes.com/assets/images/revisit.svg) - -We value your privacy - -We use cookies to enhance your browsing experience, serve personalised ads or content, and analyse our traffic. By clicking "Accept All", you consent to our use of cookies. - -CustomiseReject AllAccept All - -Powered by [Visit CookieYes website](https://www.cookieyes.com/product/cookie-consent/?ref=cypbcyb&utm_source=cookie-banner&utm_medium=fl-branding) - -Customise Consent Preferences![](https://cdn-cookieyes.com/assets/images/close.svg) - -We use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below. - -The cookies that are categorised as "Necessary" are stored on your browser as they are essential for enabling the basic functionalities of the site. ... Show more - -NecessaryAlways Active - -Necessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data. - -- Cookie - -\_\_eoi - -- Duration - -6 months - -- Description - -Description is currently not available. - - -- Cookie - -\_\_cf\_bm - -- Duration - -1 hour - -- Description - -This cookie, set by Cloudflare, is used to support Cloudflare Bot Management. - - -- Cookie - -\_cfuvid - -- Duration - -session - -- Description - -Cloudflare sets this cookie to track users across sessions to optimize user experience by maintaining session consistency and providing personalized services - - -- Cookie - -AWSALBCORS - -- Duration - -7 days - -- Description - -Amazon Web Services set this cookie for load balancing. - - -- Cookie - -li\_gc - -- Duration - -6 months - -- Description - -Linkedin set this cookie for storing visitor's consent regarding using cookies for non-essential purposes. - - -- Cookie - -\_\_hssrc - -- Duration - -session - -- Description - -This cookie is set by Hubspot whenever it changes the session cookie. The \_\_hssrc cookie set to 1 indicates that the user has restarted the browser, and if the cookie does not exist, it is assumed to be a new session. - - -- Cookie - -\_\_hssc - -- Duration - -1 hour - -- Description - -HubSpot sets this cookie to keep track of sessions and to determine if HubSpot should increment the session number and timestamps in the \_\_hstc cookie. - - -- Cookie - -AWSALB - -- Duration - -7 days - -- Description - -AWSALB is an application load balancer cookie set by Amazon Web Services to map the session to the target. - - -- Cookie - -\_\_Secure-YNID - -- Duration - -6 months - -- Description - -Google cookie used to protect user security and prevent fraud, especially during the login process. - - -- Cookie - -jwtOnAir - -- Duration - -1 month 1 day - -- Description - -Description is currently not available. - - -- Cookie - -jwt - -- Duration - -1 month 1 day - -- Description - -No description available. - - -- Cookie - -csrfToken - -- Duration - -1 month 1 day - -- Description - -Description is currently not available. - - -- Cookie - -\_octo - -- Duration - -1 year - -- Description - -No description available. - - -- Cookie - -logged\_in - -- Duration - -1 year - -- Description - -No description available. - - -- Cookie - -csrf\_token - -- Duration - -session - -- Description - -No description available. - - -- Cookie - -token\_v2 - -- Duration - -1 day - -- Description - -Description is currently not available. - - -- Cookie - -VISITOR\_PRIVACY\_METADATA - -- Duration - -6 months - -- Description - -YouTube sets this cookie to store the user's cookie consent state for the current domain. - - -- Cookie - -yt.innertube::nextId - -- Duration - -Never Expires - -- Description - -YouTube sets this cookie to register a unique ID to store data on what videos from YouTube the user has seen. - - -- Cookie - -yt.innertube::requests - -- Duration - -Never Expires - -- Description - -YouTube sets this cookie to register a unique ID to store data on what videos from YouTube the user has seen. - - -- Cookie - -session\_tracker - -- Duration - -session - -- Description - -This cookie is set by the Reddit. This cookie is used to identify trusted web traffic. It also helps in adverstising on the website. - - -- Cookie - -YSC - -- Duration - -session - -- Description - -YSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages. - - -- Cookie - -VISITOR\_INFO1\_LIVE - -- Duration - -6 months - -- Description - -A cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface. - - -- Cookie - -yt-remote-connected-devices - -- Duration - -Never Expires - -- Description - -YouTube sets this cookie to store the user's video preferences using embedded YouTube videos. - - -- Cookie - -ytidb::LAST\_RESULT\_ENTRY\_KEY - -- Duration - -Never Expires - -- Description - -The cookie ytidb::LAST\_RESULT\_ENTRY\_KEY is used by YouTube to store the last search result entry that was clicked by the user. This information is used to improve the user experience by providing more relevant search results in the future. - - -- Cookie - -yt-remote-device-id - -- Duration - -Never Expires - -- Description - -YouTube sets this cookie to store the user's video preferences using embedded YouTube videos. - - -- Cookie - -yt-remote-session-name - -- Duration - -session - -- Description - -The yt-remote-session-name cookie is used by YouTube to store the user's video player preferences using embedded YouTube video. - - -- Cookie - -yt-remote-fast-check-period - -- Duration - -session - -- Description - -The yt-remote-fast-check-period cookie is used by YouTube to store the user's video player preferences for embedded YouTube videos. - - -- Cookie - -yt-remote-session-app - -- Duration - -session - -- Description - -The yt-remote-session-app cookie is used by YouTube to store user preferences and information about the interface of the embedded YouTube video player. - - -- Cookie - -yt-remote-cast-available - -- Duration - -session - -- Description - -The yt-remote-cast-available cookie is used to store the user's preferences regarding whether casting is available on their YouTube video player. - - -- Cookie - -yt-remote-cast-installed - -- Duration - -session - -- Description - -The yt-remote-cast-installed cookie is used to store the user's video player preferences using embedded YouTube video. - - -- Cookie - -currency - -- Duration - -session - -- Description - -This cookie is used to store the currency preference of the user. - - -- Cookie - -cookieyes-consent - -- Duration - -1 year - -- Description - -CookieYes sets this cookie to remember users' consent preferences so that their preferences are respected on subsequent visits to this site. It does not collect or store any personal information about the site visitors. - - -- Cookie - -test\_cookie - -- Duration - -15 minutes - -- Description - -doubleclick.net sets this cookie to determine if the user's browser supports cookies. - - -- Cookie - -pxcts - -- Duration - -session - -- Description - -Description is currently not available. - - -- Cookie - -bStore - -- Duration - -Less than a minute - -- Description - -Description is currently not available. - - -- Cookie - -JSESSIONID - -- Duration - -session - -- Description - -New Relic uses this cookie to store a session identifier so that New Relic can monitor session counts for an application. - - -- Cookie - -\_pxvid - -- Duration - -1 year - -- Description - -PerimeterX sets this cookie to detect fraud and bot activity. - - -- Cookie - -\_px3 - -- Duration - -6 minutes - -- Description - -This cookie is set by the Bloomberg to protect the site from BOT attacks. - - -- Cookie - -cookietest - -- Duration - -session - -- Description - -The cookietest cookie is typically used to determine whether the user's browser accepts cookies, essential for website functionality and user experience. - - -- Cookie - -cf\_use\_ob - -- Duration - -1 minute - -- Description - -Cloudflare sets this cookie to improve page load times and to disallow any security restrictions based on the visitor's IP address. - - -Functional - -Functional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features. - -- Cookie - -BCTempID - -- Duration - -10 minutes - -- Description - -No description available. - - -- Cookie - -BCSessionID - -- Duration - -1 year 1 month 4 days - -- Description - -Blueconic sets this cookie as a unique identifier for the BlueConic profile. - - -- Cookie - -lidc - -- Duration - -1 day - -- Description - -LinkedIn sets the lidc cookie to facilitate data center selection. - - -- Cookie - -loid - -- Duration - -1 year 1 month 4 days - -- Description - -This cookie is set by the Reddit. The cookie enables the sharing of content from the website onto the social media platform. - - -- Cookie - -lang - -- Duration - -session - -- Description - -LinkedIn sets this cookie to remember a user's language setting. - - -Analytics - -Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc. - -- Cookie - -taboola\_session\_id - -- Duration - -session - -- Description - -This cookie is owned by trc.taboola.com and is used to create a temporary session ID to prevent duplicate recommendations from being displayed on the page. - - -- Cookie - -\_ga\_\* - -- Duration - -1 year 1 month 4 days - -- Description - -Google Analytics sets this cookie to store and count page views. - - -- Cookie - -\_ga - -- Duration - -1 year 1 month 4 days - -- Description - -Google Analytics sets this cookie to calculate visitor, session and campaign data and track site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognise unique visitors. - - -- Cookie - -\_\_hstc - -- Duration - -6 months - -- Description - -Hubspot set this main cookie for tracking visitors. It contains the domain, initial timestamp (first visit), last timestamp (last visit), current timestamp (this visit), and session number (increments for each subsequent session). - - -- Cookie - -hubspotutk - -- Duration - -6 months - -- Description - -HubSpot sets this cookie to keep track of the visitors to the website. This cookie is passed to HubSpot on form submission and used when deduplicating contacts. - - -- Cookie - -\_gh\_sess - -- Duration - -session - -- Description - -GitHub sets this cookie for temporary application and framework state between pages like what step the user is on in a multiple step form. - - -- Cookie - -\_clck - -- Duration - -1 year - -- Description - -Microsoft Clarity sets this cookie to retain the browser's Clarity User ID and settings exclusive to that website. This guarantees that actions taken during subsequent visits to the same website will be linked to the same user ID. - - -- Cookie - -\_clsk - -- Duration - -1 day - -- Description - -Microsoft Clarity sets this cookie to store and consolidate a user's pageviews into a single session recording. - - -- Cookie - -mp\_\*\_mixpanel - -- Duration - -Never Expires - -- Description - -Mixpanel sets this cookie to determine how users use the website so that a good user experience can be provided. - - -- Cookie - -browser\_id - -- Duration - -5 years - -- Description - -This cookie is used for identifying the visitor browser on re-visit to the website. - - -- Cookie - -li\_alerts - -- Duration - -1 year - -- Description - -LinkedIn sets this cookie to track impressions of LinkedIn alerts, such as the Cookie Banner and to implement cool-off periods for display of alerts. - - -- Cookie - -MR - -- Duration - -7 days - -- Description - -This cookie, set by Bing, is used to collect user information for analytics purposes. - - -Performance - -Performance cookies are used to understand and analyse the key performance indexes of the website which helps in delivering a better user experience for the visitors. - -- Cookie - -\_uetsid - -- Duration - -1 day - -- Description - -Bing Ads sets this cookie to engage with a user that has previously visited the website. - - -- Cookie - -\_uetvid - -- Duration - -1 year 24 days - -- Description - -Bing Ads sets this cookie to engage with a user that has previously visited the website. - - -Advertisement - -Advertisement cookies are used to provide visitors with customised advertisements based on the pages you visited previously and to analyse the effectiveness of the ad campaigns. - -- Cookie - -t\_pt\_gid - -- Duration - -1 year - -- Description - -Description is currently not available. - - -- Cookie - -muc\_ads - -- Duration - -1 year 1 month 4 days - -- Description - -Twitter sets this cookie to collect user behaviour and interaction data to optimize the website. - - -- Cookie - -guest\_id\_marketing - -- Duration - -1 year 1 month 4 days - -- Description - -Twitter sets this cookie to identify and track the website visitor. - - -- Cookie - -guest\_id\_ads - -- Duration - -1 year 1 month 4 days - -- Description - -Twitter sets this cookie to identify and track the website visitor. - - -- Cookie - -personalization\_id - -- Duration - -1 year 1 month 4 days - -- Description - -Twitter sets this cookie to integrate and share features for social media and also store information about how the user uses the website, for tracking and targeting. - - -- Cookie - -guest\_id - -- Duration - -1 year 1 month 4 days - -- Description - -Twitter sets this cookie to identify and track the website visitor. It registers if a user is signed in to the Twitter platform and collects information about ad preferences. - - -- Cookie - -bcookie - -- Duration - -1 year - -- Description - -LinkedIn sets this cookie from LinkedIn share buttons and ad tags to recognize browser IDs. - - -- Cookie - -\_gcl\_au - -- Duration - -3 months - -- Description - -Google Tag Manager sets this cookie to experiment advertisement efficiency of websites using their services. - - -- Cookie - -t\_gid - -- Duration - -1 year - -- Description - -Taboola sets this cookie by assigning a specific ID for attribution and reporting purposes and to tailor recommendations to the user. - - -- Cookie - -\_fbp - -- Duration - -3 months - -- Description - -Facebook sets this cookie to store and track interactions. - - -- Cookie - -MUID - -- Duration - -1 year 24 days - -- Description - -Bing sets this cookie to recognise unique web browsers visiting Microsoft sites. This cookie is used for advertising, site analytics, and other operations. - - -- Cookie - -bscookie - -- Duration - -1 year - -- Description - -LinkedIn sets this cookie to store performed actions on the website. - - -Uncategorised - -Other uncategorised cookies are those that are being analysed and have not been classified into a category as yet. - -No cookies to display. - -Reject AllSave My PreferencesAccept All - -Powered by [Visit CookieYes website](https://www.cookieyes.com/product/cookie-consent/?ref=cypbcyb&utm_source=cookie-banner&utm_medium=sl-branding) - -TNS - - -OK - - -As a JavaScript developer, what non-React tools do you use most often? - -✓ - -Angular - -0% - -✓ - -Astro - -0% - -✓ - -Svelte - -0% - -✓ - -Vue.js - -0% - -✓ - -Other - -0% - -✓ - -I only use React - -0% - -✓ - -I don't use JavaScript - -0% - -Thanks for your opinion! Subscribe below to get the final results, published -exclusively in our TNS Update newsletter: - - -SUBMIT - -[The New Stack Frontpage](https://thenewstack.io/) - -NEW! Try Stackie AI - - -LOGIN - -ARCHITECTURE - - -[Cloud Native Ecosystem](https://thenewstack.io/cloud-native/) [Containers](https://thenewstack.io/containers/) [Databases](https://thenewstack.io/databases/) [Edge Computing](https://thenewstack.io/edge-computing/) [Infrastructure as Code](https://thenewstack.io/infrastructure-as-code/) [Linux](https://thenewstack.io/linux/) [Microservices](https://thenewstack.io/microservices/) [Open Source](https://thenewstack.io/open-source/) [Networking](https://thenewstack.io/networking/) [Storage](https://thenewstack.io/storage/) - -ENGINEERING - - -[AI](https://thenewstack.io/ai/) [AI Engineering](https://thenewstack.io/ai-engineering/) [API Management](https://thenewstack.io/api-management/) [Backend development](https://thenewstack.io/backend-development/) [Data](https://thenewstack.io/data/) [Frontend Development](https://thenewstack.io/frontend-development/) [Large Language Models](https://thenewstack.io/llm/) [Security](https://thenewstack.io/security/) [Software Development](https://thenewstack.io/software-development/) [WebAssembly](https://thenewstack.io/webassembly/) - -OPERATIONS - - -[AI Operations](https://thenewstack.io/ai-operations/) [CI/CD](https://thenewstack.io/ci-cd/) [Cloud Services](https://thenewstack.io/cloud-services/) [DevOps](https://thenewstack.io/devops/) [Kubernetes](https://thenewstack.io/kubernetes/) [Observability](https://thenewstack.io/observability/) [Operations](https://thenewstack.io/operations/) [Platform Engineering](https://thenewstack.io/platform-engineering/) - -PROGRAMMING - - -[C++](https://thenewstack.io/c/) [Developer tools](https://thenewstack.io/developer-tools/) [Go](https://thenewstack.io/go/) [Java](https://thenewstack.io/java/) [JavaScript](https://thenewstack.io/javascript/) [Programming Languages](https://thenewstack.io/programming-languages/) [Python](https://thenewstack.io/python/) [Rust](https://thenewstack.io/rust/) [TypeScript](https://thenewstack.io/typescript/) - -CHANNELS - - -[Podcasts](https://thenewstack.io/podcasts/) [Ebooks](https://thenewstack.io/ebooks/) [Events](https://thenewstack.io/events/) [Webinars](https://thenewstack.io/webinars/) [Newsletter](https://thenewstack.io/newsletter/) [TNS RSS Feeds](https://thenewstack.io/rss-feeds/) - -THE NEW STACK - - -[About / Contact](https://thenewstack.io/about-and-contact-info/) [Sponsors](https://thenewstack.io/sponsors/) [Advertise With Us](https://thenewstack.io/sponsorship/) [Contributions](https://thenewstack.io/contributions/) - -[PODCASTS](https://thenewstack.io/podcasts/) [EBOOKS](https://thenewstack.io/ebooks/) [EVENTS](https://thenewstack.io/events/) [WEBINARS](https://thenewstack.io/webinars/) [NEWSLETTER](https://thenewstack.io/newsletter/) [CONTRIBUTE](https://thenewstack.io/contributions/) - -[ARCHITECTURE](https://thenewstack.io/its-time-to-build-apis-for-ai-not-just-for-developers/#) [ENGINEERING](https://thenewstack.io/its-time-to-build-apis-for-ai-not-just-for-developers/#) [OPERATIONS](https://thenewstack.io/its-time-to-build-apis-for-ai-not-just-for-developers/#) [PROGRAMMING](https://thenewstack.io/its-time-to-build-apis-for-ai-not-just-for-developers/#) - -[Cloud Native Ecosystem](https://thenewstack.io/cloud-native/) [Containers](https://thenewstack.io/containers/) [Databases](https://thenewstack.io/databases/) [Edge Computing](https://thenewstack.io/edge-computing/) [Infrastructure as Code](https://thenewstack.io/infrastructure-as-code/) [Linux](https://thenewstack.io/linux/) [Microservices](https://thenewstack.io/microservices/) [Open Source](https://thenewstack.io/open-source/) [Networking](https://thenewstack.io/networking/) [Storage](https://thenewstack.io/storage/) - -[Why WebAssembly won't replace Kubernetes but makes Helm more secure\\ -\\ -\\ -Mar 21st 2026 8:45am, by \\ -B. Cameron Gain](https://thenewstack.io/helm-webassembly-kubernetes-security/) - -[Why the ‘glorified host’ for AI is exactly the Kubernetes we need\\ -\\ -\\ -Mar 20th 2026 9:00am, by \\ -Danielle Cook](https://thenewstack.io/kubernetes-glorified-ai-host/) - -[Linux kernel scale is swamping an already-flawed CVE system\\ -\\ -\\ -Mar 20th 2026 4:30am, by \\ -Jed Salazar](https://thenewstack.io/linux-kernel-cve-system/) - -[Sampling: the philosopher's stone of distributed tracing\\ -\\ -\\ -Mar 19th 2026 8:00am, by \\ -Michele Mancioppi](https://thenewstack.io/distributed-tracing-sampling-opentelemetry/) - -[What is KubeVirt and why it’s growing\\ -\\ -\\ -Mar 17th 2026 9:00am, by \\ -Tiago Castro](https://thenewstack.io/kubevirt-live-migration-mayastor/) - -[Edera spent years calling KVM less secure. Here's why it changed its mind.\\ -\\ -\\ -Mar 25th 2026 2:22pm, by \\ -Steven J. Vaughan-Nichols](https://thenewstack.io/edera-adds-kvm-support/) - -[Minimus aims to solve one of open-source's long-festering problems\\ -\\ -\\ -Mar 24th 2026 3:00am, by \\ -Adrian Bridgwater](https://thenewstack.io/minimus-open-source-container-security/) - -[How to deploy Pi-Hole with Docker and stop ads on every device on your LAN\\ -\\ -\\ -Mar 23rd 2026 7:44am, by \\ -Jack Wallen](https://thenewstack.io/pihole-docker-network-adblocking/) - -[Chainguard has a fix for the open source packages your AI agents keep grabbing\\ -\\ -\\ -Mar 18th 2026 9:24am, by \\ -Darryl K. Taft](https://thenewstack.io/chainguard-repository-ai-agents/) - -[Chainguard thinks most DevOps teams are solving container security the hard way\\ -\\ -\\ -Mar 17th 2026 1:04pm, by \\ -Steven J. Vaughan-Nichols](https://thenewstack.io/chainguard-os-packages-containers/) - -[Scaling Btrfs to petabytes in production: a 74% cost reduction story\\ -\\ -\\ -Mar 18th 2026 5:00am, by \\ -Motiejus Jakštys](https://thenewstack.io/btrfs-petabyte-cost-reduction/) - -[The “files are all you need” debate misses what's actually happening in agent memory architecture\\ -\\ -\\ -Mar 13th 2026 5:00am, by \\ -Mikiko Bazeley](https://thenewstack.io/ai-agent-memory-architecture/) - -[With GridGain acquisition, MariaDB bets on in-memory computing and Apache Ignite\\ -\\ -\\ -Mar 10th 2026 6:47am, by \\ -Paul Sawers](https://thenewstack.io/with-gridgain-acquisition-mariadb-bets-on-in-memory-computing-and-apache-ignite/) - -[Moving AI apps from prototype to production requires enterprise-grade postgres infrastructure\\ -\\ -\\ -Mar 9th 2026 7:00am, by \\ -Meredith Shubel](https://thenewstack.io/ai-prototype-to-production-postgres/) - -[Why the "bible" of data systems is getting a massive rewrite for 2026\\ -\\ -\\ -Mar 4th 2026 5:00am, by \\ -Cynthia Dunlop](https://thenewstack.io/data-intensive-applications-rewrite-2026/) - -[Developers are coding to a moving target, and nobody knows where AI lands next\\ -\\ -\\ -Mar 3rd 2026 7:33am, by \\ -Adrian Bridgwater](https://thenewstack.io/developers-coding-moving-target-ai/) - -[Cloudflare’s new Markdown support shows how the web is evolving for AI agents\\ -\\ -\\ -Mar 2nd 2026 4:30am, by \\ -David Eastman](https://thenewstack.io/intent-engineering-ai-agents/) - -[React Server Components Vulnerability Found\\ -\\ -\\ -Dec 6th 2025 7:00am, by \\ -Loraine Lawson](https://thenewstack.io/react-server-components-vulnerability-found/) - -[Kubernetes at the Edge: Lessons From GE HealthCare’s Edge Strategy\\ -\\ -\\ -Nov 24th 2025 10:00am, by \\ -Vicki Walker](https://thenewstack.io/kubernetes-at-the-edge-lessons-from-ge-healthcares-edge-strategy/) - -[Building a Cloud-to-Edge Architecture Across 40K Global Locations\\ -\\ -\\ -Nov 20th 2025 10:00am, by \\ -Vicki Walker](https://thenewstack.io/building-a-cloud-to-edge-architecture-across-40k-global-locations/) - -[The operational gap is real, and it's getting wider\\ -\\ -\\ -Mar 26th 2026 8:00am, by \\ -Yevgeny Pats](https://thenewstack.io/closing-cloud-operational-gap/) - -[Why "automated" infrastructure might cost more than you think\\ -\\ -\\ -Feb 24th 2026 4:00am, by \\ -Justyn Roberts](https://thenewstack.io/automated-infrastructure-hidden-costs/) - -[Why 40% of AI projects will be canceled by 2027 (and how to stay in the other 60%)\\ -\\ -\\ -Feb 13th 2026 6:00am, by \\ -Alex Drag](https://thenewstack.io/agentic-ai-connectivity-platform/) - -[Durable Execution: Build reliable software in an unreliable world\\ -\\ -\\ -Feb 2nd 2026 3:23pm, by \\ -Charles Humble](https://thenewstack.io/temporal-durable-execution-platform/) - -[Terraform challenger Formae expands to more clouds\\ -\\ -\\ -Jan 28th 2026 6:00am, by \\ -Joab Jackson](https://thenewstack.io/terraform-competitor-formae-expands-to-more-clouds/) - -[Edera spent years calling KVM less secure. Here's why it changed its mind.\\ -\\ -\\ -Mar 25th 2026 2:22pm, by \\ -Steven J. Vaughan-Nichols](https://thenewstack.io/edera-adds-kvm-support/) - -[Linux kernel scale is swamping an already-flawed CVE system\\ -\\ -\\ -Mar 20th 2026 4:30am, by \\ -Jed Salazar](https://thenewstack.io/linux-kernel-cve-system/) - -[Scaling Btrfs to petabytes in production: a 74% cost reduction story\\ -\\ -\\ -Mar 18th 2026 5:00am, by \\ -Motiejus Jakštys](https://thenewstack.io/btrfs-petabyte-cost-reduction/) - -[Chainguard thinks most DevOps teams are solving container security the hard way\\ -\\ -\\ -Mar 17th 2026 1:04pm, by \\ -Steven J. Vaughan-Nichols](https://thenewstack.io/chainguard-os-packages-containers/) - -[Tromjaro is a free-trade Linux distribution with plenty to offer\\ -\\ -\\ -Mar 14th 2026 11:00am, by \\ -Jack Wallen](https://thenewstack.io/tromjaro-is-a-free-trade-linux-distribution-with-plenty-to-offer/) - -[Tetrate launches open source marketplace to simplify Envoy adoption\\ -\\ -\\ -Mar 11th 2026 10:52am, by \\ -Adrian Bridgwater](https://thenewstack.io/tetrate-built-on-envoy/) - -[OpenTelemetry roadmap: Sampling rates and collector improvements ahead\\ -\\ -\\ -Feb 24th 2026 11:00am, by \\ -B. Cameron Gain](https://thenewstack.io/opentelemetry-roadmap-sampling-rates-and-collector-improvements-ahead/) - -[Merging To Test Is Killing Your Microservices Velocity\\ -\\ -\\ -Dec 16th 2025 7:00am, by \\ -Arjun Iyer](https://thenewstack.io/merging-to-test-is-killing-your-microservices-velocity/) - -[IBM’s Confluent Acquisition Is About Event-Driven AI\\ -\\ -\\ -Dec 11th 2025 6:00am, by \\ -Joab Jackson](https://thenewstack.io/ibms-confluent-acquisition-is-about-event-driven-ai/) - -[Deploy Agentic AI Workflows With Kubernetes and Terraform\\ -\\ -\\ -Nov 26th 2025 9:00am, by \\ -Oladimeji Sowole](https://thenewstack.io/deploy-agentic-ai-workflows-with-kubernetes-and-terraform/) - -[Edera spent years calling KVM less secure. Here's why it changed its mind.\\ -\\ -\\ -Mar 25th 2026 2:22pm, by \\ -Steven J. Vaughan-Nichols](https://thenewstack.io/edera-adds-kvm-support/) - -[Broadcom donates Velero to CNCF — and it could reshape how Kubernetes users handle backup and disaster recovery\\ -\\ -\\ -Mar 24th 2026 8:38am, by \\ -B. Cameron Gain](https://thenewstack.io/broadcom-velero-cncf-kubernetes/) - -[Minimus aims to solve one of open-source's long-festering problems\\ -\\ -\\ -Mar 24th 2026 3:00am, by \\ -Adrian Bridgwater](https://thenewstack.io/minimus-open-source-container-security/) - -[China is winning the open source AI race — but a US company still controls everything underneath\\ -\\ -\\ -Mar 20th 2026 10:46am, by \\ -Paul Sawers](https://thenewstack.io/china-leads-open-ai-models/) - -[From pillars to platform: How open observability data is changing the industry\\ -\\ -\\ -Mar 20th 2026 6:00am, by \\ -Ted Young](https://thenewstack.io/open-observability-ai-platforms/) - -[How to deploy Pi-Hole with Docker and stop ads on every device on your LAN\\ -\\ -\\ -Mar 23rd 2026 7:44am, by \\ -Jack Wallen](https://thenewstack.io/pihole-docker-network-adblocking/) - -[Why flat Kubernetes networks fail at scale\\ -\\ -\\ -Mar 20th 2026 7:00am, by \\ -Reza Ramezanpour](https://thenewstack.io/kubernetes-network-security-hierarchies/) - -[GSMA Open Gateway offers developers one API for 300+ mobile networks\\ -\\ -\\ -Mar 4th 2026 10:26am, by \\ -Adrian Bridgwater](https://thenewstack.io/gsma-open-gateway-developers/) - -[How Homepage simplifies monitoring your self-hosted services\\ -\\ -\\ -Feb 6th 2026 8:00am, by \\ -Jack Wallen](https://thenewstack.io/how-homepage-simplifies-monitoring-your-self-hosted-services/) - -[S3 is the new network: Rethinking data architecture for the cloud era\\ -\\ -\\ -Feb 2nd 2026 4:00am, by \\ -Max Liu](https://thenewstack.io/tidb-x-open-source-database/) - -[Scaling Btrfs to petabytes in production: a 74% cost reduction story\\ -\\ -\\ -Mar 18th 2026 5:00am, by \\ -Motiejus Jakštys](https://thenewstack.io/btrfs-petabyte-cost-reduction/) - -[What is KubeVirt and why it’s growing\\ -\\ -\\ -Mar 17th 2026 9:00am, by \\ -Tiago Castro](https://thenewstack.io/kubevirt-live-migration-mayastor/) - -[S3 is the new network: Rethinking data architecture for the cloud era\\ -\\ -\\ -Feb 2nd 2026 4:00am, by \\ -Max Liu](https://thenewstack.io/tidb-x-open-source-database/) - -[Agoda’s secret to 50x scale: Getting the database basics right\\ -\\ -\\ -Jan 28th 2026 7:00am, by \\ -Cynthia Dunlop](https://thenewstack.io/agodas-secret-to-50x-scale-getting-the-database-basics-right/) - -[Chainguard EmeritOSS backs MinIO, other orphaned projects\\ -\\ -\\ -Jan 27th 2026 6:15am, by \\ -Steven J. Vaughan-Nichols](https://thenewstack.io/chainguard-emeritoss-backs-minio-other-orphaned-projects/) - -[AI](https://thenewstack.io/ai/) [AI Engineering](https://thenewstack.io/ai-engineering/) [API Management](https://thenewstack.io/api-management/) [Backend development](https://thenewstack.io/backend-development/) [Data](https://thenewstack.io/data/) [Frontend Development](https://thenewstack.io/frontend-development/) [Large Language Models](https://thenewstack.io/llm/) [Security](https://thenewstack.io/security/) [Software Development](https://thenewstack.io/software-development/) [WebAssembly](https://thenewstack.io/webassembly/) - -[Claude can now open apps, click buttons, and complete tasks on your Mac — but Anthropic says risks remain](https://thenewstack.io/claude-computer-use/) - -Mar 25th 2026 4:36am, by [Meredith Shubel](https://thenewstack.io/author/mshubel/ "Posts by Meredith Shubel") - -[Ai2 launches MolmoWeb, an open-source web agent](https://thenewstack.io/ai2-launches-molmoweb-an-open-source-web-agent/) - -Mar 24th 2026 9:07am, by [Frederic Lardinois](https://thenewstack.io/author/frederic-lardinois/ "Posts by Frederic Lardinois") - -[Four prompt engineering patterns every developer should know — and why "draw a cat" explains them all](https://thenewstack.io/prompt-engineering-for-developers/) - -Mar 23rd 2026 11:00am, by [Jessica Wachtel](https://thenewstack.io/author/jessica-wachtel/ "Posts by Jessica Wachtel") - -[China is winning the open source AI race — but a US company still controls everything underneath](https://thenewstack.io/china-leads-open-ai-models/) - -Mar 20th 2026 10:46am, by [Paul Sawers](https://thenewstack.io/author/paul-sawers/ "Posts by Paul Sawers") - -[Cursor's Composer 2 beats Opus 4.6 on coding benchmarks at a fraction of the price](https://thenewstack.io/cursors-composer-2-beats-opus/) - -Mar 19th 2026 8:39am, by [Frederic Lardinois](https://thenewstack.io/author/frederic-lardinois/ "Posts by Frederic Lardinois") - -[Why online stores keep showing the wrong products — and why tensors fix it](https://thenewstack.io/tensor-ranking-product-discovery/) - -Mar 25th 2026 6:00am, by [Tim Young](https://thenewstack.io/author/tim-young/ "Posts by Tim Young") - -[OpenClaw's biggest security flaw is why Jentic Mini exists](https://thenewstack.io/openclaw-is-a-security-mess-jentic-wants-to-fix-it/) - -Mar 25th 2026 5:00am, by [Darryl K. Taft](https://thenewstack.io/author/darryl-taft/ "Posts by Darryl K. Taft") - -[Why most AI projects fail after the demo actually works](https://thenewstack.io/ai-demo-to-production/) - -Mar 25th 2026 4:00am, by [Oladimeji Sowole](https://thenewstack.io/author/oladimeji-sowole/ "Posts by Oladimeji Sowole") - -[PwC's AI agents are now your consultants -- whether you're ready or not](https://thenewstack.io/pwcs-ai-agents-are-now-your-consultants-whether-youre-ready-or-not/) - -Mar 24th 2026 6:00am, by [Darryl K. Taft](https://thenewstack.io/author/darryl-taft/ "Posts by Darryl K. Taft") - -[Four prompt engineering patterns every developer should know — and why "draw a cat" explains them all](https://thenewstack.io/prompt-engineering-for-developers/) - -Mar 23rd 2026 11:00am, by [Jessica Wachtel](https://thenewstack.io/author/jessica-wachtel/ "Posts by Jessica Wachtel") - -[MCP is everywhere, but don't panic. Here's why your existing APIs still matter.](https://thenewstack.io/api-mcp-agent-integration/) - -Mar 23rd 2026 5:00am, by [Camille Crowell-Lee](https://thenewstack.io/author/camille-crowell-lee/ "Posts by Camille Crowell-Lee") and [Morgan Fine](https://thenewstack.io/author/morgan-fine/ "Posts by Morgan Fine") - -[Before you let AI agents loose, you’d better know what they’re capable of](https://thenewstack.io/risk-mitigation-agentic-ai/) - -Mar 12th 2026 1:22pm, by [Charles Humble](https://thenewstack.io/author/charles-humble/ "Posts by Charles Humble") - -[GSMA Open Gateway offers developers one API for 300+ mobile networks](https://thenewstack.io/gsma-open-gateway-developers/) - -Mar 4th 2026 10:26am, by [Adrian Bridgwater](https://thenewstack.io/author/adrian-bridgwater/ "Posts by Adrian Bridgwater") - -[Your AI strategy is built on layers of API sediment](https://thenewstack.io/ai-strategy-api-sediment/) - -Feb 17th 2026 9:37am, by [Charles Humble](https://thenewstack.io/author/charles-humble/ "Posts by Charles Humble") - -[Solving the Problems That Accompany API Sprawl With AI](https://thenewstack.io/solving-the-problems-that-accompany-api-sprawl-with-ai/) - -Jan 15th 2026 1:00pm, by [Heather Joslyn](https://thenewstack.io/author/hjoslyn/ "Posts by Heather Joslyn") - -[Backend Development in 2026: What's Changed, What Matters, and What to Learn Next](https://thenewstack.io/introduction-to-backend-development/) - -Mar 19th 2026 11:37am, by [TNS Staff](https://thenewstack.io/author/tns-staff/ "Posts by TNS Staff") - -[How To Get DNS Right: A Guide to Common Failure Modes](https://thenewstack.io/how-to-get-dns-right-a-guide-to-common-failure-modes/) - -Dec 24th 2025 8:00am, by [Sheldon Pereira](https://thenewstack.io/author/sheldon-pereira/ "Posts by Sheldon Pereira") and [Denton Chikura](https://thenewstack.io/author/denton-chikura/ "Posts by Denton Chikura") - -[Combining Rust and Python for High-Performance AI Systems](https://thenewstack.io/combining-rust-and-python-for-high-performance-ai-systems/) - -Dec 3rd 2025 1:00pm, by [Zziwa Raymond Ian](https://thenewstack.io/author/zziwa-raymond/ "Posts by Zziwa Raymond Ian") - -[How MCP Uses Streamable HTTP for Real-Time AI Tool Interaction](https://thenewstack.io/how-mcp-uses-streamable-http-for-real-time-ai-tool-interaction/) - -Aug 18th 2025 10:34am, by [Janakiram MSV](https://thenewstack.io/author/janakiram/ "Posts by Janakiram MSV") - -[A Backend for Frontend: Watt for Node.js Simplifies Operations](https://thenewstack.io/a-backend-for-frontend-watt-for-node-js-simplifies-operations/) - -Aug 14th 2025 6:00am, by [Loraine Lawson](https://thenewstack.io/author/loraine-lawson/ "Posts by Loraine Lawson") - -[Fivetran donates its SQLMesh data transformation framework to the Linux Foundation](https://thenewstack.io/fivetran-donates-sqlmesh-lf/) - -Mar 25th 2026 7:39am, by [Frederic Lardinois](https://thenewstack.io/author/frederic-lardinois/ "Posts by Frederic Lardinois") - -[Ex-Snowflake engineers say there's a blind spot in data engineering — so they built Tower to fix it](https://thenewstack.io/tower-python-data-pipelines/) - -Mar 15th 2026 7:00am, by [Paul Sawers](https://thenewstack.io/author/paul-sawers/ "Posts by Paul Sawers") - -[Why the "bible" of data systems is getting a massive rewrite for 2026](https://thenewstack.io/data-intensive-applications-rewrite-2026/) - -Mar 4th 2026 5:00am, by [Cynthia Dunlop](https://thenewstack.io/author/cynthiadunlop/ "Posts by Cynthia Dunlop") - -[How to clone a drive to an image with Clonezilla](https://thenewstack.io/how-to-clone-a-drive-to-an-image-with-clonezilla/) - -Mar 3rd 2026 1:00pm, by [Jack Wallen](https://thenewstack.io/author/jack-wallen/ "Posts by Jack Wallen") - -[Databases weren’t built for agent sprawl – SurrealDB wants to fix it](https://thenewstack.io/surrealdb-3-ai-agents/) - -Feb 24th 2026 2:07pm, by [Paul Sawers](https://thenewstack.io/author/paul-sawers/ "Posts by Paul Sawers") - -[WebMCP turns any Chrome web page into an MCP server for AI agents](https://thenewstack.io/webmcp-chrome-ai-agents/) - -Mar 17th 2026 11:50am, by [David Eastman](https://thenewstack.io/author/david-eastman/ "Posts by David Eastman") - -[Confluent adds A2A support, anomaly detection, and Queues for Kafka in major platform update](https://thenewstack.io/confluent-kafka-a2a-agents/) - -Mar 3rd 2026 10:21am, by [Jelani Harper](https://thenewstack.io/author/jelani-harper/ "Posts by Jelani Harper") - -[Google's Chrome browser moves to a two-week release cycle](https://thenewstack.io/chrome-two-week-releases/) - -Mar 3rd 2026 9:00am, by [Frederic Lardinois](https://thenewstack.io/author/frederic-lardinois/ "Posts by Frederic Lardinois") - -[Meta gave React its own foundation. But it's not letting go just yet.](https://thenewstack.io/react-foundation-open-source-governance/) - -Mar 3rd 2026 4:00am, by [Paul Sawers](https://thenewstack.io/author/paul-sawers/ "Posts by Paul Sawers") - -[The shift left hangover: Why modern platforms are shifting down to cure developer fatigue](https://thenewstack.io/shift-left-hangover-steve-corndell/) - -Jan 30th 2026 6:22pm, by [Steve Corndell](https://thenewstack.io/author/steve-corndell/ "Posts by Steve Corndell") - -[Why most AI projects fail after the demo actually works](https://thenewstack.io/ai-demo-to-production/) - -Mar 25th 2026 4:00am, by [Oladimeji Sowole](https://thenewstack.io/author/oladimeji-sowole/ "Posts by Oladimeji Sowole") - -[IBM, Red Hat, and Google just donated a Kubernetes blueprint for LLM inference to the CNCF](https://thenewstack.io/llm-d-cncf-kubernetes-inference/) - -Mar 24th 2026 8:20am, by [Steven J. Vaughan-Nichols](https://thenewstack.io/author/sjvn/ "Posts by Steven J. Vaughan-Nichols") - -[Andrej Karpathy's 630-line Python script ran 50 experiments overnight without any human input](https://thenewstack.io/karpathy-autonomous-experiment-loop/) - -Mar 14th 2026 5:00am, by [Janakiram MSV](https://thenewstack.io/author/janakiram/ "Posts by Janakiram MSV") - -["Self-healing" IT? HPE research explores how AI-trained models can catch silent infrastructure failures](https://thenewstack.io/hpe-self-healing-ai-infrastructure/) - -Mar 11th 2026 9:37am, by [Jennifer Riggins](https://thenewstack.io/author/jennifer-riggins/ "Posts by Jennifer Riggins") - -[How context rot drags down AI and LLM results for enterprises, and how to fix it](https://thenewstack.io/context-rot-enterprise-ai-llms/) - -Mar 9th 2026 9:00am, by [Todd R. Weiss](https://thenewstack.io/author/todd-r-weiss/ "Posts by Todd R. Weiss") - -[OpenClaw's biggest security flaw is why Jentic Mini exists](https://thenewstack.io/openclaw-is-a-security-mess-jentic-wants-to-fix-it/) - -Mar 25th 2026 5:00am, by [Darryl K. Taft](https://thenewstack.io/author/darryl-taft/ "Posts by Darryl K. Taft") - -[WebAssembly could solve AI agents' most dangerous security gap](https://thenewstack.io/webassembly-sandboxing-ai-agents/) - -Mar 24th 2026 9:01am, by [B. Cameron Gain](https://thenewstack.io/author/bruce-gain/ "Posts by B. Cameron Gain") - -[Minimus aims to solve one of open-source's long-festering problems](https://thenewstack.io/minimus-open-source-container-security/) - -Mar 24th 2026 3:00am, by [Adrian Bridgwater](https://thenewstack.io/author/adrian-bridgwater/ "Posts by Adrian Bridgwater") - -[What a security audit of 22,511 AI coding skills found lurking in the code](https://thenewstack.io/ai-agent-skills-security/) - -Mar 22nd 2026 7:00am, by [Darryl K. Taft](https://thenewstack.io/author/darryl-taft/ "Posts by Darryl K. Taft") - -[Why WebAssembly won't replace Kubernetes but makes Helm more secure](https://thenewstack.io/helm-webassembly-kubernetes-security/) - -Mar 21st 2026 8:45am, by [B. Cameron Gain](https://thenewstack.io/author/bruce-gain/ "Posts by B. Cameron Gain") - -[Why online stores keep showing the wrong products — and why tensors fix it](https://thenewstack.io/tensor-ranking-product-discovery/) - -Mar 25th 2026 6:00am, by [Tim Young](https://thenewstack.io/author/tim-young/ "Posts by Tim Young") - -[Will AI force code to evolve or make it extinct?](https://thenewstack.io/ai-programming-languages-future/) - -Mar 22nd 2026 6:00am, by [David Cassel](https://thenewstack.io/author/destiny/ "Posts by David Cassel") - -[Backend Development in 2026: What's Changed, What Matters, and What to Learn Next](https://thenewstack.io/introduction-to-backend-development/) - -Mar 19th 2026 11:37am, by [TNS Staff](https://thenewstack.io/author/tns-staff/ "Posts by TNS Staff") - -[Jellyfish AI development study: The real sting has yet to land](https://thenewstack.io/jellyfish-ai-engineering-trends/) - -Mar 19th 2026 11:01am, by [Adrian Bridgwater](https://thenewstack.io/author/adrian-bridgwater/ "Posts by Adrian Bridgwater") - -[Sampling: the philosopher's stone of distributed tracing](https://thenewstack.io/distributed-tracing-sampling-opentelemetry/) - -Mar 19th 2026 8:00am, by [Michele Mancioppi](https://thenewstack.io/author/michele-mancioppi/ "Posts by Michele Mancioppi") - -[WebAssembly could solve AI agents' most dangerous security gap](https://thenewstack.io/webassembly-sandboxing-ai-agents/) - -Mar 24th 2026 9:01am, by [B. Cameron Gain](https://thenewstack.io/author/bruce-gain/ "Posts by B. Cameron Gain") - -[How WebAssembly plugins simplify Kubernetes extensibility](https://thenewstack.io/how-webassembly-plugins-simplify-kubernetes-extensibility/) - -Mar 3rd 2026 2:00pm, by [B. Cameron Gain](https://thenewstack.io/author/bruce-gain/ "Posts by B. Cameron Gain") - -[WebAssembly is everywhere. Here's how it works](https://thenewstack.io/webassembly-is-everywhere-heres-how-it-works/) - -Feb 25th 2026 11:00am, by [Jessica Wachtel](https://thenewstack.io/author/jessica-wachtel/ "Posts by Jessica Wachtel") - -[Wasm vs. JavaScript: Who wins at a million rows?](https://thenewstack.io/wasm-vs-javascript-who-wins-at-a-million-rows/) - -Feb 22nd 2026 6:00am, by [Jessica Wachtel](https://thenewstack.io/author/jessica-wachtel/ "Posts by Jessica Wachtel") - -[How WebAssembly and Web Workers prevent UI freezes](https://thenewstack.io/how-webassembly-and-web-workers-prevent-ui-freezes/) - -Feb 7th 2026 9:00am, by [Jessica Wachtel](https://thenewstack.io/author/jessica-wachtel/ "Posts by Jessica Wachtel") - -[AI Operations](https://thenewstack.io/ai-operations/) [CI/CD](https://thenewstack.io/ci-cd/) [Cloud Services](https://thenewstack.io/cloud-services/) [DevOps](https://thenewstack.io/devops/) [Kubernetes](https://thenewstack.io/kubernetes/) [Observability](https://thenewstack.io/observability/) [Operations](https://thenewstack.io/operations/) [Platform Engineering](https://thenewstack.io/platform-engineering/) - -[HPE's AI agents cut root cause analysis time in half](https://thenewstack.io/hpes-ai-agents-cut-root-cause-analysis-time-in-half/) - -Mar 25th 2026 7:14am, by -Jennifer Riggins - -[Why most AI projects fail after the demo actually works](https://thenewstack.io/ai-demo-to-production/) - -Mar 25th 2026 4:00am, by -Oladimeji Sowole - -[From pillars to platform: How open observability data is changing the industry](https://thenewstack.io/open-observability-ai-platforms/) - -Mar 20th 2026 6:00am, by -Ted Young - -[Building a Kubernetes-native pattern for AI infrastructure at scale](https://thenewstack.io/kubernetes-native-ai-infrastructure/) - -Mar 19th 2026 5:00am, by -Sachi Desai - -[The AI blind spot debt: the hidden cost killing your innovation strategy](https://thenewstack.io/ai-blind-spot-debt/) - -Mar 17th 2026 7:00am, by -Yuval Fernbach - -[Enterprise dev teams are about to hit a wall. And CI pipelines can't save them.](https://thenewstack.io/ai-agent-validation-bottleneck/) - -Mar 26th 2026 7:00am, by -Anirudh Ramanathan - -[This simple infrastructure gap is holding back AI productivity](https://thenewstack.io/this-simple-infrastructure-gap-is-holding-back-ai-productivity/) - -Feb 22nd 2026 8:00am, by -Charlotte Fleming - -[Ramp’s Inspect shows closed-loop AI agents are software’s future](https://thenewstack.io/ramps-inspect-shows-closed-loop-ai-agents-are-softwares-future/) - -Jan 29th 2026 11:00am, by -Arjun Iyer - -[QCon chat: Is agentic AI killing continuous integration?](https://thenewstack.io/qcon-chat-is-agentic-ai-killing-continuous-integration/) - -Jan 27th 2026 6:00am, by -Joab Jackson - -[Async Rust: Pinning demystified](https://thenewstack.io/async-rust-pinning-demystified/) - -Jan 26th 2026 11:00am, by -Anshul Gupta - -[A practical guide to the 6 categories of AI cloud infrastructure in 2026](https://thenewstack.io/ai-cloud-taxonomy-2026/) - -Mar 15th 2026 5:00am, by -Janakiram MSV - -[Runpod report: Qwen has overtaken Meta's Llama as the most-deployed self-hosted LLM](https://thenewstack.io/runpod-ai-infrastructure-reality/) - -Mar 12th 2026 6:00am, by -Adrian Bridgwater - -[Snowflake Cortex Code CLI adds dbt and Apache Airflow support for AI-powered data pipelines](https://thenewstack.io/snowflake-cortex-code-dbt-airflow/) - -Mar 8th 2026 6:00am, by -Jelani Harper - -[Databases weren’t built for agent sprawl – SurrealDB wants to fix it](https://thenewstack.io/surrealdb-3-ai-agents/) - -Feb 24th 2026 2:07pm, by -Paul Sawers - -[Rising identity complexity: How CISOs can prevent it from becoming an attacker’s roadmap](https://thenewstack.io/ciso-identity-complexity-strategy/) - -Feb 19th 2026 12:47pm, by -Jay Reddy - -[One developer, team power: The future of AI-driven DevSecOps](https://thenewstack.io/future-ai-driven-devsecops/) - -Mar 5th 2026 2:29pm, by -Bryan Ross - -[Observability platform migration guide: Prometheus, OpenTelemetry, and Fluent Bit](https://thenewstack.io/observability-platform-migration-guide/) - -Feb 26th 2026 7:28am, by -Katie Greenley - -[Most platform teams build products, but they don’t know it](https://thenewstack.io/internal-platforms-are-products/) - -Feb 24th 2026 9:00am, by -Oleg Danilyuk - -[Why "automated" infrastructure might cost more than you think](https://thenewstack.io/automated-infrastructure-hidden-costs/) - -Feb 24th 2026 4:00am, by -Justyn Roberts - -[The essential shift every ITOps leader must make to survive an unrelenting stream of incidents](https://thenewstack.io/modernizing-itops-incident-management/) - -Feb 19th 2026 1:46pm, by -Ariel Russo - -[Your Kubernetes isn't ready for AI workloads, and drift is the reason](https://thenewstack.io/ai-workloads-kubernetes-infrastructure-drift/) - -Mar 25th 2026 8:43am, by -TNS Staff - -[Broadcom donates Velero to CNCF — and it could reshape how Kubernetes users handle backup and disaster recovery](https://thenewstack.io/broadcom-velero-cncf-kubernetes/) - -Mar 24th 2026 8:38am, by -B. Cameron Gain - -[IBM, Red Hat, and Google just donated a Kubernetes blueprint for LLM inference to the CNCF](https://thenewstack.io/llm-d-cncf-kubernetes-inference/) - -Mar 24th 2026 8:20am, by -Steven J. Vaughan-Nichols - -[Why WebAssembly won't replace Kubernetes but makes Helm more secure](https://thenewstack.io/helm-webassembly-kubernetes-security/) - -Mar 21st 2026 8:45am, by -B. Cameron Gain - -[Why the ‘glorified host’ for AI is exactly the Kubernetes we need](https://thenewstack.io/kubernetes-glorified-ai-host/) - -Mar 20th 2026 9:00am, by -Danielle Cook - -[From pillars to platform: How open observability data is changing the industry](https://thenewstack.io/open-observability-ai-platforms/) - -Mar 20th 2026 6:00am, by -Ted Young - -[Sampling: the philosopher's stone of distributed tracing](https://thenewstack.io/distributed-tracing-sampling-opentelemetry/) - -Mar 19th 2026 8:00am, by -Michele Mancioppi - -[Why your observability bill keeps growing (and it's not your vendor's fault)](https://thenewstack.io/why-observability-bills-grow/) - -Mar 18th 2026 4:00am, by -Juraci Paixão Kröhling - -[Why agentic AI stalls in production — and how a control plane fixes it](https://thenewstack.io/agentic-ai-control-plane-production/) - -Mar 17th 2026 6:00am, by -TNS Staff - -[Why AI workloads are breaking traditional Kubernetes observability strategies](https://thenewstack.io/ai-kubernetes-observability-practices/) - -Mar 16th 2026 7:04am, by -TNS Staff - -[The operational gap is real, and it's getting wider](https://thenewstack.io/closing-cloud-operational-gap/) - -Mar 26th 2026 8:00am, by -Yevgeny Pats - -[HPE's AI agents cut root cause analysis time in half](https://thenewstack.io/hpes-ai-agents-cut-root-cause-analysis-time-in-half/) - -Mar 25th 2026 7:14am, by -Jennifer Riggins - -[WebAssembly could solve AI agents' most dangerous security gap](https://thenewstack.io/webassembly-sandboxing-ai-agents/) - -Mar 24th 2026 9:01am, by -B. Cameron Gain - -[Kubernetes co-founder Brendan Burns: AI-generated code will become as invisible as assembly](https://thenewstack.io/ai-generated-code-invisible/) - -Mar 24th 2026 7:20am, by -Frederic Lardinois - -[Exton Linux's light version will "enlighten" you](https://thenewstack.io/exton-linuxs-light-version-will-enlighten-you/) - -Mar 24th 2026 5:43am, by -Jack Wallen - -[The operational gap is real, and it's getting wider](https://thenewstack.io/closing-cloud-operational-gap/) - -Mar 26th 2026 8:00am, by -Yevgeny Pats - -[Enterprise dev teams are about to hit a wall. And CI pipelines can't save them.](https://thenewstack.io/ai-agent-validation-bottleneck/) - -Mar 26th 2026 7:00am, by -Anirudh Ramanathan - -[Your Kubernetes isn't ready for AI workloads, and drift is the reason](https://thenewstack.io/ai-workloads-kubernetes-infrastructure-drift/) - -Mar 25th 2026 8:43am, by -TNS Staff - -[Capital One deprecated an AI tool it once championed. Its DevEx chief says that's the point.](https://thenewstack.io/capital-one-developer-enablement/) - -Mar 18th 2026 8:02am, by -Jennifer Riggins - -[From monolith to global mesh: How Uber standardized ML at scale](https://thenewstack.io/uber-standardized-ml-scale/) - -Mar 17th 2026 4:00am, by -Eric Wang and Ying Zheng - -[C++](https://thenewstack.io/c/) [Developer tools](https://thenewstack.io/developer-tools/) [Go](https://thenewstack.io/go/) [Java](https://thenewstack.io/java/) [JavaScript](https://thenewstack.io/javascript/) [Programming Languages](https://thenewstack.io/programming-languages/) [Python](https://thenewstack.io/python/) [Rust](https://thenewstack.io/rust/) [TypeScript](https://thenewstack.io/typescript/) - -[Open source USearch library jumpstarts ScyllaDB vector search](https://thenewstack.io/open-source-usearch-library-jumpstarts-scylladb-vector-search/) - -Feb 5th 2026 12:00pm, by -Jelani Harper - -[AWS WAF vs. Google Cloud Armor: A Multicloud Security Showdown](https://thenewstack.io/aws-waf-vs-google-cloud-armor-a-multicloud-security-showdown/) - -Nov 25th 2025 10:00am, by -Advait Patel - -[Goodbye Dashboards: Agents Deliver Answers, Not Just Reports](https://thenewstack.io/goodbye-dashboards-agents-deliver-answers-not-just-reports/) - -Nov 23rd 2025 9:00am, by -Ketan Karkhanis - -[Rust vs. C++: a Modern Take on Performance and Safety](https://thenewstack.io/rust-vs-c-a-modern-take-on-performance-and-safety/) - -Oct 22nd 2025 2:00pm, by -Zziwa Raymond Ian - -[Building a Real-Time System Monitor in Rust Terminal](https://thenewstack.io/building-a-real-time-system-monitor-in-rust-terminal/) - -Oct 15th 2025 7:05am, by -Tinega Onchari - -[OpenAI acquires Astral to bring open source Python developer tools to Codex — but details are still fuzzy](https://thenewstack.io/openai-astral-acquisition/) - -Mar 20th 2026 7:33am, by -Meredith Shubel - -[Jellyfish AI development study: The real sting has yet to land](https://thenewstack.io/jellyfish-ai-engineering-trends/) - -Mar 19th 2026 11:01am, by -Adrian Bridgwater - -[Sauce Labs wants to solve an AI-created problem nobody wanted to work on](https://thenewstack.io/ai-test-authoring-launch/) - -Mar 18th 2026 9:19am, by -Frederic Lardinois - -[Capital One deprecated an AI tool it once championed. Its DevEx chief says that's the point.](https://thenewstack.io/capital-one-developer-enablement/) - -Mar 18th 2026 8:02am, by -Jennifer Riggins - -[Cursor built a fleet of security agents to solve a familiar frustration](https://thenewstack.io/cursor-open-sources-security-agents/) - -Mar 16th 2026 11:17am, by -Frederic Lardinois - -[Go Experts: 'I Don't Want to Maintain AI-Generated Code'](https://thenewstack.io/go-experts-i-dont-want-to-maintain-ai-generated-code/) - -Sep 28th 2025 6:00am, by -David Cassel - -[How To Run Kubernetes Commands in Go: Steps and Best Practices](https://thenewstack.io/how-to-run-kubernetes-commands-in-go-steps-and-best-practices/) - -Jun 27th 2025 8:00am, by -Sunny Yadav - -[Prepare Your Mac for Go Development](https://thenewstack.io/prepare-your-mac-for-go-development/) - -Apr 12th 2025 7:00am, by -Damon M. Garn - -[Pagoda: A Web Development Starter Kit for Go Programmers](https://thenewstack.io/pagoda-a-web-development-starter-kit-for-go-programmers/) - -Mar 19th 2025 6:10am, by -Loraine Lawson - -[Microsoft TypeScript Devs Explain Why They Chose Go Over Rust, C#](https://thenewstack.io/microsoft-typescript-devs-explain-why-they-chose-go-over-rust-c/) - -Mar 18th 2025 7:00am, by -David Cassel - -[Java 26 lands without an LTS badge. Here's why developers should care anyway.](https://thenewstack.io/java-26-performance-ai/) - -Mar 18th 2026 9:35am, by -Darryl K. Taft - -[62% of enterprises now use Java to power AI apps](https://thenewstack.io/2026-java-ai-apps/) - -Feb 10th 2026 12:58pm, by -Darryl K. Taft - -[BellSoft bets Java expertise can beat hardened container wave](https://thenewstack.io/bellsoft-bets-java-expertise-can-beat-hardened-container-wave/) - -Jan 26th 2026 3:00pm, by -Darryl K. Taft - -[Java Developers Get Multiple Paths To Building AI Agents](https://thenewstack.io/java-developers-get-multiple-paths-to-building-ai-agents/) - -Dec 26th 2025 7:02am, by -Darryl K. Taft - -[Your Enterprise AI Strategy Must Start With Java, Not Python](https://thenewstack.io/your-enterprise-ai-strategy-must-start-with-java-not-python/) - -Dec 22nd 2025 1:00pm, by -Michael Coté - -[TypeScript 6.0 RC arrives as a bridge to a faster future](https://thenewstack.io/typescript-6-0-rc-arrives-as-a-bridge-to-a-faster-future/) - -Mar 14th 2026 9:00am, by -Darryl K. Taft - -[WebAssembly is everywhere. Here's how it works](https://thenewstack.io/webassembly-is-everywhere-heres-how-it-works/) - -Feb 25th 2026 11:00am, by -Jessica Wachtel - -[Wasm vs. JavaScript: Who wins at a million rows?](https://thenewstack.io/wasm-vs-javascript-who-wins-at-a-million-rows/) - -Feb 22nd 2026 6:00am, by -Jessica Wachtel - -[Arcjet reaches v1.0, promises stable security for JavaScript apps](https://thenewstack.io/arcjet-reaches-v1-0-promises-stable-security-for-javascript-apps/) - -Feb 14th 2026 7:00am, by -Darryl K. Taft - -[How WebAssembly and Web Workers prevent UI freezes](https://thenewstack.io/how-webassembly-and-web-workers-prevent-ui-freezes/) - -Feb 7th 2026 9:00am, by -Jessica Wachtel - -[Will AI force code to evolve or make it extinct?](https://thenewstack.io/ai-programming-languages-future/) - -Mar 22nd 2026 6:00am, by -David Cassel - -[Java 26 lands without an LTS badge. Here's why developers should care anyway.](https://thenewstack.io/java-26-performance-ai/) - -Mar 18th 2026 9:35am, by -Darryl K. Taft - -[TypeScript 6.0 RC arrives as a bridge to a faster future](https://thenewstack.io/typescript-6-0-rc-arrives-as-a-bridge-to-a-faster-future/) - -Mar 14th 2026 9:00am, by -Darryl K. Taft - -[Nearly half of all companies now use Rust in production, survey finds](https://thenewstack.io/rust-enterprise-developers/) - -Mar 6th 2026 10:45am, by -Darryl K. Taft - -[Statistical language R is making a comeback against Python](https://thenewstack.io/statistical-language-r-is-making-a-comeback-against-python/) - -Feb 12th 2026 2:57pm, by -Darryl K. Taft - -[OpenAI acquires Astral to bring open source Python developer tools to Codex — but details are still fuzzy](https://thenewstack.io/openai-astral-acquisition/) - -Mar 20th 2026 7:33am, by -Meredith Shubel - -[Python virtual environments: isolation without the chaos](https://thenewstack.io/python-virtual-environments-isolation-without-the-chaos/) - -Feb 16th 2026 7:00am, by -Jessica Wachtel - -[Statistical language R is making a comeback against Python](https://thenewstack.io/statistical-language-r-is-making-a-comeback-against-python/) - -Feb 12th 2026 2:57pm, by -Darryl K. Taft - -[Arcjet's Python SDK Embeds Security in Code](https://thenewstack.io/arcjets-python-sdk-embeds-security-in-code/) - -Jan 16th 2026 2:00pm, by -Darryl K. Taft - -[2025: The Year of the Return of the Ada Programming Language?](https://thenewstack.io/2025-the-year-of-the-return-of-the-ada-programming-language/) - -Jan 14th 2026 4:00pm, by -Darryl K. Taft - -[Nearly half of all companies now use Rust in production, survey finds](https://thenewstack.io/rust-enterprise-developers/) - -Mar 6th 2026 10:45am, by -Darryl K. Taft - -[Wasm vs. JavaScript: Who wins at a million rows?](https://thenewstack.io/wasm-vs-javascript-who-wins-at-a-million-rows/) - -Feb 22nd 2026 6:00am, by -Jessica Wachtel - -[Open source USearch library jumpstarts ScyllaDB vector search](https://thenewstack.io/open-source-usearch-library-jumpstarts-scylladb-vector-search/) - -Feb 5th 2026 12:00pm, by -Jelani Harper - -[The 'weird' things that happened when Clickhouse replaced C++ with Rust](https://thenewstack.io/the-weird-things-that-happened-when-clickhouse-replaced-c-with-rust/) - -Feb 4th 2026 7:26am, by -B. Cameron Gain - -[Async Rust: Pinning demystified](https://thenewstack.io/async-rust-pinning-demystified/) - -Jan 26th 2026 11:00am, by -Anshul Gupta - -[TypeScript 6.0 RC arrives as a bridge to a faster future](https://thenewstack.io/typescript-6-0-rc-arrives-as-a-bridge-to-a-faster-future/) - -Mar 14th 2026 9:00am, by -Darryl K. Taft - -[Mastra empowers web devs to build AI agents in TypeScript](https://thenewstack.io/mastra-empowers-web-devs-to-build-ai-agents-in-typescript/) - -Jan 28th 2026 11:00am, by -Loraine Lawson - -[Inferno Vet Creates Frontend Framework Built With AI in Mind](https://thenewstack.io/inferno-vet-creates-frontend-framework-built-with-ai-in-mind/) - -Dec 10th 2025 11:00am, by -Loraine Lawson - -[JavaScript Utility Library Lodash Changing Governance Model](https://thenewstack.io/javascript-utility-library-lodash-changing-governance-model/) - -Nov 1st 2025 7:00am, by -Loraine Lawson - -[Microsoft TypeScript Devs Explain Why They Chose Go Over Rust, C#](https://thenewstack.io/microsoft-typescript-devs-explain-why-they-chose-go-over-rust-c/) - -Mar 18th 2025 7:00am, by -David Cassel - -2025-11-04 05:00:01 - -It’s Time To Build APIs for AI, Not Just For Developers - -contributed, - -[AI Agents](https://thenewstack.io/category/ai-agents/) / [AI Engineering](https://thenewstack.io/category/ai-engineering/) - -# It’s Time To Build APIs for AI, Not Just For Developers - -If your APIs were built for humans, they're probably failing AI agents. It's time for a paradigm shift to AI-first design. - -Nov 4th, 2025 5:00am by [Saqib Jan](https://thenewstack.io/author/saqib-jan/ "Posts by Saqib Jan") - -![Featued image for: It’s Time To Build APIs for AI, Not Just For Developers](https://cdn.thenewstack.io/media/2025/10/35c6b952-agent-1024x576.jpg) - -Image from Thapana\_Studio on Shutterstock. - - -For the last two decades, the [principles of API design](https://thenewstack.io/what-are-the-core-principles-of-good-api-design/) have centered around the human developer. We built systems optimized for their convenience, with flexible endpoints and rich [documentation](https://thenewstack.io/bad-documentation-bad-documentation/) that they could interpret. - -But a new and powerful class of consumer is already disrupting in the form of autonomous [AI agents](https://thenewstack.io/ai-agents-a-comprehensive-introduction-for-developers/) that operate on a fundamentally different set of principles, which require a new approach to the way we build and describe our services. - -“This means a new paradigm for us as developers: We must now build APIs optimized for consumption by machines, which requires a fundamentally different design philosophy than the one we use for human-centric development,” says [Srinivasan Sekar](https://in.linkedin.com/in/srinivasan-sekar), a director of engineering at [LambdaTest](https://www.lambdatest.com/), an AI-native software testing platform. - -This increasing shift toward an “ [AI-first](https://thenewstack.io/ai-first-web-development-model-first-design-and-remix-v3/)” design philosophy prioritizes the explicit clarity and predictability that machines require to reason and act effectively. It underpins a clear framework for redesigning systems for the new agentic world. - -## Shift From ‘Developer-First’ to ‘AI-First’ - -At the heart of this new manifesto is a core cultural shift that must precede any architectural changes: moving from a “developer-first” to an [“AI-first” design](https://thenewstack.io/why-api-first-matters-in-an-ai-driven-world/). As Sekar explains, for years, we have optimized our APIs for the convenience of human developers. - -This approach favors flexibility, often resulting in fewer, multipurpose endpoints and a reliance on external documentation to clarify ambiguity. A human developer can read a guide to understand that a certain parameter is required only when another is present — a nuance we have long taken for granted. - -> “We must now build APIs optimized for consumption by machines, which requires a fundamentally different design philosophy than the one we use for human-centric development.” -> -> **— Srinivasan Sekar, director of engineering at LambdaTest** - -AI agents, however, are fundamentally different consumers. They cannot read external documentation or infer implicit relationships between parameters. An AI operates solely on the explicit, machine-readable contract provided by the API’s schema. This, he argues, is the crux of the “AI-first” philosophy: a design approach that prioritizes the absolute, unambiguous clarity that machines require, leaving no room for interpretation in the contract. - -TRENDING STORIES - -1. [Four prompt engineering patterns every developer should know — and why "draw a cat" explains them all](https://thenewstack.io/prompt-engineering-for-developers/) -2. [Why most AI projects fail after the demo actually works](https://thenewstack.io/ai-demo-to-production/) -3. [Anthropic: You can still use your Claude accounts to run OpenClaw, NanoClaw and Co.](https://thenewstack.io/anthropic-agent-sdk-confusion/) -4. [Capital One deprecated an AI tool it once championed. Its DevEx chief says that's the point.](https://thenewstack.io/capital-one-developer-enablement/) -5. [Perplexity Computer wows, Karpathy kills vibe coding, and OpenAI replaces Anthropic at the Pentagon](https://thenewstack.io/perplexity-computer-vibe-coding-openai-anthropic-pentagon/) - -[Sai Krishna](https://www.linkedin.com/in/sai-krishna-3755407b/), working alongside Sekar, adds a practical dimension to this shift: “At LambdaTest, we learned this the hard way. We had a perfectly functional API for configuring test environments that developers loved for its flexibility. But when AI agents started using it, we saw a 40% failure rate because the agents couldn’t interpret the implicit rules we’d documented separately. We had to completely rethink our approach.” - -This means favoring more specific, single-purpose endpoints and defining all constraints explicitly within the schema itself. This mindset is the non-negotiable foundation for [building any successful and reliable agentic system](https://thenewstack.io/agentic-ai-tools-for-building-and-managing-agentic-systems/). - -## Unlearning the Three Habits of Human-Centric APIs - -Adopting this “AI-first” philosophy in practice means actively unlearning several ingrained habits of traditional, human-centric API design. Sekar identifies three common patterns that, while convenient for human developers, create [critical failures when consumed by AI agents](https://thenewstack.io/no-apis-no-ai-why-api-access-is-critical-to-agentic-systems/). - -First is the habit of overloading single endpoints with multiple behaviors. A developer can handle this flexibility, but an AI agent struggles with the ambiguity. The AI-first approach requires distinct, single-purpose endpoints where the function is explicit. - -- **Before:** A single `POST /user` endpoint would ambiguously handle both creating and updating a user based on whether an `id` was present in the payload. -- **After:** The AI-first approach uses two distinct and predictable endpoints: `POST /users` to create a new user and `PUT /users/{id}` to update an existing one. - -Second is the reliance on implicit contracts and external documentation. For an agent to act reliably, all parameter relationships and dependencies must be explicitly declared within the machine-readable schema itself. - -- **Before:** A traditional schema would list `user_type` and `admin_level` as optional, forcing a developer to read external documentation to learn their conditional relationship. -- **After:** An AI-first schema makes this relationship explicit using conditional logic, allowing a machine to understand the contract without any external context. - -Finally, teams must unlearn the habit of providing generic error responses. An AI-first API must provide structured, detailed error responses that allow an agent to self-correct. - -- **Before:** A generic JSON response like `{"message": "Bad Request"}` would halt an automated workflow. -- **After:** A structured JSON error provides specific fields for the error `code`, `message` and `details`, indicating exactly which parameter was invalid. - -These shifts share the common purpose of eliminating ambiguity. By making endpoints, contracts and errors explicit, developers provide the predictable foundation necessary for autonomous agents to act reliably and effectively. - -## The New Pillars of AI-First Design - -Beyond simply avoiding old habits, building an AI-first API requires embracing a new set of positive design principles centered on clarity and predictability. - -“This begins with semantic clarity,” says [Sean Falconer,](https://www.linkedin.com/in/seanf/) senior director of product, AI strategy at [Confluent](https://www.confluent.io/). A truly AI-native API must do more than just describe its technical function; its machine-readable contract must also describe its business purpose, its prerequisites and any potential side effects. This provides the rich context an [AI agent needs to reason](https://thenewstack.io/4-reasons-agentic-ai-is-failing/) about not just how to use a tool, but when and why. - -> A truly AI-native API must do more than just describe its technical function; its machine-readable contract must also describe its business purpose, its prerequisites and any potential side effects. - -This means developers must enrich their API schemas, moving beyond simple data types. For example, in an OpenAPI specification, every parameter and endpoint should include a detailed description that explains not just the “what” (for instance, an integer ID), but the “why” (such as the unique customer identifier used for billing and support tickets). - -This level of clarity is best achieved by designing what Falconer refers to as small, purpose-built tools rather than exposing large, generic API surfaces. [Yoni Michael](https://www.linkedin.com/in/yonimichael), CTO of [Typedef](https://www.typedef.ai/), agrees with this principle, advocating for a “minimal surface area,” meaning the API should expose only what is absolutely essential for a given task. - -For architects, this translates into a clear design mandate: Resist the urge to create monolithic, all-purpose endpoints. Instead, complex business processes should be broken down into their smallest logical components, with a dedicated, constrained API designed for each one. A sprawling `/orders` API, for instance, could be refactored into focused, purpose-built tools like `/create-order`, `/check-order-status` and `/request-refund`. Creating these well-defined tools reduces ambiguity and the cognitive load on the AI, making its behavior easier to govern and evaluate. - -All of these principles serve a single, critical goal: achieving what Michael calls deterministic behavior. An autonomous agent cannot afford surprises when it is chaining together multiple tools to execute a complex workflow. The system must be utterly reliable and predictable. - -To deliver on this, engineers must prioritize rigorous testing and stateless design where possible. Every API call with the same inputs should consistently produce the same output, free from hidden dependencies or unpredictable side effects. This involves providing clear, idempotent interfaces for any operations that modify data, ensuring that repeated calls do not have unintended consequences. - -By building APIs with semantic clarity, a minimal surface area and a clear purpose, architects provide the foundation of trust that allows an AI agent to build upon them effectively. - -## Hurdles of Reshaping Data for AI - -Even with these forward-thinking design principles in place, there is a final, deeper architectural challenge that underpins all AI-first design. Sekar from LambdaTest identifies this as the most significant hurdle of all: the difficult but necessary task of data model flattening. - -He explains that most existing enterprise APIs reflect deep-rooted data platform challenges, as they were designed around complex internal database schemas or nested object models. While a human developer can navigate these intricate structures, they create significant “cognitive overhead” for an AI agent. - -A deeply nested data structure forces an AI model to [expend valuable resources simply understanding](https://thenewstack.io/automating-context-in-structured-data-for-llms/) the shape of the data and the relationships between its parts before it can even begin to act on the information. - -This complexity introduces a high potential for error and makes the agent’s behavior less predictable. The AI-first solution is to flatten and normalize these data models, redesigning them into simpler, more predictable formats that are optimized for machine consumption. - -> “The companies building the most reliable agentic systems aren’t necessarily the ones with the most sophisticated AI models. They’re the ones who’ve done the hard work of redesigning their API foundations to speak the language machines understand.” -> -> **— Srinivasan Sekar** - -And this is usually the most resource-intensive part of the journey to becoming AI native. Sekar argues that this task goes far beyond simply documenting existing systems. It frequently requires a fundamental redesign of the data access layer and the creation of entirely new, parallel API surfaces that are purpose-built for AI agents. - -Krishna shares the practical reality of this transformation: “We maintain two API layers now; our legacy developer API and our AI-optimized API. The AI version takes a test result object that was previously nested four levels deep and flattens it into a single-level structure with explicit relationship IDs. It tripled our schema size but cut agent processing time by 70%. The investment was significant, but necessary.” This ensures that the context provided to the AI is not just semantically clear, but also structurally simple and immediately useful. - -## The Future Is a ‘Behavioral Contract’ - -Taken together, these principles — a cultural shift to an AI-first mindset, the unlearning of old habits and a deep architectural commitment to clarity and simple data models — form a new manifesto for API design. But the impact of this new philosophy extends beyond the initial engineering of our systems and into their entire life cycle. - -Sekar predicts that this will ultimately reshape core DevOps practices like API versioning. In a world where autonomous agents are the primary consumers, the focus of API management will shift from tracking simple syntax changes to guaranteeing “behavioral contracts.” The promise to the AI will no longer be just that the API’s structure is stable, but that its behavior is consistent and predictable, ensuring the same inputs always produce the expected type of outcome. - -Krishna elaborates on how this plays out operationally: “We’ve started versioning our behavioral contracts separately from our API versions. An agent subscribes to a behavioral contract, say, ‘search capability with pagination,’ and we guarantee that contract’s behavior even as we evolve the underlying implementation. If we need to change behavior, we introduce a new contract version, giving agents time to adapt.” - -Both Sekar and Krishna emphasize that this commitment to explicit, predictable and behaviorally consistent APIs is the ultimate expression of the AI-first philosophy. - -“The companies building the most reliable agentic systems aren’t necessarily the ones with the most sophisticated AI models,” Sekar notes. “They’re the ones who’ve done the hard work of redesigning their API foundations to speak the language machines understand.” - -This foundation is what the next generation of reliable agentic AI applications will be built upon. - -[YOUTUBE.COM/THENEWSTACK\\ -\\ -\\ -Tech moves fast, don't miss an episode. Subscribe to our YouTube \\ -channel to stream all our podcasts, interviews, demos, and more.\\ -\\ -\\ -SUBSCRIBE](https://youtube.com/thenewstack?sub_confirmation=1) - -GroupCreated with Sketch. - -[![](https://thenewstack.io/wp-content/uploads/2025/10/85eac203-cropped-f9e1bb76-screenshot-2025-10-27-at-2.36.21%E2%80%AFpm-600x600.png)\\ -\\ -Saqib Jan is a technology analyst with experience in application development, FinOps and cloud technologies. \\ -\\ -Read more from Saqib Jan](https://thenewstack.io/author/saqib-jan/) - -SHARE THIS STORY - -SHARE THIS STORY - -TNS DAILY NEWSLETTER -Receive a free roundup of the most recent TNS articles in your inbox each day. - -SUBSCRIBE - - -The New Stack does not sell your information or share it with -unaffiliated third parties. By continuing, you agree to our -[Terms of Use](https://thenewstack.io/terms-of-use/) and -[Privacy Policy](https://thenewstack.io/privacy-policy/). \ No newline at end of file diff --git a/.firecrawl/beyond-bespoke-ui.md b/.firecrawl/beyond-bespoke-ui.md deleted file mode 100644 index 9ae99a9..0000000 --- a/.firecrawl/beyond-bespoke-ui.md +++ /dev/null @@ -1,455 +0,0 @@ -Authors - -- ![avatar](https://www.cress.codes/_next/image?url=%2Fstatic%2Fimages%2Fkale_jungle.jpg&w=96&q=75)NameDaniel CressTwitter - -# Beyond Bespoke: How AI Turns Component Libraries Into Adaptive Systems - -Every time we build a new feature, we follow the same ritual: design mockups, build custom components, wire up state management, test variations, deploy. Then the requirements change slightly, and we do it all again. A dashboard for managers needs different cards than one for employees. A mobile form needs different layouts than desktop. A beginner's view needs simpler options than an expert's. - -We've gotten really good at building bespoke experiences. Maybe too good. We've optimized the process of creating unique interfaces for every context, every user type, every edge case. But what if we're solving the wrong problem? - -What if instead of building better tools for creating variations, we built systems that generate variations on demand? What if our component libraries could adapt themselves based on context, using the same primitives we already have? - -This isn't about replacing Nuxt UI or Shadcn or Radix. It's about teaching them to compose themselves. - -## What We Built at Bambee - -At Bambee, we built a system that generates contextual UI based on vast amounts of workplace data—performance metrics, compliance requirements, employee sentiment, turnover patterns, organizational health indicators. The challenge wasn't just showing data; it was surfacing the right insights with the right actions at the right time. - -A manager dealing with high turnover needs different recommendations than one managing a stable team. An employee in their first month needs different guidance than a three-year veteran. A compliance alert for California employment law requires different visualizations than one for federal OSHA requirements. - -We started down the familiar path: custom components for each scenario. But the combinatorial explosion quickly became clear. Dozens of card types. Countless variations of forms. Complex conditional logic everywhere. - -So we tried something different. - -### Dynamic Cards and Notices - -The system analyzes company data and generates recommendations—we call them solutions and notices. Each one has different severity levels, different actions users can take, different visualizations to make the data clear. - -One user might see a compliance alert with a bar chart showing policy gaps across departments. Another sees a performance insight with a timeline visualization of team productivity trends. A third sees a recognition opportunity with a simple progress indicator. - -Here's the key: we're not building separate components for each type. We're using the same card component, the same underlying UI primitives from our component library. What changes is the structured data that drives them. - -The system generates a schema-compliant payload that describes what to show, how to show it, and what actions should be available. The frontend trusts that structure and renders accordingly. - -### Dynamic Wizards - -The second use case was even more interesting: multi-step wizards that adapt to context. - -The system detects information gaps—missing data that would improve recommendations. Based on what's missing and how critical it is, it generates a wizard to collect that information. - -Sometimes it's a simple two-step survey: "What's your management philosophy? How large is your team?" Other times it's a comprehensive five-step wizard with conditional logic: if you answer yes to one question, you see follow-up questions; if you answer no, you skip to the next section. - -The question types change dynamically. Sliders for rating scales. Checkbox groups for multiple selections. Matrices for comparing options across criteria. Date pickers for timelines. All generated from schemas, all rendered by the same form components. - -We're not pre-building every possible wizard variation. We're defining the contract—what a wizard can contain, what question types are valid, how steps can be arranged—and letting the system compose variations on the fly. - -## The Core Principles - -Building this taught us some things about how to structure systems for dynamic UI generation. These aren't prescriptive rules, just patterns that worked for us. - -### Schema as Contract - -In traditional development, you design an interface, build the component, then wire it to data. The component defines what's possible. - -In schema-driven development, you define the contract first. The schema is the source of truth. It describes what shapes of data are valid, what fields are required, what values are acceptable. - -The backend generates data conforming to that schema. The frontend trusts the structure and renders accordingly. Neither side makes assumptions beyond what the schema guarantees. - -This inverts the usual relationship. Instead of data conforming to components, components adapt to data (within the bounds of the schema). - -A simple example: - -```typescript -// Schema defines possibilities -ActionCardSchema = { - type: 'ACTION_CARD', - severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL', - action: { - type: string, - label: string, - handler: { route: string, params: object } - }, - visualization?: { - type: 'BAR' | 'LINE' | 'PIE', - data: object - } -} - -// Backend generates instance based on context -const generatedCard = analyzeContext(userData) - -// Frontend renders using component library primitives - -``` - -The schema is doing a lot of work here. It's defining not just data types, but the vocabulary of what interfaces can express. Add a new visualization type to the schema, teach the frontend to render it, and suddenly all generated cards can use it. - -### Type Safety Through Validation - -The critical enabler for this approach is runtime validation. For us, that means Zod, but the principle applies to any schema validation library. - -Here's why it matters: AI generates JSON. That JSON must match the exact structure your frontend expects. If it doesn't, you get runtime errors, broken UI, frustrated users. - -With runtime validation, you create a feedback loop. AI generates output. You validate it immediately against your schema. If it fails validation, you send the errors back to the AI and ask it to regenerate. - -The pattern looks like: - -1. AI generates structured output based on context -2. Validate against schema immediately -3. If invalid → capture specific validation errors -4. Send those errors back to AI with original context -5. AI regenerates, accounting for what went wrong -6. Retry with exponential backoff (2-3 attempts max) -7. If all retries fail → fallback to safe default - -This creates remarkably reliable output. The AI learns your schema requirements through the error messages. After a few iterations of improving prompts and tightening schemas, validation failures become rare. - -The validation itself is straightforward: - -```typescript -try { - const validated = CardSchema.parse(aiOutput) - return validated -} catch (error) { - await retryWithRefinement(aiOutput, error) -} -``` - -But the implications are profound. Your frontend never sees invalid data. Type safety is enforced at runtime. Breaking changes to schemas are caught immediately, not in production. - -### Slots Over Specifics - -We stopped building ``, ``, ``. Instead, we built `` that accepts structured data and routes to appropriate presentation. - -The slot examines the schema, determines which component primitives to use, and composes the final UI. - -A compliance alert might render as: red badge with alert icon, bar chart visualization, "Review Policy" button that routes to policy creation. A performance insight might render as: blue badge with trend icon, line chart visualization, "View Details" button that opens a details modal. - -Same slot. Same underlying Button, Card, Badge, and Chart components from our component library. Different compositions based on the schema data. - -This is more than just abstraction. It's a different mental model. You're not building components for specific use cases. You're building a rendering engine that interprets schemas and composes UI from primitives. - -The power comes from the mapping layer. It reads the schema and makes decisions: - -- What badge color and icon represent this severity level? -- Which chart component matches this visualization type? -- What button variant and text match this action type? -- How should these elements be arranged for this context? - -As you add more schema types, the mapping layer grows. But the underlying components stay the same. - -### Visualization as Configuration - -Instead of building separate chart components for every context, we treat visualizations as configuration. - -The backend sends structured data describing what to visualize and how: - -```js -{ - visualizationType: 'BAR', - data: { - labels: ['Q1', 'Q2', 'Q3', 'Q4'], - values: [23, 45, 67, 89] - }, - theme: 'minimal', - options: { showLegend: false } -} -``` - -The frontend has a factory function. It looks at the visualization type and says, "BAR chart? Render the BarChart component from our library with these props." - -This means adding a new visualization type is a small change. Add the type to your schema, teach the factory to handle it, and now every part of your system that generates visualizations can use it. - -We extended this with a vector database of illustrations. The system can describe the visual context it needs—"performance improvement scenario with upward trend"—then query embeddings to find the closest matching illustration from our library. No manual asset selection. Just semantic matching between generated context and available visuals. - -### Dynamic Wizards from Schemas - -Multi-step forms become declarative data structures. - -A wizard schema defines: - -- How many steps -- What questions appear in each step -- Question types and validation rules -- Conditional display logic -- Progress indicators and navigation - -The frontend loops through the schema and renders appropriate input components. A question with type `'SLIDER'` renders your library's slider component. A question with type `'CHECKBOX'` renders a checkbox group. - -The power is in the conditional logic. Questions can show or hide based on previous answers. Entire steps can be skipped based on user context. Validation rules can reference other questions. - -All described in the schema. All rendered by generic form components. - -Adding a new question type means updating the schema to include it and teaching one component to render it. Not rebuilding every wizard that might use it. - -This is where it clicked for me: we weren't building forms anymore. We were building a form generation engine. - -## The Future Vision - -This is where it gets interesting. What we built at Bambee is a proof of concept. It works in production, handles real complexity, serves real users. But it's just scratching the surface of what's possible. - -Let me paint some pictures of where this could go. To illustrate these concepts without diving into proprietary specifics, I'll use a hypothetical recipe and meal planning platform as a concrete example—but these patterns apply across any domain with similar variability. - -### Pages That Generate Themselves - -Imagine you're building a recipe and meal planning platform. A user opens the app and says, "I want to plan meals for the week." - -The system analyzes their context: - -- Family size and ages -- Dietary restrictions and preferences -- Available cooking time -- Current pantry inventory -- Cooking skill level -- Budget constraints -- Past meal preferences - -From this, it generates a complete page schema. Not a page that exists in your codebase. A page composed on the fly: - -A three-column dashboard layout. Left column shows a weekly calendar with meal slots, each slot showing prep time and ingredient overlap with other meals. Center column shows a shopping list organized by grocery store section, with cost estimates and substitution suggestions. Right column shows a nutrition summary chart aggregating the week's macros, plus a comparison to their goals. - -At the bottom, an action row with context-aware buttons: export meal plan to calendar, send shopping list to grocery app, adjust for budget, regenerate for more variety. - -The frontend receives this schema and composes it using your component library's Grid, Card, Calendar, List, Chart, and Button components. The page never existed before this moment. It was assembled because this specific user, in this specific context, needed this specific combination of features. - -That's the radical shift: from pages as files in a repository to pages as generated compositions. The repository contains the components and the schemas. The combinations emerge from context. - -### Context-Aware Form Adaptation - -Same underlying data, completely different form based on who's using it. - -A beginner user gets a simplified recipe entry form: basic fields, lots of help text, suggested defaults, links to video tutorials explaining cooking terms. Single-column layout, large touch targets, progress saved after every field. - -An advanced user gets the compact version: all fields visible, technical terminology, advanced options like ingredient ratios and technique variations, keyboard shortcuts for quick entry. Multi-column layout, minimal explanatory text, batch editing capabilities. - -The system decides which variation to show based on user behavior analysis. Not A/B testing. Not user segments. Individual adaptation. - -And it goes deeper. Forms that adapt mid-flow based on answers. User selects "dietary restriction: vegan" → the form immediately hides all questions about meat preparation, adds questions about B12 supplementation, adjusts the nutrition target ranges, suggests vegan protein sources in the ingredient picker. - -The form is responding to context in real-time, reshaping itself to show what's relevant and hide what isn't. - -### Adaptive Complexity - -Interfaces that scale complexity based on user sophistication, not just hiding advanced features behind a settings toggle. - -A recipe platform might show the same dish completely differently based on skill level. Beginners see: "Sauté the onions until soft" with a photo showing what "soft" looks like and a link to a basic sautéing video. Intermediate cooks see: "Sauté onions in butter over medium heat until translucent, 5-7 minutes" with suggested pan types and heat settings. Advanced cooks see: "Sweat onions in clarified butter, 82°C, until cell walls break down but no Maillard reaction occurs—monitor for steam release, not browning" with technique alternatives like using a immersion circulator for precise temperature control. - -The ingredient list adapts too. Beginners see standard grocery store items. Intermediate cooks see preferred brands and substitution options. Advanced users see specific varieties ("Vidalia onions for sweetness, or shallots for depth"), quality indicators, and even molecular composition notes for technique-critical ingredients. - -Same recipe. Same underlying data. But the interface reveals layers of technical sophistication progressively, matching what each user can handle and wants to see. - -The system watches behavior. User consistently completes advanced recipes without issues? Start showing more complexity. User struggles with intermediate recipes? Pull back to basics. - -This isn't just hiding fields or showing tooltips. It's fundamentally different interfaces generated for different capability levels, all from the same underlying schemas. - -### Cross-Domain Schema Standards - -Here's where my mind goes to interesting places. - -What if schema patterns became standardized across domains? - -An `ACTION_CARD` schema could power meal suggestions in a recipe app, workout recommendations in a fitness app, budget alerts in a finance app, treatment plan updates in a healthcare app. Different domains, same structure: context analysis → recommended action → visualization → user choice. - -A `WIZARD` schema could power dietary preference surveys in a recipe app, goal-setting wizards in a fitness app, budget creation flows in a finance app, symptom checkers in a healthcare app. Same multi-step structure, same question types, same conditional logic patterns. - -Your component library becomes a universal renderer for structured intents. You build the primitives once—cards, forms, charts, buttons—and they work across every domain that speaks the schema language. - -This is bigger than code reuse. It's conceptual reuse. The patterns for how to structure adaptive UI become portable knowledge, not locked into specific implementations. - -Imagine open schema standards for common UI patterns. Like how we have standard HTTP methods or standard database query languages, we could have standard schemas for "action recommendation with visualization" or "multi-step data collection with conditional logic." - -Build a great implementation once, use it everywhere. - -### The Self-Assembling Application - -Push this to its logical endpoint: applications that materialize from intent. - -You describe what you want in natural language: "I want to help users plan healthy meals on a budget with easy recipes they can actually make." - -The AI generates schemas for: - -- Data models (user profiles, recipes, pantry items, meal plans) -- UI patterns (dashboard layouts, recipe cards, planning wizards) -- Action types (save recipe, generate shopping list, track spending, suggest substitutions) -- Visualizations (nutrition charts, budget tracking, ingredient freshness timelines) - -You review the schemas, refine them, approve them. The frontend already knows how to render any valid schema. The backend already knows how to validate and store schema-conforming data. - -What you're doing is no longer building features. You're curating and refining schemas. The system does the composition. - -This sounds far-fetched until you realize we're already doing pieces of it. Code generation tools are getting better. Schema validation is mature. Component libraries are comprehensive. AI understands context remarkably well. - -We're just connecting the pieces. - -### Personalization Without Fragmentation - -Traditional personalization means building variants: "Here's the health-focused version. Here's the budget-focused version. Here's the time-saving version." - -You end up managing three codebases pretending to be one. Changes require updating all variants. Testing multiplies. Maintenance becomes painful. - -Schema-driven personalization means generating the optimal interface for each user from the same underlying system. - -User A cares about health. Their recipe cards prominently display nutrition information, macro breakdowns, ingredient quality scores, health impact summaries. The charts show nutrient density. The recommendations prioritize nutritional completeness. - -User B cares about time. Their recipe cards show prep time first, active vs. passive time breakdowns, make-ahead options, batch cooking opportunities. The charts show time saved through meal prep. The recommendations prioritize efficiency. - -User C cares about budget. Their recipe cards show cost per serving, bulk buying opportunities, seasonal ingredient savings, leftover utilization. The charts show cost comparisons. The recommendations prioritize affordability. - -Same data. Same component library. Same schemas. Infinitely variable presentation based on what matters to each individual user. - -No variant management. No A/B test fragments. No "which version am I in?" confusion. Just contextual generation. - -And because it's schema-driven, you can combine dimensions. User D cares about both health and budget. They get nutrition data weighted by cost-effectiveness. User E cares about time and is also vegan. They get quick recipes that happen to be plant-based, not "vegan recipes" as a special category. - -The combinations emerge from the generation logic, not from pre-built variants. - -## The Trade-offs - -This sounds exciting, and it is. But it's not free. The complexity moves around; it doesn't disappear. - -### Schema Management Becomes Critical - -Your schemas are your contract. They're what enables the whole system to work. Which means changing them is like changing your API. - -You need versioning strategies. How do you evolve schemas without breaking existing data? How do you migrate old schema instances to new versions? How do you deprecate schema fields while maintaining backward compatibility? - -You need synchronization mechanisms. The backend that generates schemas and the frontend that renders them must stay aligned. A mismatch means broken UI or validation errors. - -You need discovery tools. As schemas multiply, developers need ways to find them, understand them, know which one to use for which scenario. Documentation becomes more important, not less. - -This is real work. You might need a schema registry, similar to what you'd use for event-driven architectures. You might need automated testing that validates schema compatibility across versions. You might need tooling to generate TypeScript types from schemas and keep them in sync. Tools like Storybook become invaluable—you can document not just components, but how those components render different schema variations. Each story becomes a living example of "here's this schema shape, here's how it renders," making it easier for developers to understand which schema to use for which scenario. - -Schema management is now a first-class concern in your architecture. - -### Database Structure Gets Messy - -The relational database purist in you will not like this. - -Instead of neat columns with proper foreign keys and database-level constraints, you end up with JSONB blobs. The validation that would normally happen at the database layer moves to application code. Querying becomes harder—you can't easily "show me all high-priority compliance actions" when that data is buried in JSON. - -There are workarounds. Hybrid models where you extract commonly-queried fields to columns and keep the dynamic data as JSON. PostgreSQL's JSONB type with indexes on frequently-accessed paths. Generated columns that pull specific values out of JSON for querying. Materialized views for complex queries that need to run often. - -But it's more complex than traditional relational design. You're trading structure for flexibility. - -The database is no longer your source of truth for what data is valid. Your schemas are. The database is just storage. - -This is a philosophical shift as much as a technical one. - -### Debugging Becomes Archaeology - -When something renders wrong, you can't just look at a component file and see what's broken. - -You need to trace: What was the user's context? What did the AI decide based on that context? What schema did it generate? Did it pass validation? How did the mapping layer interpret it? Which component got selected? What props were passed? - -That's a lot of layers between "user saw wrong thing" and "here's the bug." - -You need comprehensive logging at each step. You need replay tools that can take a saved context and schema and show you exactly how it rendered. You need schema versioning so you know which version of which schema generated which UI at which time. You need visibility into AI decision-making—why did it choose this action type over that one? - -Debugging a static component is straightforward. Debugging a generated interface is detective work. - -The tooling helps, but the conceptual overhead is real. - -### Testing Strategy Becomes Critical - -Testing dynamically generated UIs requires a different approach than testing traditional components. You can't just write unit tests for a component and call it done—the component itself might be simple, but the schema that drives it can vary infinitely. - -Our testing strategy has three layers: - -**Schema validation tests** are the foundation. Every schema gets comprehensive validation tests that verify the structure itself is correct. These tests catch issues like missing required fields, invalid enum values, or type mismatches. We treat schemas as first-class code artifacts with their own test suites. - -**Contract tests** verify the relationship between schemas and components. Given a valid schema, does the component render without errors? We maintain a library of example schemas—edge cases, common patterns, minimal valid schemas—and run them through the rendering pipeline. This catches breaking changes when either schemas or components evolve. - -**Integration tests** validate the full generation pipeline. We mock the AI responses with known schemas, then verify the entire flow: context analysis → schema generation → validation → rendering. This ensures the retry logic works, fallbacks activate correctly, and error boundaries catch failures gracefully. - -We rely heavily on snapshot testing for the rendered output. When a schema changes, snapshot tests highlight exactly what UI changes resulted. This gives us confidence that schema evolution doesn't break existing interfaces unexpectedly. - -The biggest shift is acceptance that you can't test every possible variation. Instead, you test the boundaries: minimum valid schemas, maximum complexity schemas, common patterns, and known edge cases. Type safety through Zod catches most issues at compile time, and runtime validation catches the rest before users see them. - -### Error Handling Multiplies - -More moving parts means more things that can go wrong. - -AI generation can fail. Network timeout, rate limit, malformed response. Validation can fail. AI generated something that doesn't match the schema. Retry loop can exhaust. After three attempts, still no valid schema. Rendering can fail. Unknown schema type, missing required data, component error. - -You need graceful fallbacks for every failure mode. - -Default schemas that are safe to show when generation fails. Error boundaries in the frontend that catch rendering failures and show something useful. Monitoring and alerting for validation failures so you know when your prompts or schemas need adjustment. User-friendly error states—"We're having trouble generating recommendations right now, here's what we suggest generally..." - -Every dynamic system trades simplicity for resilience engineering. - -### Performance Considerations - -AI generation adds latency. LLM API calls can take seconds. You can't generate fresh schemas on every page load. - -You need strategies: pre-generation for common scenarios, caching generated schemas by context hash, background generation with optimistic UI, hybrid approaches where you show static defaults while dynamic enhancement loads, edge computing to move generation closer to users. - -But you're adding complexity to maintain responsiveness. The simple "render component with props" is now "check cache, maybe generate, validate, render, handle failure cases." - -The performance budget gets spent differently. - -### Team Learning Curve - -This is a different way of thinking about UI development. - -Your team needs to understand schema design—what makes a good schema, how to evolve them, how to version them. They need to understand runtime validation and how to write schemas that AI can reliably generate. They need to understand slot-based architecture and mapping layers. They need to understand the trade-offs between flexibility and predictability. - -Not every team wants this complexity. For simple, predictable applications, it's overkill. The traditional component-per-feature approach works fine when features are truly unique and don't follow patterns. - -You're choosing a different set of problems. More upfront design work on schemas, less repetitive component building. More system-level thinking, less feature-level implementation. - -It's not objectively better. It's different. And it requires buy-in. - -## When Does This Make Sense? - -So when should you actually consider this approach? - -**Good fit:** - -You're building something with high variability in user contexts or data types. The same underlying features need to look different for different users, different roles, different situations. - -You have frequent new requirements that follow similar patterns. Not "build a completely new feature," but "this feature needs to work slightly differently for this new context." - -Your domain is one where AI can make intelligent contextual decisions. There are patterns to learn, data to analyze, reasonable inferences to make. - -Your team is comfortable with schema-driven development. Or willing to learn. And has the capacity to manage the additional architectural complexity. - -Your users benefit meaningfully from personalized, adaptive experiences. The variability actually matters to them; it's not just engineer preference. - -**Bad fit:** - -You have pixel-perfect design requirements. Brand campaigns, marketing sites, anything where the exact visual presentation is non-negotiable. Schema-driven generation gives you flexibility, not precision. - -Your feature set is predictable and stable. If you're building ten truly unique features with no pattern between them, there's no schema to extract. Just build the ten features. - -You have a small team without capacity for schema management. The overhead might outweigh the benefits. - -You're working on performance-critical real-time interactions. The latency of generation and validation might not be acceptable. - -You have regulatory requirements for fixed UI flows. Sometimes the law requires specific workflows in specific orders. Dynamic generation adds compliance risk. - -**The litmus test:** If you find yourself building slight variations of the same component over and over—same structure, different data, different actions, different styling—you're a candidate. You have patterns worth extracting into schemas. - -If every feature is truly unique, truly bespoke, you're probably not. - -## Components Learning to Think - -Component libraries aren't dead. They're evolving. - -We're moving from tools we manually compose to systems that compose themselves based on context. - -What we built at Bambee is proof that this works in production. Dynamic wizards that adapt to what information is missing. Adaptive cards that surface different insights for different users. Contextual visualizations that show what matters most. All using our component library—Nuxt UI—just arranged by the system instead of by developers. - -But it's early. The schemas are still simple. The generation logic is straightforward. The mapping layers are manageable. - -What comes next is more interesting. - -More sophisticated schemas that can express complex layouts, responsive variations, accessibility requirements, animation preferences. Cross-domain schema standards that let us share UI patterns across completely different applications. Entire pages assembled from intent rather than files. Vector-powered asset selection that makes every interface feel custom. Progressive complexity that adapts to user capability in real-time. Mass personalization without the maintenance burden of variants. - -The vision: developers define schemas and provide component libraries. AI generates optimal UI for each user's context. Users see interfaces that feel custom-built for them. No custom building required. - -This isn't replacing the craft of UI development. It's augmenting it. Moving us from pixel-pushing to pattern-defining. From building variations to building systems that generate variations. From asking "how do I build this interface?" to asking "how do I describe the space of possible interfaces?" - -The future of UI development might not be about building interfaces. It might be about building the systems that build interfaces. - -Component libraries aren't dying. They're learning to think. \ No newline at end of file diff --git a/.firecrawl/byteiota-vite8.md b/.firecrawl/byteiota-vite8.md deleted file mode 100644 index 6c7db9b..0000000 --- a/.firecrawl/byteiota-vite8.md +++ /dev/null @@ -1,244 +0,0 @@ -Share - -- [Share on Facebook](https://www.facebook.com/sharer.php?u=https%3A%2F%2Fbyteiota.com%2Fvite-8-0-rolldown-migration-guide-10-30x-faster-builds%2F "Share on Facebook") -- [Share on Twitter](https://twitter.com/share?url=https%3A%2F%2Fbyteiota.com%2Fvite-8-0-rolldown-migration-guide-10-30x-faster-builds%2F&text=Vite%208.0%20Rolldown%20Migration%20Guide:%2010-30x%20Faster%20Builds "Share on Twitter") - -- [Share on Linkedin](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fbyteiota.com%2Fvite-8-0-rolldown-migration-guide-10-30x-faster-builds%2F "Share on Linkedin") - -Vite 8.0 stable dropped on March 12, 2026, replacing its dual-bundler architecture with [Rolldown](https://rolldown.rs/), a single Rust-based bundler delivering 10-30x faster builds. Linear saw production builds shrink from 46 seconds to 6 seconds—an 87% reduction. With Vite downloaded 65 million times weekly, this upgrade affects millions of developers. Here’s your migration guide. - -## Vite 8 Unifies Build Pipeline with Rolldown - -Vite 8 consolidates two bundlers into one. Previously, Vite used esbuild for fast development and Rollup for optimized production builds. This dual-bundler approach worked but created potential inconsistencies between dev and prod environments. Rolldown eliminates that split. - -Rolldown is a Rust-based bundler with full Rollup API compatibility. It matches esbuild’s development speed while delivering 10-30x faster production builds than Rollup. In official benchmarks testing 19,000 modules, Rolldown completed in 1.61 seconds versus Rollup’s 40.10 seconds—a 25x improvement. - -The architectural unification simplifies configuration. Developers no longer juggle separate esbuild and rollupOptions settings. One bundler, one config, consistent behavior across environments. - -## 10-30x Faster Builds in Real-World Projects - -Performance gains are substantial. [Linear reduced production build times by 87%](https://vite.dev/blog/announcing-vite8), dropping from 46 seconds to 6 seconds. Beehiiv’s large codebase saw 64% improvement. Mercedes-Benz.io cut build times by 38%. - -However, performance gains scale with project size. Small projects under 100 modules see 2-5x improvements. Mid-sized projects between 100-500 modules hit 5-10x. Large projects with 500+ modules achieve the advertised 10-30x gains. - -One developer testing a single-page app watched builds shrink from 3.8 seconds to 0.8 seconds—a clean 5x improvement. For large enterprise apps, these savings multiply across hundreds of daily builds, cutting hours from CI/CD pipelines. - -## How to Migrate to Vite 8 - -Migration is straightforward for most projects. Update Vite to 8.0, test locally, deploy if no issues arise. A compatibility layer auto-converts esbuild and rollupOptions configurations to Rolldown equivalents. - -Basic migration: - -```bash -# Update to Vite 8.0 -npm install vite@8 - -# Test development server -npm run dev - -# Test production build -npm run build - -# Benchmark performance -time npm run build -``` - -Most projects work without configuration changes. The compatibility layer handles the transition automatically. If you encounter issues, [Vite provides a gradual migration path](https://main.vite.dev/guide/migration): test with rolldown-vite on Vite 7 first, then upgrade to Vite 8 stable. This two-step approach isolates Rolldown-specific problems from general upgrade issues. - -## Should You Upgrade? Decision Framework - -Upgrade priority depends on project size and build frequency. Large codebases with 500+ modules benefit most—10-30x gains justify immediate migration. Teams running multiple builds daily see compounding time savings. If CI/CD pipelines take 40 seconds per build, Rolldown cuts that to 2 seconds, saving 38 seconds × 100 builds = 63 minutes daily. - -Mid-sized projects between 100-500 modules should upgrade within the month. You’ll see 5-10x improvements—noticeable but not game-changing. Standard release cycles (daily or weekly deploys) make this a medium priority. - -Small projects under 100 modules see 2-5x gains. Still worthwhile, but less impactful. If you’re risk-averse or running mission-critical production apps, waiting 1-2 months for community feedback is reasonable. Let others find the edge cases first. - -Skip immediate upgrade if you rely on obscure Rollup plugins that may lack Rolldown compatibility. Check the Vite plugin registry first. Also skip if you’re on Vite 6 or older—address that gap before jumping to Vite 8. - -## Troubleshooting Common Migration Issues - -Three issues account for most migration headaches: CommonJS interop changes, manualChunks deprecation, and esbuild transform failures. - -CommonJS imports may break due to Rolldown’s stricter module handling. If runtime errors appear when importing CJS modules, add `legacy.inconsistentCjsInterop: true` to your config temporarily. Long-term, migrate to ESM or fix module resolution. This isn’t Vite’s fault—it’s exposing existing module system inconsistencies. - -The `manualChunks` config no longer works. Vite 8 uses `codeSplitting` instead, offering more granular control: - -```javascript -// OLD (Vite 7) -export default defineConfig({ - build: { - rollupOptions: { - output: { - manualChunks(id) { - if (/\/react(?:-dom)?/.test(id)) { - return 'vendor' - } - } - } - } - } -}) - -// NEW (Vite 8) -export default defineConfig({ - build: { - rolldownOptions: { - output: { - codeSplitting: { - groups: [\ - { name: 'vendor', test: /\/react(?:-dom)?/ }\ - ] - } - } - } - } -}) -``` - -Plugins using `transformWithEsbuild` will fail because esbuild is no longer bundled. Migrate to `transformWithOxc` or install esbuild manually as a peer dependency. The @vitejs/plugin-react v6 already made this switch, using Oxc for React Refresh transforms and eliminating the Babel dependency entirely. - -## What’s Next for Vite - -Vite’s roadmap includes Full Bundle Mode (experimental), which serves bundled files in development for 3× faster dev server startup, 40% faster full reloads, and 10× fewer network requests. This addresses one of Vite’s last pain points—hundreds of separate module requests in large apps. - -[VoidZero](https://voidzero.dev/posts/announcing-rolldown-rc), the team behind Vite and Rolldown, is building a unified Rust toolchain for JavaScript development. Rolldown handles bundling, Oxc powers compilation and minification, and more tools are coming. The trend is clear: Rust-based tooling is replacing JavaScript-based build tools across the ecosystem, from swc to turbopack to Biome. - -## Key Takeaways - -- Vite 8.0 stable replaces esbuild + Rollup with a single Rust bundler (Rolldown), delivering 10-30x faster production builds while maintaining plugin compatibility -- Large projects (500+ modules) see the biggest gains (10-30x), mid-sized projects hit 5-10x, small projects get 2-5x—performance scales with codebase size -- Most projects migrate without config changes thanks to auto-conversion, but CommonJS interop and manualChunks require manual fixes -- Upgrade now if you’re on Vite 7 with large codebases or frequent builds—the stable release is production-ready and compatibility is high -- Future Vite improvements (Full Bundle Mode, Rust toolchain expansion) show continued innovation, making this a safe long-term bet - -Vite 8 isn’t just faster—it’s simpler. One bundler, one config, one mental model. The dual-bundler era is over. - -### Share - -![ByteBot]() - -[ByteBot](https://byteiota.com/author/bytebot/ "Posts by ByteBot") - -I am a playful and cute mascot inspired by computer programming. I have a rectangular body with a smiling face and buttons for eyes. My mission is to cover latest tech news, controversies, and summarizing them into byte-sized and easily digestible information. - -[Previous](https://byteiota.com/bitnet-tutorial-run-100b-llms-on-cpu-with-1-bit-inference/) - -### [BitNet Tutorial: Run 100B LLMs on CPU with 1-Bit Inference](https://byteiota.com/bitnet-tutorial-run-100b-llms-on-cpu-with-1-bit-inference/) - -[Next](https://byteiota.com/openclaw-china-ban-first-ai-agent-crackdown/) - -### [OpenClaw China Ban: First AI Agent Crackdown](https://byteiota.com/openclaw-china-ban-first-ai-agent-crackdown/) - -#### You may also like - -### [Reddit Bot Verification: 100K Daily Removals Drive Crackdown](https://byteiota.com/reddit-bot-verification-100k-daily-removals-drive-crackdown/) - -2 hours ago - -### [AMD Ryzen 9 9950X3D2: First Dual-Cache CPU Hits 208MB](https://byteiota.com/amd-ryzen-9-9950x3d2-first-dual-cache-cpu-hits-208mb/) - -4 hours ago - -[![]()](https://byteiota.com/cloud-waste-2026-235b-lost-to-idle-resources/) - -### [Cloud Waste 2026: $235B Lost to Idle Resources](https://byteiota.com/cloud-waste-2026-235b-lost-to-idle-resources/) - -5 hours ago - -[![]()](https://byteiota.com/lg-1hz-display-pushes-dell-xps-16-to-27-hour-battery-life/) - -### [LG 1Hz Display Pushes Dell XPS 16 to 27-Hour Battery Life](https://byteiota.com/lg-1hz-display-pushes-dell-xps-16-to-27-hour-battery-life/) - -6 hours ago - -### [macOS 26 Consistently Bad: It’s Design, Not Bugs](https://byteiota.com/macos-26-consistently-bad-its-design-not-bugs/) - -8 hours ago - -[![]()](https://byteiota.com/cursor-composer-2-10x-cheaper-than-claude-beats-opus-4-6/) - -### [Cursor Composer 2: 10x Cheaper Than Claude, Beats Opus 4.6](https://byteiota.com/cursor-composer-2-10x-cheaper-than-claude-beats-opus-4-6/) - -9 hours ago - -### Leave a reply [Cancel reply](https://byteiota.com/vite-8-0-rolldown-migration-guide-10-30x-faster-builds/\#respond) - -Your email address will not be published.Required fields are marked \* - -Comment - -Name \* - -Email \* - -Website - -Save my name, email, and website in this browser for the next time I comment. - -Δ - -#### More in: [JavaScript](https://byteiota.com/programming/javascript/) - -[![Featured image for HTMX Tutorial 2026: Replace React with 14KB HTML]()](https://byteiota.com/htmx-tutorial-2026-replace-react-with-14kb-html/) - -### [HTMX Tutorial 2026: Replace React with 14KB HTML](https://byteiota.com/htmx-tutorial-2026-replace-react-with-14kb-html/) - -5 days ago - -[![Featured image for TanStack Start: Type-Safe React Framework for 2026]()](https://byteiota.com/tanstack-start-type-safe-react-framework-for-2026/) - -### [TanStack Start: Type-Safe React Framework for 2026](https://byteiota.com/tanstack-start-type-safe-react-framework-for-2026/) - -5 days ago - -[![Featured image for Hono Framework: Build Edge APIs on Cloudflare Workers]()](https://byteiota.com/hono-framework-build-edge-apis-on-cloudflare-workers/) - -### [Hono Framework: Build Edge APIs on Cloudflare Workers](https://byteiota.com/hono-framework-build-edge-apis-on-cloudflare-workers/) - -6 days ago - -[![Featured image for React Server Components: The Practical Guide for 2026]()](https://byteiota.com/react-server-components-the-practical-guide-for-2026/) - -### [React Server Components: The Practical Guide for 2026](https://byteiota.com/react-server-components-the-practical-guide-for-2026/) - -6 days ago - -### [JavaScript Bloat: 3 Pillars Killing Bundle Size](https://byteiota.com/javascript-bloat-3-pillars-killing-bundle-size/) - -6 days ago - -### [Hono Framework: 14KB Edge API Alternative to Express](https://byteiota.com/hono-framework-14kb-edge-api-alternative-to-express/) - -March 13, 2026 - -Next Article: - -March 13, 2026 - -min read - --21 % - -## [![logo]()](https://byteiota.com/) - -[✕Close](https://byteiota.com/vite-8-0-rolldown-migration-guide-10-30x-faster-builds/#atbs-ceris-offcanvas-primary) - -## [![logo]()](https://byteiota.com/) - -[✕](https://byteiota.com/vite-8-0-rolldown-migration-guide-10-30x-faster-builds/#atbs-ceris-offcanvas-mobile) - -## Latest Posts - -### [Reddit Bot Verification: 100K Daily Removals Drive Crackdown](https://byteiota.com/reddit-bot-verification-100k-daily-removals-drive-crackdown/) - -### [AMD Ryzen 9 9950X3D2: First Dual-Cache CPU Hits 208MB](https://byteiota.com/amd-ryzen-9-9950x3d2-first-dual-cache-cpu-hits-208mb/) - -### [Cloud Waste 2026: $235B Lost to Idle Resources](https://byteiota.com/cloud-waste-2026-235b-lost-to-idle-resources/) - -### [LG 1Hz Display Pushes Dell XPS 16 to 27-Hour Battery Life](https://byteiota.com/lg-1hz-display-pushes-dell-xps-16-to-27-hour-battery-life/) - -### [macOS 26 Consistently Bad: It’s Design, Not Bugs](https://byteiota.com/macos-26-consistently-bad-its-design-not-bugs/) - -[![feedmatters.com](https://byteiota.com/wp-content/uploads/2026/02/promote-feedmatters-edited.png)](https://feedmatters.com/?utm_source=byteiota&utm_medium=banner&utm_campaign=popup) - -× \ No newline at end of file diff --git a/.firecrawl/corvu-dynamic.md b/.firecrawl/corvu-dynamic.md deleted file mode 100644 index ecca94b..0000000 --- a/.firecrawl/corvu-dynamic.md +++ /dev/null @@ -1,112 +0,0 @@ -# Dynamic Components - -All primitive components that render a DOM element are dynamic, which means that you can modify the element or the component they should render as. - -## Native elements [Section titled Native elements](https://corvu.dev/docs/dynamic-components/\#native-elements) - -In most cases, you shouldn’t need to change the DOM element that the primitive component renders. corvu has sensible defaults for all components. But there are cases where it makes sense to change them. An example would be the `Tooltip` trigger which renders as a `button` element. You may want to render a tooltip on a link (`a` tag) instead. To do this, you have to specify the `as` property on the trigger component: - -``` - - corvu.dev - -``` - -## Solid components [Section titled Solid components](https://corvu.dev/docs/dynamic-components/\#solid-components) - -A much more common use case is to render a primitive component as a custom Solid component. This is useful to apply default styling or to add additional functionality. - -For example, you might have your own, custom-styled button component and want to use it as a trigger for a dialog: - -``` -import { - ComponentProps, - splitProps, -} from 'solid-js' -import Dialog from '@corvu/dialog' - -const CustomButton = ( - props: ComponentProps<'button'> & { variant: 'fill' | 'outline' }, -) => { - const [local, rest] = splitProps(props, ['variant']) - // Apply your custom styling here - return - - Label - - - ) -} -``` - -Every primitive provides different properties in its context, have a look at the API section of each primitive to see what’s available. - -## Children callbacks [Section titled Children callbacks](https://corvu.dev/docs/state/\#children-callbacks) - -The `Root` component of every primitive (and in a few cases others) also accepts a function as its children. By doing this, we can pass the internal state to the children for you to access. An example of this looks like this: - -``` -import Dialog from '@corvu/dialog' -import { createSignal } from 'solid-js' - -const MyDialog = () => { - return ( - - {(props) => ( - <> -

The dialog is {props.open() ? 'open' : 'closed'}

- - Open Dialog - - Label - - - )} -
- ) -} -``` - -Note that the props passed from the `Root` component include reactive getters. Make sure to access them in a reactive scope, like you would in any other Solid component. - -## Keyed context [Section titled Keyed context](https://corvu.dev/docs/state/\#keyed-context) - -There may be situations where you want to use nested instances of the same primitive. For example, multiple dialogs with multiple trigger buttons that are hard to separate in the template. For this case, corvu allows you to pass a `contextId` to every primitive component to tell which context to use. - -Here’s how two nested dialogs would look like: - -``` - - - - Open Dialog 1 - Open Dialog 2 - - - Dialog 1 - - - - Dialog 2 - - - - -``` - -When using keyed contexts, you can pass the same key to the `useContext()` function to access the context of the respective primitive. - -``` -const { open, setOpen } = Dialog.useContext('dialog-1') -``` - -Developed and designed by [Jasmin](https://github.com/GiyoMoon/) \ No newline at end of file diff --git a/.firecrawl/corvu-styling.md b/.firecrawl/corvu-styling.md deleted file mode 100644 index 9c07567..0000000 --- a/.firecrawl/corvu-styling.md +++ /dev/null @@ -1,91 +0,0 @@ -# Styling - -corvu leaves the styling up to you. You can use Tailwind CSS, any CSS-in-JS library or just plain old CSS to style primitives. - -## Data attributes [Section titled Data attributes](https://corvu.dev/docs/styling/\#data-attributes) - -Components that can be in different states, e.g. `open` or `closed` for a dialog, provide data attributes to style them accordingly. - -Here is an example of how to style a dialog based on its open state: - -``` -.dialog_content[data-open] { - /* styles to apply when open */ -} -.dialog_content[data-closed] { - /* styles to apply when closed */ -} -``` - -Don’t forget to add the `dialog_content` class to your Dialog content component: - -``` -... -``` - -Additionally, every corvu component has a data attribute for you to use. A dialog content element would render like this: - -``` -
...
-``` - -You can use it to style all components of the same kind at once: - -``` -[data-corvu-dialog-content] { - /* styles to apply to the dialog content */ -} -[data-corvu-dialog-content][data-open] { - /* styles to apply when open */ -} -[data-corvu-dialog-content][data-closed] { - /* styles to apply when closed */ -} -``` - -Additionally, corvu provides plugins for these CSS frameworks: - -- [Tailwind CSS plugin](https://corvu.dev/docs/installation/#tailwind-css-plugin) -- [UnoCSS preset](https://corvu.dev/docs/installation/#unocss-preset) - -They make it easy to style components based on their current state using modifiers. - -**Available modifiers** - -- `corvu-open` -\> `&[data-open]` -- `corvu-closed` -\> `&[data-closed]` -- `corvu-expanded` -\> `&[data-expanded]` -- `corvu-collapsed` -\> `&[data-collapsed]` -- `corvu-transitioning` -\> `&[data-transitioning]` -- `corvu-opening` -\> `&[data-opening]` -- `corvu-closing` -\> `&[data-closing]` -- `corvu-snapping` -\> `&[data-snapping]` -- `corvu-resizing` -\> `&[data-resizing]` -- `corvu-disabled` -\> `&[data-disabled]` -- `corvu-active` -\> `&[data-active]` -- `corvu-dragging` -\> `&[data-dragging]` -- `corvu-selected` -\> `&[data-selected]` -- `corvu-today` -\> `&[data-today]` -- `corvu-range-start` -\> `&[data-range-start]` -- `corvu-range-end` -\> `&[data-range-end]` -- `corvu-in-range` -\> `&[data-in-range]` -- `corvu-side-top` -\> `&[data-side='top']` -- `corvu-side-right` -\> `&[data-side='right']` -- `corvu-side-bottom` -\> `&[data-side='bottom']` -- `corvu-side-left` -\> `&[data-side='left']` - -These two CSS framework use similar syntax. You can style components like this: - -``` - - ... - -``` - -## Animation [Section titled Animation](https://corvu.dev/docs/styling/\#animation) - -corvu has built-in support for CSS animations and waits for any pending animation to finish before removing an element from the DOM. This means you can use CSS animations to animate the appearance and disappearance of primitives. Every unmountable component also provides a `forceMount` property which forces it to stay mounted in the DOM even when it is not visible. This is useful when using third-party animation libraries. - -Developed and designed by [Jasmin](https://github.com/GiyoMoon/) \ No newline at end of file diff --git a/.firecrawl/csszone-anchor.md b/.firecrawl/csszone-anchor.md deleted file mode 100644 index d4d3bd6..0000000 --- a/.firecrawl/csszone-anchor.md +++ /dev/null @@ -1,79 +0,0 @@ -# CSS Anchor Positioning 2026: Practical Guide for Tooltips, Menus, and Smart Overlays - -Positioning contextual UI has always been painful. Dropdowns, tooltips, and popovers often require JavaScript calculations, viewport checks, and custom collision logic. CSS Anchor Positioning moves a large part of this work into native styling. - -## Why It Matters - -- dropdown clipped on small screens -- tooltip detached from trigger on scroll -- menu appears off-screen in RTL or localized UI - -## Core Mental Model - -Define an anchor element -Attach floating UI to that anchor -Let CSS handle alignment behavior - -## Real Use Cases - -- action menu in data tables -- profile dropdown in sticky headers -- inline help tooltip in forms -- contextual edit controls in CMS - -## UX Rules - -- keep overlays close to trigger -- preserve keyboard focus flow -- add deterministic closing behavior -- avoid huge animation while repositioning - -## Rollout Strategy - -tooltip -dropdown -popover with richer content - -## Conclusion - -Anchor positioning is a structural improvement that reduces UI fragility in real products. - -## Related posts - -Continue reading on nearby topics. - -[Latest CSS Gradient Features and Trends for 2026Latest CSS gradient features for 2026: new color combinations, mesh techniques, animated transitions, and practical production patterns.](https://css-zone.com/blog/css-gradient-trends-2026) [Core Web Vitals 2026: CSS Playbook for Faster LCP, Better INP, and Stable CLSA practical Core Web Vitals 2026 guide focused on CSS architecture, rendering strategy, font loading, and layout stability for real products.](https://css-zone.com/blog/core-web-vitals-2026-css-playbook) [CSS Best Practices for Real Projects: A Practical Playbook from CSS-Zone.comA practical CSS guide for production teams: architecture, naming, tokens, responsive strategy, performance, and accessibility. Includes many copy-paste-ready examples and workflows used on CSS-Zone.com.](https://css-zone.com/blog/css-best-practices-real-projects-css-zone) [Modern CSS Features You Should Use in 2026Explore the latest CSS features that are changing web development: container queries, :has() selector, cascade layers, and more cutting-edge techniques.](https://css-zone.com/blog/modern-css-features-2026) - -## Comments - -0 - -Sign in to leave a comment. - -Sign in - -No comments yet. Be the first. - -Cookies - -## We use cookies to keep things smooth - -They help keep you signed in, remember your preferences, and measure what features land. You control what happens next. - -[Privacy Policy](https://css-zone.com/privacy-policy) [Cookie rules](https://css-zone.com/cookie-policy) - -Not nowAccept cookies - -Contact - -CSS file\_type\_scss - -reCAPTCHA - -Recaptcha requires verification. - -[Privacy](https://www.google.com/intl/en/policies/privacy/) \- [Terms](https://www.google.com/intl/en/policies/terms/) - -protected by **reCAPTCHA** - -[Privacy](https://www.google.com/intl/en/policies/privacy/) \- [Terms](https://www.google.com/intl/en/policies/terms/) \ No newline at end of file diff --git a/.firecrawl/devproportal-radix-react-aria.md b/.firecrawl/devproportal-radix-react-aria.md deleted file mode 100644 index 1ca3e65..0000000 --- a/.firecrawl/devproportal-radix-react-aria.md +++ /dev/null @@ -1,382 +0,0 @@ -[↓\\ -Skip to main content](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/#main-content) - -[DevPro Portal](https://devproportal.com/) - -Table of Contents - - -Table of Contents - - -It’s 2026. If you are still wrestling with `!important` overrides in Material UI or trying to hack the internal DOM structure of a Bootstrap component just to match a Figma design, you’re doing it the hard way. - -The React ecosystem has matured. We’ve moved past the era of “All-in-One” component kits that dictate your styling. We are firmly in the era of **Headless UI**. - -As senior developers and architects, our goal isn’t just to put pixels on the screen; it’s to ship accessible, robust, and performant interfaces that scale. We want full control over the CSS (likely via Tailwind or CSS-in-JS) without reinventing the complex logic required for keyboard navigation, focus management, and screen reader support. - -This article dives deep into the two heavyweights of the headless world: **Radix UI** and **React Aria**. We’ll compare them, build real components, and discuss the architectural implications of choosing one over the other. - -## The Headless Architecture [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#the-headless-architecture) - -Before we touch the code, let’s align on the mental model. “Headless” doesn’t mean “no UI”; it means “unopinionated UI”. - -In a traditional library (like AntD or MUI), the logic and the styling are coupled. In a Headless library, the library provides the **behavior** and **state**, while you provide the **rendering** and **styling**. - -Here is how the data flow looks in a modern Headless setup: - -Your Code - -Headless Layer (Radix/Aria) - -User Interaction - -State Management - -WAI-ARIA Roles - -Focus Trap / Loops - -Keyboard/Mouse Events - -Tailwind / CSS Modules - -JSX Structure - -Framer Motion - -Rendered DOM - -### Why does this matter? [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#why-does-this-matter) - -1. **Accessibility (a11y) is hard:** Implementing a fully accessible Dropdown Menu takes weeks of testing across VoiceOver, NVDA, and JAWS. Headless libraries give you this for free. -2. **Design Freedom:** You own the `className`. -3. **Bundle Size:** You only import the logic you need. - -* * * - -## Prerequisites and Environment [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#prerequisites-and-environment) - -To follow along, ensure you have a modern React environment set up. We are assuming a 2026 standard stack: - -- **Node.js:** v20+ (LTS) -- **React:** v19 -- **Styling:** Tailwind CSS v4 (or v3.4+) -- **Icons:** Lucide React (optional but recommended) - -### Setup [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#setup) - -We’ll create a lightweight sandbox. - -Copy - -```bash -# Create a Vite project -npm create vite@latest headless-demo -- --template react-ts - -# Enter directory -cd headless-demo - -# Install dependencies (We will use both for comparison) -npm install @radix-ui/react-popover @radix-ui/react-dialog react-aria-components class-variance-authority clsx tailwind-merge framer-motion - -# Start dev server -npm run dev -``` - -_Note: We included `class-variance-authority` (CVA) and `tailwind-merge`. These are the bread and butter for handling styles in headless components._ - -* * * - -## The Contenders: Radix vs. React Aria [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#the-contenders-radix-vs-react-aria) - -Choosing between these two is often the first architectural decision when building a Design System. - -| Feature | Radix UI | React Aria (Adobe) | -| --- | --- | --- | -| **Philosophy** | Component-first. Provides unstyled primitives (e.g., ``). | Hooks-first (historically), now offers Components. “Industrial Grade” a11y. | -| **API Surface** | simpler, cleaner JSX. Very “React-y”. | Extremely granular. Offers `useButton`, `useSelect`, etc., plus a new Component API. | -| **Styling** | Agnostic. Works perfectly with Tailwind. | Agnostic. The new `react-aria-components` has a specific `className` function for states (hover/focus). | -| **Animation** | Relies on external libs or CSS keyframes. Works great with Framer Motion. | Has built-in animation support in the new components API, but generally external. | -| **Mobile** | Good, but sometimes lacks nuanced touch interactions. | Best in class. Adobe tests on everything. Handles virtual keyboard quirks brilliantly. | -| **Bundle Size** | Modular. You install packages individually (e.g., `@radix-ui/react-tooltip`). | Modular, but the core logic is heavier due to extreme robustness. | - -* * * - -## Part 1: Building with Radix UI [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#part-1-building-with-radix-ui) - -Radix is generally the favorite for teams that want to move fast but maintain high quality. It powers the popular `shadcn/ui` collection. - -Let’s build a **Popover** component. This isn’t just a tooltip; it needs to handle focus trapping (optional), closing on outside clicks, and keyboard formatting. - -### The Implementation [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#the-implementation) - -We will use Tailwind for styling and `lucide-react` for an icon. - -Copy - -```tsx -// src/components/RadixPopover.tsx -import * as React from 'react'; -import * as Popover from '@radix-ui/react-popover'; -import { Settings2, X } from 'lucide-react'; -import { clsx, type ClassValue } from 'clsx'; -import { twMerge } from 'tailwind-merge'; - -// Utility for cleaner classes -function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} - -export default function UserSettingsPopover() { - return ( - - - - - - - -
-

Dimensions

- -
- - -
- -
- - -
-
- - - - - - -
-
-
- ); -} -``` - -### Analysis [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#analysis) - -1. **`asChild` Pattern:** Notice ``. This is Radix’s signature move. It merges the event handlers and ARIA attributes onto _your_ DOM node (` - - ` - overflow-auto rounded-lg drop-shadow-lg border border-slate-200 bg-white - w-[var(--trigger-width)] - ${isEntering ? 'animate-in fade-in zoom-in-95 duration-200' : ''} - ${isExiting ? 'animate-out fade-out zoom-out-95 duration-200' : ''} - `}> - - {['React', 'Vue', 'Svelte', 'Angular', 'Qwik'].map((item) => ( - ` - cursor-default select-none rounded px-2 py-1.5 text-sm outline-none - ${isFocused ? 'bg-blue-100 text-blue-900' : 'text-slate-700'} - ${isSelected ? 'font-semibold' : ''} - `} - > - {({ isSelected }) => ( -
- {item} - {isSelected && } -
- )} -
- ))} -
-
- - ); -} -``` - -### Analysis [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#analysis-1) - -1. **Render Props for Styling:** RAC uses render props heavily for styling classes (e.g., `className={({ isFocused }) => ...}`). This exposes the internal interaction state directly to Tailwind. You don’t need `data-` attributes; you have direct JS boolean access. -2. **Adaptive Behavior:** Adobe put incredible effort into mobile. On mobile devices, this component handles touch cancellation, scrolling behavior, and virtual keyboard avoidance better than almost any other library. -3. **Semantics:** The `` and `` components ensure correct ARIA roles (`role="listbox"`, `role="option"`) are applied, which are different from a standard navigation menu. - -* * * - -## Performance and Common Pitfalls [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#performance-and-common-pitfalls) - -When implementing Headless UI in a production environment, watch out for these traps. - -### 1\. The Bundle Size Myth [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#1-the-bundle-size-myth) - -You might think, “I’m importing a huge library!” Not really. Both libraries support tree-shaking. - -- **Radix:** You usually install specific packages (`@radix-ui/react-dialog`). -- **React Aria:** The monolithic package exports everything, but modern bundlers (Vite/Rollup/Webpack 5) shake out unused exports effectively. - -However, React Aria IS logically heavier because it includes code for edge cases you didn’t know existed (like specific screen reader bugs in older iOS versions). - -### 2\. Focus Management [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#2-focus-management) - -The number one bug in custom modals is **Focus Trapping**. - -- **Scenario:** User opens a modal. User hits `Tab`. Focus goes _behind_ the modal to the URL bar or the background content. -- **Solution:** Both libraries handle this, but you must ensure you don’t accidentally unmount the component before the closing animation finishes. Radix handles this with `data-state` and animations, but manual conditional rendering (`{isOpen && }`) without `AnimatePresence` (if using Framer) can break the focus return feature. - -### 3\. Z-Index Wars [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#3-z-index-wars) - -Both libraries use **Portals**. - -- **Trap:** If your global CSS sets a high z-index on a sticky header, your ported modal might end up under it if the portal container isn’t managed correctly. -- **Best Practice:** Create a dedicated stacking context or ensure your portal root (usually `body`) is handled correctly in your Tailwind config (`z-50` usually suffices for modals). - -* * * - -## Conclusion: Which one should you choose? [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#conclusion-which-one-should-you-choose) - -As an architect, your choice depends on your team’s priorities. - -**Choose Radix UI if:** - -- You want a developer experience that feels “native” to React. -- You are heavily invested in the Tailwind ecosystem (it pairs beautifully). -- You need to ship fast and “Very Good” accessibility is acceptable. -- You are building a standard B2B SaaS dashboard. - -**Choose React Aria if:** - -- **Accessibility is non-negotiable.** (e.g., Government, Healthcare, Education). -- You need robust touch/mobile interactions (drag and drop, swipes). -- You prefer render-props for styling logic over CSS selectors. -- You are building a complex design system that needs to last 5+ years. - -Both libraries represent the pinnacle of React component development in 2026. By separating behavior from design, they allow us to build UIs that are unique to our brand but universal in their usability. - -### Further Reading [\#](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/\#further-reading) - -- [WAI-ARIA Authoring Practices Guide (APG)](https://www.w3.org/WAI/ARIA/apg/) \- The bible for accessible patterns. -- [Radix UI Docs](https://www.radix-ui.com/) -- [React Aria Components Docs](https://react-spectrum.adobe.com/react-aria/components.html) - -**Stop reinventing the wheel. Import the wheel, and paint it whatever color you want.** - -## Related Articles - -- · [React Compiler: The End of Manual Memoization and the Era of Auto-Optimization](https://devproportal.com/frontend/react/react-compiler-eliminates-memoization/) -- · [Mastering Concurrent Rendering: A Deep Dive into Transitions and Deferring](https://devproportal.com/frontend/react/mastering-react-concurrent-mode-transitions-deferring/) -- · [React 19 Deep Dive: Mastering the Compiler, Actions, and Advanced Hooks](https://devproportal.com/frontend/react/react-19-deep-dive-compiler-actions-hooks/) -- · [State of React State: Redux Toolkit vs. Zustand vs. Signals](https://devproportal.com/frontend/react/react-state-management-showdown-redux-zustand-signals/) -- · [React 19 Architecture: Mastering the Server vs. Client Component Paradigm](https://devproportal.com/frontend/react/react-19-server-vs-client-components-guide/) - -## The Architect’s Pulse: Engineering Intelligence - -As a CTO with 21+ years of experience, I deconstruct the complexities of high-performance backends. Join our technical circle to receive weekly strategic drills on JVM internals, Go concurrency, and cloud-native resilience. No fluff, just pure architectural execution. - -Which technical challenge are you currently deconstructing? - -Option A: Master patterns in Go, Java, and Node.js. - -Option B: Deep-dive into Database internals and Sharding. - -Option C: Orchestrating resilience with K8s and Microservices. - -Option D: Deconstructing real-world architectural case studies. - -Join the Inner Circle - -[Built with Kit](https://kit.com/features/forms?utm_campaign=poweredby&utm_content=form&utm_medium=referral&utm_source=dynamic) - -[↑](https://devproportal.com/frontend/react/mastering-headless-ui-radix-vs-react-aria/#the-top "Scroll to top") - -* * * - -[![DevPro Portal Logo](https://devproportal.com/images/devproportal_banner_light.jpg)![DevPro Portal Logo](https://devproportal.com/images/devproportal_banner_dark.jpg)](https://devproportal.com/) - -© 2026 DevPro Portal. All rights reserved. - - -Powered by [Stonehenge EdTech](https://www.stonehengeedtech.com/). - - -[About Us](https://devproportal.com/about-us) [Terms of Service](https://devproportal.com/terms-of-service) [Privacy Policy](https://devproportal.com/privacy-policy) [Cookie Policy](https://devproportal.com/cookie-policy) [Support & Contact](https://devproportal.com/contact) \ No newline at end of file diff --git a/.firecrawl/dewidar-headless-patterns.md b/.firecrawl/dewidar-headless-patterns.md deleted file mode 100644 index 80863c9..0000000 --- a/.firecrawl/dewidar-headless-patterns.md +++ /dev/null @@ -1,224 +0,0 @@ -[Back to Blog](https://mohameddewidar.com/blog) - -# Headless UI Patterns in React - -Headless UI is a pattern that separates **logic** from **presentation**. The component controls state and behavior while leaving all markup and styling to the consumer. This pattern is used in modern design systems and UI libraries because it gives developers full visual freedom without sacrificing predictable logic. - -This article explains the pattern clearly, shows how to implement it in React, and provides real world examples that scale in production systems. - -## 1\. What Headless UI Means - -A headless component does not render its own layout. It exposes: - -- state -- actions -- event handlers -- accessibility helpers - -The consumer decides how the UI looks. - -Example of a headless toggle hook: - -``` -function useToggle(initial = false) { - const [on, setOn] = useState(initial); - return { - on, - toggle: () => setOn((v) => !v), - setOn - }; -} -``` - -Usage with custom UI: - -``` -const toggle = useToggle(); - - -``` - -The hook manages behavior. The UI is entirely customizable. - -## 2\. Why Headless UI Matters - -Headless components solve real problems: - -### Problem 1. Components that restrict styling - -Teams often fight against rigid components that force markup or CSS structures. - -### Problem 2. Hard to integrate with custom design systems - -Headless logic works with any HTML structure and any design system. - -### Problem 3. Difficult to reuse logic without duplicating UI - -The logic lives in one place. The UI can vary by use case. - -### Problem 4. Mixed concerns - -UI, behavior, and state are combined in one file. Headless UI splits these into clear boundaries. - -## 3\. Headless UI With Render Props - -Render props expose behavior through a function. - -``` -function Dropdown({ children }) { - const [open, setOpen] = useState(false); - - return children({ - open, - toggle: () => setOpen((v) => !v) - }); -} -``` - -Usage: - -``` - - {({ open, toggle }) => ( - <> - - {open &&
...
} - - )} -
-``` - -This gives complete visual control. - -## 4\. Headless UI With Context and Compound Components - -This pattern is cleaner for multi part components like modals, dropdowns, and accordions. - -### Step 1. Create context driven logic - -``` -const AccordionContext = createContext(null); - -function Accordion({ children }) { - const [open, setOpen] = useState(false); - - const value = { - open, - toggle: () => setOpen((v) => !v) - }; - - return ( - - {children} - - ); -} -``` - -### Step 2. Separate UI components - -``` -function AccordionTrigger({ children }) { - const { toggle } = useContext(AccordionContext); - return ; -} - -function AccordionContent({ children }) { - const { open } = useContext(AccordionContext); - return open ?
{children}
: null; -} -``` - -Usage: - -``` - - Show Details - Here are the details... - -``` - -The logic is shared. The UI remains flexible. - -## 5\. Building a Headless Select Component - -Logic: - -``` -function useSelect(items) { - const [selected, setSelected] = useState(null); - - return { - items, - selected, - select: (item) => setSelected(item) - }; -} -``` - -Usage: - -``` -const select = useSelect(["A", "B", "C"]); - -
    - {select.items.map((item) => ( -
  • select.select(item)}> - {item} {select.selected === item ? "(selected)" : ""} -
  • - ))} -
-``` - -## 6\. Accessibility in Headless UI - -A headless design system should expose accessibility helpers. - -``` -function useDialog() { - const [open, setOpen] = useState(false); - - return { - open, - triggerProps: { - "aria-haspopup": "dialog", - onClick: () => setOpen(true) - }, - dialogProps: { - role: "dialog", - "aria-modal": true - }, - close: () => setOpen(false) - }; -} -``` - -Usage: - -``` -const dialog = useDialog(); - - - -{dialog.open && ( -
- Modal content - -
-)} -``` - -## 7\. Anti Patterns to Avoid - -- Forcing DOM structure -- Mixing styling inside the logic -- Bloated configuration props -- Hooks that try to manage both logic and rendering - -## Final Thoughts - -Headless UI patterns help teams build flexible and reusable components that scale with evolving design requirements. By separating logic from presentation, React applications become easier to maintain, more customizable, and more predictable. - -[Back to Blog](https://mohameddewidar.com/blog) \ No newline at end of file diff --git a/.firecrawl/json-render.md b/.firecrawl/json-render.md deleted file mode 100644 index 8485bc3..0000000 --- a/.firecrawl/json-render.md +++ /dev/null @@ -1,597 +0,0 @@ -The Generative UI Framework - -# AI → json-render → UI - -Generate dynamic, personalized UIs from prompts without sacrificing reliability. Predefined components and actions for safe, predictable output. - -Create a contact form with name, email, and message - -Create a login form with email and passwordBuild a feedback form with rating stars - -jsonnestedstreamcatalog - -``` -{"op":"add","path":"/root","value":"card"} -{"op":"add","path":"/elements/name","value":{"type":"Input","props":{"label":"Name","name":"name","statePath":"/form/name","checks":[{"type":"required","message":"Name is required"}]}}} -{"op":"add","path":"/elements/email","value":{"type":"Input","props":{"label":"Email","name":"email","type":"email","statePath":"/form/email","checks":[{"type":"required","message":"Email is required"},{"type":"email","message":"Please enter a valid email"}]}}} -``` - -``` -{ - "root": "card", - "state": { - "form": { - "name": "", - "email": "", - "message": "" - } - }, - "elements": { - "card": { - "type": "Card", - "props": { - "title": "Contact Us", - "maxWidth": "md" - }, - "children": [\ - "name",\ - "email"\ - ] - }, - "name": { - "type": "Input", - "props": { - "label": "Name", - "name": "name", - "statePath": "/form/name", - "checks": [\ - {\ - "type": "required",\ - "message": "Name is required"\ - }\ - ] - } - }, - "email": { - "type": "Input", - "props": { - "label": "Email", - "name": "email", - "type": "email", - "statePath": "/form/email", - "checks": [\ - {\ - "type": "required",\ - "message": "Email is required"\ - },\ - {\ - "type": "email",\ - "message": "Please enter a valid email"\ - }\ - ] - } - } - } -} -``` - -``` -{ - "state": { - "form": { - "name": "", - "email": "", - "message": "" - } - }, - "elements": { - "type": "Card", - "props": { - "title": "Contact Us", - "maxWidth": "md" - }, - "children": [\ - {\ - "type": "Input",\ - "props": {\ - "label": "Name",\ - "name": "name",\ - "statePath": "/form/name",\ - "checks": [\ - {\ - "type": "required",\ - "message": "Name is required"\ - }\ - ]\ - }\ - },\ - {\ - "type": "Input",\ - "props": {\ - "label": "Email",\ - "name": "email",\ - "type": "email",\ - "statePath": "/form/email",\ - "checks": [\ - {\ - "type": "required",\ - "message": "Email is required"\ - },\ - {\ - "type": "email",\ - "message": "Please enter a valid email"\ - }\ - ]\ - }\ - }\ - ] - } -} -``` - -components (39)actions (6) - -Accordion - -Collapsible sections. Items as \[{title, content}\]. Type 'single' (default) or 'multiple'. - -items: arraytype: enum? - -Alert - -Alert banner - -title: stringmessage: string?type: enum? - -Avatar - -User avatar with fallback initials - -src: string?name: stringsize: enum? - -Badge - -Status badge - -text: stringvariant: enum? - -BarGraph - -Vertical bar chart - -title: string?data: array - -Button - -Clickable button. Bind on.press for handler. - -label: stringvariant: enum?disabled: boolean? - -on.press - -ButtonGroup - -Segmented button group. Use { $bindState } on selected for selected value. - -buttons: arrayselected: string? - -on.change - -Cardslots: default - -Container card for content sections. Use for forms/content boxes, NOT for page headers. - -title: string?description: string?maxWidth: enum?centered: boolean? - -Carousel - -Horizontally scrollable carousel of cards. - -items: array - -Checkbox - -Checkbox input. Use { $bindState } on checked for binding. - -label: stringname: stringchecked: boolean? - -on.change - -Collapsibleslots: default - -Collapsible section with trigger. Children render inside. - -title: stringdefaultOpen: boolean? - -Dialogslots: default - -Modal dialog. Set openPath to a boolean state path. Use setState to toggle. - -title: stringdescription: string?openPath: string - -Drawerslots: default - -Bottom sheet drawer. Set openPath to a boolean state path. Use setState to toggle. - -title: stringdescription: string?openPath: string - -DropdownMenu - -Dropdown menu with trigger button and selectable items. - -label: stringitems: array - -on.select - -Gridslots: default - -Grid layout (1-6 columns) - -columns: number?gap: enum? - -Heading - -Heading text (h1-h4) - -text: stringlevel: enum? - -Image - -Placeholder image (displays alt text in a styled box) - -alt: stringwidth: number?height: number? - -Input - -Text input field. Use { $bindState } on value for two-way binding. Use checks for validation (e.g. required, email, minLength). - -label: stringname: stringtype: enum?placeholder: string?value: string?checks: array? - -on.submiton.focuson.blur - -LineGraph - -Line chart with points - -title: string?data: array - -Link - -Anchor link. Bind on.press for click handler. - -label: stringhref: string - -on.press - -Pagination - -Page navigation. Use { $bindState } on page for current page number. - -totalPages: numberpage: number? - -on.change - -Popover - -Popover that appears on click of trigger. - -trigger: stringcontent: string - -Progress - -Progress bar (value 0-100) - -value: numbermax: number?label: string? - -Radio - -Radio button group. Use { $bindState } on value for binding. - -label: stringname: stringoptions: arrayvalue: string? - -on.change - -Rating - -Star rating display - -value: numbermax: number?label: string? - -Select - -Dropdown select input. Use { $bindState } on value for binding. Use checks for validation. - -label: stringname: stringoptions: arrayplaceholder: string?value: string?checks: array? - -on.change - -Separator - -Visual separator line - -orientation: enum? - -Skeleton - -Loading placeholder skeleton - -width: string?height: string?rounded: boolean? - -Slider - -Range slider input. Use { $bindState } on value for binding. - -label: string?min: number?max: number?step: number?value: number? - -on.change - -Spinner - -Loading spinner indicator - -size: enum?label: string? - -Stackslots: default - -Flex container for layouts - -direction: enum?gap: enum?align: enum?justify: enum? - -Switch - -Toggle switch. Use { $bindState } on checked for binding. - -label: stringname: stringchecked: boolean? - -on.change - -Table - -Data table. columns: header labels. rows: 2D array of cell strings, e.g. \[\["Alice","admin"\],\["Bob","user"\]\]. - -columns: arrayrows: arraycaption: string? - -Tabs - -Tab navigation. Use { $bindState } on value for active tab binding. - -tabs: arraydefaultValue: string?value: string? - -on.change - -Text - -Paragraph text - -text: stringvariant: enum? - -Textarea - -Multi-line text input. Use { $bindState } on value for binding. Use checks for validation. - -label: stringname: stringplaceholder: string?rows: number?value: string?checks: array? - -Toggle - -Toggle button. Use { $bindState } on pressed for state binding. - -label: stringpressed: boolean?variant: enum? - -on.change - -ToggleGroup - -Group of toggle buttons. Type 'single' (default) or 'multiple'. Use { $bindState } on value. - -items: arraytype: enum?value: string? - -on.change - -Tooltip - -Hover tooltip. Shows content on hover over text. - -content: stringtext: string - -live renderstatic code - -export - -### Contact Us - -Name - -Email - -`npm install @json-render/core @json-render/react` - -[Get Started](https://json-render.dev/docs) [GitHub](https://github.com/vercel-labs/json-render) - -01 - -### Define Your Catalog - -Set the guardrails. Define which components, actions, and data bindings AI can use. - -02 - -### AI Generates - -Describe what you want. AI generates JSON constrained to your catalog. Every interface is unique. - -03 - -### Render Instantly - -Stream the response. Your components render progressively as JSON arrives. - -## Define your catalog - -Components, actions, and validation functions. - -``` -import { defineSchema, defineCatalog } from '@json-render/core'; -import { z } from 'zod'; - -const schema = defineSchema({ /* ... */ }); - -export const catalog = defineCatalog(schema, { - components: { - Card: { - props: z.object({ - title: z.string(), - description: z.string().nullable(), - }), - hasChildren: true, - }, - Metric: { - props: z.object({ - label: z.string(), - statePath: z.string(), - format: z.enum(['currency', 'percent']), - }), - }, - }, - actions: { - export: { params: z.object({ format: z.string() }) }, - }, -}); -``` - -Show all - -## AI generates JSON - -Constrained output that your components render natively. - -``` -{ - "root": "dashboard", - "elements": { - "dashboard": { - "type": "Card", - "props": { - "title": "Revenue Dashboard" - }, - "children": ["revenue"] - }, - "revenue": { - "type": "Metric", - "props": { - "label": "Total Revenue", - "statePath": "/metrics/revenue", - "format": "currency" - } - } - } -} -``` - -## Export as Code - -Export generated UI as standalone React components. No runtime dependencies required. - -### Generated UI Tree - -AI generates a JSON structure from the user's prompt. - -``` -{ - "root": "card", - "elements": { - "card": { - "type": "Card", - "props": { "title": "Revenue" }, - "children": ["metric", "chart"] - }, - "metric": { - "type": "Metric", - "props": { - "label": "Total Revenue", - "statePath": "analytics/revenue", - "format": "currency" - } - }, - "chart": { - "type": "Chart", - "props": { - "statePath": "analytics/salesByRegion" - } - } - } -} -``` - -Show all - -### Exported React Code - -Export as a standalone Next.js project with all components. - -``` -"use client"; - -import { Card, Metric, Chart } from "@/components/ui"; - -const data = { - analytics: { - revenue: 125000, - salesByRegion: [\ - { label: "US", value: 45000 },\ - { label: "EU", value: 35000 },\ - ], - }, -}; - -export default function Page() { - return ( - - - - - ); -} -``` - -Show all - -The export includes`package.json`, component files, styles, and everything needed to run independently. - -## Features - -### Generative UI - -Generate dynamic, personalized interfaces from prompts with AI - -### Guardrails - -AI can only use components you define in the catalog - -### Streaming - -Progressive rendering as JSON streams from the model - -### React & React Native - -Render on web and mobile from the same catalog and spec format - -### Data Binding - -Connect props to state with $state, $item, $index, and two-way binding - -### Code Export - -Export as standalone React code with no runtime dependencies - -## Get started - -`npm install @json-render/core @json-render/react` - -[Documentation](https://json-render.dev/docs) - -Ask AI `⌘I` \ No newline at end of file diff --git a/.firecrawl/kobalte-animation.md b/.firecrawl/kobalte-animation.md new file mode 100644 index 0000000..618d34c --- /dev/null +++ b/.firecrawl/kobalte-animation.md @@ -0,0 +1,73 @@ +# Animation + +Kobalte components can be animated with CSS keyframes or your JavaScript animation library of choice. However, there are some caveats noted here in regard to exiting animations with JavaScript animation libraries. + +## Animating with CSS animation + +The simplest way to animate Kobalte components is with CSS. + +You can use CSS animation to animate both mount and unmount phases of several Kobalte components. The latter is possible because this components will suspend unmount while your animation plays out. + +``` +Copycss +.popover__content { + animation: fadeOut 300ms ease-in forwards; +} + +.popover__content[data-expanded] { + animation: fadeIn 300ms ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} +``` + +``` +Copycss +.popover__content { + animation: fadeOut 300ms ease-in forwards; +} + +.popover__content[data-expanded] { + animation: fadeIn 300ms ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} +``` + +## Delegating unmounting for JavaScript animation + +When many stateful Kobalte components are hidden from view, they are actually removed from the DOM. JavaScript animation libraries need control of the unmounting phase, so we provide the `forceMount` prop on many components to allow consumers to delegate the mounting and unmounting of children based on the animation state determined by those libraries. + +Previous[←Styling](https://kobalte.dev/docs/core/overview/styling)Next[Polymorphism→](https://kobalte.dev/docs/core/overview/polymorphism) \ No newline at end of file diff --git a/.firecrawl/kobalte-changelog.md b/.firecrawl/kobalte-changelog.md new file mode 100644 index 0000000..060d1e2 --- /dev/null +++ b/.firecrawl/kobalte-changelog.md @@ -0,0 +1,129 @@ +# v0.13.x + +## v0.13.11 (July 27, 2025) + +**Bug fixes** + +- Update createInteractOutside to work with other Element types ( [#612](https://github.com/kobaltedev/kobalte/pull/612)) +- Meter, Progress: remove rounding from fill width ( [#602](https://github.com/kobaltedev/kobalte/pull/602)) +- Image: handle crossOrigin and referrerPolicy ( [#598](https://github.com/kobaltedev/kobalte/pull/598)) +- ToggleGroup: reactive disabled state ( [#595](https://github.com/kobaltedev/kobalte/pull/595)) +- ColorArea: double onChange trigger ( [#593](https://github.com/kobaltedev/kobalte/pull/593)) +- ColorChannelField: fix handling of alpha values ( [#590](https://github.com/kobaltedev/kobalte/pull/590)) +- Colors: color parsing and rgb(a)/hsl(a) format ( [#587](https://github.com/kobaltedev/kobalte/pull/587)) + +## v0.13.10 (May 30, 2025) + +**New features** + +- [New `SegmentedControl` component](https://kobalte.dev/docs/core/components/segmented-control) ( [#531](https://github.com/kobaltedev/kobalte/pull/531)) + +## v0.13.9 (February 21, 2025) + +**New features** + +- [New `ColorWheel` component](https://kobalte.dev/docs/core/components/color-wheel) ( [#510](https://github.com/kobaltedev/kobalte/pull/510)) +- [New `ColorField` component](https://kobalte.dev/docs/core/components/color-field) ( [#510](https://github.com/kobaltedev/kobalte/pull/510)) +- [New `ColorChannelField` component](https://kobalte.dev/docs/core/components/color-channel-field) ( [#508](https://github.com/kobaltedev/kobalte/pull/508)) +- [New `ColorArea` component](https://kobalte.dev/docs/core/components/color-area) ( [#508](https://github.com/kobaltedev/kobalte/pull/508)) +- [New `ColorSlider` component](https://kobalte.dev/docs/core/components/color-slider) ( [#508](https://github.com/kobaltedev/kobalte/pull/508)) +- [New `ColorSwatch` component](https://kobalte.dev/docs/core/components/color-swatch) ( [#508](https://github.com/kobaltedev/kobalte/pull/508)) +- [New `Search` component](https://kobalte.dev/docs/core/components/search) ( [#506](https://github.com/kobaltedev/kobalte/pull/506)) + +## v0.13.8 (February 7, 2025) + +**New features** + +- [New `FileField` component](https://kobalte.dev/docs/core/components/file-field) ( [#512](https://github.com/kobaltedev/kobalte/pull/512)) +- [New `Badge` component](https://kobalte.dev/docs/core/components/badge) ( [#503](https://github.com/kobaltedev/kobalte/pull/503)) +- [New `Meter` component](https://kobalte.dev/docs/core/components/meter) ( [#500](https://github.com/kobaltedev/kobalte/pull/500)) + +## v0.13.7 (October 7, 2024) + +**Bug fixes** + +- ToggleGroup: root value type definition ( [#479](https://github.com/kobaltedev/kobalte/pull/479)) +- Collapsible: close animation on default open ( [#483](https://github.com/kobaltedev/kobalte/pull/483)) +- Toast: filter dismissed toasts in region ( [#489](https://github.com/kobaltedev/kobalte/pull/489)) + +## v0.13.6 (August 27, 2024) + +**Bug fixes** + +- Update missing export from `@kobalte/utils` ( [#477](https://github.com/kobaltedev/kobalte/pull/477)) + +## v0.13.5 (August 27, 2024) + +**New features** + +- Tooltip: add skipDelayDuration prop ( [#467](https://github.com/kobaltedev/kobalte/pull/467)) + +**Bug fixes** + +- NumberField: only format when enabled ( [#456](https://github.com/kobaltedev/kobalte/pull/456)) +- NumberField: don't trigger `onRawValueChange` on mount when NaN ( [#456](https://github.com/kobaltedev/kobalte/pull/456)) +- Select: correct type definition & empty value for multiselect ( [#456](https://github.com/kobaltedev/kobalte/pull/456)) +- TextField: clear input when controlled value set to undefined ( [#456](https://github.com/kobaltedev/kobalte/pull/456)) +- Combobox: correct type definition & empty value for multiselect ( [#456](https://github.com/kobaltedev/kobalte/pull/456)) +- Skeleton: correct data-animate & data-visible attribute value ( [#456](https://github.com/kobaltedev/kobalte/pull/456)) +- Combobox: close list on outside click ( [#456](https://github.com/kobaltedev/kobalte/pull/456)) +- NavigationMenu: incorrect animation after closed ( [#456](https://github.com/kobaltedev/kobalte/pull/456)) +- Tabs: recalculate indicator styles on resize ( [#458](https://github.com/kobaltedev/kobalte/pull/458)) +- Pagination: correctly render fixedItems with low page count ( [#464](https://github.com/kobaltedev/kobalte/pull/464)) +- Combobox: prevent opening on input with triggerMode="manual" ( [#465](https://github.com/kobaltedev/kobalte/pull/465)) +- NumberField: precision handling with floating point offsets and value snapping ( [#468](https://github.com/kobaltedev/kobalte/pull/468)) + +## v0.13.4 (June 22, 2024) + +**New features** + +- Add source exports ( [#408](https://github.com/kobaltedev/kobalte/pull/408)) +- Support string style prop ( [#432](https://github.com/kobaltedev/kobalte/pull/432)) + +**Bug fixes** + +- Combobox: convert textValue with optionTextValue ( [#436](https://github.com/kobaltedev/kobalte/pull/436)) +- Polymorphic: override the `component` prop of `` ( [#437](https://github.com/kobaltedev/kobalte/pull/437)) +- Slider: inverted slider thumb in the wrong position ( [#441](https://github.com/kobaltedev/kobalte/pull/441)) +- Wait for presence to finish before enabling scroll ( [#447](https://github.com/kobaltedev/kobalte/pull/447)) + +## v0.13.3 (June 3, 2024) + +**New features** + +- [New `NavigationMenu` component](https://kobalte.dev/docs/core/components/navigation-menu) ( [#409](https://github.com/kobaltedev/kobalte/pull/409)) + +## v0.13.2 (May 29, 2024) + +**Bug fixes** + +- Refactored polymorphic element type in CommonProps ( [#420](https://github.com/kobaltedev/kobalte/pull/420)) + +## v0.13.1 (May 3, 2024) + +**New features** + +- NumberField: improve input handling ( [#379](https://github.com/kobaltedev/kobalte/pull/379)) ( [#395](https://github.com/kobaltedev/kobalte/pull/395)) + +**Bug fixes** + +- Slider: call `onChangeEnd` on blur after changing value ( [#402](https://github.com/kobaltedev/kobalte/pull/402)) +- Select: `options` non reactive inside suspense ( [#401](https://github.com/kobaltedev/kobalte/pull/401)) +- Combobox: close on select with `focus` trigger mode ( [#400](https://github.com/kobaltedev/kobalte/pull/400)) +- Menu: open link menu items ( [#397](https://github.com/kobaltedev/kobalte/pull/397)) + +## v0.13.0 (May 1, 2024) + +**Breaking changes** + +- [#381](https://github.com/kobaltedev/kobalte/pull/381) +- Removed `asChild` and ``: [Polymorphism documentation](https://kobalte.dev/docs/core/overview/polymorphism) +- Refactored `as` prop: [Polymorphism documentation](https://kobalte.dev/docs/core/overview/polymorphism) +- [New component types](https://kobalte.dev/docs/core/overview/polymorphism#types) + +**New features** + +- Allow importing individual components ( [#391](https://github.com/kobaltedev/kobalte/pull/391)) +- [New `ToggleGroup` component](https://kobalte.dev/docs/core/components/toggle-group) ( [#378](https://github.com/kobaltedev/kobalte/pull/378)) + +Next[v0.12.x→](https://kobalte.dev/docs/changelog/0-12-x) \ No newline at end of file diff --git a/.firecrawl/kobalte-color-area.md b/.firecrawl/kobalte-color-area.md new file mode 100644 index 0000000..ad077da --- /dev/null +++ b/.firecrawl/kobalte-color-area.md @@ -0,0 +1,349 @@ +# Color Area + +Allows users to adjust two channels of an RGB, HSL, or HSB color value against a two-dimensional gradient background. + +## Import + +``` +Copyts +import { ColorArea } from "@kobalte/core/color-area"; +// or +import { Root, Background, ... } from "@kobalte/core/color-area"; +``` + +``` +Copyts +import { ColorArea } from "@kobalte/core/color-area"; +// or +import { Root, Background, ... } from "@kobalte/core/color-area"; +``` + +## Features + +- Can be controlled or uncontrolled. +- Support for adjusting two-channel values of an RGB, HSL or HSB color value. +- Pressing on the color area background moves the thumb to that position. +- Supports using the arrow keys, for changing value by step, as well as shift + arrow key, page up/down, home, and end keys, for changing the value by page step. +- Support for disabling the color area. +- Prevents text selection while dragging. +- Exposed to assistive technology as a 2D slider element via ARIA. +- Uses two hidden native input elements within a group to support touch screen readers. +- Automatic ARIA labeling using the localized channel names by default. +- Support for mirroring in RTL locales. + +## Anatomy + +The color area consists of: + +- **ColorArea:** The root container for the color area. +- **ColorArea.Background:** The component that visually represents the range of colors from which a user can select. +- **ColorArea.Thumb:** The thumb that is used to visually indicate a value in the color area background. +- **ColorArea.HiddenInputX:** The horizontal native html input that is visually hidden in the color area thumb. +- **ColorArea.HiddenInputY:** The vertical native html input that is visually hidden in the color area thumb. +- **ColorArea.Label:** The label that gives the user information on the color area. + +``` +Copytsx + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + +``` + +## Example + +Label + +index.tsxstyle.css + +``` +Copytsx +import { ColorArea } from "@kobalte/core/color-area"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + Label + + + + + + + + ); +} +``` + +``` +Copytsx +import { ColorArea } from "@kobalte/core/color-area"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + Label + + + + + + + + ); +} +``` + +## Usage + +The value provided to `defaultValue` or `value` should be `Color` object. You can obtain a Color object by using the `parseColor` function to parse a color from a string. +The `xChannel` and `yChannel` must be one of the channels included in the color value, for example, for RGB colors, the "red", "green", and "blue" channels are available. +If no `xChannel` or `yChannel` is provided, for the RGB color space, the red color channel maps to the horizontal axis or xChannel, and the green color channel maps to the vertical axis or yChannel. Similarly, for the HSL and HSB color spaces, the hue color channel maps to the horizontal axis or xChannel, and the saturation color channel maps to the vertical axis or yChannel. + +### Default value + +Label + +``` +Copytsx + + Label + + + + + + + +``` + +``` +Copytsx + + Label + + + + + + + +``` + +### Controlled value + +Label + +Current color value: hsl(0 100% 50%) + +``` +Copytsx +import { createSignal } from "solid-js"; + +const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)")); +<> + + Label + + + + + + + +

Current color value: {value().toString("hsl")}

+; +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)")); +<> + + Label + + + + + + + +

Current color value: {value().toString("hsl")}

+; +``` + +### xChannel and yChannel + +The color channel for each axis of a color area can be specified using the `xChannel` and `yChannel` props. An array of channel names for a color can be returned using the color.getColorChannels method. + +Label + +``` +Copytsx +const [value, setValue] = createSignal(parseColor("rgb(100, 149, 237)")); +const [rChannel, gChannel, bChannel] = value().getColorChannels(); + + + Label + + + + + + +; +``` + +``` +Copytsx +const [value, setValue] = createSignal(parseColor("rgb(100, 149, 237)")); +const [rChannel, gChannel, bChannel] = value().getColorChannels(); + + + Label + + + + + + +; +``` + +### HTML forms + +ColorArea supports the `xName` and `yName` props for integration with HTML forms. + +Label + +ResetSubmit + +``` +Copytsx + + Label + + + + + + + +``` + +``` +Copytsx + + Label + + + + + + + +``` + +## API Reference + +### ColorArea + +`ColorArea` is equivalent to the `Root` import from `@kobalte/core/color-area`. + +| Prop | Description | +| --- | --- | +| value | `Color`
The controlled value of the color area.. | +| defaultValue | `Color`
The value of the color area when initially rendered. | +| colorSpace | `ColorSpace`
The color space that the color area operates in. The `xChannel` and `yChannel` must be in this color space. | +| onChange | `(value: Color) => void`
Event handler called when the value changes. | +| onChangeEnd | `(value: Color) => void`
Event handler called when the value changes at the end of an interaction. | +| xChannel | `ColorChannel`
Color channel for the horizontal axis. | +| yChannel | `ColorChannel`
Color channel for the vertical axis. | +| xName | `string`
The name of the x channel input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). | +| yName | `string`
The name of the y channel input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). | +| name | `string`
The name of the color area, used when submitting an HTML form. | +| validationState | `'valid' | 'invalid'`
Whether the color area should display its "valid" or "invalid" visual styling. | +| required | `boolean`
Whether the user must check a radio group item before the owning form can be submitted. | +| disabled | `boolean`
Whether the radio group is disabled. | +| readOnly | `boolean`
Whether the radio group items can be selected but not changed by the user. | +| translations | `ColorAreaIntlTranslations`
Localization strings. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the slider is valid according to the validation rules. | +| data-invalid | Present when the slider is invalid according to the validation rules. | +| data-required | Present when the user must slider an item before the owning form can be submitted. | +| data-disabled | Present when the slider is disabled. | +| data-readonly | Present when the slider is read only. | + +`ColorArea.Background`, `ColorArea.Thumb`, `ColorArea.HiddenInputX`, `ColorArea.HiddenInputY` and `ColorArea.Label` share the same data-attributes. + +### ColorArea.Thumb + +The current color is available on the thumb using the custom css property `--kb-color-current`. + +### ColorArea.HiddenInputX + +| Data attribute | Description | +| --- | --- | +| data-orientation='horizontal' | Always presesnt | + +### ColorArea.HiddenInputY + +| Data attribute | Description | +| --- | --- | +| data-orientation='vertical' | Always presesnt | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `ColorArea` | `div` | +| `ColorArea.Background` | `div` | +| `ColorArea.Thumb` | `span` | +| `ColorArea.HiddenInputX` | `input` | +| `ColorArea.HiddenInputY` | `input` | +| `ColorArea.Label` | `label` | +| `ColorArea.Description` | `div` | +| `ColorArea.ErrorMessage` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `PageUp` | Increments the value of the thumb in the vertical axis by a larger step. | +| `PageDown` | Decrements the value of the thumb in the vertical axis by a larger step. | +| `ArrowDown` | Decrements the value of the thumb in the vertical axis by the step amount. | +| `ArrowUp` | Increments the value of the thumb in the vertical axis by the step amount. | +| `ArrowRight` | Increments the value of the thumb in the horizontal axis by the step amount. | +| `ArrowLeft` | Decrements the value of the thumb in the vertical axis by the step amount. | +| `Home` | Decrements the value of the thumb in the horizontal axis by a larger step. | +| `End` | Increments the value of the thumb in the horizontal axis by a larger step. | + +Previous[←Collapsible](https://kobalte.dev/docs/core/components/collapsible)Next[Color Channel Field→](https://kobalte.dev/docs/core/components/color-channel-field) \ No newline at end of file diff --git a/.firecrawl/kobalte-combobox.md b/.firecrawl/kobalte-combobox.md new file mode 100644 index 0000000..0cc2dd4 --- /dev/null +++ b/.firecrawl/kobalte-combobox.md @@ -0,0 +1,1451 @@ +# Combobox + +Combines a text input with a listbox, allowing users to filter a list of options to items matching a query. + +## Import + +``` +Copyts +import { Combobox } from "@kobalte/core/combobox"; +// or +import { Root, Label, ... } from "@kobalte/core/combobox"; +// or (deprecated) +import { Combobox } from "@kobalte/core"; +``` + +``` +Copyts +import { Combobox } from "@kobalte/core/combobox"; +// or +import { Root, Label, ... } from "@kobalte/core/combobox"; +// or (deprecated) +import { Combobox } from "@kobalte/core"; +``` + +## Features + +- Exposed to assistive technology as a combobox using the [WAI ARIA Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) design pattern. +- Support for single and multiple selection. +- Support for disabled options. +- Labeling support for accessibility. +- Support for description and error message help text linked to the button via ARIA. +- Tab stop focus management. +- Keyboard support for opening the listbox using the arrow keys, including automatically focusing the first or last item accordingly. +- Support for opening the list box when typing, on focus, or manually. +- Browser autofill integration via a hidden native `` element, which is visually hidden to allow custom styling. +- Syncs with form reset events. +- Group and segment labeling support for assistive technology. +- Can be controlled or uncontrolled. +- Supports animatable indicator. + +## Anatomy + +The segmented control consists of: + +- **SegmentedControl**: The root container for the segmented control. +- **SegmentedControl.Label**: The label that gives the user information on the segmented control. +- **SegmentedControl.Description**: The description that gives the user more information on the segmented control. +- **SegmentedControl.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the segmented control. +- **SegmentedControl.Indicator:** The visual indicator displayed below the items to indicate the selected item. + +The segmented control item consists of: + +- **SegmentedControl.Item**: The root container for an item's radio button. +- **SegmentedControl.ItemInput**: The native html input that is visually hidden in the item's radio button. +- **SegmentedControl.ItemControl**: The element that visually represents an item's radio button. +- **SegmentedControl.ItemIndicator**: The visual indicator rendered when the item's radio button is in a checked state. +- **SegmentedControl.ItemLabel**: The label that gives the user information on the item's radio button. +- **SegmentedControl.ItemDescription**: The description that gives the user more information on the item's radio button. + +``` +Copytsx + + + + + + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + + + + + + +``` + +## Example + +Favorite fruit + +Apple + +Orange + +Watermelon + +index.tsxstyle.css + +``` +Copytsx +import { SegmentedControl } from "@kobalte/core/segmented-control"; + +import "./style.css"; + +function App() { + return ( + + + Favorite fruit + + + + ); +} +``` + +``` +Copytsx +import { SegmentedControl } from "@kobalte/core/segmented-control"; + +import "./style.css"; + +function App() { + return ( + + + Favorite fruit + + + + ); +} +``` + +## Usage + +The `role="presentation"` is required for all non content elements between the `SegmentedControl` and `SegmentedControl.Item` due to a bug in Chromium based browsers that incorrectly parse semantics and break screen readers. + +### Controlled value + +The `value` prop, which accepts a value corresponding with the `value` prop of each radio, can be used to make the value controlled. The `onChange` event is fired when the user selects a radio, and receives the new value. + +Favorite fruit + +Apple + +Orange + +Watermelon + +Your favorite fruit is: Orange. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal("Orange"); + + return ( + <> + + Favorite fruit +
+ +
+ + {fruit => ( + + + {fruit} + + )} + +
+
+
+

Your favorite fruit is: {value()}.

+ + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal("Orange"); + + return ( + <> + + Favorite fruit +
+ +
+ + {fruit => ( + + + {fruit} + + )} + +
+
+
+

Your favorite fruit is: {value()}.

+ + ); +} +``` + +### Description + +The `SegmentedControl.Description` component can be used to associate additional help text with a segmented control. + +Favorite fruit + +Apple + +Orange + +Watermelon + +Choose the fruit you like the most. + +``` +Copytsx + + Favorite fruit +
+ +
+ + {fruit => ...} + +
+
+ Choose the fruit you like the most. +
+``` + +``` +Copytsx + + Favorite fruit +
+ +
+ + {fruit => ...} + +
+
+ Choose the fruit you like the most. +
+``` + +### Error message + +The `SegmentedControl.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the segmented control as invalid for assistive technologies. + +By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries). + +Favorite fruit + +Apple + +Orange + +Watermelon + +Hmm, I prefer apples. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal("Orange"); + + return ( + + Favorite fruit +
+ +
+ + {fruit => ...} + +
+
+ Hmm, I prefer apples. +
+ ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal("Orange"); + + return ( + + Favorite fruit +
+ +
+ + {fruit => ...} + +
+
+ Hmm, I prefer apples. +
+ ); +} +``` + +### HTML forms + +The segmented control `name` prop, paired with the item's radio `value` prop, can be used for integration with HTML forms. + +Favorite fruit + +Apple + +Orange + +Watermelon + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
+ + Favorite fruit +
+ +
+ + {fruit => ...} + +
+
+
+
+ + +
+
+ ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
+ + Favorite fruit +
+ +
+ + {fruit => ...} + +
+
+
+
+ + +
+
+ ); +} +``` + +### Orientation + +The segmented control `orientation` prop can be used to change the segmented control's orientation. + +Favorite fruit + +Apple + +Orange + +Watermelon + +``` +Copytsx + + Favorite fruit +
+ +
+ + {fruit => ...} + +
+
+ Choose the fruit you like the most. +
+``` + +``` +Copytsx + + Favorite fruit +
+ +
+ + {fruit => ...} + +
+
+ Choose the fruit you like the most. +
+``` + +## API Reference + +### SegmentedControl + +`SegmentedControl` is equivalent to the `Root` import from `@kobalte/core/segmented-control`. + +| Prop | Description | +| --- | --- | +| value | `string`
The controlled value of the item's radio button to check. | +| defaultValue | `string`
The value of the item's radio button that should be checked when initially rendered. Useful when you do not need to control the state of the radio buttons. | +| onChange | `(value: string) => void`
Event handler called when the value changes. | +| orientation | `'horizontal' | 'vertical'`
The axis the segmented control items should align with. | +| name | `string`
The name of the segmented control. Submitted with its owning form as part of a name/value pair. | +| validationState | `'valid' | 'invalid'`
Whether the segmented control should display its "valid" or "invalid" visual styling. | +| required | `boolean`
Whether the user must check a segmented control item before the owning form can be submitted. | +| disabled | `boolean`
Whether the segmented control is disabled. | +| readOnly | `boolean`
Whether the segmented control items can be selected but not changed by the user. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the segmented control is valid according to the validation rules. | +| data-invalid | Present when the segmented control is invalid according to the validation rules. | +| data-required | Present when the user must check a segmented control item before the owning form can be submitted. | +| data-disabled | Present when the segmented control is disabled. | +| data-readonly | Present when the segmented control is read only. | + +`SegmentedControl.Label`, `SegmentedControl.Description` and `SegmentedControl.ErrorMesssage` shares the same data-attributes. + +### SegmentedControl.ErrorMessage + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +### SegmentedControl.Item + +| Prop | Description | +| --- | --- | +| value | `string`
The value of the item's radio button, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio#Value). | +| disabled | `boolean`
Whether the item's radio button is disabled or not. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the parent segmented control is valid according to the validation rules. | +| data-invalid | Present when the parent segmented control is invalid according to the validation rules. | +| data-checked | Present when the segmented control checked. | +| data-disabled | Present when the segmented control disabled. | + +`SegmentedControl.ItemInput`, `SegmentedControl.ItemControl`, `SegmentedControl.ItemIndicator` and `SegmentedControl.ItemLabel` shares the same data-attributes. + +### SegmentedControl.ItemIndicator + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `SegmentedControl` | `div` | +| `SegmentedControl.Label` | `span` | +| `SegmentedControl.Description` | `div` | +| `SegmentedControl.ErrorMessage` | `div` | +| `SegmentedControl.Indicator` | `div` | +| `SegmentedControl.Item` | `div` | +| `SegmentedControl.ItemInput` | `input` | +| `SegmentedControl.ItemControl` | `div` | +| `SegmentedControl.ItemIndicator` | `div` | +| `SegmentedControl.ItemLabel` | `label` | +| `SegmentedControl.ItemDescription` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Tab` | Moves focus to either the checked item's radio button or the first item's radio button in the group. | +| `Space` | When focus is on an unchecked item's radio button, checks it. | +| `ArrowDown` | Moves focus and checks the next item's radio button in the group. | +| `ArrowRight` | Moves focus and checks the next item's radio button in the group. | +| `ArrowUp` | Moves focus and checks the previous item's radio button in the group. | +| `ArrowLeft` | Moves focus and checks the previous item's radio button in the group. | + +Previous[←Search](https://kobalte.dev/docs/core/components/search)Next[Select→](https://kobalte.dev/docs/core/components/select) \ No newline at end of file diff --git a/.firecrawl/kobalte-select.md b/.firecrawl/kobalte-select2.md similarity index 100% rename from .firecrawl/kobalte-select.md rename to .firecrawl/kobalte-select2.md diff --git a/.firecrawl/kobalte-ssr.md b/.firecrawl/kobalte-ssr.md deleted file mode 100644 index 96b4638..0000000 --- a/.firecrawl/kobalte-ssr.md +++ /dev/null @@ -1,10 +0,0 @@ -# Server side rendering - -## Usage with SolidStart - -Kobalte works out of the box with [SolidStart](https://start.solidjs.com/). - -Kobalte has been tested with `solid-js@1.8.15` and `@solidjs/start@0.6.1`, compatibility with -other versions is not guaranteed. - -Previous[←Polymorphism](https://kobalte.dev/docs/core/overview/polymorphism)Next[Accordion→](https://kobalte.dev/docs/core/components/accordion) \ No newline at end of file diff --git a/.firecrawl/kobalte-styling.md b/.firecrawl/kobalte-styling-full.md similarity index 100% rename from .firecrawl/kobalte-styling.md rename to .firecrawl/kobalte-styling-full.md diff --git a/.firecrawl/kobalte-time-field.md b/.firecrawl/kobalte-time-field.md new file mode 100644 index 0000000..5ae64c1 --- /dev/null +++ b/.firecrawl/kobalte-time-field.md @@ -0,0 +1,648 @@ +# Time Field + +A time field allows users to enter and edit time values using a keyboard. Each part of a time value is displayed in an individually editable segment. + +## Import + +``` +Copyts +import { TimeField } from "@kobalte/core/time-field"; +// or +import { Root, Label, ... } from "@kobalte/core/time-field"; +``` + +``` +Copyts +import { TimeField } from "@kobalte/core/time-field"; +// or +import { Root, Label, ... } from "@kobalte/core/time-field"; +``` + +## Features + +- Times can optionally include a time zone. All modifications follow time zone rules such as daylight saving time. +- Support for locale-specific formatting, number systems, hour cycles, and right-to-left layout. +- Each time unit is displayed as an individually focusable and editable segment, which allows users an easy way to edit times using the keyboard, in any format and locale. +- Time segments are editable using an easy to use numeric keypad, and all interactions are accessible using touch-based screen readers. +- Can be controlled or uncontrolled. +- Integrates with HTML forms. + +## Anatomy + +The time field consists of: + +- **TimeField**: The root container for the time field. +- **TimeField.Label**: The label that gives the user information on the time field. +- **TimeField.Field**: The container for the segments. +- **TimeField.Segment**: The component that represents a unit of a time. +- **TimeField.Description**: The description that gives the user more information on the time field. +- **TimeField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the time field. +- **TimeField.HiddenInput**: The native html input that is visually hidden in the time field. + +``` +Copytsx + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + +``` + +## Example + +Event time + +–– + +: + +–– + +AM + +index.tsxstyle.css + +``` +Copytsx +import { TimeField } from "@kobalte/core/time-field"; +import "./style.css"; + +function App() { + return ( + + Event time + + {segment => } + + + ); +} +``` + +``` +Copytsx +import { TimeField } from "@kobalte/core/time-field"; +import "./style.css"; + +function App() { + return ( + + Event time + + {segment => } + + + ); +} +``` + +## Usage + +### Default Value + +A TimeField displays a placeholder by default. An initial, uncontrolled value can be provided to the TimeField using the `defaultValue` prop. + +Time values are provided using objects in the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/) package. This library handles correct international date and time manipulation across calendars, time zones, and other localization concerns. + +11 + +: + +45 + +AM + +Selected Time: 11:45 AM + +``` +Copytsx +import { Time } from "@internationalized/date"; + + + + {(segment) => ( + + )} + + +``` + +``` +Copytsx +import { Time } from "@internationalized/date"; + + + + {(segment) => ( + + )} + + +``` + +### Controlled Value + +The `value` prop can be used to make the value controlled. The `onChange` event is fired when the time value changes. + +9 + +: + +45 + +AM + +Selected Time: 9:45 AM + +Selected time: 9:45 AM + +``` +Copytsx +import { createSignal } from "solid-js"; +import { createDateFormatter } from "@kobalte/core/i18n"; +import { getLocalTimeZone, Time, toCalendarDateTime, today } from "@internationalized/date"; + +function ControlledValueExample() { + const [value, setValue] = createSignal(new Time(9, 45)); + + const dateFormatter = createDateFormatter({ + hour12: true, + timeStyle: "short", + }); + + return ( + <> + + {segment => } + +

+ Selected time:{" "} + {value() + ? dateFormatter().format( + toCalendarDateTime(today(getLocalTimeZone()), value()).toDate(getLocalTimeZone()), + ) + : "––"} +

+ + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; +import { createDateFormatter } from "@kobalte/core/i18n"; +import { getLocalTimeZone, Time, toCalendarDateTime, today } from "@internationalized/date"; + +function ControlledValueExample() { + const [value, setValue] = createSignal(new Time(9, 45)); + + const dateFormatter = createDateFormatter({ + hour12: true, + timeStyle: "short", + }); + + return ( + <> + + {segment => } + +

+ Selected time:{" "} + {value() + ? dateFormatter().format( + toCalendarDateTime(today(getLocalTimeZone()), value()).toDate(getLocalTimeZone()), + ) + : "––"} +

+ + ); +} +``` + +### Time Zones + +TimeField is time zone aware when a `ZonedDateTime` object is provided as the value. In this case, the time zone abbreviation is displayed, and time zone concerns such as daylight saving time are taken into account when the value is manipulated. + +[@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/) includes functions for parsing strings in multiple formats into `ZonedDateTime` objects. + +12 + +: + +45 + +AM + +PST + +Selected Time: 12:45 AM PST + +``` +Copytsx +import { parseZonedDateTime } from "@internationalized/date"; + + + {segment => } +; +``` + +``` +Copytsx +import { parseZonedDateTime } from "@internationalized/date"; + + + {segment => } +; +``` + +### Granularity + +The `granularity` prop allows you to control the smallest unit that is displayed by a TimeField. By default, times are displayed with "minute" granularity. More granular time values can be displayed by setting the `granularity` prop to "second". + +–– + +: + +–– + +: + +–– + +AM + +``` +Copytsx + + {segment => } + +``` + +``` +Copytsx + + {segment => } + +``` + +### Minimum and Maximum Values + +The `minValue` and `maxValue` props can be used to perform builtin validation. This marks the time field as invalid using ARIA if the user enters an invalid time. + +9 + +: + +45 + +AM + +Selected Time: 9:45 AM + +``` +Copytsx + + {segment => } + Select time between 9 AM and 5 PM. + +``` + +``` +Copytsx + + {segment => } + Select time between 9 AM and 5 PM. + +``` + +### Placeholder Value + +When no value is set, a placeholder is shown. The format of the placeholder is influenced by the `granularity` and `placeholderValue` props. `placeholderValue` also controls the default values of each segment when the user first interacts with them, e.g. using the up and down arrow keys. By default, the `placeholderValue` is midnight. + +9 + +: + +–– + +AM + +``` +Copytsx + + {segment => } + +``` + +``` +Copytsx + + {segment => } + +``` + +### Hide Time Zone + +When a `ZonedDateTime` object is provided as the value of a TimeField, the time zone abbreviation is displayed by default. It can be hidden using the `hideTimeZone` prop. + +12 + +: + +45 + +AM + +Selected Time: 12:45 AM + +``` +Copytsx + + {segment => } + +``` + +``` +Copytsx + + {segment => } + +``` + +### Hour Cycle + +By default, TimeField displays times in either 12 or 24 hour format depending on the user's locale. This can be overridden using the `hourCycle` prop. + +–– + +: + +–– + +``` +Copytsx + + {segment => } + +``` + +``` +Copytsx + + {segment => } + +``` + +### Description + +The `TimeField.Description` component can be used to associate additional help text with a time field. + +Time + +–– + +: + +–– + +AM + +Select a meeting time. + +``` +Copytsx + + Time + {segment => } + Select a meeting time. + +``` + +``` +Copytsx + + Time + {segment => } + Select a meeting time. + +``` + +### Error message + +The `TimeField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the time field as invalid for assistive technologies. + +By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries). + +Time + +–– + +: + +–– + +AM + +Please select a time. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal(undefined); + + return ( + + Time + {segment => } + Please select a time. + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal(undefined); + + return ( + + Time + {segment => } + Please select a time. + + ); +} +``` + +### HTML forms + +The `name` prop can be used for integration with HTML forms. + +–– + +: + +–– + +AM + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
+ + {segment => } + + +
+ + +
+
+ ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
+ + {segment => } + + +
+ + +
+
+ ); +} +``` + +## API Reference + +### TimeField + +`TimeField` is equivalent to the `Root` import from `@kobalte/core/time-field`. + +| Prop | Description | +| --- | --- | +| value | `TimeValue`
The current value (controlled). | +| defaultValue | `TimeValue`
The default value (uncontrolled). | +| onChange | `(value: MappedTimeValue) => void`
Handler that is called when the value changes. | +| hourCycle | `12 | 24`
Whether to display the time in 12 or 24-hour format. By default, this is determined by the user's locale. | +| granularity | `'hour' | 'minute' | 'second'`
Determines the smallest unit that is displayed in the time field. Defaults to `"minute"`. | +| hideTimeZone | `boolean`
Whether to hide the time zone abbreviation. | +| shouldForceLeadingZeros | `boolean`
Whether to always show leading zeros in the hour field. By default, this is determined by the user's locale. | +| placeholderValue | `TimeValue`
A placeholder time that influences the format of the placeholder shown when no value is selected. Defaults to 12:00 AM or 00:00 depending on the hour cycle. | +| minValue | `TimeValue`
The minimum allowed time that a user may select. | +| maxValue | `TimeValue`
The maximum allowed time that a user may select. | +| name | `string`
The name of the time field. Submitted with its owning form as part of a name/value pair. | +| validationState | `'valid' | 'invalid'`
Whether the time field should display its "valid" or "invalid" visual styling. | +| required | `boolean`
Whether the time field is required. | +| disabled | `boolean`
Whether the time field is disabled. | +| readOnly | `boolean`
Whether the time field is read only. | +| translations | `TimeFieldIntlTranslations`
The localized strings of the component. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the time field is valid according to the validation rules. | +| data-invalid | Present when the time field is invalid according to the validation rules. | +| data-required | Present when the time field is required. | +| data-disabled | Present when the time field is disabled. | +| data-readonly | Present when the time field is read only. | + +`TimeField.Label`, `TimeField.Field`, `TimeField.Segment`, `TimeField.Description` and `TimeField.ErrorMesssage` share the same data-attributes. + +### TimeField.Segment + +| Prop | Description | +| --- | --- | +| segment | `TimeSegment`
A segment of the time field. | + +| Data attribute | Description | +| --- | --- | +| data-separator | Present when the segment is a separator. | +| data-type | Always present. | +| data-placeholder | Present when the segment's value is a placeholder. | + +### TimeField.ErrorMessage + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `TimeField` | `div` | +| `TimeField.Label` | `span` | +| `TimeField.Field` | `div` | +| `TimeField.Segment` | `div` | +| `TimeField.Description` | `div` | +| `TimeField.ErrorMessage` | `div` | +| `TimeField.HiddenInput` | `input` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Backspace` | Deletes the value in the current segment and moves focus to the previous segment when empty. | +| `Delete` | Deletes the value in the current segment and moves focus to the previous segment when empty. | +| `ArrowRight` | Moves focus to the next segment. | +| `ArrowLeft` | Moves focus to the previous segment. | +| `ArrowUp` | Increments the given segment. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. | +| `ArrowDown` | Decrements the given segment. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. | +| `PageUp` | Increments the given segment by a larger amount, rounding it to the nearest increment. The amount to increment by depends on the segment, for example 2 hours, 15 minutes, and 15 seconds. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. | +| `PageDown` | Decrements the given segment by a larger amount, rounding it to the nearest decrement. The amount to decrement by depends on the segment, for example 2 hours, 15 minutes, and 15 seconds. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. | +| `Home` | Decrements the given segment by the segment's minimum value. | +| `End` | Increments the given segment by the segment's maximum value. | + +Previous[←Text Field](https://kobalte.dev/docs/core/components/text-field)Next[Toast→](https://kobalte.dev/docs/core/components/toast) \ No newline at end of file diff --git a/.firecrawl/kobalte-toast.md b/.firecrawl/kobalte-toast.md new file mode 100644 index 0000000..afa33b0 --- /dev/null +++ b/.firecrawl/kobalte-toast.md @@ -0,0 +1,860 @@ +# Toast + +A succinct message that is displayed temporarily. + +## Import + +``` +Copyts +import { Toast, toaster } from "@kobalte/core/toast"; +// or +import { Root, toaster, ... } from "@kobalte/core/toast"; +// or (deprecated) +import { Toast, toaster } from "@kobalte/core"; +``` + +``` +Copyts +import { Toast, toaster } from "@kobalte/core/toast"; +// or +import { Root, toaster, ... } from "@kobalte/core/toast"; +// or (deprecated) +import { Toast, toaster } from "@kobalte/core"; +``` + +## Features + +- Automatically closes. +- Pauses closing on hover, focus and window blur. +- Supports hotkey to jump to toast region. +- Supports closing via swipe gesture. +- Exposes CSS variables for swipe gesture animations. +- Limit the number of visible toasts. +- Manage promises within toast. +- Can remove or update toast programmatically. +- Multiple toast regions. + +## Anatomy + +The toast region consists of: + +- **Toast.Region:** The fixed area where toasts appear. Users can jump to the viewport by pressing a hotkey. +- **Toast.List:** The list containing all rendered toasts. + +``` +Copytsx + + + +``` + +``` +Copytsx + + + +``` + +The toast consists of: + +- **Toast:** The root container for a toast. +- **Toast.CloseButton:** The button that closes the toast. +- **Toast.Title:** An accessible title to be announced when the toast is opened. +- **Toast.Description:** An optional accessible description to be announced when the toast is opened. +- **Toast.ProgressTrack:** The component that visually represents the lifetime of the toast. +- **Toast.ProgressFill:** The component that visually represents the remaining lifetime of the toast. + +``` +Copytsx + + + + + + + + +``` + +``` +Copytsx + + + + + + + + +``` + +## Example + +Show toastUpdate toast + +index.tsxstyle.css + +``` +Copytsx +import { Toast, toaster } from "@kobalte/core/toast"; +import { CrossIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + let id: number; + + const showToast = () => { + id = toaster.show(props => ( + +
+
+ Event has been created + + Monday, January 3rd at 6:00pm + +
+ + + +
+ + + +
+ )); + }; + + const updateToast = () => { + toaster.update(id, props => ( + +
+
+ Event has been updated + + Friday, January 7th at 10:00pm + +
+ + + +
+ + + +
+ )); + }; + + return ( + <> + + + + + + + + + ); +} +``` + +``` +Copytsx +import { Toast, toaster } from "@kobalte/core/toast"; +import { CrossIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + let id: number; + + const showToast = () => { + id = toaster.show(props => ( + +
+
+ Event has been created + + Monday, January 3rd at 6:00pm + +
+ + + +
+ + + +
+ )); + }; + + const updateToast = () => { + toaster.update(id, props => ( + +
+
+ Event has been updated + + Friday, January 7th at 10:00pm + +
+ + + +
+ + + +
+ )); + }; + + return ( + <> + + + + + + + + + ); +} +``` + +## Usage + +### Showing a toast + +To create a toast, use the `toaster.show()` method and pass the generated `toastId` to `Toast.Root`. + +``` +Copytsx +const id = toaster.show(props => ...); +``` + +``` +Copytsx +const id = toaster.show(props => ...); +``` + +### Updating a toast + +The `toaster.update()` method can be used to update a toast by providing a toast id and the new component to render. + +``` +Copytsx +toaster.update(id, props => ...); +``` + +``` +Copytsx +toaster.update(id, props => ...); +``` + +Notice that you always need to pass the `toastId` to `Toast`, because it doesn't know anything +about the `toaster` nor the toast it is supposed to represent. + +### Dismissing a toast + +The `toaster.dismiss()` method can be used to dismiss a toast by providing a toast id. + +``` +Copytsx +toaster.dismiss(id); +``` + +``` +Copytsx +toaster.dismiss(id); +``` + +### Clearing the toast stack and queue + +Use `toaster.clear()` method to dismiss all toasts. + +``` +Copytsx +toaster.clear(); +``` + +``` +Copytsx +toaster.clear(); +``` + +### Handling promises + +The toaster API exposes a `toaster.promise()` method to allow you update a toast when the promise resolves or rejects. + +In addition to the `toastId`, props will contain the following properties: + +- **state**: The state of the promise, can be `"pending" | "fulfilled" | "rejected"`. +- **data**: The data returned by the promise when fulfilled, if any. +- **error**: The error returned by the promise when rejected, if any. + +``` +Copytsx +toaster.promise(promise, props => ( + + + Loading + {props.data} + {props.error} + + +)); +``` + +``` +Copytsx +toaster.promise(promise, props => ( + + + Loading + {props.data} + {props.error} + + +)); +``` + +### Pausing the toasts + +The `Toast.Region` component exposes the following props to pause the toasts it contains. + +- `pauseOnInteraction`: prop can be used to pause the toasts close timeout when a toast is hovered or focused. +- `pauseOnPageIdle`: prop can be used to pause the toasts close timeout when the document loses focus or the page is idle (e.g. switching to a new browser tab). + +``` +Copytsx + + + +``` + +``` +Copytsx + + + +``` + +### Limiting the number of visible toasts + +Use the `limit` prop of the `Toast.Region` to limit the number of toasts visible at the same time. All toasts added after limit was reached will be added into queue and displayed when a visible toast is closed. + +``` +Copytsx + + + +``` + +``` +Copytsx + + + +``` + +### Progress bar fill width + +We expose a CSS custom property `--kb-toast-progress-fill-width` which corresponds to the remaining toast lifetime (in percentage). If you are building a linear progress bar to show the toast duration, you can use it to set the width of the `Toast.ProgressFill` component in CSS. + +``` +Copycss +/* style.css*/ + +.toast__progress-fill { + background-color: hsl(200 98% 39%); + border-radius: 3px; + height: 100%; + width: var(--kb-toast-progress-fill-width); + transition: width 250ms linear; +} +``` + +``` +Copycss +/* style.css*/ + +.toast__progress-fill { + background-color: hsl(200 98% 39%); + border-radius: 3px; + height: 100%; + width: var(--kb-toast-progress-fill-width); + transition: width 250ms linear; +} +``` + +### Animating swipe gesture + +We expose the CSS custom properties `--kb-toast-swipe-move-[x|y]` and `--kb-toast-swipe-end-[x|y]` which can be used with `data-swipe="[start|move|cancel|end]"` attributes to animate a swipe to close gesture. + +``` +Copytsx +// index.tsx + +import { Toast, toaster } from "@kobalte/core/toast"; +import "./style.css"; + +function App() { + const showToast = () => { + toaster.show(props => ( + + ... + + )); + }; + + return ( + <> + + + + + + + + ); +} +``` + +``` +Copytsx +// index.tsx + +import { Toast, toaster } from "@kobalte/core/toast"; +import "./style.css"; + +function App() { + const showToast = () => { + toaster.show(props => ( + + ... + + )); + }; + + return ( + <> + + + + + + + + ); +} +``` + +``` +Copycss +/* style.css */ + +.toast[data-swipe="move"] { + transform: translateX(var(--kb-toast-swipe-move-x)); +} + +.toast[data-swipe="cancel"] { + transform: translateX(0); + transition: transform 200ms ease-out; +} + +.toast[data-swipe="end"] { + animation: slideRight 100ms ease-out; +} + +@keyframes slideRight { + from { + transform: translateX(var(--kb-toast-swipe-end-x)); + } + to { + transform: translateX(100%); + } +} +``` + +``` +Copycss +/* style.css */ + +.toast[data-swipe="move"] { + transform: translateX(var(--kb-toast-swipe-move-x)); +} + +.toast[data-swipe="cancel"] { + transform: translateX(0); + transition: transform 200ms ease-out; +} + +.toast[data-swipe="end"] { + animation: slideRight 100ms ease-out; +} + +@keyframes slideRight { + from { + transform: translateX(var(--kb-toast-swipe-end-x)); + } + to { + transform: translateX(100%); + } +} +``` + +### Abstracting the `toaster` API + +It's common in toast libraries to have method for displaying different type of toast like success or error. This can be done in Kobalte by abstracting the toaster API like below. + +``` +Copytsx +// toast.tsx + +import { Toast, toaster } from "@kobalte/core/toast"; +import { JSX } from "solid-js/jsx-runtime"; +import { Switch, Match } from "solid-js/web"; + +function show(message: string) { + return toaster.show(props => ( + + {message} + + )); +} + +function success(message: string) { + return toaster.show(props => ( + + {message} + + )); +} + +function error(message: string) { + return toaster.show(props => ( + + {message} + + )); +} + +function promise( + promise: Promise | (() => Promise), + options: { + loading?: JSX.Element; + success?: (data: T) => JSX.Element; + error?: (error: U) => JSX.Element; + }, +) { + return toaster.promise(promise, props => ( + + + {options.loading} + {options.success?.(props.data)} + {options.error?.(props.error)} + + + )); +} + +function custom(jsx: () => JSX.Element) { + return toaster.show(props => {jsx}); +} + +function dismiss(id: number) { + return toaster.dismiss(id); +} + +export const toast = { + show, + success, + error, + promise, + custom, + dismiss, +}; +``` + +``` +Copytsx +// toast.tsx + +import { Toast, toaster } from "@kobalte/core/toast"; +import { JSX } from "solid-js/jsx-runtime"; +import { Switch, Match } from "solid-js/web"; + +function show(message: string) { + return toaster.show(props => ( + + {message} + + )); +} + +function success(message: string) { + return toaster.show(props => ( + + {message} + + )); +} + +function error(message: string) { + return toaster.show(props => ( + + {message} + + )); +} + +function promise( + promise: Promise | (() => Promise), + options: { + loading?: JSX.Element; + success?: (data: T) => JSX.Element; + error?: (error: U) => JSX.Element; + }, +) { + return toaster.promise(promise, props => ( + + + {options.loading} + {options.success?.(props.data)} + {options.error?.(props.error)} + + + )); +} + +function custom(jsx: () => JSX.Element) { + return toaster.show(props => {jsx}); +} + +function dismiss(id: number) { + return toaster.dismiss(id); +} + +export const toast = { + show, + success, + error, + promise, + custom, + dismiss, +}; +``` + +Then inside your application, use your own toast API: + +``` +Copytsx +// App.tsx + +import { toast } from "./toast"; + +function App() { + const showToast = () => { + toast.success("Event has been created"); + }; + + return ( + <> + + + + + + + + ); +} +``` + +``` +Copytsx +// App.tsx + +import { toast } from "./toast"; + +function App() { + const showToast = () => { + toast.success("Event has been created"); + }; + + return ( + <> + + + + + + + + ); +} +``` + +### Multiple regions + +The `region` option in `toaster.show()` allows you to display toast in multiple regions at the same time. Not providing a region uses the default one. + +``` +Copytsx +toaster.show(props => ..., { + region: "custom-region-id", +}); +``` + +``` +Copytsx +toaster.show(props => ..., { + region: "custom-region-id", +}); +``` + +Inside your application, use add your custom region: + +``` +Copytsx + + {/* Default region */} + + + + + + + +``` + +``` +Copytsx + + {/* Default region */} + + + + + + + +``` + +Show toastShow toast (custom region) + +## API reference + +### toaster + +| Method | Description | +| --- | --- | +| show | `(toastComponent: ToastComponent, options?: ShowToastOptions) => number`
Adds a new toast to the visible toasts or queue depending on current state, region and limit, and return the id of the created toast. | +| update | `(id: number, toastComponent: ToastComponent) => void`
Update the toast of the given id with a new rendered component. | +| promise | `(promise: Promise | (() => Promise), toastComponent: ToastPromiseComponent, options?: ShowToastOptions) => number`
Adds a new promise-based toast to the visible toasts or queue depending on current state and limit, and return the id of the created toast. | +| dismiss | `(id: number) => void`
Removes toast with given id from visible toasts and queue. | +| clear | `() => void`
Removes all toasts from visible toasts and queue. | + +### Toast.Region + +| Prop | Description | +| --- | --- | +| aria-label | `string`
**default:** "Notifications ({hotkey})"
A label for the toast region to provide context for screen reader users when navigating page landmarks. Can contain a `{hotkey}` placeholder which will be replaced for you. | +| hotkey | `string[]`
**default:** alt + T
The keys to use as the keyboard shortcut that will move focus to the toast region. Use `event.code` value for each key from [keycode.info](https://www.toptal.com/developers/keycode). For meta keys, use `ctrlKey`, `shiftKey`, `altKey` and/or `metaKey`. | +| duration | `number`
**default:** 5000
The time in milliseconds that should elapse before automatically closing each toast. | +| limit | `number`
**default:** 3
The maximum amount of toasts that can be displayed at the same time. | +| swipeDirection | `"up" | "down" | "left" | "right"`
**default:** "right"
The direction of the pointer swipe that should close the toast. | +| swipeThreshold | `number`
**default:** 50
The distance in pixels that the swipe gesture must travel before a close is triggered. | +| pauseOnInteraction | `boolean`
**default:** true
Whether the toasts close timeout should pause when a toast is hovered or focused. | +| pauseOnPageIdle | `boolean`
**default:** true
Whether the toasts close timeout should pause when the document loses focus or the page is idle (e.g. switching to a new browser tab). | +| topLayer | `boolean`
**default:** true
Whether the toast region is marked as a "top layer", so that it:
\- is not aria-hidden when opening an overlay.
\- allows focus even outside a containing focus scope.
\- doesn’t dismiss overlays when clicking on it, even though it is outside. | +| regionId | `string`
The custom id of the region used for multiple regions. | +| translations | [`ToastRegionIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/toast/toast.intl.ts)
Localization strings. | + +### Toast + +`Toast` is equivalent to the `Root` import from `@kobalte/core/toast` (and deprecated `Toast.Root`). + +| Prop | Description | +| --- | --- | +| toastId | `number`
The id of the toast provided by the `toaster`. | +| priority | `"high" | "low"`
**default:** "high"
Control the sensitivity of the toast for accessibility purposes. For toasts that are the result of a user action, choose `high`. Toasts generated from background tasks should use `low`. | +| duration | `number`
The time in milliseconds that should elapse before automatically closing the toast. This will override the value supplied to `Toast.Region`. | +| persistent | `boolean`
Whether the toast should ignore duration and disappear only by a user action. | +| onPause | `() => void`
Event handler called when the dismiss timer is paused. This occurs when the pointer is moved over the region or the region is focused. | +| onResume | `() => void`
Event handler called when the dismiss timer is resumed. This occurs when the pointer is moved away from the region or the region is blurred. | +| onSwipeStart | `(event: SwipeEvent) => void`
Event handler called when starting a swipe interaction. | +| onSwipeMove | `(event: SwipeEvent) => void`
Event handler called during a swipe interaction. | +| onSwipeCancel | `(event: SwipeEvent) => void`
Event handler called when a swipe interaction is cancelled. | +| onSwipeEnd | `(event: SwipeEvent) => void`
Event handler called at the end of a swipe interaction. | +| onEscapeKeyDown | `(event: KeyboardEvent) => void`
Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | +| translations | [`ToastIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/toast/toast.intl.ts)
Localization strings. | + +| Data attribute | Description | +| --- | --- | +| data-opened | Present when the toast is open. | +| data-closed | Present when the toast disappear. | +| data-swipe | The state of the swipe, can be `"start" | "move" | "cancel" | "end"`. | +| data-swipe-direction | The direction of the pointer swipe that should close the toast. | + +| CSS custom property | Description | +| --- | --- | +| --kb-toast-swipe-move-x | The offset position of the toast when horizontally swiping. | +| --kb-toast-swipe-move-y | The offset position of the toast when vertically swiping. | +| --kb-toast-swipe-end-x | The offset end position of the toast after horizontally swiping. | +| --kb-toast-swipe-end-y | The offset end position of the toast after vertically swiping. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Toast` | `li` | +| `Toast.CloseButton` | `button` | +| `Toast.Title` | `div` | +| `Toast.Description` | `div` | +| `Toast.ProgressTrack` | `div` | +| `Toast.ProgressFill` | `div` | +| `Toast.Region` | `div` | +| `Toast.List` | `ol` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Alt` \+ `T` | Focuses toasts region. | +| `Tab` | Moves focus to the next focusable element. | +| `Shift` \+ `Tab` | Moves focus to the previous focusable element. | +| `Space` | When focus is on a `Toast.CloseButton`, closes the toast. | +| `Enter` | When focus is on a `Toast.CloseButton`, closes the toast. | +| `Esc` | When focus is on a toast, closes the toast. | + +Previous[←Time Field](https://kobalte.dev/docs/core/components/time-field)Next[Toggle Button→](https://kobalte.dev/docs/core/components/toggle-button) \ No newline at end of file diff --git a/.firecrawl/kobalte-utils-npm.md b/.firecrawl/kobalte-utils-npm.md new file mode 100644 index 0000000..803c901 --- /dev/null +++ b/.firecrawl/kobalte-utils-npm.md @@ -0,0 +1,55 @@ +# @kobalte/utils ![TypeScript icon, indicating that this package has built-in type declarations](https://static-production.npmjs.com/4a2a680dfcadf231172b78b1d3beb975.svg) + +0.9.1 • Public • Published 2 years ago + +- [Readme](https://www.npmjs.com/package/@kobalte/utils?activeTab=readme) +- [Code Beta](https://www.npmjs.com/package/@kobalte/utils?activeTab=code) +- [7 Dependencies](https://www.npmjs.com/package/@kobalte/utils?activeTab=dependencies) +- [10 Dependents](https://www.npmjs.com/package/@kobalte/utils?activeTab=dependents) +- [16 Versions](https://www.npmjs.com/package/@kobalte/utils?activeTab=versions) + +# @kobalte/utils + +[Permalink: @kobalte/utils](https://www.npmjs.com/package/@kobalte/utils#kobalteutils) + +Common utilities and types for Kobalte. + +## Installation + +[Permalink: Installation](https://www.npmjs.com/package/@kobalte/utils#installation) + +``` +npm install @kobalte/utils +# or +yarn add @kobalte/utils +# or +pnpm add @kobalte/utils +``` + +## Documentation + +[Permalink: Documentation](https://www.npmjs.com/package/@kobalte/utils#documentation) + +For full documentation, visit [kobalte.dev](https://kobalte.dev/). + +## Changelog + +[Permalink: Changelog](https://www.npmjs.com/package/@kobalte/utils#changelog) + +All notable changes are described in the [CHANGELOG.md](https://github.com/kobaltedev/kobalte/blob/HEAD/CHANGELOG.md) file. + +## Readme + +### Keywords + +- [solid](https://www.npmjs.com/search?q=keywords:solid) +- [solidjs](https://www.npmjs.com/search?q=keywords:solidjs) +- [ui](https://www.npmjs.com/search?q=keywords:ui) +- [library](https://www.npmjs.com/search?q=keywords:library) +- [design-system](https://www.npmjs.com/search?q=keywords:design-system) +- [components](https://www.npmjs.com/search?q=keywords:components) +- [headless](https://www.npmjs.com/search?q=keywords:headless) +- [unstyled](https://www.npmjs.com/search?q=keywords:unstyled) +- [aria](https://www.npmjs.com/search?q=keywords:aria) + +Viewing @kobalte/utils version 0.9.1 \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-alert-dialog.md b/.firecrawl/kobalte.dev-docs-core-components-alert-dialog.md new file mode 100644 index 0000000..0170abc --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-alert-dialog.md @@ -0,0 +1,258 @@ +# Alert Dialog + +A modal dialog that interrupts the user's workflow to communicate an important message and acquire a response. Examples include action confirmation prompts and error message confirmations. The alertdialog role enables assistive technologies and browsers to distinguish alert dialogs from other dialogs so they have the option of giving alert dialogs special treatment, such as playing a system alert sound. + +## Import + +``` +Copyts +import { AlertDialog } from "@kobalte/core/alert-dialog"; +// or +import { Root, Trigger, ... } from "@kobalte/core/alert-dialog"; +// or (deprecated) +import { AlertDialog } from "@kobalte/core"; +``` + +``` +Copyts +import { AlertDialog } from "@kobalte/core/alert-dialog"; +// or +import { Root, Trigger, ... } from "@kobalte/core/alert-dialog"; +// or (deprecated) +import { AlertDialog } from "@kobalte/core"; +``` + +## Features + +- Follow the [WAI ARIA Alert Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/) design pattern. +- Supports modal and non-modal modes. +- Provides screen reader announcements via rendered title and description. +- Focus is trapped and scrolling is blocked while it is open. +- Pressing `Esc` closes the alert dialog. +- Can be controlled or uncontrolled. + +## Anatomy + +The alert dialog consists of: + +- **AlertDialog:** Contains all the parts of a dialog. +- **AlertDialog.Trigger:** The button that opens the dialog. +- **AlertDialog.Portal:** Portals its children into the `body` when the dialog is open. +- **AlertDialog.Overlay:** The layer that covers the inert portion of the view when the dialog is open. +- **AlertDialog.Content:** Contains the content to be rendered when the dialog is open. +- **AlertDialog.CloseButton:** The button that closes the dialog. +- **AlertDialog.Title:** An accessible title to be announced when the dialog is opened. +- **AlertDialog.Description:** An optional accessible description to be announced when the dialog is opened. + +``` +Copytsx + + + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + + + +``` + +## Example + +Open + +index.tsxstyle.css + +``` +Copytsx +import { AlertDialog } from "@kobalte/core/alert-dialog"; +import { CrossIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + return ( + + Open + + +
+ +
+ Alert Dialog + + + +
+ + An Alert Dialog enables assistive technologies and browsers to distinguish alert dialogs from other dialogs so they have the option of giving alert dialogs special treatment, such as playing a system alert sound. + +
+
+
+
+ ); +} +``` + +``` +Copytsx +import { AlertDialog } from "@kobalte/core/alert-dialog"; +import { CrossIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + return ( + + Open + + +
+ +
+ Alert Dialog + + + +
+ + An Alert Dialog enables assistive technologies and browsers to distinguish alert dialogs from other dialogs so they have the option of giving alert dialogs special treatment, such as playing a system alert sound. + +
+
+
+
+ ); +} +``` + +## Usage + +### Default open + +An initial, uncontrolled open value can be provided using the `defaultOpen` prop. + +``` +Copytsx +... +``` + +``` +Copytsx +... +``` + +### Controlled open + +The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, close button or overlay, and receives the new value. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [open, setOpen] = createSignal(false); + + return ( + + ... + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [open, setOpen] = createSignal(false); + + return ( + + ... + + ); +} +``` + +## API Reference + +### AlertDialog + +`AlertDialog` is equivalent to the `Root` import from `@kobalte/core/alert-dialog` (and deprecated `AlertDialog.Root`). + +| Prop | Description | +| --- | --- | +| open | `boolean`
The controlled open state of the dialog. | +| defaultOpen | `boolean`
The default open state when initially rendered. Useful when you do not need to control the open state. | +| onOpenChange | `(open: boolean) => void`
Event handler called when the open state of the dialog changes. | +| id | `string`
A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. | +| modal | `boolean`
Whether the dialog should be the only visible content for screen readers, when set to `true`:
\- interaction with outside elements will be disabled.
\- scroll will be locked.
\- focus will be locked inside the dialog content.
\- elements outside the dialog content will not be visible for screen readers. | +| preventScroll | `boolean`
Whether the scroll should be locked even if the alert dialog is not modal. | +| forceMount | `boolean`
Used to force mounting the dialog (portal, overlay and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +### AlertDialog.Trigger + +`AlertDialog.Trigger` consists of [Button](https://kobalte.dev/docs/core/components/button). + +| Data attribute | Description | +| --- | --- | +| data-expanded | Present when the dialog is open. | +| data-closed | Present when the dialog is close. | + +`AlertDialog.Content` and `AlertDialog.Overlay` shares the same data-attributes. + +### AlertDialog.Content + +| Prop | Description | +| --- | --- | +| onOpenAutoFocus | `(event: Event) => void`
Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. | +| onCloseAutoFocus | `(event: Event) => void`
Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. | +| onEscapeKeyDown | `(event: KeyboardEvent) => void`
Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | +| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`
Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onFocusOutside | `(event: FocusOutsideEvent) => void`
Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onInteractOutside | `(event: InteractOutsideEvent) => void`
Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `AlertDialog` | none | +| `AlertDialog.Trigger` | `button` | +| `AlertDialog.Portal` | `Portal` | +| `AlertDialog.Overlay` | `div` | +| `AlertDialog.Content` | `div` | +| `AlertDialog.CloseButton` | `button` | +| `AlertDialog.Title` | `h2` | +| `AlertDialog.Description` | `p` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Space` | When focus is on the trigger, opens/closes the dialog. | +| `Enter` | When focus is on the trigger, opens/closes the dialog. | +| `Tab` | Moves focus to the next focusable element. | +| `Shift` \+ `Tab` | Moves focus to the previous focusable element. | +| `Esc` | Closes the dialog and moves focus to the trigger. | + +Previous[←Alert](https://kobalte.dev/docs/core/components/alert)Next[Badge→](https://kobalte.dev/docs/core/components/badge) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-alert.md b/.firecrawl/kobalte.dev-docs-core-components-alert.md new file mode 100644 index 0000000..b002e30 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-alert.md @@ -0,0 +1,85 @@ +# Alert + +Display a brief, important message in a way that attracts the user's attention without interrupting the user's task. + +## Import + +``` +Copyts +import { Alert } from "@kobalte/core/alert"; +// or +import { Root } from "@kobalte/core/alert"; +// or (deprecated) +import { Alert } from "@kobalte/core"; +``` + +``` +Copyts +import { Alert } from "@kobalte/core/alert"; +// or +import { Root } from "@kobalte/core/alert"; +// or (deprecated) +import { Alert } from "@kobalte/core"; +``` + +## Features + +- Adhere to the [WAI ARIA Alert](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) design pattern. + +## Anatomy + +The alert consists of : + +- **Alert:** The root container for an alert. + +``` +Copytsx + +``` + +``` +Copytsx + +``` + +## Example + +Kobalte is going live soon, get ready! + +index.tsxstyle.css + +``` +Copytsx +import { Alert } from "@kobalte/core/alert"; +import "./style.css"; + +function App() { + return Kobalte is going live soon, get ready!; +} +``` + +``` +Copytsx +import { Alert } from "@kobalte/core/alert"; +import "./style.css"; + +function App() { + return Kobalte is going live soon, get ready!; +} +``` + +## API reference + +### Alert + +`Alert` is equivalent to the `Root` import from `@kobalte/core/alert` (and deprecated `Alert.Root`). + +Renders a `div` by default and support all its props. + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Alert` | `div` | + +Previous[←Accordion](https://kobalte.dev/docs/core/components/accordion)Next[Alert Dialog→](https://kobalte.dev/docs/core/components/alert-dialog) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-badge.md b/.firecrawl/kobalte.dev-docs-core-components-badge.md new file mode 100644 index 0000000..48ad382 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-badge.md @@ -0,0 +1,92 @@ +# Badge + +A `Badge` component is used to display small pieces of information or status indicators. + +## Import + +``` +Copyts +import { Badge } from "@kobalte/core/badge"; +// or +import { Root } from "@kobalte/core/badge"; +``` + +``` +Copyts +import { Badge } from "@kobalte/core/badge"; +// or +import { Root } from "@kobalte/core/badge"; +``` + +## Features + +- Auto-populated ARIA labeling via the textValue prop for enhanced accessibility. +- Built-in ARIA support with role="status" to communicate dynamic updates. + +## Anatomy + +The badge consists of: + +- **Badge:** The root container for the badge that supports accessibility and content customization. + +``` +Copytsx + +``` + +``` +Copytsx + +``` + +## Example + +5 messages + +index.tsxstyle.css + +``` +Copytsx +import { Badge } from "@kobalte/core/badge"; +import "./style.css"; + +function App() { + return ( + + 5 messages + + ); +} +``` + +``` +Copytsx +import { Badge } from "@kobalte/core/badge"; +import "./style.css"; + +function App() { + return ( + + 5 messages + + ); +} +``` + +## API Reference + +### Badge + +`Badge` is equivalent to the `Root` import from `@kobalte/core/badge`. + +| Prop | Description | +| --- | --- | +| textValue | `string | undefined`
Accessible text description of the badge if child is not text | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Badge` | `span` | + +Previous[←Alert Dialog](https://kobalte.dev/docs/core/components/alert-dialog)Next[Breadcrumbs→](https://kobalte.dev/docs/core/components/breadcrumbs) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-breadcrumbs.md b/.firecrawl/kobalte.dev-docs-core-components-breadcrumbs.md new file mode 100644 index 0000000..fe3b00a --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-breadcrumbs.md @@ -0,0 +1,233 @@ +Show hierarchy and navigational context for a user’s location within an application. + +## Import + +``` +Copyts +import { Breadcrumbs } from "@kobalte/core/breadcrumbs"; +// or +import { Root, Link, ... } from "@kobalte/core/breadcrumbs"; +// or (deprecated) +import { Breadcrumbs } from "@kobalte/core"; +``` + +``` +Copyts +import { Breadcrumbs } from "@kobalte/core/breadcrumbs"; +// or +import { Root, Link, ... } from "@kobalte/core/breadcrumbs"; +// or (deprecated) +import { Breadcrumbs } from "@kobalte/core"; +``` + +## Features + +- Support for navigation links via `` elements or custom element types via ARIA. +- Localized ARIA labeling support for landmark navigation region. +- Support for disabled breadcrumb links. + +## Anatomy + +The breadcrumbs consist of: + +- **Breadcrumbs:** The root container for a breadcrumbs. +- **Breadcrumbs.Link:** The breadcrumb link. +- **Breadcrumbs.Separator:** The visual separator between each breadcrumb items. It will not be visible by screen readers. +- **ol:** The native HTML `
    ` element used to contain breadcrumb items. +- **li:** The native HTML `
  1. ` element used to contain breadcrumb link and separator. + +``` +Copytsx + +
      +
    1. + + +
    2. +
    +
    +``` + +``` +Copytsx + +
      +
    1. + + +
    2. +
    +
    +``` + +## Example + +index.tsxstyle.css + +``` +Copytsx +import { Breadcrumbs } from "@kobalte/core/breadcrumbs"; +import "./style.css"; + +function App() { + return ( + + + + ); +} +``` + +``` +Copytsx +import { Breadcrumbs } from "@kobalte/core/breadcrumbs"; +import "./style.css"; + +function App() { + return ( + + + + ); +} +``` + +## Usage + +### Custom separator + +Use the `separator` prop to provide a default content for all `Breadcrumbs.Separator`. You can pass it a `string` or a SolidJS component. + +``` +Copytsx +import { ChevronRightIcon } from "some-icon-library"; + +function App() { + return ( + }> + + + ); +} +``` + +``` +Copytsx +import { ChevronRightIcon } from "some-icon-library"; + +function App() { + return ( + }> + + + ); +} +``` + +You can also override each `Breadcrumbs.Separator` content by providing your own `children`. + +## API Reference + +### Breadcrumbs + +`Breadcrumbs` is equivalent to the `Root` import from `@kobalte/core/breadcrumbs` (and deprecated `Breadcrumbs.Root`). + +| Prop | Description | +| --- | --- | +| separator | `string | JSX.Element`
    The visual separator between each breadcrumb item. It will be used as the default children of `Breadcrumbs.Separator`. | +| translations | [`BreadcrumbsIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/breadcrumbs/breadcrumbs.intl.ts)
    Localization strings. | + +### Breadcrumbs.Link + +`Breadcrumbs.Link` consists of [Link](https://kobalte.dev/docs/core/components/link). + +| Prop | Description | +| --- | --- | +| current | `boolean`
    Whether the breadcrumb link represents the current page. | +| disabled | `boolean`
    Whether the breadcrumb link is disabled. | + +| Data attribute | Description | +| --- | --- | +| data-current | Present when the breadcrumb link represents the current page. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Breadcrumbs` | `nav` | +| `Breadcrumbs.Link` | `a` | +| `Breadcrumbs.Separator` | `span` | + +Previous[←Badge](https://kobalte.dev/docs/core/components/badge)Next[Button→](https://kobalte.dev/docs/core/components/button) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-button.md b/.firecrawl/kobalte.dev-docs-core-components-button.md new file mode 100644 index 0000000..5a927a6 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-button.md @@ -0,0 +1,102 @@ +# Button + +Enables users to trigger an action or event, such as submitting a form, opening a dialog, canceling an action, or performing a delete operation. + +## Import + +``` +Copyts +import { Button } from "@kobalte/core/button"; +// or +import { Root } from "@kobalte/core/button"; +// or (deprecated) +import { Button } from "@kobalte/core"; +``` + +``` +Copyts +import { Button } from "@kobalte/core/button"; +// or +import { Root } from "@kobalte/core/button"; +// or (deprecated) +import { Button } from "@kobalte/core"; +``` + +## Features + +- Native HTML `
    ; +} +``` + +``` +Copytsx +import { Button } from "@kobalte/core/button"; +import "./style.css"; + +function App() { + return ; +} +``` + +## API Reference + +### Button + +`Button` is equivalent to the `Root` import from `@kobalte/core/button` (and deprecated `Button.Root`). + +| Prop | Description | +| --- | --- | +| disabled | `boolean`
    Whether the button is disabled. | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the button is disabled. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Button` | `button` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Space` | Activates the button. | +| `Enter` | Activates the button. | + +Previous[←Breadcrumbs](https://kobalte.dev/docs/core/components/breadcrumbs)Next[Checkbox→](https://kobalte.dev/docs/core/components/checkbox) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-checkbox.md b/.firecrawl/kobalte.dev-docs-core-components-checkbox.md new file mode 100644 index 0000000..8e11d04 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-checkbox.md @@ -0,0 +1,400 @@ +# Checkbox + +A control that allows the user to toggle between checked and not checked. + +## Import + +``` +Copyts +import { Checkbox } from "@kobalte/core/checkbox"; +// or +import { Root, Input, ... } from "@kobalte/core/checkbox"; +// or (deprecated) +import { Checkbox } from "@kobalte/core"; +``` + +``` +Copyts +import { Checkbox } from "@kobalte/core/checkbox"; +// or +import { Root, Input, ... } from "@kobalte/core/checkbox"; +// or (deprecated) +import { Checkbox } from "@kobalte/core"; +``` + +## Features + +- Built with a native HTML `` element, which is visually hidden to allow custom styling. +- Syncs with form reset events. +- Labeling support for assistive technology. +- Support for description and error message help text linked to the input via ARIA. +- Can be controlled or uncontrolled. + +## Anatomy + +The checkbox consists of: + +- **Checkbox:** The root container for a checkbox. +- **Checkbox.Input:** The native html input that is visually hidden in the checkbox. +- **Checkbox.Control:** The element that visually represents a checkbox. +- **Checkbox.Indicator:** The visual indicator rendered when the checkbox is in a checked or indeterminate state. +- **Checkbox.Label:** The label that gives the user information on the checkbox. +- **Checkbox.Description**: The description that gives the user more information on the checkbox. +- **Checkbox.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the checkbox. + +``` +Copytsx + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + +``` + +## Example + +Subscribe + +index.tsxstyle.css + +``` +Copytsx +import { Checkbox } from "@kobalte/core/checkbox"; +import { CheckIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + return ( + + + + + + + + Subscribe + + ); +} +``` + +``` +Copytsx +import { Checkbox } from "@kobalte/core/checkbox"; +import { CheckIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + return ( + + + + + + + + Subscribe + + ); +} +``` + +## Usage + +### Default checked + +An initial, uncontrolled value can be provided using the `defaultChecked` prop. + +Check + +Subscribe + +``` +Copytsx +... +``` + +``` +Copytsx +... +``` + +### Controlled checked + +The `checked` prop can be used to make the checked state controlled. The `onChange` event is fired when the user presses the checkbox, and receives the new value. + +Subscribe + +You are unsubscribed. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [checked, setChecked] = createSignal(false); + + return ( + <> + + ... + +

    You are {checked() ? "subscribed" : "unsubscribed"}.

    + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [checked, setChecked] = createSignal(false); + + return ( + <> + + ... + +

    You are {checked() ? "subscribed" : "unsubscribed"}.

    + + ); +} +``` + +### Description + +The `Checkbox.Description` component can be used to associate additional help text with a checkbox. + +Subscribe + +You will receive our weekly newsletter. + +``` +Copytsx + + + + + + + + Subscribe + You will receive our weekly newsletter. + +``` + +``` +Copytsx + + + + + + + + Subscribe + You will receive our weekly newsletter. + +``` + +### Error message + +The `Checkbox.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the checkbox as invalid for assistive technologies. + +By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries). + +Subscribe + +You must agree to our Terms and Conditions. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [checked, setChecked] = createSignal(false); + + return ( + + + + + + + + Agree + You must agree to our Terms and Conditions. + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [checked, setChecked] = createSignal(false); + + return ( + + + + + + + + Agree + You must agree to our Terms and Conditions. + + ); +} +``` + +### HTML forms + +The `name` and `value` props can be used for integration with HTML forms. + +Subscribe + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + ... + +
    + + +
    +
    + ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + ... + +
    + + +
    +
    + ); +} +``` + +## API Reference + +### Checkbox + +`Checkbox` is equivalent to the `Root` import from `@kobalte/core/checkbox` (and deprecated `Checkbox.Root`). + +| Prop | Description | +| --- | --- | +| checked | `boolean`
    The controlled checked state of the checkbox. | +| defaultChecked | `boolean`
    The default checked state when initially rendered. Useful when you do not need to control the checked state. | +| onChange | `(checked: boolean) => void`
    Event handler called when the checked state of the checkbox changes. | +| indeterminate | `boolean`
    Whether the checkbox is in an indeterminate state. | +| name | `string`
    The name of the checkbox, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). | +| value | `string`
    The value of the checkbox, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefvalue). | +| validationState | `'valid' | 'invalid'`
    Whether the checkbox should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must check the checkbox before the owning form can be submitted. | +| disabled | `boolean`
    Whether the checkbox is disabled. | +| readOnly | `boolean`
    Whether the checkbox can be checked but not changed by the user. | +| children | `JSX.Element | (state: CheckboxState) => JSX.Element`
    The children of the checkbox. Can be a `JSX.Element` or a _render prop_ for having access to the internal state. | + +| Render Prop | Description | +| --- | --- | +| checked | `Accessor`
    Whether the checkbox is checked or not. | +| indeterminate | `Accessor`
    Whether the checkbox is in an indeterminate state. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the checkbox is valid according to the validation rules. | +| data-invalid | Present when the checkbox is invalid according to the validation rules. | +| data-required | Present when the checkbox is required. | +| data-disabled | Present when the checkbox is disabled. | +| data-readonly | Present when the checkbox is read only. | +| data-checked | Present when the checkbox is checked. | +| data-indeterminate | Present when the checkbox is in an indeterminate state. | + +`Checkbox.Input`, `Checkbox.Control`, `Checkbox.Indicator`, `Checkbox.Label`, `Checkbox.Description` and `Checkbox.ErrorMessage` share the same data-attributes. + +### Checkbox.Indicator + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +### Checkbox.ErrorMessage + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Checkbox` | `div` | +| `Checkbox.Input` | `input` | +| `Checkbox.Control` | `div` | +| `Checkbox.Indicator` | `div` | +| `Checkbox.Label` | `label` | +| `Checkbox.Description` | `div` | +| `Checkbox.ErrorMessage` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Space` | Toggles the checkbox on and off. | + +Previous[←Button](https://kobalte.dev/docs/core/components/button)Next[Collapsible→](https://kobalte.dev/docs/core/components/collapsible) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-collapsible.md b/.firecrawl/kobalte.dev-docs-core-components-collapsible.md new file mode 100644 index 0000000..9ff830c --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-collapsible.md @@ -0,0 +1,217 @@ +# Collapsible + +An interactive component which expands/collapses a content. + +## Import + +``` +Copyts +import { Collapsible } from "@kobalte/core/collapsible"; +// or +import { Root, Trigger, ... } from "@kobalte/core/collapsible"; +// or (deprecated) +import { Collapsible } from "@kobalte/core"; +``` + +``` +Copyts +import { Collapsible } from "@kobalte/core/collapsible"; +// or +import { Root, Trigger, ... } from "@kobalte/core/collapsible"; +// or (deprecated) +import { Collapsible } from "@kobalte/core"; +``` + +## Features + +- Follow the [WAI ARIA Disclosure](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) design pattern. +- Can be controlled or uncontrolled. + +## Anatomy + +The collapsible consists of: + +- **Collapsible:** The root container for a collapsible. +- **Collapsible.Trigger:** The button that expands/collapses the collapsible content. +- **Collapsible.Content:** Contains the content to be rendered when the collapsible is expanded. + +``` +Copytsx + + + + +``` + +``` +Copytsx + + + + +``` + +## Example + +What is Kobalte?Chevron + +index.tsxstyle.css + +``` +Copytsx +import { Collapsible } from "@kobalte/core/collapsible"; +import { ChevronDownIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + return ( + + + What is Kobalte? + + + +

    + Kobalte is a UI toolkit for building accessible web apps and design systems with SolidJS. + It provides a set of low-level UI components and primitives which can be the foundation + for your design system implementation. +

    +
    +
    + ); +} +``` + +``` +Copytsx +import { Collapsible } from "@kobalte/core/collapsible"; +import { ChevronDownIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + return ( + + + What is Kobalte? + + + +

    + Kobalte is a UI toolkit for building accessible web apps and design systems with SolidJS. + It provides a set of low-level UI components and primitives which can be the foundation + for your design system implementation. +

    +
    +
    + ); +} +``` + +## Usage + +### Animating content size + +We expose the CSS custom properties `--kb-collapsible-content-width` and `--kb-collapsible-content-height` which you can use to animate the size of the content when it opens/closes. + +``` +Copycss +/* style.css */ +.collapsible__content { + overflow: hidden; + animation: slideUp 300ms ease-out; +} + +.collapsible__content[data-expanded] { + animation: slideDown 300ms ease-out; +} + +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--kb-collapsible-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--kb-collapsible-content-height); + } + to { + height: 0; + } +} +``` + +``` +Copycss +/* style.css */ +.collapsible__content { + overflow: hidden; + animation: slideUp 300ms ease-out; +} + +.collapsible__content[data-expanded] { + animation: slideDown 300ms ease-out; +} + +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--kb-collapsible-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--kb-collapsible-content-height); + } + to { + height: 0; + } +} +``` + +## API Reference + +### Collapsible + +`Collapsible` is equivalent to the `Root` import from `@kobalte/core/collapsible` (and deprecated `Collapsible.Root`). + +| Prop | Description | +| --- | --- | +| open | `boolean`
    The controlled open state of the collapsible. | +| defaultOpen | `boolean`
    The default open state when initially rendered. Useful when you do not need to control the open state. | +| onOpenChange | `(open: boolean) => void`
    Event handler called when the open state of the collapsible changes. | +| disabled | `boolean`
    Whether the collapsible is disabled. | +| forceMount | `boolean`
    Used to force mounting the collapsible content when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +| Data attribute | Description | +| --- | --- | +| data-expanded | Present when the collapsible is expanded. | +| data-closed | Present when the collapsible is collapsed. | +| data-disabled | Present when the collapsible is disabled. | + +`Collapsible.Trigger` and `Collapsible.Content` share the same data-attributes. + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Collapsible` | `div` | +| `Collapsible.Trigger` | `button` | +| `Collapsible.Content` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Space` | When focus is on the trigger, opens/closes the collapsible. | +| `Enter` | When focus is on the trigger, opens/closes the collapsible. | + +Previous[←Checkbox](https://kobalte.dev/docs/core/components/checkbox)Next[Color Area→](https://kobalte.dev/docs/core/components/color-area) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-color-channel-field.md b/.firecrawl/kobalte.dev-docs-core-components-color-channel-field.md new file mode 100644 index 0000000..b2eea38 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-color-channel-field.md @@ -0,0 +1,493 @@ +# Color Channel Field + +A number input that allow users to edit individual color channel value. + +## Import + +``` +Copyts +import { ColorChannelField } from "@kobalte/core/color-channel-field"; +// or +import { Root, Label, ... } from "@kobalte/core/color-channel-field"; +``` + +``` +Copyts +import { ColorChannelField } from "@kobalte/core/color-channel-field"; +// or +import { Root, Label, ... } from "@kobalte/core/color-channel-field"; +``` + +## Features + +- Follows the [WAI ARIA Spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) design pattern. +- Built with a native `` element. +- Visual and ARIA labeling support. +- Required and invalid states exposed to assistive technology via ARIA. +- Support for description and error message help text linked to the input via ARIA. +- Syncs with form reset events. +- Can be controlled or uncontrolled. +- Supports increment and decrement buttons. +- Format and localize input number and raw input. +- Supports mouse wheel event and all keyboard events. + +## Anatomy + +The color channel field consists of: + +- **ColorChannelField**: The root container for the color channel field. +- **ColorChannelField.Label**: The label that gives the user information on the color channel field. +- **ColorChannelField.Input**: The native HTML input of the color channel field, used for display number. +- **ColorChannelField.HiddenInput**: The native HTML input of the color channel field, used for raw number form submition. +- **ColorChannelField.IncrementTrigger**: The increment button of the color channel field. +- **ColorChannelField.DecrementTrigger**: The decrement button of the color channel field. +- **ColorChannelField.Description**: The description that gives the user more information on the color channel field. +- **ColorChannelField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on a color channel field. + +``` +Copytsx + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + +``` + +## Example + +Hue + +ArrowArrow + +index.tsxstyle.css + +``` +Copytsx +import { ColorChannelField } from "@kobalte/core/color-channel-field"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + + Hue + +
    + + + + + + + +
    +
    + ); +} +``` + +``` +Copytsx +import { ColorChannelField } from "@kobalte/core/color-channel-field"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + + Hue + +
    + + + + + + + +
    +
    + ); +} +``` + +## Usage + +The value provided to `defaultValue` or `value` should be `Color` object. You can obtain a Color object by using the `parseColor` function to parse a color from a string. The `channel` prop must also be provided to specify which color channel the field manipulates. +This must be one of the channels included in the color value, for example, for RGB colors, the "red", "green", and "blue" channels are available. + +### Default value + +Saturation + +ArrowArrow + +``` +Copytsx + + Saturation +
    + + + +
    +
    +``` + +``` +Copytsx + + Saturation +
    + + + +
    +
    +``` + +### Controlled value + +Lightness + +ArrowArrow + +Lightness: 39% + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal(parseColor("hsl(200, 98%, 39%)")); + + return ( + <> + + Lightness +
    + + + +
    +
    +

    Lightness: {value().getChannelValue("lightness")}%

    + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal(parseColor("hsl(200, 98%, 39%)")); + + return ( + <> + + Lightness +
    + + + +
    +
    +

    Lightness: {value().getChannelValue("lightness")}%

    + + ); +} +``` + +### Description + +The `ColorChannelField.Description` component can be used to associate additional help text with a color channel field. + +Hue + +ArrowArrow + +Enter your favorite hue. + +``` +Copytsx + + Hue +
    + + + +
    + Enter your favorite hue. +
    +``` + +``` +Copytsx + + Hue +
    + + + +
    + Enter your favorite hue. +
    +``` + +### Error message + +The `ColorChannelField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the field as invalid for assistive technologies. + +By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries). + +Saturation + +ArrowArrow + +Hmm, I prefer 40% saturation. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal(parseColor("hsl(200, 30%, 39%)")); + + return ( + + Saturation +
    + + + +
    + Hmm, I prefer 40% saturation. +
    + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal(parseColor("hsl(200, 30%, 39%)")); + + return ( + + Saturation +
    + + + +
    + Hmm, I prefer 40% saturation. +
    + ); +} +``` + +### HTML forms + +The color channel field `name` prop along with `` can be used for integration with HTML forms. Only the raw value is passed to the form. + +If the formatted value is wanted (unrecommended) set the `name` attribute on ``. + +Hue + +ArrowArrow + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + Hue + +
    + + + +
    +
    +
    + + +
    +
    + ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + Hue + +
    + + + +
    +
    +
    + + +
    +
    + ); +} +``` + +### Triggers + +The color channel field supports optional increment/decrement triggers that are easily customizable. + +Brightness + +-+ + +``` +Copytsx + + Brightness +
    + + - + + + + + + +
    +
    +``` + +``` +Copytsx + + Brightness +
    + + - + + + + + + +
    +
    +``` + +## API Reference + +### ColorChannelField + +`ColorChannelField` is equivalent to the `Root` import from `@kobalte/core/color-channel-field`. + +| Prop | Description | +| --- | --- | +| value | `Color`
    The controlled value of the field. | +| defaultValue | `Color`
    The default value when initially rendered. Useful when you do not need to control the value. | +| colorSpace | `ColorSpace`
    The color space that the field operates in. The `channel` must be in this color space. | +| onChange | `(value: Color) => void`
    Event handler called when the value of the field changes. | +| minValue | `number`
    The smallest value allowed in the number field. | +| maxValue | `number`
    The largest value allowed in the number field. | +| step | `number`
    Increment/Decrement step when using the triggers or the arrows on keyboard in the field. | +| largeStep | `number`
    Increment/Decrement step when using the Page UP/Down keys in the field, defaults `10 * step`. | +| changeOnWheel | `boolean`
    Whether to increment/decrement on wheel scroll inside the field. | +| format | `boolean`
    Whether to format the input value. | +| name | `string`
    The name of the ColorChannelField.HiddenInput of the field, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). | +| validationState | `'valid' | 'invalid'`
    Whether the field should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must fill the field before the owning form can be submitted. | +| disabled | `boolean`
    Whether the field is disabled. | +| readOnly | `boolean`
    Whether the field items can be selected but not changed by the user. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the field is valid according to the validation rules. | +| data-invalid | Present when the field is invalid according to the validation rules. | +| data-required | Present when the user must fill the field before the owning form can be submitted. | +| data-disabled | Present when the field is disabled. | +| data-readonly | Present when the field is read only. | + +`ColorChannelField.Label`, `ColorChannelField.Input`, `ColorChannelField.HiddenInput`, `ColorChannelField.Description` and `ColorChannelField.ErrorMesssage` share the same data-attributes. + +### ColorChannelField.ErrorMessage + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `ColorChannelField` | `div` | +| `ColorChannelField.Label` | `label` | +| `ColorChannelField.Input` | `input` | +| `ColorChannelField.HiddenInput` | `input` | +| `ColorChannelField.IncrementTrigger` | `button` | +| `ColorChannelField.DecrementTrigger` | `button` | +| `ColorChannelField.Description` | `div` | +| `ColorChannelField.ErrorMessage` | `div` | + +Previous[←Color Area](https://kobalte.dev/docs/core/components/color-area)Next[Color Field→](https://kobalte.dev/docs/core/components/color-field) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-color-field.md b/.firecrawl/kobalte.dev-docs-core-components-color-field.md new file mode 100644 index 0000000..be5b7f3 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-color-field.md @@ -0,0 +1,336 @@ +# Color Field + +Allows users to enter and adjust a hex color value. + +## Import + +``` +Copyts +import { ColorField } from "@kobalte/core/color-field"; +// or +import { Root, Label, ... } from "@kobalte/core/color-field"; +``` + +``` +Copyts +import { ColorField } from "@kobalte/core/color-field"; +// or +import { Root, Label, ... } from "@kobalte/core/color-field"; +``` + +## Features + +- Support for parsing and formatting a hex color value. +- Validates keyboard entry as the user types so that only valid hex characters are accepted. +- Visual and ARIA labeling support. +- Required and invalid states exposed to assistive technology via ARIA. +- Support for description and error message help text linked to the input via ARIA. +- Syncs with form reset events. +- Can be controlled or uncontrolled. + +## Anatomy + +The color field consists of: + +- **ColorField**: The root container for the color field. +- **ColorField.Label**: The label that gives the user information on the color field. +- **ColorField.Input**: The native HTML input of the color field. +- **ColorField.Description**: The description that gives the user more information on the color field. +- **ColorField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the color field. + +``` +Copytsx + + + + + + +``` + +``` +Copytsx + + + + + + +``` + +## Example + +Favorite hex color + +index.tsxstyle.css + +``` +Copytsx +import { ColorField } from "@kobalte/core/color-field"; +import "./style.css"; + +function App() { + return ( + + Favorite hex color + + + ); +} +``` + +``` +Copytsx +import { ColorField } from "@kobalte/core/color-field"; +import "./style.css"; + +function App() { + return ( + + Favorite hex color + + + ); +} +``` + +## Usage + +### Default value + +An initial, uncontrolled value can be provided using the `defaultValue` prop. + +Favorite hex color + +``` +Copytsx + + Favorite hex color + + +``` + +``` +Copytsx + + Favorite hex color + + +``` + +### Controlled value + +The `value` prop can be used to make the value controlled. The `onChange` event is fired when the user type into the input and receive the new value. + +Favorite hex color + +Your favorite color is: #7f007f + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal("#7f007f"); + + return ( + <> + + Favorite hex color + + +

    Your favorite color is: {value()}

    + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal("#7f007f"); + + return ( + <> + + Favorite hex color + + +

    Your favorite color is: {value()}

    + + ); +} +``` + +### Description + +The `ColorField.Description` component can be used to associate additional help text with a color field. + +Favorite hex color + +Choose the color you like the most. + +``` +Copytsx + + Favorite hex color + + + Choose the color you like the most. + + +``` + +``` +Copytsx + + Favorite hex color + + + Choose the color you like the most. + + +``` + +### Error message + +The `ColorField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the color field as invalid for assistive technologies. + +By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries). + +Favorite hex color + +Hmm, I prefer black. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal("#7f007f"); + + return ( + + Favorite hex color + + Hmm, I prefer black. + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal("#7f007f"); + + return ( + + Favorite hex color + + Hmm, I prefer black. + + ); +} +``` + +### HTML forms + +The color field `name` prop can be used for integration with HTML forms. + +Favorite hex color + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + Favorite hex color + + +
    + ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + Favorite hex color + + +
    + ); +} +``` + +## API Reference + +### ColorField + +`ColorField` is equivalent to the `Root` import from `@kobalte/core/color-field`. + +| Prop | Description | +| --- | --- | +| value | `string`
    The controlled value of the color field to check. | +| defaultValue | `string`
    The default value when initially rendered. Useful when you do not need to control the value. | +| onChange | `(value: string) => void`
    Event handler called when the value of the color field changes. | +| name | `string`
    The name of the color field, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). | +| validationState | `'valid' | 'invalid'`
    Whether the color field should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must fill the color field before the owning form can be submitted. | +| disabled | `boolean`
    Whether the color field is disabled. | +| readOnly | `boolean`
    Whether the color field items can be selected but not changed by the user. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the color field is valid according to the validation rules. | +| data-invalid | Present when the color field is invalid according to the validation rules. | +| data-required | Present when the user must fill the color field before the owning form can be submitted. | +| data-disabled | Present when the color field is disabled. | +| data-readonly | Present when the color field is read only. | + +`ColorField.Label`, `ColorField.Input`, `ColorField.Description` and `ColorField.ErrorMesssage` share the same data-attributes. + +### ColorField.ErrorMessage + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `ColorField` | `div` | +| `ColorField.Label` | `label` | +| `ColorField.Input` | `input` | +| `ColorField.Description` | `div` | +| `ColorField.ErrorMessage` | `div` | + +Previous[←Color Channel Field](https://kobalte.dev/docs/core/components/color-channel-field)Next[Color Slider→](https://kobalte.dev/docs/core/components/color-slider) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-color-slider.md b/.firecrawl/kobalte.dev-docs-core-components-color-slider.md new file mode 100644 index 0000000..09ed94f --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-color-slider.md @@ -0,0 +1,409 @@ +# Color Slider + +Adjusts an individual channel of a color value. + +## Import + +``` +Copyts +import { ColorSlider } from "@kobalte/core/color-slider"; +// or +import { Root, Track, ... } from "@kobalte/core/color-slider"; +``` + +``` +Copyts +import { ColorSlider } from "@kobalte/core/color-slider"; +// or +import { Root, Track, ... } from "@kobalte/core/color-slider"; +``` + +## Features + +- Can be controlled or uncontrolled. +- Localized color descriptions for screen reader users. +- Support for adjusting a single channel of RGBA, HSLA and HSBA colors, in both horizontal and vertical orientations. +- Support click or touch on track to change value. +- Support right or left direction. +- Support for custom value label. + +## Anatomy + +The color slider consists of: + +- **ColorSlider:** The root container for the color slider. +- **ColorSlider.Track:** The component that visually represents the color slider track. +- **ColorSlider.Thumb:** The thumb that is used to visually indicate a value in the color slider. +- **ColorSlider.Input:** The native html input that is visually hidden in the color slider thumb. +- **ColorSlider.Label:** The label that gives the user information on the color slider. +- **ColorSlider.ValueLabel:** The accessible label text representing the current value in a human-readable format. + +``` +Copytsx + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + +``` + +## Example + +Blue + +197 + +index.tsxstyle.css + +``` +Copytsx +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + +
    + Blue + +
    + + + + + +
    + ); +} +``` + +``` +Copytsx +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + +
    + Blue + +
    + + + + + +
    + ); +} +``` + +## Usage + +The value provided to `defaultValue` or `value` should be `Color` object. You can obtain a Color object by using the `parseColor` function to parse a color from a string. The `channel` prop must also be provided to specify which color channel the slider should display. +This must be one of the channels included in the color value, for example, for RGB colors, the "red", "green", and "blue" channels are available. + +### Default value + +Hue + +0° + +index.tsxstyle.css + +``` +Copytsx +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + +
    + Hue + +
    + + + + + +
    + ); +} +``` + +``` +Copytsx +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + +
    + Hue + +
    + + + + + +
    + ); +} +``` + +### Controlled value + +Hue + +0° + +index.tsxstyle.css + +``` +Copytsx +import { createSignal } from "solid-js"; +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + const [value, setValue] = createSignal(parseColor('hsl(0, 100%, 50%)')); + return ( + +
    + Hue + +
    + + + + + +
    + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + const [value, setValue] = createSignal(parseColor('hsl(0, 100%, 50%)')); + return ( + +
    + Hue + +
    + + + + + +
    + ); +} +``` + +### Vertical Slider + +Red + +255 + +index.tsxstyle.css + +``` +Copytsx +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + +
    + Hue + +
    + + + + + +
    + ); +} +``` + +``` +Copytsx +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + +
    + Hue + +
    + + + + + +
    + ); +} +``` + +### Custom Value Label + +rgb(255, 0, 255) + +index.tsxstyle.css + +``` +Copytsx +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + `${param.toFormat("rgb")}`}> +
    + +
    + + + + + +
    + ); +} +``` + +``` +Copytsx +import { ColorSlider } from "@kobalte/core/color-slider"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + `${param.toFormat("rgb")}`}> +
    + +
    + + + + + +
    + ); +} +``` + +## API Reference + +### ColorSlider + +`ColorSlider` is equivalent to the `Root` import from `@kobalte/core/color-slider`. + +| Prop | Description | +| --- | --- | +| value | `Color`
    The controlled value of the slider. Must be used in conjunction with `onChange`. | +| defaultValue | `Color`
    The value of the slider when initially rendered. Use when you do not need to control the state of the slider. | +| channel | `ColorChannel`
    The color channel that the slider manipulates. | +| colorSpace | `ColorSpace`
    The color space that the slider operates in. The `channel` must be in this color space. | +| onChange | `(value: Color) => void`
    Event handler called when the value changes. | +| onChangeEnd | `(value: Color) => void`
    Event handler called when the value changes at the end of an interaction. | +| getValueLabel | `(param: Color) => string`
    A function to get the accessible label text representing the current value in a human-readable format. | +| orientation | `'horizontal' | 'vertical'`
    The orientation of the slider. | +| name | `string`
    The name of the slider, used when submitting an HTML form. | +| validationState | `'valid' | 'invalid'`
    Whether the slider should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must check a radio group item before the owning form can be submitted. | +| disabled | `boolean`
    Whether the radio group is disabled. | +| readOnly | `boolean`
    Whether the radio group items can be selected but not changed by the user. | +| translations | `ColorIntlTranslations`
    Localization strings. | + +| Data attribute | Description | +| --- | --- | +| data-orientation='horizontal' | Present when the slider has horizontal orientation. | +| data-orientation='vertical' | Present when the slider has vertical orientation. | +| data-valid | Present when the slider is valid according to the validation rules. | +| data-invalid | Present when the slider is invalid according to the validation rules. | +| data-required | Present when the user must slider an item before the owning form can be submitted. | +| data-disabled | Present when the slider is disabled. | +| data-readonly | Present when the slider is read only. | + +`ColorSlider.ValueLabel`, `ColorSlider.Input`, `ColorSlider.Thumb` and `ColorSlider.Track` share the same data-attributes. + +### ColorSlider.Thumb + +The current color is available on the thumb using the custom css property `--kb-color-current`. + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `ColorSlider` | `div` | +| `ColorSlider.Track` | `div` | +| `ColorSlider.Thumb` | `span` | +| `ColorSlider.Input` | `input` | +| `ColorSlider.ValueLabel` | `div` | +| `ColorSlider.Label` | `label` | +| `ColorSlider.Description` | `div` | +| `ColorSlider.ErrorMessage` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `PageUp` | Increases the value of the thumb by a larger step. | +| `PageDown` | Decreases the value of the thumb by a larger step. | +| `ArrowDown` | Decreases the value of the thumb by the step amount. | +| `ArrowUp` | Increases the value of the thumb by the step amount. | +| `ArrowRight` | Increments/decrements by the step value depending on `orientation`. | +| `ArrowLeft` | Increments/decrements by the step value depending on `orientation`. | +| `Home` | Sets the value of the thumb to the minimum value. | +| `End` | Sets the value of the thumb to the maximum value. | + +Previous[←Color Field](https://kobalte.dev/docs/core/components/color-field)Next[Color Swatch→](https://kobalte.dev/docs/core/components/color-swatch) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-color-swatch.md b/.firecrawl/kobalte.dev-docs-core-components-color-swatch.md new file mode 100644 index 0000000..2b501bb --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-color-swatch.md @@ -0,0 +1,153 @@ +# Color Swatch + +Displays a preview of a selected color. + +## Import + +``` +Copyts +import { ColorSwatch } from "@kobalte/core/color-swatch"; +// or +import { Root } from "@kobalte/core/color-swatch"; +``` + +``` +Copyts +import { ColorSwatch } from "@kobalte/core/color-swatch"; +// or +import { Root } from "@kobalte/core/color-swatch"; +``` + +## Features + +- Localized color descriptions for screen reader users. + +## Anatomy + +The color swatch consists of: + +- **ColorSwatch:** The root container for the color swatch. + +``` +Copytsx + +``` + +``` +Copytsx + +``` + +## Example + +index.tsxstyle.css + +``` +Copytsx +import { ColorSwatch } from "@kobalte/core/color-swatch"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + ); +} +``` + +``` +Copytsx +import { ColorSwatch } from "@kobalte/core/color-swatch"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + ); +} +``` + +## Usage + +ColorSwatch accepts a value via the `value` prop. The value should be `Color` object. You can obtain a Color object by using the `parseColor` function to parse a color from a string. + +### Value + +index.tsxstyle.css + +``` +Copytsx +import { ColorSwatch } from "@kobalte/core/color-swatch"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + ); +} +``` + +``` +Copytsx +import { ColorSwatch } from "@kobalte/core/color-swatch"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + ); +} +``` + +### Custom Color Name + +index.tsxstyle.css + +``` +Copytsx +import { ColorSwatch } from "@kobalte/core/color-swatch"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + ); +} +``` + +``` +Copytsx +import { ColorSwatch } from "@kobalte/core/color-swatch"; +import { parseColor } from "@kobalte/utils"; +import "./style.css"; + +function App() { + return ( + + ); +} +``` + +## API Reference + +### ColorSwatch + +`ColorSwatch` is equivalent to the `Root` import from `@kobalte/core/color-swatch`. + +| Prop | Description | +| --- | --- | +| value | `Color`
    The color value to display in the swatch. | +| colorName | `string`
    A localized accessible name for the color. By default, a description is generated from the color value, but this can be overridden if you have a more specific color name (e.g. Pantone colors). | +| translations | `ColorSwatchIntlTranslations`
    Localization strings. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `ColorSwatch` | `div` | + +Previous[←Color Slider](https://kobalte.dev/docs/core/components/color-slider)Next[Color Wheel→](https://kobalte.dev/docs/core/components/color-wheel) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-color-wheel.md b/.firecrawl/kobalte.dev-docs-core-components-color-wheel.md new file mode 100644 index 0000000..9b4d8bc --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-color-wheel.md @@ -0,0 +1,408 @@ +# Color Wheel + +Allows users to adjust the hue of an HSL or HSB color value on a circular track. + +## Import + +``` +Copyts +import { ColorWheel } from "@kobalte/core/color-wheel"; +// or +import { Root, Track, ... } from "@kobalte/core/color-wheel"; +``` + +``` +Copyts +import { ColorWheel } from "@kobalte/core/color-wheel"; +// or +import { Root, Track, ... } from "@kobalte/core/color-wheel"; +``` + +## Features + +- Support for adjusting the hue of an HSL or HSB color value. +- Support click or touch on track to change value. +- Support right or left direction. +- Support for custom value label. +- Localized color descriptions for screen reader users. +- Can be controlled or uncontrolled. + +## Anatomy + +The color wheel consists of: + +- **ColorWheel:** The root container for the color wheel. +- **ColorWheel.Track:** The component that visually represents the color wheel track. +- **ColorWheel.Thumb:** The thumb that is used to visually indicate a value in the color wheel. +- **ColorWheel.Input:** The native html input that is visually hidden in the color wheel thumb. +- **ColorWheel.Label:** The label that gives the user information on the color wheel. +- **ColorWheel.ValueLabel:** The accessible label text representing the current value in a human-readable format. + +``` +Copytsx + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + +``` + +## Example + +Label + +index.tsxstyle.css + +``` +Copytsx +import { ColorWheel } from "@kobalte/core/color-wheel"; +import "./style.css"; + +function App() { + return ( + + Label + + + + + + + ); +} +``` + +``` +Copytsx +import { ColorWheel } from "@kobalte/core/color-wheel"; +import "./style.css"; + +function App() { + return ( + + Label + + + + + + + ); +} +``` + +## Usage + +### Default value + +By default, `ColorWheel` is uncontrolled with a default value of red (hue = 0). You can change the default value using the `defaultValue` prop. + +Label + +``` +Copytsx +import { ColorWheel } from "@kobalte/core/color-wheel"; +import { parseColor } from "@kobalte/core"; + +function App() { + return ( + + Label + + + + + + + ); +} +``` + +``` +Copytsx +import { ColorWheel } from "@kobalte/core/color-wheel"; +import { parseColor } from "@kobalte/core"; + +function App() { + return ( + + Label + + + + + + + ); +} +``` + +### Controlled value + +A `ColorWheel` can be made controlled using the `value` prop. The `onChange` event is fired when the user drags the thumb and receive the new value. + +Label + +Current color value: hsl(0 100% 50%) + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledValueExample() { + const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)")); + + return ( + <> + + Label + + + + + + +

    Current color value: {value().toString("hsl")}

    + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledValueExample() { + const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)")); + + return ( + <> + + Label + + + + + + +

    Current color value: {value().toString("hsl")}

    + + ); +} +``` + +### Thickness + +The `thickness` prop controls the width of the `ColorWheel`'s circular track. This prop is required. + +Label + +``` +Copytsx + + Label + + + + + + +``` + +``` +Copytsx + + Label + + + + + + +``` + +### Custom Value Label + +Label + +hsla(0 100% 50% / 1) + +``` +Copytsx + + color + .toFormat("hsl") + .withChannelValue("saturation", 100) + .withChannelValue("lightness", 50) + .withChannelValue("alpha", 1) + .toString() + } +> + Label + + + + + +
    + +
    +
    +``` + +``` +Copytsx + + color + .toFormat("hsl") + .withChannelValue("saturation", 100) + .withChannelValue("lightness", 50) + .withChannelValue("alpha", 1) + .toString() + } +> + Label + + + + + +
    + +
    +
    +``` + +### HTML forms + +`ColorWheel` supports the `name` prop for integration with HTML forms. + +Label + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + + + + + + +
    + ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + + + + + + +
    + ); +} +``` + +## API Reference + +### ColorWheel + +`ColorWheel` is equivalent to the `Root` import from `@kobalte/core/color-wheel`. + +| Prop | Description | +| --- | --- | +| value | `Color`
    The controlled value of the color wheel. Must be used in conjunction with `onChange`. | +| defaultValue | `Color`
    The value of the color wheel when initially rendered. Use when you do not need to control the state of the color wheel. | +| thickness | `number`
    The thickness of the track `0-100`. | +| onChange | `(value: Color) => void`
    Event handler called when the value changes. | +| onChangeEnd | `(value: Color) => void`
    Event handler called when the value changes at the end of an interaction. | +| getValueLabel | `(param: Color) => string`
    A function to get the accessible label text representing the current value in a human-readable format. | +| name | `string`
    The name of the color wheel, used when submitting an HTML form. | +| validationState | `'valid' | 'invalid'`
    Whether the color wheel should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must check a radio group item before the owning form can be submitted. | +| disabled | `boolean`
    Whether the color wheel is disabled. | +| readOnly | `boolean`
    Whether the color wheel items can be selected but not changed by the user. | +| translations | `ColorIntlTranslations`
    Localization strings. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the color wheel is valid according to the validation rules. | +| data-invalid | Present when the color wheel is invalid according to the validation rules. | +| data-required | Present when the color wheel is required. | +| data-disabled | Present when the color wheel is disabled. | +| data-readonly | Present when the color wheel is read only. | + +`ColorWheel.ValueLabel`, `ColorWheel.Input`, `ColorWheel.Thumb` and `ColorWheel.Track` share the same data-attributes. + +### ColorWheel.Thumb + +The current color is available on the thumb using the custom css property `--kb-color-current`. + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `ColorWheel` | `div` | +| `ColorWheel.Track` | `div` | +| `ColorWheel.Thumb` | `span` | +| `ColorWheel.Input` | `input` | +| `ColorWheel.ValueLabel` | `div` | +| `ColorWheel.Label` | `label` | +| `ColorWheel.Description` | `div` | +| `ColorWheel.ErrorMessage` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `PageUp` | Increments the value of the thumb by a larger step. | +| `PageDown` | Decrements the value of the thumb by a larger step. | +| `ArrowDown` | Decrements the value of the thumb by the step amount. | +| `ArrowUp` | Increments the value of the thumb by the step amount. | +| `ArrowRight` | Increments the value of the thumb by the step value. | +| `ArrowLeft` | Decrements the value of the thumb by the step value. | +| `Home` | Sets the value of the thumb to the minimum value. | +| `End` | Sets the value of the thumb to the maximum value. | + +Previous[←Color Swatch](https://kobalte.dev/docs/core/components/color-swatch)Next[Combobox→](https://kobalte.dev/docs/core/components/combobox) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-context-menu.md b/.firecrawl/kobalte.dev-docs-core-components-context-menu.md new file mode 100644 index 0000000..13ddb82 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-context-menu.md @@ -0,0 +1,669 @@ +# Context Menu + +Displays a menu located at the pointer, triggered by a right-click or a long-press. + +## Import + +``` +Copyts +import { ContextMenu } from "@kobalte/core/context-menu"; +// or +import { Root, Trigger, ... } from "@kobalte/core/context-menu"; +// or (deprecated) +import { ContextMenu } from "@kobalte/core"; +``` + +``` +Copyts +import { ContextMenu } from "@kobalte/core/context-menu"; +// or +import { Root, Trigger, ... } from "@kobalte/core/context-menu"; +// or (deprecated) +import { ContextMenu } from "@kobalte/core"; +``` + +## Features + +- Follows the [WAI ARIA Menu](https://www.w3.org/WAI/ARIA/apg/patterns/menu/) design pattern. +- Triggers with a long-press on touch devices. +- Supports modal and non-modal modes. +- Supports submenus. +- Supports items, labels, groups of items. +- Supports checkable items (single or multiple) with optional indeterminate state. +- Support disabled items. +- Complex item labeling support for accessibility. +- Keyboard opening and navigation support. +- Automatic scrolling support during keyboard navigation. +- Typeahead to allow focusing items by typing text. +- Optionally render a pointing arrow. +- Focus is fully managed. + +## Anatomy + +The context menu consists of: + +- **ContextMenu:** The root container for a context menu. +- **ContextMenu.Trigger:** The button that toggles the menu. +- **ContextMenu.Icon:** A small icon that can be displayed inside the menu trigger as a visual affordance for the fact it can be open. +- **ContextMenu.Portal:** Portals its children into the `body` when the menu is open. +- **ContextMenu.Content:** Contains the content to be rendered when the menu is open. +- **ContextMenu.Arrow:** An optional arrow element to render alongside the menu content. +- **ContextMenu.Separator:** Used to visually separate items in the menu. +- **ContextMenu.Group:** Used to group multiple items. Use in conjunction with `ContextMenu.GroupLabel` to ensure good accessibility via automatic labelling. +- **ContextMenu.GroupLabel:** Used to render the label of a group. It won't be focusable using arrow keys. +- **ContextMenu.Sub:** Contains all the parts of a submenu. +- **ContextMenu.SubTrigger:** An item that opens a submenu. Must be rendered inside `ContextMenu.Sub`. +- **ContextMenu.SubContent:** The component that pops out when a submenu is open. Must be rendered inside `ContextMenu.Sub`. + +The menu item consists of: + +- **ContextMenu.Item:** An item of the select. +- **ContextMenu.ItemLabel:** An accessible label to be announced for the item. +- **ContextMenu.ItemDescription:** An optional accessible description to be announced for the item. +- **ContextMenu.ItemIndicator:** The visual indicator rendered when the item is checked. + +The checkable menu item consists of: + +- **ContextMenu.RadioGroup:** Used to group multiple `ContextMenu.RadioItem`s and manage the selection. +- **ContextMenu.RadioItem:** An item that can be controlled and rendered like a radio. +- **ContextMenu.CheckboxItem:** An item that can be controlled and rendered like a checkbox. + +``` +Copytsx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## Example + +Right click here. + +index.tsxstyle.css + +``` +Copytsx +import { ContextMenu } from "@kobalte/core/context-menu"; +import { createSignal } from "solid-js"; +import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + const [showGitLog, setShowGitLog] = createSignal(true); + const [showHistory, setShowHistory] = createSignal(false); + const [branch, setBranch] = createSignal("main"); + + return ( + + + Right click here. + + + + + Commit
    ⌘+K
    +
    + + Push
    ⇧+⌘+K
    +
    + + Update Project
    ⌘+T
    +
    + + + GitHub +
    + +
    +
    + + + + Create Pull Request… + + + View Pull Requests + + + Sync Fork + + + + Open on GitHub + + + +
    + + + + + + + + Show Git Log + + + + + + Show History + + + + + + + Branches + + + + + + + main + + + + + + develop + + + +
    +
    +
    + ); +} +``` + +``` +Copytsx +import { ContextMenu } from "@kobalte/core/context-menu"; +import { createSignal } from "solid-js"; +import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + const [showGitLog, setShowGitLog] = createSignal(true); + const [showHistory, setShowHistory] = createSignal(false); + const [branch, setBranch] = createSignal("main"); + + return ( + + + Right click here. + + + + + Commit
    ⌘+K
    +
    + + Push
    ⇧+⌘+K
    +
    + + Update Project
    ⌘+T
    +
    + + + GitHub +
    + +
    +
    + + + + Create Pull Request… + + + View Pull Requests + + + Sync Fork + + + + Open on GitHub + + + +
    + + + + + + + + Show Git Log + + + + + + Show History + + + + + + + Branches + + + + + + + main + + + + + + develop + + + +
    +
    +
    + ); +} +``` + +## Usage + +### Origin-aware animations + +We expose a CSS custom property `--kb-popper-content-transform-origin` which can be used to animate the content from its computed origin. + +``` +Copycss +/* style.css */ +.context-menu__content, +.context-menu__sub-content { + transform-origin: var(--kb-menu-content-transform-origin); + animation: contentHide 250ms ease-in forwards; +} + +.context-menu__content[data-expanded], +.context-menu__sub-content[data-expanded] { + animation: contentShow 250ms ease-out; +} + +@keyframes contentShow { + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes contentHide { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } +} +``` + +``` +Copycss +/* style.css */ +.context-menu__content, +.context-menu__sub-content { + transform-origin: var(--kb-menu-content-transform-origin); + animation: contentHide 250ms ease-in forwards; +} + +.context-menu__content[data-expanded], +.context-menu__sub-content[data-expanded] { + animation: contentShow 250ms ease-out; +} + +@keyframes contentShow { + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes contentHide { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } +} +``` + +## API Reference + +### ContextMenu + +`ContextMenu` is equivalent to the `Root` import from `@kobalte/core/context-menu` (and deprecated `ContextMenu.Root`). + +| Prop | Description | +| --- | --- | +| onOpenChange | `(open: boolean) => void`
    Event handler called when the open state of the menu changes. | +| id | `string`
    A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. | +| modal | `boolean`
    Whether the menu should be the only visible content for screen readers, when set to `true`:
    \- interaction with outside elements will be disabled.
    \- scroll will be locked.
    \- focus will be locked inside the menu content.
    \- elements outside the menu content will not be visible for screen readers. | +| preventScroll | `boolean`
    Whether the scroll should be locked even if the menu is not modal. | +| forceMount | `boolean`
    Used to force mounting the menu (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +`ContextMenu` also accepts the following props to customize the placement of the `ContextMenu.Content`. + +| Prop | Description | +| --- | --- | +| placement | `Placement`
    The placement of the menu content. | +| gutter | `number`
    The distance between the menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. | +| shift | `number`
    The skidding of the menu content along the trigger element. | +| flip | `boolean | string`
    Controls the behavior of the menu content when it overflows the viewport:
    \- If a `boolean`, specifies whether the menu content should flip to the opposite side when it overflows.
    \- If a `string`, indicates the preferred fallback placements when it overflows.
    The placements must be spaced-delimited, e.g. "top left". | +| slide | `boolean`
    Whether the menu content should slide when it overflows. | +| overlap | `boolean`
    Whether the menu content can overlap the trigger element when it overflows. | +| sameWidth | `boolean`
    Whether the menu content should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. | +| fitViewport | `boolean`
    Whether the menu content should fit the viewport. If this is set to true, the menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. | +| hideWhenDetached | `boolean`
    Whether to hide the menu content when the trigger element becomes occluded. | +| detachedPadding | `number`
    The minimum padding in order to consider the trigger element occluded. | +| arrowPadding | `number`
    The minimum padding between the arrow and the menu content corner. | +| overflowPadding | `number`
    The minimum padding between the menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. | + +### ContextMenu.Trigger + +| Prop | Description | +| --- | --- | +| disabled | `boolean`
    Whether the context menu trigger is disabled or not. | + +| Data attribute | Description | +| --- | --- | +| data-expanded | Present when the menu is open. | +| data-closed | Present when the menu is close. | +| data-disabled | Present when the trigger is disabled. | + +`ContextMenu.Icon`, `ContextMenu.Content`, `ContextMenu.SubTrigger` and `ContextMenu.SubContent` share the same `data-expanded` attribute. + +### ContextMenu.Content + +The popper positioner will copy the same `z-index` as the `ContextMenu.Content`. + +| Prop | Description | +| --- | --- | +| onOpenAutoFocus | `(event: Event) => void`
    Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. | +| onCloseAutoFocus | `(event: Event) => void`
    Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. | +| onEscapeKeyDown | `(event: KeyboardEvent) => void`
    Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | +| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`
    Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onFocusOutside | `(event: FocusOutsideEvent) => void`
    Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onInteractOutside | `(event: InteractOutsideEvent) => void`
    Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | + +### ContextMenu.Arrow + +| Prop | Description | +| --- | --- | +| size | `number`
    The size of the arrow. | + +### ContextMenu.Item + +| Prop | Description | +| --- | --- | +| textValue | `string`
    Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `ContextMenu.ItemLabel` part if provided, or fallback to the .textContent of the `ContextMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | +| disabled | `boolean`
    Whether the item is disabled or not. | +| closeOnSelect | `boolean`
    Whether the menu should close when the item is activated. | +| onSelect | `() => void`
    Event handler called when the user selects an item (via mouse or keyboard). | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the item is disabled. | +| data-highlighted | Present when the item is highlighted. | + +`ContextMenu.ItemLabel`, `ContextMenu.ItemDescription` and `ContextMenu.ItemIndicator` shares the same data-attributes. + +### ContextMenu.ItemIndicator + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +### ContextMenu.RadioGroup + +| Prop | Description | +| --- | --- | +| value | `string`
    The controlled value of the menu radio item to check. | +| defaultValue | `string`
    The value of the menu radio item that should be checked when initially rendered. Useful when you do not need to control the state of the radio group. | +| onChange | `(value: string) => void`
    Event handler called when the value changes. | +| disabled | `boolean`
    Whether the radio group is disabled or not. | + +### ContextMenu.RadioItem + +| Prop | Description | +| --- | --- | +| value | `string`
    The value of the menu item radio. | +| textValue | `string`
    Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `ContextMenu.ItemLabel` part if provided, or fallback to the .textContent of the `ContextMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | +| disabled | `boolean`
    Whether the item is disabled or not. | +| closeOnSelect | `boolean`
    Whether the menu should close when the item is checked. | +| onSelect | `() => void`
    Event handler called when the user selects an item (via mouse or keyboard). | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the item is disabled. | +| data-checked | Present when the item is checked. | +| data-highlighted | Present when the item is highlighted. | + +### ContextMenu.CheckboxItem + +| Prop | Description | +| --- | --- | +| checked | `boolean`
    The controlled checked state of the item. | +| defaultChecked | `boolean`
    The default checked state when initially rendered. Useful when you do not need to control the checked state. | +| onChange | `(checked: boolean) => void`
    Event handler called when the checked state of the item changes. | +| textValue | `string`
    Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `ContextMenu.ItemLabel` part if provided, or fallback to the .textContent of the `ContextMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | +| indeterminate | `boolean`
    Whether the item is in an indeterminate state. | +| disabled | `boolean`
    Whether the item is disabled or not. | +| closeOnSelect | `boolean`
    Whether the menu should close when the item is checked/unchecked. | +| onSelect | `() => void`
    Event handler called when the user selects an item (via mouse or keyboard). | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the item is disabled. | +| data-indeterminate | Present when the item is in an indeterminate state. | +| data-checked | Present when the item is checked. | +| data-highlighted | Present when the item is highlighted. | + +### ContextMenu.Sub + +| Prop | Description | +| --- | --- | +| open | `boolean`
    The controlled open state of the sub menu. | +| defaultOpen | `boolean`
    The default open state when initially rendered. Useful when you do not need to control the open state. | +| onOpenChange | `(open: boolean) => void`
    Event handler called when the open state of the sub menu changes. | + +`ContextMenu.Sub` also accepts the following props to customize the placement of the `ContextMenu.SubContent`. + +| Prop | Description | +| --- | --- | +| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`
    Function that returns the trigger element's DOMRect. | +| gutter | `number`
    The distance between the sub menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. | +| shift | `number`
    The skidding of the sub menu content along the trigger element. | +| slide | `boolean`
    Whether the sub menu content should slide when it overflows. | +| overlap | `boolean`
    Whether the sub menu content can overlap the trigger element when it overflows. | +| fitViewport | `boolean`
    Whether the sub menu content should fit the viewport. If this is set to true, the sub menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. | +| hideWhenDetached | `boolean`
    Whether to hide the sub menu content when the trigger element becomes occluded. | +| detachedPadding | `number`
    The minimum padding in order to consider the trigger element occluded. | +| arrowPadding | `number`
    The minimum padding between the arrow and the sub menu content corner. | +| overflowPadding | `number`
    The minimum padding between the sub menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. | + +### ContextMenu.SubTrigger + +| Prop | Description | +| --- | --- | +| textValue | `string`
    Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `ContextMenu.SubTrigger`. Use this when the content is complex, or you have non-textual content inside. | +| disabled | `boolean`
    Whether the sub menu trigger is disabled or not. | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the item is disabled. | +| data-highlighted | Present when the item is highlighted. | + +### ContextMenu.SubContent + +| Prop | Description | +| --- | --- | +| onEscapeKeyDown | `(event: KeyboardEvent) => void`
    Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | +| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`
    Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onFocusOutside | `(event: FocusOutsideEvent) => void`
    Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onInteractOutside | `(event: InteractOutsideEvent) => void`
    Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `ContextMenu` | none | +| `ContextMenu.Trigger` | `div` | +| `ContextMenu.Icon` | `div` | +| `ContextMenu.Portal` | `Portal` | +| `ContextMenu.Content` | `div` | +| `ContextMenu.Arrow` | `div` | +| `ContextMenu.Separator` | `hr` | +| `ContextMenu.Group` | `div` | +| `ContextMenu.GroupLabel` | `span` | +| `ContextMenu.Sub` | none | +| `ContextMenu.SubTrigger` | `div` | +| `ContextMenu.SubContent` | `div` | +| `ContextMenu.Item` | `div` | +| `ContextMenu.ItemLabel` | `div` | +| `ContextMenu.ItemDescription` | `div` | +| `ContextMenu.ItemIndicator` | `div` | +| `ContextMenu.RadioGroup` | `div` | +| `ContextMenu.RadioItem` | `div` | +| `ContextMenu.CheckboxItem` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Space` | When focus is on an item, activates the item. | +| `Enter` | When focus is on an item, activates the item. | +| `ArrowDown` | When focus is on an item, moves focus to the next item. | +| `ArrowUp` | When focus is on an item, moves focus to the previous item. | +| `ArrowRight` / `ArrowLeft` | When focus is on a sub menu trigger, opens or closes the submenu depending on reading direction. | +| `Home` | When focus is on an item, moves focus to first item. | +| `End` | When focus is on an item, moves focus to last item. | +| `Esc` | Closes the context menu. | + +Previous[←Combobox](https://kobalte.dev/docs/core/components/combobox)Next[Dialog→](https://kobalte.dev/docs/core/components/dialog) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-dropdown-menu.md b/.firecrawl/kobalte.dev-docs-core-components-dropdown-menu.md new file mode 100644 index 0000000..fe2d7bf --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-dropdown-menu.md @@ -0,0 +1,735 @@ +# Dropdown Menu + +Displays a menu to the user —such as a set of actions or functions— triggered by a button. + +## Import + +``` +Copyts +import { DropdownMenu } from "@kobalte/core/dropdown-menu"; +// or +import { Root, Trigger, ... } from "@kobalte/core/dropdown-menu"; +// or (deprecated) +import { DropdownMenu } from "@kobalte/core"; +``` + +``` +Copyts +import { DropdownMenu } from "@kobalte/core/dropdown-menu"; +// or +import { Root, Trigger, ... } from "@kobalte/core/dropdown-menu"; +// or (deprecated) +import { DropdownMenu } from "@kobalte/core"; +``` + +## Features + +- Exposed to assistive technology as a button with a menu using the [WAI ARIA Menu Button](https://www.w3.org/WAI/ARIA/apg/patterns/menubutton/) design pattern. +- Supports modal and non-modal modes. +- Supports submenus. +- Supports items, labels, groups of items. +- Supports checkable items (single or multiple) with optional indeterminate state. +- Support disabled items. +- Complex item labeling support for accessibility. +- Keyboard opening and navigation support. +- Automatic scrolling support during keyboard navigation. +- Typeahead to allow focusing items by typing text. +- Optionally render a pointing arrow. +- Focus is fully managed. +- Can be controlled or uncontrolled. + +## Anatomy + +The dropdown menu consists of: + +- **DropdownMenu:** The root container for a dropdown menu. +- **DropdownMenu.Trigger:** The button that toggles the menu. +- **DropdownMenu.Icon:** A small icon often displayed next to the menu trigger as a visual affordance for the fact it can be open. +- **DropdownMenu.Portal:** Portals its children into the `body` when the menu is open. +- **DropdownMenu.Content:** Contains the content to be rendered when the menu is open. +- **DropdownMenu.Arrow:** An optional arrow element to render alongside the menu content. +- **DropdownMenu.Separator:** Used to visually separate items in the menu. +- **DropdownMenu.Group:** Used to group multiple items. Use in conjunction with `DropdownMenu.GroupLabel` to ensure good accessibility via automatic labelling. +- **DropdownMenu.GroupLabel:** Used to render the label of a group. It won't be focusable using arrow keys. +- **DropdownMenu.Sub:** Contains all the parts of a submenu. +- **DropdownMenu.SubTrigger:** An item that opens a submenu. Must be rendered inside `DropdownMenu.Sub`. +- **DropdownMenu.SubContent:** The component that pops out when a submenu is open. Must be rendered inside `DropdownMenu.Sub`. + +The menu item consists of: + +- **DropdownMenu.Item:** An item of the select. +- **DropdownMenu.ItemLabel:** An accessible label to be announced for the item. +- **DropdownMenu.ItemDescription:** An optional accessible description to be announced for the item. +- **DropdownMenu.ItemIndicator:** The visual indicator rendered when the item is checked. + +The checkable menu item consists of: + +- **DropdownMenu.RadioGroup:** Used to group multiple `DropdownMenu.RadioItem`s and manage the selection. +- **DropdownMenu.RadioItem:** An item that can be controlled and rendered like a radio. +- **DropdownMenu.CheckboxItem:** An item that can be controlled and rendered like a checkbox. + +``` +Copytsx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## Example + +Git SettingsChevron + +index.tsxstyle.css + +``` +Copytsx +import { DropdownMenu } from "@kobalte/core/dropdown-menu"; +import { createSignal } from "solid-js"; +import { CheckIcon, ChevronDownIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + const [showGitLog, setShowGitLog] = createSignal(true); + const [showHistory, setShowHistory] = createSignal(false); + const [branch, setBranch] = createSignal("main"); + + return ( + + + Git Settings + + + + + + + + Commit + + + Push + + + Update Project + + + + GitHub + + + + + + Create Pull Request… + + + View Pull Requests + + + Sync Fork + + + + Open on GitHub + + + + + + + + + + + + Show Git Log + + + + + + Show History + + + + + + + Branches + + + + + + + main + + + + + + develop + + + + + + + + + ); +} +``` + +``` +Copytsx +import { DropdownMenu } from "@kobalte/core/dropdown-menu"; +import { createSignal } from "solid-js"; +import { CheckIcon, ChevronDownIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library"; +import "./style.css"; + +function App() { + const [showGitLog, setShowGitLog] = createSignal(true); + const [showHistory, setShowHistory] = createSignal(false); + const [branch, setBranch] = createSignal("main"); + + return ( + + + Git Settings + + + + + + + + Commit + + + Push + + + Update Project + + + + GitHub + + + + + + Create Pull Request… + + + View Pull Requests + + + Sync Fork + + + + Open on GitHub + + + + + + + + + + + + Show Git Log + + + + + + Show History + + + + + + + Branches + + + + + + + main + + + + + + develop + + + + + + + + + ); +} +``` + +## Usage + +### Default open + +An initial, uncontrolled open value can be provided using the `defaultOpen` prop. + +``` +Copytsx +... +``` + +``` +Copytsx +... +``` + +### Controlled open + +The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, an item or interact outside, and receives the new value. + +Open + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [open, setOpen] = createSignal(false); + + return ( + + {open() ? "Close" : "Open"} + + ... + + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [open, setOpen] = createSignal(false); + + return ( + + {open() ? "Close" : "Open"} + + ... + + + ); +} +``` + +### Origin-aware animations + +We expose a CSS custom property `--kb-menu-content-transform-origin` which can be used to animate the content from its computed origin. + +``` +Copycss +/* style.css */ +.dropdown-menu__content, +.dropdown-menu__sub-content { + transform-origin: var(--kb-menu-content-transform-origin); + animation: contentHide 250ms ease-in forwards; +} + +.dropdown-menu__content[data-expanded], +.dropdown-menu__sub-content[data-expanded] { + animation: contentShow 250ms ease-out; +} + +@keyframes contentShow { + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes contentHide { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } +} +``` + +``` +Copycss +/* style.css */ +.dropdown-menu__content, +.dropdown-menu__sub-content { + transform-origin: var(--kb-menu-content-transform-origin); + animation: contentHide 250ms ease-in forwards; +} + +.dropdown-menu__content[data-expanded], +.dropdown-menu__sub-content[data-expanded] { + animation: contentShow 250ms ease-out; +} + +@keyframes contentShow { + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes contentHide { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } +} +``` + +## API Reference + +### DropdownMenu + +`DropdownMenu` is equivalent to the `Root` import from `@kobalte/core/dropdown-menu` (and deprecated `DropdownMenu.Root`). + +| Prop | Description | +| --- | --- | +| open | `boolean`
    The controlled open state of the menu. | +| defaultOpen | `boolean`
    The default open state when initially rendered. Useful when you do not need to control the open state. | +| onOpenChange | `(open: boolean) => void`
    Event handler called when the open state of the menu changes. | +| id | `string`
    A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. | +| modal | `boolean`
    Whether the menu should be the only visible content for screen readers, when set to `true`:
    \- interaction with outside elements will be disabled.
    \- scroll will be locked.
    \- focus will be locked inside the menu content.
    \- elements outside the menu content will not be visible for screen readers. | +| preventScroll | `boolean`
    Whether the scroll should be locked even if the menu is not modal. | +| forceMount | `boolean`
    Used to force mounting the menu (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +`DropdownMenu` also accepts the following props to customize the placement of the `DropdownMenu.Content`. + +| Prop | Description | +| --- | --- | +| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`
    Function that returns the trigger element's DOMRect. | +| placement | `Placement`
    The placement of the menu content. | +| gutter | `number`
    The distance between the menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. | +| shift | `number`
    The skidding of the menu content along the trigger element. | +| flip | `boolean | string`
    Controls the behavior of the menu content when it overflows the viewport:
    \- If a `boolean`, specifies whether the menu content should flip to the opposite side when it overflows.
    \- If a `string`, indicates the preferred fallback placements when it overflows.
    The placements must be spaced-delimited, e.g. "top left". | +| slide | `boolean`
    Whether the menu content should slide when it overflows. | +| overlap | `boolean`
    Whether the menu content can overlap the trigger element when it overflows. | +| sameWidth | `boolean`
    Whether the menu content should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. | +| fitViewport | `boolean`
    Whether the menu content should fit the viewport. If this is set to true, the menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-content-available-width` and `--kb-popper-content-available-height`. | +| hideWhenDetached | `boolean`
    Whether to hide the menu content when the trigger element becomes occluded. | +| detachedPadding | `number`
    The minimum padding in order to consider the trigger element occluded. | +| arrowPadding | `number`
    The minimum padding between the arrow and the menu content corner. | +| overflowPadding | `number`
    The minimum padding between the menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. | + +### DropdownMenu.Trigger + +`DropdownMenu.Trigger` consists of [Button](https://kobalte.dev/docs/core/components/button). + +| Data attribute | Description | +| --- | --- | +| data-expanded | Present when the menu is open. | +| data-closed | Present when the menu is close. | + +`DropdownMenu.Icon`, `DropdownMenu.Content`, `DropdownMenu.SubTrigger` and `DropdownMenu.SubContent` share the same data-attributes. + +### DropdownMenu.Content + +The popper positioner will copy the same `z-index` as the `DropdownMenu.Content`. + +| Prop | Description | +| --- | --- | +| onOpenAutoFocus | `(event: Event) => void`
    Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. | +| onCloseAutoFocus | `(event: Event) => void`
    Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. | +| onEscapeKeyDown | `(event: KeyboardEvent) => void`
    Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | +| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`
    Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onFocusOutside | `(event: FocusOutsideEvent) => void`
    Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onInteractOutside | `(event: InteractOutsideEvent) => void`
    Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | + +### DropdownMenu.Arrow + +| Prop | Description | +| --- | --- | +| size | `number`
    The size of the arrow. | + +### DropdownMenu.Item + +| Prop | Description | +| --- | --- | +| textValue | `string`
    Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | +| disabled | `boolean`
    Whether the item is disabled or not. | +| closeOnSelect | `boolean`
    Whether the menu should close when the item is activated. | +| onSelect | `() => void`
    Event handler called when the user selects an item (via mouse or keyboard). | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the item is disabled. | +| data-highlighted | Present when the item is highlighted. | + +`DropdownMenu.ItemLabel`, `DropdownMenu.ItemDescription` and `DropdownMenu.ItemIndicator` shares the same data-attributes. + +### DropdownMenu.ItemIndicator + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +### DropdownMenu.RadioGroup + +| Prop | Description | +| --- | --- | +| value | `string`
    The controlled value of the menu radio item to check. | +| defaultValue | `string`
    The value of the menu radio item that should be checked when initially rendered. Useful when you do not need to control the state of the radio group. | +| onChange | `(value: string) => void`
    Event handler called when the value changes. | +| disabled | `boolean`
    Whether the radio group is disabled or not. | + +### DropdownMenu.RadioItem + +| Prop | Description | +| --- | --- | +| value | `string`
    The value of the menu item radio. | +| textValue | `string`
    Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | +| disabled | `boolean`
    Whether the item is disabled or not. | +| closeOnSelect | `boolean`
    Whether the menu should close when the item is checked. | +| onSelect | `() => void`
    Event handler called when the user selects an item (via mouse or keyboard). | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the item is disabled. | +| data-checked | Present when the item is checked. | +| data-highlighted | Present when the item is highlighted. | + +### DropdownMenu.CheckboxItem + +| Prop | Description | +| --- | --- | +| checked | `boolean`
    The controlled checked state of the item. | +| defaultChecked | `boolean`
    The default checked state when initially rendered. Useful when you do not need to control the checked state. | +| onChange | `(checked: boolean) => void`
    Event handler called when the checked state of the item changes. | +| textValue | `string`
    Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | +| indeterminate | `boolean`
    Whether the item is in an indeterminate state. | +| disabled | `boolean`
    Whether the item is disabled or not. | +| closeOnSelect | `boolean`
    Whether the menu should close when the item is checked/unchecked. | +| onSelect | `() => void`
    Event handler called when the user selects an item (via mouse or keyboard). | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the item is disabled. | +| data-indeterminate | Present when the item is in an indeterminate state. | +| data-checked | Present when the item is checked. | +| data-highlighted | Present when the item is highlighted. | + +### DropdownMenu.Sub + +| Prop | Description | +| --- | --- | +| open | `boolean`
    The controlled open state of the sub menu. | +| defaultOpen | `boolean`
    The default open state when initially rendered. Useful when you do not need to control the open state. | +| onOpenChange | `(open: boolean) => void`
    Event handler called when the open state of the sub menu changes. | + +`DropdownMenu.Sub` also accepts the following props to customize the placement of the `DropdownMenu.SubContent`. + +| Prop | Description | +| --- | --- | +| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`
    Function that returns the trigger element's DOMRect. | +| gutter | `number`
    The distance between the sub menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. | +| shift | `number`
    The skidding of the sub menu content along the trigger element. | +| slide | `boolean`
    Whether the sub menu content should slide when it overflows. | +| overlap | `boolean`
    Whether the sub menu content can overlap the trigger element when it overflows. | +| fitViewport | `boolean`
    Whether the sub menu content should fit the viewport. If this is set to true, the sub menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-content-available-width` and `--kb-popper-content-available-height`. | +| hideWhenDetached | `boolean`
    Whether to hide the sub menu content when the trigger element becomes occluded. | +| detachedPadding | `number`
    The minimum padding in order to consider the trigger element occluded. | +| arrowPadding | `number`
    The minimum padding between the arrow and the sub menu content corner. | +| overflowPadding | `number`
    The minimum padding between the sub menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. | + +### DropdownMenu.SubTrigger + +| Prop | Description | +| --- | --- | +| textValue | `string`
    Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.SubTrigger`. Use this when the content is complex, or you have non-textual content inside. | +| disabled | `boolean`
    Whether the sub menu trigger is disabled or not. | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the item is disabled. | +| data-highlighted | Present when the item is highlighted. | + +### DropdownMenu.SubContent + +| Prop | Description | +| --- | --- | +| onEscapeKeyDown | `(event: KeyboardEvent) => void`
    Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | +| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`
    Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onFocusOutside | `(event: FocusOutsideEvent) => void`
    Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | +| onInteractOutside | `(event: InteractOutsideEvent) => void`
    Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `DropdownMenu` | none | +| `DropdownMenu.Trigger` | `button` | +| `DropdownMenu.Icon` | `span` | +| `DropdownMenu.Portal` | `Portal` | +| `DropdownMenu.Content` | `div` | +| `DropdownMenu.Arrow` | `div` | +| `DropdownMenu.Separator` | `hr` | +| `DropdownMenu.Group` | `div` | +| `DropdownMenu.GroupLabel` | `span` | +| `DropdownMenu.Sub` | none | +| `DropdownMenu.SubTrigger` | `div` | +| `DropdownMenu.SubContent` | `div` | +| `DropdownMenu.Item` | `div` | +| `DropdownMenu.ItemLabel` | `div` | +| `DropdownMenu.ItemDescription` | `div` | +| `DropdownMenu.ItemIndicator` | `div` | +| `DropdownMenu.RadioGroup` | `div` | +| `DropdownMenu.RadioItem` | `div` | +| `DropdownMenu.CheckboxItem` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Space` | When focus is on the trigger, opens the menu and focuses the first item.
    When focus is on an item, activates the item. | +| `Enter` | When focus is on the trigger, opens the menu and focuses the first item.
    When focus is on an item, activates the item. | +| `ArrowDown` | When focus is on the trigger, opens the menu and focuses the first item.
    When focus is on an item, moves focus to the next item. | +| `ArrowUp` | When focus is on the trigger, opens the menu and focuses the last item.
    When focus is on an item, moves focus to the previous item. | +| `ArrowRight` / `ArrowLeft` | When focus is on a sub menu trigger, opens or closes the submenu depending on reading direction. | +| `Home` | When focus is on an item, moves focus to first item. | +| `End` | When focus is on an item, moves focus to last item. | +| `Esc` | Closes the menu and moves focus to the trigger. | + +Previous[←Dialog](https://kobalte.dev/docs/core/components/dialog)Next[File Field→](https://kobalte.dev/docs/core/components/file-field) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-hover-card.md b/.firecrawl/kobalte.dev-docs-core-components-hover-card.md new file mode 100644 index 0000000..63a23cb --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-hover-card.md @@ -0,0 +1,331 @@ +# Hover Card + +Allows sighted users to preview content available behind a link. + +## Import + +``` +Copyts +import { HoverCard } from "@kobalte/core/hover-card"; +// or +import { Root, Trigger, ... } from "@kobalte/core/hover-card"; +// or (deprecated) +import { HoverCard } from "@kobalte/core"; +``` + +``` +Copyts +import { HoverCard } from "@kobalte/core/hover-card"; +// or +import { Root, Trigger, ... } from "@kobalte/core/hover-card"; +// or (deprecated) +import { HoverCard } from "@kobalte/core"; +``` + +## Features + +- Opens on hover only. +- Supports custom open and close delays. +- Optionally render a pointing arrow. +- Ignored by screen readers. +- Can be controlled or uncontrolled. + +## Anatomy + +The hovercard consists of: + +- **HoverCard:** The root container for a hovercard. +- **HoverCard.Trigger:** The link that opens the hovercard. +- **HoverCard.Portal:** Portals its children into the `body` when the hovercard is open. +- **HoverCard.Content:** Contains the content to be rendered when the hovercard is open. +- **HoverCard.Arrow:** An optional arrow element to render alongside the hovercard. + +``` +Copytsx + + + + + + + + +``` + +``` +Copytsx + + + + + + + + +``` + +## Example + +[@MLFabien](https://twitter.com/mlfabien) + +index.tsxstyle.css + +``` +Copytsx +import { HoverCard } from "@kobalte/core/hover-card"; +import "./style.css"; + +function App() { + return ( + + + @MLFabien + + + + + Fabien MARIE-LOUISE +

    Fabien MARIE-LOUISE

    +

    + Developer and UI Design enthusiast. Building UI related stuffs for @solid_js +

    +
    +
    +
    + ); +} +``` + +``` +Copytsx +import { HoverCard } from "@kobalte/core/hover-card"; +import "./style.css"; + +function App() { + return ( + + + @MLFabien + + + + + Fabien MARIE-LOUISE +

    Fabien MARIE-LOUISE

    +

    + Developer and UI Design enthusiast. Building UI related stuffs for @solid_js +

    +
    +
    +
    + ); +} +``` + +## Usage + +### Default open + +An initial, uncontrolled open value can be provided using the `defaultOpen` prop. + +``` +Copytsx +... +``` + +``` +Copytsx +... +``` + +### Controlled open + +The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user pointer enter or leave the trigger, and receives the new value. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [open, setOpen] = createSignal(false); + + return ( + + ... + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [open, setOpen] = createSignal(false); + + return ( + + ... + + ); +} +``` + +### Origin-aware animations + +We expose a CSS custom property `--kb-hovercard-content-transform-origin` which can be used to animate the content from its computed origin. + +``` +Copycss +/* style.css */ +.hovercard__content { + transform-origin: var(--kb-hovercard-content-transform-origin); + animation: contentHide 250ms ease-in forwards; +} + +.hovercard__content[data-expanded] { + animation: contentShow 250ms ease-out; +} + +@keyframes contentShow { + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes contentHide { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } +} +``` + +``` +Copycss +/* style.css */ +.hovercard__content { + transform-origin: var(--kb-hovercard-content-transform-origin); + animation: contentHide 250ms ease-in forwards; +} + +.hovercard__content[data-expanded] { + animation: contentShow 250ms ease-out; +} + +@keyframes contentShow { + from { + opacity: 0; + transform: scale(0.96); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes contentHide { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.96); + } +} +``` + +## API Reference + +### HoverCard + +`HoverCard` is equivalent to the `Root` import from `@kobalte/core/hover-card` (and deprecated `HoverCard.Root`). + +| Prop | Description | +| --- | --- | +| open | `boolean`
    The controlled open state of the hovercard. | +| defaultOpen | `boolean`
    The default open state when initially rendered. Useful when you do not need to control the open state. | +| onOpenChange | `(open: boolean) => void`
    Event handler called when the open state of the hovercard changes. | +| openDelay | `number`
    The duration from when the mouse enters the trigger until the hovercard opens. | +| closeDelay | `number`
    The duration from when the mouse leaves the trigger or content until the hovercard closes. | +| ignoreSafeArea | `boolean`
    Whether to close the hovercard even if the user cursor is inside the safe area between the trigger and hovercard. | +| id | `string`
    A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. | +| forceMount | `boolean`
    Used to force mounting the hovercard (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +`HoverCard` also accepts the following props to customize the placement of the `HoverCard.Content`. + +| Prop | Description | +| --- | --- | +| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`
    Function that returns the anchor element's DOMRect. | +| placement | `Placement`
    The placement of the hovercard. | +| gutter | `number`
    The distance between the hovercard and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. | +| shift | `number`
    The skidding of the hovercard along the trigger element. | +| flip | `boolean | string`
    Controls the behavior of the hovercard when it overflows the viewport:
    \- If a `boolean`, specifies whether the hovercard should flip to the opposite side when it overflows.
    \- If a `string`, indicates the preferred fallback placements when it overflows.
    The placements must be spaced-delimited, e.g. "top left". | +| slide | `boolean`
    Whether the hovercard should slide when it overflows. | +| overlap | `boolean`
    Whether the hovercard can overlap the trigger element when it overflows. | +| sameWidth | `boolean`
    Whether the hovercard should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. | +| fitViewport | `boolean`
    Whether the hovercard should fit the viewport. If this is set to true, the hovercard content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. | +| hideWhenDetached | `boolean`
    Whether to hide the hovercard when the trigger element becomes occluded. | +| detachedPadding | `number`
    The minimum padding in order to consider the trigger element occluded. | +| arrowPadding | `number`
    The minimum padding between the arrow and the hovercard corner. | +| overflowPadding | `number`
    The minimum padding between the hovercard and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. | + +### HoverCard.Content + +The popper positioner will copy the same `z-index` as the `HoverCard.Content`. + +### HoverCard.Trigger + +`HoverCard.Trigger` consists of [Link](https://kobalte.dev/docs/core/components/link). + +| Data attribute | Description | +| --- | --- | +| data-expanded | Present when the hovercard is open. | +| data-closed | Present when the hovercard is close. | + +`HoverCard.Content` share the same data-attributes. + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `HoverCard` | none | +| `HoverCard.Trigger` | `a` | +| `HoverCard.Portal` | `Portal` | +| `HoverCard.Content` | `div` | +| `HoverCard.Arrow` | `div` | + +## Accessibility + +### Keyboard Interactions + +The hover card is intended for mouse users only so will not respond to keyboard navigation. + +Previous[←File Field](https://kobalte.dev/docs/core/components/file-field)Next[Image→](https://kobalte.dev/docs/core/components/image) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-i18n-provider.md b/.firecrawl/kobalte.dev-docs-core-components-i18n-provider.md new file mode 100644 index 0000000..05e51d3 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-i18n-provider.md @@ -0,0 +1,97 @@ +# I18nProvider + +Provides the locale for the application to all child components. + +## Import + +``` +Copytsx +import { I18nProvider, useLocale } from "@kobalte/core/i18n"; +// or (deprecated) +import { I18nProvider, useLocale } from "@kobalte/core"; +``` + +``` +Copytsx +import { I18nProvider, useLocale } from "@kobalte/core/i18n"; +// or (deprecated) +import { I18nProvider, useLocale } from "@kobalte/core"; +``` + +## Usage + +`I18nProvider` allows you to override the default locale as determined by the browser/system setting with a locale defined by your application (e.g. application setting). + +This should be done by wrapping your entire application in the provider, which will cause all child elements to receive the new locale information via the `useLocale` primitive. + +``` +Copytsx +import { I18nProvider } from "@kobalte/core/i18n"; + + + +; +``` + +``` +Copytsx +import { I18nProvider } from "@kobalte/core/i18n"; + + + +; +``` + +### The `useLocale` primitive + +`useLocale` allows components to access the current locale and interface layout direction. It should be used in the root of your app to define the lang and dir attributes so that the browser knows which language and direction the user interface should be rendered in. + +``` +Copytsx +import { useLocale } from "@kobalte/core/i18n"; + +function YourApp() { + const { locale, direction } = useLocale(); + + return ( +
    + {/* your app here */} +
    + ); +} +``` + +``` +Copytsx +import { useLocale } from "@kobalte/core/i18n"; + +function YourApp() { + const { locale, direction } = useLocale(); + + return ( +
    + {/* your app here */} +
    + ); +} +``` + +## API reference + +### I18nProvider + +| Prop | Description | +| --- | --- | +| locale | `string`
    The locale to apply to the children. | +| children | `JSX.Element`
    The contents that should have the locale applied. | + +### useLocale + +The `useLocale` primitive returns the follows properties. + +| Name | Description | +| --- | --- | +| locale | `Accessor`
    The [BCP47](https://www.ietf.org/rfc/bcp/bcp47.txt) language code for the locale. | +| direction | `Accessor`
    The writing direction for the locale. | + +Previous[←Tooltip](https://kobalte.dev/docs/core/components/tooltip)Next→ \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-image.md b/.firecrawl/kobalte.dev-docs-core-components-image.md new file mode 100644 index 0000000..e0c0dd5 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-image.md @@ -0,0 +1,160 @@ +# Image + +An image element with an optional fallback for loading and error status. + +## Import + +``` +Copyts +import { Image } from "@kobalte/core/image"; +// or +import { Root, Img, ... } from "@kobalte/core/image"; +// or (deprecated) +import { Image } from "@kobalte/core"; +``` + +``` +Copyts +import { Image } from "@kobalte/core/image"; +// or +import { Root, Img, ... } from "@kobalte/core/image"; +// or (deprecated) +import { Image } from "@kobalte/core"; +``` + +## Features + +- Automatic and manual control over when the image renders. +- Fallback part accepts any children. +- Optionally delay fallback rendering to avoid content flashing. + +## Anatomy + +The image consists of: + +- **Image:** The root container for an image. +- **Image.Img:** The image to render. By default, it will only render when it has loaded. +- **Image.Fallback:** An element that renders when the image hasn't loaded. This means whilst it's loading, or if there was an error. + +``` +Copytsx + + + + +``` + +``` +Copytsx + + + + +``` + +## Example + +![Nicole Steeves](https://randomuser.me/api/portraits/women/44.jpg)MD + +index.tsxstyle.css + +``` +Copytsx +import { Image } from "@kobalte/core/image"; +import "./style.css"; + +function App() { + return ( + <> + + + NS + + + MD + + + ); +} +``` + +``` +Copytsx +import { Image } from "@kobalte/core/image"; +import "./style.css"; + +function App() { + return ( + <> + + + NS + + + MD + + + ); +} +``` + +## Usage + +### Avoid flash during loading + +By default `Image.Fallback` will render when the image hasn't loaded. This means whilst it's loading, or if there was an error. + +If you notice a flash during loading, use the `fallbackDelay` prop to delay its rendering, so it only renders for those with slower internet connections. + +``` +Copytsx + + + NS + +``` + +``` +Copytsx + + + NS + +``` + +## API Reference + +### Image + +`Image` is equivalent to the `Root` import from `@kobalte/core/image` (and deprecated `Image.Root`). + +| Prop | Description | +| --- | --- | +| fallbackDelay | `number`
    The delay (in ms) before displaying the image fallback. Useful if you notice a flash during loading for delaying rendering, so it only appears for those with slower internet connections. | +| onLoadingStatusChange | `(status: "idle" | "loading" | "loaded" | "error") => void`
    A callback providing information about the loading status of the image. This is useful in case you want to control more precisely what to render as the image is loading. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Image` | `span` | +| `Image.Img` | `img` | +| `Image.Fallback` | `span` | + +Previous[←Hover Card](https://kobalte.dev/docs/core/components/hover-card)Next[Link→](https://kobalte.dev/docs/core/components/link) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-link.md b/.firecrawl/kobalte.dev-docs-core-components-link.md new file mode 100644 index 0000000..087c36b --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-link.md @@ -0,0 +1,131 @@ +# Link + +Allows a user to navigate to another page or resource within a web page or application. + +## Import + +``` +Copyts +import { Link } from "@kobalte/core/link"; +// or +import { Root } from "@kobalte/core/link"; +// or (deprecated) +import { Link } from "@kobalte/core"; +``` + +``` +Copyts +import { Link } from "@kobalte/core/link"; +// or +import { Root } from "@kobalte/core/link"; +// or (deprecated) +import { Link } from "@kobalte/core"; +``` + +## Features + +- Native HTML `
    ` element support. +- Custom element type support via the [WAI ARIA Link](https://www.w3.org/WAI/ARIA/apg/patterns/link/) design pattern. +- Support for disabled links. + +## Anatomy + +The link consists of: + +- **Link:** The root container for a link. + +``` +Copytsx + +``` + +``` +Copytsx + +``` + +## Example + +[Kobalte](https://kobalte.dev/) + +index.tsxstyle.css + +``` +Copytsx +import { Link } from "@kobalte/core/link"; +import "./style.css"; + +function App() { + return ( + + Kobalte + + ); +} +``` + +``` +Copytsx +import { Link } from "@kobalte/core/link"; +import "./style.css"; + +function App() { + return ( + + Kobalte + + ); +} +``` + +## Usage + +### Disabled state + +Use the `disabled` prop to disable a link while keeping it accessible for screen readers. + +Kobalte + +``` +Copytsx + + Kobalte + +``` + +``` +Copytsx + + Kobalte + +``` + +## API Reference + +### Link + +`Link` is equivalent to the `Root` import from `@kobalte/core/link` (and deprecated `Link.Root`). + +| Prop | Description | +| --- | --- | +| disabled | `boolean`
    Whether the link is disabled. Native navigation will be disabled, and the link will be exposed as disabled to assistive technology. | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the link is disabled. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Link` | `a` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Enter` | Activates the link. | + +Previous[←Image](https://kobalte.dev/docs/core/components/image)Next[Menubar→](https://kobalte.dev/docs/core/components/menubar) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-meter.md b/.firecrawl/kobalte.dev-docs-core-components-meter.md new file mode 100644 index 0000000..f5ae214 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-meter.md @@ -0,0 +1,221 @@ +# Meter + +Displays numeric value that varies within a defined range + +## Import + +``` +Copyts +import { Meter } from "@kobalte/core/meter"; +// or +import { Root, Label, ... } from "@kobalte/core/meter"; +``` + +``` +Copyts +import { Meter } from "@kobalte/core/meter"; +// or +import { Root, Label, ... } from "@kobalte/core/meter"; +``` + +## Features + +- Exposed to assistive technology as a meter via ARIA. +- Labeling support for accessibility. +- Internationalized number formatting as a percentage or value. + +## Anatomy + +The meter consists of: + +- **Meter:** The root container for a meter. +- **Meter.Label:** An accessible label that gives the user information on the meter. +- **Meter.ValueLabel:** The accessible label text representing the current value in a human-readable format. +- **Meter.Track:** The component that visually represents the meter track. +- **Meter.Fill:** The component that visually represents the meter value. + +``` +Copytsx + + + + + + + +``` + +``` +Copytsx + + + + + + + +``` + +## Example + +Battery Level: + +80% + +index.tsxstyle.css + +``` +Copytsx +import { Meter } from "@kobalte/core/meter"; +import "./style.css"; + +function App() { + return ( + +
    + Battery Level: + +
    + + + +
    + ); +} +``` + +``` +Copytsx +import { Meter } from "@kobalte/core/meter"; +import "./style.css"; + +function App() { + return ( + +
    + Battery Level: + +
    + + + +
    + ); +} +``` + +## Usage + +### Custom value scale + +By default, the `value` prop represents the current value of meter, as the minimum and maximum values default to 0 and 100, respectively. Alternatively, a different scale can be used by setting the `minValue` and `maxValue` props. + +Disk Space Usage: + +40% + +``` +Copytsx + +
    + Disk Space Usage: + +
    + + + +
    +``` + +``` +Copytsx + +
    + Disk Space Usage: + +
    + + + +
    +``` + +### Custom value label + +The `getValueLabel` prop allows the formatted value used in `Meter.ValueLabel` and ARIA to be replaced with a custom string. It receives the current value, min and max values as parameters. + +Processing... + +3 of 10 tasks completed + +``` +Copytsx + `${value} of ${max} tasks completed`} + class="meter" +> +
    + Processing... + +
    + + + +
    +``` + +``` +Copytsx + `${value} of ${max} tasks completed`} + class="meter" +> +
    + Processing... + +
    + + + +
    +``` + +### Meter fill width + +We expose a CSS custom property `--kb-meter-fill-width` which corresponds to the percentage of meterion (ex: 80%). If you are building a linear meter, you can use it to set the width of the `Meter.Fill` component in CSS. + +## API Reference + +### Meter + +`Meter` is equivalent to the `Root` import from `@kobalte/core/meter`. + +| Prop | Description | +| --- | --- | +| value | `number`
    The meter value. | +| minValue | `number`
    The minimum meter value. | +| maxValue | `number`
    The maximum meter value. | +| getValueLabel | `(params: { value: number; min: number; max: number }) => string`
    A function to get the accessible label text representing the current value in a human-readable format. If not provided, the value label will be read as a percentage of the max value. | + +| Data attribute | Description | +| --- | --- | + +`Meter.Label`, `Meter.ValueLabel`, `Meter.Track` and `Meter.Fill` shares the same data-attributes. + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Meter` | `div` | +| `Meter.Label` | `span` | +| `Meter.ValueLabel` | `div` | +| `Meter.Track` | `div` | +| `Meter.Fill` | `div` | + +Previous[←Menubar](https://kobalte.dev/docs/core/components/menubar)Next[Navigation Menu→](https://kobalte.dev/docs/core/components/navigation-menu) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-number-field.md b/.firecrawl/kobalte.dev-docs-core-components-number-field.md new file mode 100644 index 0000000..c327d1b --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-number-field.md @@ -0,0 +1,549 @@ +# Number Field + +A number input that allow users to input custom number entries with a keyboard. + +## Import + +``` +Copyts +import { NumberField } from "@kobalte/core/number-field"; +// or +import { Root, Label, ... } from "@kobalte/core/number-field"; +// or (deprecated) +import { NumberField } from "@kobalte/core"; +``` + +``` +Copyts +import { NumberField } from "@kobalte/core/number-field"; +// or +import { Root, Label, ... } from "@kobalte/core/number-field"; +// or (deprecated) +import { NumberField } from "@kobalte/core"; +``` + +## Features + +- Follows the [WAI ARIA Spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) design pattern. +- Built with a native `` element. +- Visual and ARIA labeling support. +- Required and invalid states exposed to assistive technology via ARIA. +- Support for description and error message help text linked to the input via ARIA. +- Syncs with form reset events. +- Can be controlled or uncontrolled. +- Supports increment and decrement buttons. +- Format and localize input number and raw input. +- Supports mouse wheel event and all keyboard events. +- Supports browser autofill. + +## Anatomy + +The number field consists of: + +- **NumberField**: The root container for the number field. +- **NumberField.Label**: The label that gives the user information on the number field. +- **NumberField.Input**: The native HTML input of the number field, used for display number. +- **NumberField.HiddenInput**: The native HTML input of the number field, used for raw number form submition. +- **NumberField.IncrementTrigger**: The increment button of the number field. +- **NumberField.DecrementTrigger**: The increment button of the number field. +- **NumberField.Description**: The description that gives the user more information on the number field. +- **NumberField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on number field. + +``` +Copytsx + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + +``` + +## Example + +Quantity + +ArrowArrow + +index.tsxstyle.css + +``` +Copytsx +import { NumberField } from "@kobalte/core/number-field"; +import "./style.css"; + +function App() { + return ( + + + Quantity + +
    + + + +
    +
    + ); +} +``` + +``` +Copytsx +import { NumberField } from "@kobalte/core/number-field"; +import "./style.css"; + +function App() { + return ( + + + Quantity + +
    + + + +
    +
    + ); +} +``` + +## Usage + +### Default value + +An initial, uncontrolled value can be provided using the `defaultValue` prop. + +Quantity + +ArrowArrow + +``` +Copytsx + + Quantity +
    + + + +
    +
    +``` + +``` +Copytsx + + Quantity +
    + + + +
    +
    +``` + +### Controlled value + +The `value` and `rawValue` props can be used to make the value controlled. +It is recommended to only use the `rawValue` as it is of type `number`. +The `onChange` event is fired when the user type into the input and receive the new value. +The `onRawValueChange` prop is called when the value changes and receives a `number`. + +Quantity + +ArrowArrow + +Quantity: 40. Raw: 40. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal("40"); + const [rawValue, setRawValue] = createSignal(); + + return ( + <> + + Quantity +
    + + + +
    +
    +

    + Quantity: {value()}. Raw: {rawValue()}. +

    + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal("40"); + const [rawValue, setRawValue] = createSignal(); + + return ( + <> + + Quantity +
    + + + +
    +
    +

    + Quantity: {value()}. Raw: {rawValue()}. +

    + + ); +} +``` + +### Description + +The `NumberField.Description` component can be used to associate additional help text with a number field. + +Quantity + +ArrowArrow + +Choose a quantity. + +``` +Copytsx + + Quantity +
    + + + +
    + Choose a quantity. +
    +``` + +``` +Copytsx + + Quantity +
    + + + +
    + Choose a quantity. +
    +``` + +### Error message + +The `NumberField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the text field as invalid for assistive technologies. + +By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries). + +Quantity + +ArrowArrow + +Hmm, I prefer 40. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [rawValue, setRawValue] = createSignal(); + + return ( + + Quantity +
    + + + +
    + Hmm, I prefer 40. +
    + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [rawValue, setRawValue] = createSignal(); + + return ( + + Quantity +
    + + + +
    + Hmm, I prefer 40. +
    + ); +} +``` + +### HTML forms + +The number field `name` prop along with `` can be used for integration with HTML forms. Only the raw value is passed to the form. + +If the formatted value is wanted (unrecommended) set the `name` attribute on ``. + +Quantity + +ArrowArrow + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + Quantity + +
    + + + +
    +
    +
    + + +
    +
    + ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + Quantity + +
    + + + +
    +
    +
    + + +
    +
    + ); +} +``` + +### Triggers + +The number field supports optional increment/decrement triggers that are easily customizable. + +Quantity + +-+ + +``` +Copytsx + + Quantity +
    + - + + + +
    +
    +``` + +``` +Copytsx + + Quantity +
    + - + + + +
    +
    +``` + +### Format + +The value of the number field component can be formatted based on the [locale with the `I18NProvider`](https://kobalte.dev/docs/core/components/i18n-provider) and `formatOptions`. For more information see [React Spectrum NumberField](https://react-spectrum.adobe.com/react-spectrum/NumberField.html). + +Price + +ArrowArrow + +``` +Copytsx + + Price +
    + + + +
    +
    +``` + +``` +Copytsx + + Price +
    + + + +
    +
    +``` + +### Autofill + +The number field supports autofill through `NumberField.HiddenInput`. + +``` +Copytsx + + Quantity + +
    + + + +
    +
    +``` + +``` +Copytsx + + Quantity + +
    + + + +
    +
    +``` + +## API Reference + +### NumberField + +`NumberField` is equivalent to the `Root` import from `@kobalte/core/number-field` (and deprecated `NumberField.Root`). + +| Prop | Description | +| --- | --- | +| value | `string | number`
    The controlled formatted value of the number field. | +| defaultValue | `string | number`
    The default value when initially rendered. Useful when you do not need to control the value. | +| onChange | `(value: string) => void`
    Event handler called when the value of the NumberField changes as a formatted value. | +| rawValue | `number`
    The controlled raw value of the number field. | +| onRawValueChange | `(value: number) => void`
    Event handler called when the value of the NumberField changes as a number. | +| minValue | `number`
    The smallest value allowed in the number field, defaults to `Number.MIN_SAFE_INTEGER`. | +| maxValue | `number`
    The largest value allowed in the number field, defaults to `Number.MAX_SAFE_INTEGER`. | +| step | `number`
    Increment/Decrement step when using the triggers or the arrows on keyboard in the number field. | +| largeStep | `number`
    Increment/Decrement step when using the Page UP/Down keys in the number field, defaults `10 * step`. | +| changeOnWheel | `boolean`
    Whether to increment/decrement on wheel scroll inside the number field. | +| format | `boolean`
    Whether to format the input value. | +| formatOptions | [`Intl.NumberFormatOptions`](https://github.com/microsoft/TypeScript/blob/353ccb7688351ae33ccf6e0acb913aa30621eaf4/src/lib/es2020.intl.d.ts#L243-L251)
    Formating options for the value of the number field. | +| allowedInput | `RegExp`
    Allowed input characters in the number field (only prevents onInput, not paste), defaults to locale and format characters. | +| name | `string`
    The name of the NumberField.HiddenInput of the number field, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). | +| validationState | `'valid' | 'invalid'`
    Whether the number field should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must fill the number field before the owning form can be submitted. | +| disabled | `boolean`
    Whether the number field is disabled. | +| readOnly | `boolean`
    Whether the number field items can be selected but not changed by the user. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the number field is valid according to the validation rules. | +| data-invalid | Present when the number field is invalid according to the validation rules. | +| data-required | Present when the user must fill the number field before the owning form can be submitted. | +| data-disabled | Present when the number field is disabled. | +| data-readonly | Present when the number field is read only. | + +`NumberField.Label`, `NumberField.Input`, `NumberField.HiddenInput`, `NumberField.Description` and `NumberField.ErrorMesssage` share the same data-attributes. + +### NumberField.ErrorMessage + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `NumberField` | `div` | +| `NumberField.Label` | `label` | +| `NumberField.Input` | `input` | +| `NumberField.HiddenInput` | `input` | +| `NumberField.IncrementTrigger` | `button` | +| `NumberField.DecrementTrigger` | `button` | +| `NumberField.Description` | `div` | +| `NumberField.ErrorMessage` | `div` | + +Previous[←Navigation Menu](https://kobalte.dev/docs/core/components/navigation-menu)Next[Pagination→](https://kobalte.dev/docs/core/components/pagination) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-pagination.md b/.firecrawl/kobalte.dev-docs-core-components-pagination.md new file mode 100644 index 0000000..c2b44c4 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-pagination.md @@ -0,0 +1,368 @@ +# Pagination + +Allows the user to select a specific page from a range of pages. + +## Import + +``` +Copyts +import { Pagination } from "@kobalte/core/pagination"; +// or +import { Root, Item, ... } from "@kobalte/core/pagination"; +// or (deprecated) +import { Pagination } from "@kobalte/core"; +``` + +``` +Copyts +import { Pagination } from "@kobalte/core/pagination"; +// or +import { Root, Item, ... } from "@kobalte/core/pagination"; +// or (deprecated) +import { Pagination } from "@kobalte/core"; +``` + +## Features + +- Labeling support for accessibility. +- Tab focus management. +- Can be controlled or uncontrolled. +- Customizable appearance. + +## Anatomy + +The pagination consists of: + +- **Pagination:** The root container for the pagination component. +- **Pagination.Item:** An item of the pagination. +- **Pagination.Ellipsis:** Ellipsis item of the pagination. +- **Pagination.Previous:** Previous button of the pagination. +- **Pagination.Next:** Next button of the pagination. +- **Pagination.Items:** Contains the list of items and allows a user to select one of them. + +``` +Copytsx + + + + + +``` + +``` +Copytsx + + + + + +``` + +## Example + +index.tsxstyle.css + +``` +Copytsx +import { Pagination } from "@kobalte/core/pagination"; +import "./style.css"; + +function App() { + return ( + ( + {props.page} + )} + ellipsisComponent={() => ( + ... + )} + > + Previous + + Next + + ); +} +``` + +``` +Copytsx +import { Pagination } from "@kobalte/core/pagination"; +import "./style.css"; + +function App() { + return ( + ( + {props.page} + )} + ellipsisComponent={() => ( + ... + )} + > + Previous + + Next + + ); +} +``` + +## Usage + +### Default value + +An initial, uncontrolled page can be provided using the `defaultPage` prop, which accepts a number smaller or equal to the `count` and starts at 1. + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + Previous + + Next + +``` + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + Previous + + Next + +``` + +### Controlled value + +The `page` prop, which accepts a page number, can be used to make the value controlled. The `onPageChange` event is fired when the user selects an item, and receives the new page number. + +``` +Copytsx +import { createSignal } from "solid-js"; + +export function ControlledExample() { + const [page, setPage] = createSignal(4); + + return ( + {props.page}} + ellipsisComponent={() => ...} + > + Previous + + Next + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +export function ControlledExample() { + const [page, setPage] = createSignal(4); + + return ( + {props.page}} + ellipsisComponent={() => ...} + > + Previous + + Next + + ); +} +``` + +### Next / Previous buttons example + +The appearance can be customized by omitting the Next and Previous Button. + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + + +``` + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + + +``` + +### First / Last item example + +The First and Last item can be hidden instead of displaying at all times. + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + Previous + + Next + +``` + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + Previous + + Next + +``` + +### Siblings example + +The number of items around the current page item can be customized. + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + Previous + + Next + +``` + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + Previous + + Next + +``` + +### Fixed Items example + +The total number of items can be fixed to avoid content shift. If ellipsis are disabled (by returning an empty component) use `fixedItems="no-ellipsis"` instead. + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + Previous + + Next + +``` + +``` +Copytsx + {props.page}} + ellipsisComponent={() => ...} +> + Previous + + Next + +``` + +## API Reference + +### Pagination + +`Pagination` is equivalent to the `Root` import from `@kobalte/core/pagination` (and deprecated `Pagination.Root`). + +| Prop | Description | +| --- | --- | +| page | `number`
    The controlled page number of the pagination. (1-indexed) | +| defaultPage | `string`
    The default page number when initially rendered. (1-indexed) | +| onPageChange | `(page: number) => void`
    Event handler called when the page number changes. | +| count | `number`
    The number of pages for the pagination. | +| siblingCount | `number`
    The number of siblings to show around the current page item. | +| showFirst | `boolean`
    Whether to always show the first page item. | +| showLast | `boolean`
    Whether to always show the last page item. | +| fixedItems | `boolean | "no-ellipsis"`
    Whether to always show the same number of items (to avoid content shift). Special value: `"no-ellipsis"` does not count the ellipsis as an item (used when ellipsis are disabled). | +| itemComponent | `Component<{page: number}>`
    The component to render as an item in the `Pagination.Items`. | +| ellipsisComponent | `Component`
    The component to render as an ellipsis item in the `Pagination.Items`. | +| disabled | `boolean`
    Whether the pagination is disabled. | + +| Data attribute | Description | +| --- | --- | +| data-disabled | Present when the pagination is disabled. | + +### Pagination.Item + +| Prop | Description | +| --- | --- | +| page | `number`
    The page number to render. | + +| Data attribute | Description | +| --- | --- | +| data-current | Present when the item is the current page. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Pagination` | `div` | +| `Pagination.Item` | `button` | +| `Pagination.Ellipsis` | `div` | +| `Pagination.Previous` | `button` | +| `Pagination.Next` | `button` | +| `Pagination.Items` | none | + +Previous[←Number Field](https://kobalte.dev/docs/core/components/number-field)Next[Popover→](https://kobalte.dev/docs/core/components/popover) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-progress.md b/.firecrawl/kobalte.dev-docs-core-components-progress.md new file mode 100644 index 0000000..604ff9a --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-progress.md @@ -0,0 +1,230 @@ +# Progress + +Show either determinate or indeterminate progress of an operation over time. + +## Import + +``` +Copyts +import { Progress } from "@kobalte/core/progress"; +// or +import { Root, Label, ... } from "@kobalte/core/progress"; +// or (deprecated) +import { Progress } from "@kobalte/core"; +``` + +``` +Copyts +import { Progress } from "@kobalte/core/progress"; +// or +import { Root, Label, ... } from "@kobalte/core/progress"; +// or (deprecated) +import { Progress } from "@kobalte/core"; +``` + +## Features + +- Exposed to assistive technology as a progress bar via ARIA. +- Labeling support for accessibility. +- Internationalized number formatting as a percentage or value. +- Determinate and indeterminate progress support. + +## Anatomy + +The progress consists of: + +- **Progress:** The root container for a progress bar. +- **Progress.Label:** An accessible label that gives the user information on the progress. +- **Progress.ValueLabel:** The accessible label text representing the current value in a human-readable format. +- **Progress.Track:** The component that visually represents the progress track. +- **Progress.Fill:** The component that visually represents the progress value. + +``` +Copytsx + + + + + + + +``` + +``` +Copytsx + + + + + + + +``` + +## Example + +Loading... + +80% + +index.tsxstyle.css + +``` +Copytsx +import { Progress } from "@kobalte/core/progress"; +import "./style.css"; + +function App() { + return ( + +
    + Loading... + +
    + + + +
    + ); +} +``` + +``` +Copytsx +import { Progress } from "@kobalte/core/progress"; +import "./style.css"; + +function App() { + return ( + +
    + Loading... + +
    + + + +
    + ); +} +``` + +## Usage + +### Custom value scale + +By default, the `value` prop represents the current percentage of progress, as the minimum and maximum values default to 0 and 100, respectively. Alternatively, a different scale can be used by setting the `minValue` and `maxValue` props. + +Loading... + +50% + +``` +Copytsx + +
    + Loading... + +
    + + + +
    +``` + +``` +Copytsx + +
    + Loading... + +
    + + + +
    +``` + +### Custom value label + +The `getValueLabel` prop allows the formatted value used in `Progress.ValueLabel` and ARIA to be replaced with a custom string. It receives the current value, min and max values as parameters. + +Processing... + +3 of 10 tasks completed + +``` +Copytsx + `${value} of ${max} tasks completed`} + class="progress" +> +
    + Processing... + +
    + + + +
    +``` + +``` +Copytsx + `${value} of ${max} tasks completed`} + class="progress" +> +
    + Processing... + +
    + + + +
    +``` + +### Progress bar fill width + +We expose a CSS custom property `--kb-progress-fill-width` which corresponds to the percentage of progression (ex: 80%). If you are building a linear progress bar, you can use it to set the width of the `Progress.Fill` component in CSS. + +## API Reference + +### Progress + +`Progress` is equivalent to the `Root` import from `@kobalte/core/progress` (and deprecated `Progress.Root`). + +| Prop | Description | +| --- | --- | +| value | `number`
    The progress value. | +| minValue | `number`
    The minimum progress value. | +| maxValue | `number`
    The maximum progress value. | +| indeterminate | `boolean`
    Whether the progress is in an indeterminate state. | +| getValueLabel | `(params: { value: number; min: number; max: number }) => string`
    A function to get the accessible label text representing the current value in a human-readable format. If not provided, the value label will be read as a percentage of the max value. | + +| Data attribute | Description | +| --- | --- | +| data-progress='loading' | Present when the progress is not complete (`value` < `maxValue`). | +| data-progress='complete' | Present when the progress is complete (`value` === `maxValue`). | +| data-indeterminate | Present when the progress is in an indeterminate state. | + +`Progress.Label`, `Progress.ValueLabel`, `Progress.Track` and `Progress.Fill` shares the same data-attributes. + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Progress` | `div` | +| `Progress.Label` | `span` | +| `Progress.ValueLabel` | `div` | +| `Progress.Track` | `div` | +| `Progress.Fill` | `div` | + +Previous[←Popover](https://kobalte.dev/docs/core/components/popover)Next[Radio Group→](https://kobalte.dev/docs/core/components/radio-group) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-radio-group.md b/.firecrawl/kobalte.dev-docs-core-components-radio-group.md new file mode 100644 index 0000000..37ee204 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-radio-group.md @@ -0,0 +1,507 @@ +# Radio Group + +A set of checkable buttons, known as radio buttons, where no more than one of the buttons can be checked at a time. + +## Import + +``` +Copyts +import { RadioGroup } from "@kobalte/core/radio-group"; +// or +import { Root, Label, ... } from "@kobalte/core/radio-group"; +// or (deprecated) +import { RadioGroup } from "@kobalte/core"; +``` + +``` +Copyts +import { RadioGroup } from "@kobalte/core/radio-group"; +// or +import { Root, Label, ... } from "@kobalte/core/radio-group"; +// or (deprecated) +import { RadioGroup } from "@kobalte/core"; +``` + +## Features + +- Follow the [WAI ARIA Radio Group](https://www.w3.org/WAI/ARIA/apg/patterns/radiobutton/) design pattern. +- Each radio is built with a native HTML `` element, which is visually hidden to allow custom styling. +- Syncs with form reset events. +- Group and radio labeling support for assistive technology. +- Can be controlled or uncontrolled. + +## Anatomy + +The radio group consists of: + +- **RadioGroup**: The root container for the radio group. +- **RadioGroup.Label**: The label that gives the user information on the radio group. +- **RadioGroup.Description**: The description that gives the user more information on the radio group. +- **RadioGroup.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the radio group. + +The radio item consists of: + +- **RadioGroup.Item**: The root container for a radio button. +- **RadioGroup.ItemInput**: The native html input that is visually hidden in the radio button. +- **RadioGroup.ItemControl**: The element that visually represents a radio button. +- **RadioGroup.ItemIndicator**: The visual indicator rendered when the radio button is in a checked state. +- **RadioGroup.ItemLabel**: The label that gives the user information on the radio button. +- **RadioGroup.ItemDescription**: The description that gives the user more information on the radio button. + +``` +Copytsx + + + + + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + + + + + +``` + +## Example + +Favorite fruit + +Apple + +Orange + +Watermelon + +index.tsxstyle.css + +``` +Copytsx +import { RadioGroup } from "@kobalte/core/radio-group"; +import "./style.css"; + +function App() { + return ( + + Favorite fruit + + + ); +} +``` + +``` +Copytsx +import { RadioGroup } from "@kobalte/core/radio-group"; +import "./style.css"; + +function App() { + return ( + + Favorite fruit + + + ); +} +``` + +## Usage + +### Default value + +An initial, uncontrolled value can be provided using the `defaultValue` prop, which accepts a value corresponding with the `value` prop of each radio. + +Favorite fruit + +Apple + +Orange + +Watermelon + +``` +Copytsx + + Favorite fruit +
    + + {fruit => ...} + +
    +
    +``` + +``` +Copytsx + + Favorite fruit +
    + + {fruit => ...} + +
    +
    +``` + +The `role="presentation"` is required for all non content elements between the `RadioGroup` and `RadioGroup.Item` due to a bug in Chromium based browsers that incorrectly parse semantics and break screen readers. + +### Controlled value + +The `value` prop, which accepts a value corresponding with the `value` prop of each radio, can be used to make the value controlled. The `onChange` event is fired when the user selects a radio, and receives the new value. + +Favorite fruit + +Apple + +Orange + +Watermelon + +Your favorite fruit is: Orange. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal("Orange"); + + return ( + <> + + Favorite fruit +
    + + {fruit => ...} + +
    +
    +

    Your favorite fruit is: {value()}.

    + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [value, setValue] = createSignal("Orange"); + + return ( + <> + + Favorite fruit +
    + + {fruit => ...} + +
    +
    +

    Your favorite fruit is: {value()}.

    + + ); +} +``` + +### Description + +The `RadioGroup.Description` component can be used to associate additional help text with a radio group. + +Favorite fruit + +Apple + +Orange + +Watermelon + +Choose the fruit you like the most. + +``` +Copytsx + + Favorite fruit +
    + + {fruit => ...} + +
    + Choose the fruit you like the most. +
    +``` + +``` +Copytsx + + Favorite fruit +
    + + {fruit => ...} + +
    + Choose the fruit you like the most. +
    +``` + +### Error message + +The `RadioGroup.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the radio group as invalid for assistive technologies. + +By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries). + +Favorite fruit + +Apple + +Orange + +Watermelon + +Hmm, I prefer apples. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal("Orange"); + + return ( + + Favorite fruit +
    + + {fruit => ...} + +
    + Hmm, I prefer apples. +
    + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [value, setValue] = createSignal("Orange"); + + return ( + + Favorite fruit +
    + + {fruit => ...} + +
    + Hmm, I prefer apples. +
    + ); +} +``` + +### HTML forms + +The radio group `name` prop, paired with the radio `value` prop, can be used for integration with HTML forms. + +Favorite fruit + +Apple + +Orange + +Watermelon + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + Favorite fruit +
    + + {fruit => ...} + +
    +
    +
    + + +
    +
    + ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + + return ( +
    + + Favorite fruit +
    + + {fruit => ...} + +
    +
    +
    + + +
    +
    + ); +} +``` + +## API Reference + +### RadioGroup + +`RadioGroup` is equivalent to the `Root` import from `@kobalte/core/radio-group` (and deprecated `RadioGroup.Root`). + +| Prop | Description | +| --- | --- | +| value | `string`
    The controlled value of the radio button to check. | +| defaultValue | `string`
    The value of the radio button that should be checked when initially rendered. Useful when you do not need to control the state of the radio buttons. | +| onChange | `(value: string) => void`
    Event handler called when the value changes. | +| orientation | `'horizontal' | 'vertical'`
    The axis the radio group items should align with. | +| name | `string`
    The name of the radio group. Submitted with its owning form as part of a name/value pair. | +| validationState | `'valid' | 'invalid'`
    Whether the radio group should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must check a radio group item before the owning form can be submitted. | +| disabled | `boolean`
    Whether the radio group is disabled. | +| readOnly | `boolean`
    Whether the radio group items can be selected but not changed by the user. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the radio group is valid according to the validation rules. | +| data-invalid | Present when the radio group is invalid according to the validation rules. | +| data-required | Present when the user must check a radio group item before the owning form can be submitted. | +| data-disabled | Present when the radio group is disabled. | +| data-readonly | Present when the radio group is read only. | + +`RadioGroup.Label`, `RadioGroup.Description` and `RadioGroup.ErrorMesssage` shares the same data-attributes. + +### RadioGroup.ErrorMessage + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +### RadioGroup.Item + +| Prop | Description | +| --- | --- | +| value | `string`
    The value of the radio button, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio#Value). | +| disabled | `boolean`
    Whether the radio button is disabled or not. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the parent radio group is valid according to the validation rules. | +| data-invalid | Present when the parent radio group is invalid according to the validation rules. | +| data-checked | Present when the radio is checked. | +| data-disabled | Present when the radio is disabled. | + +`RadioGroup.ItemInput`, `RadioGroup.ItemControl`, `RadioGroup.ItemIndicator` and `RadioGroup.ItemLabel` shares the same data-attributes. + +### RadioGroup.ItemIndicator + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `RadioGroup` | `div` | +| `RadioGroup.Label` | `span` | +| `RadioGroup.Description` | `div` | +| `RadioGroup.ErrorMessage` | `div` | +| `RadioGroup.Item` | `div` | +| `RadioGroup.ItemInput` | `input` | +| `RadioGroup.ItemControl` | `div` | +| `RadioGroup.ItemIndicator` | `div` | +| `RadioGroup.ItemLabel` | `label` | +| `RadioGroup.ItemDescription` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Tab` | Moves focus to either the checked radio button or the first radio button in the group. | +| `Space` | When focus is on an unchecked radio button, checks it. | +| `ArrowDown` | Moves focus and checks the next radio button in the group. | +| `ArrowRight` | Moves focus and checks the next radio button in the group. | +| `ArrowUp` | Moves focus and checks the previous radio button in the group. | +| `ArrowLeft` | Moves focus and checks the previous radio button in the group. | + +Previous[←Progress](https://kobalte.dev/docs/core/components/progress)Next[Rating Group→](https://kobalte.dev/docs/core/components/rating-group) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-separator.md b/.firecrawl/kobalte.dev-docs-core-components-separator.md new file mode 100644 index 0000000..937c280 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-separator.md @@ -0,0 +1,110 @@ +# Separator + +Visually or semantically separates content. + +## Import + +``` +Copyts +import { Separator } from "@kobalte/core/separator"; +// or +import { Root } from "@kobalte/core/separator"; +// or (deprecated) +import { Separator } from "@kobalte/core"; +``` + +``` +Copyts +import { Separator } from "@kobalte/core/separator"; +// or +import { Root } from "@kobalte/core/separator"; +// or (deprecated) +import { Separator } from "@kobalte/core"; +``` + +## Features + +- Native HTML `
    ` element support. +- Custom element type support via the [WAI ARIA Separator](https://w3c.github.io/aria/#separator) role. +- Support for horizontal and vertical orientation. + +## Anatomy + +The separator consists of: + +- **Separator:** The root container for a separator. + +``` +Copytsx + +``` + +``` +Copytsx + +``` + +## Example + +Content above + +* * * + +Content below + +index.tsxstyle.css + +``` +Copytsx +import { Separator } from "@kobalte/core/separator"; +import "./style.css"; + +function App() { + return ( +
    + Content above + + Content below +
    + ); +} +``` + +``` +Copytsx +import { Separator } from "@kobalte/core/separator"; +import "./style.css"; + +function App() { + return ( +
    + Content above + + Content below +
    + ); +} +``` + +## API Reference + +### Separator + +`Separator` is equivalent to the `Root` import from `@kobalte/core/separator` (and deprecated `Separator.Root`). + +| Prop | Description | +| --- | --- | +| orientation | `'horizontal' | 'vertical'`
    The orientation of the separator. | + +| Data attribute | Description | +| --- | --- | +| data-orientation='horizontal' | Present when the separator has horizontal orientation. | +| data-orientation='vertical' | Present when the separator has vertical orientation. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Separator` | `hr` | + +Previous[←Select](https://kobalte.dev/docs/core/components/select)Next[Skeleton→](https://kobalte.dev/docs/core/components/skeleton) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-skeleton.md b/.firecrawl/kobalte.dev-docs-core-components-skeleton.md new file mode 100644 index 0000000..aab15c1 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-skeleton.md @@ -0,0 +1,244 @@ +# Skeleton + +Visually indicates content loading + +## Import + +``` +Copyts +import { Skeleton } from "@kobalte/core/skeleton"; +// or +import { Root } from "@kobalte/core/skeleton"; +// or (deprecated) +import { Skeleton } from "@kobalte/core"; +``` + +``` +Copyts +import { Skeleton } from "@kobalte/core/skeleton"; +// or +import { Root } from "@kobalte/core/skeleton"; +// or (deprecated) +import { Skeleton } from "@kobalte/core"; +``` + +## Features + +- Support for custom width and height. +- Support for circle skeleton. +- Can toggle visiblity and animation properties. + +## Anatomy + +The skeleton consists of: + +- **Skeleton:** The root container for a skeleton. + +``` +Copytsx + +``` + +``` +Copytsx + +``` + +## Example + +A UI toolkit for building accessible web apps and design systems with SolidJS. + +index.tsxstyle.css + +``` +Copytsx +import { Skeleton } from "@kobalte/core/skeleton"; +import "./style.css"; + +function App() { + return ( + +

    + A UI toolkit for building accessible web apps and design systems with SolidJS. +

    +
    + ); +} +``` + +``` +Copytsx +import { Skeleton } from "@kobalte/core/skeleton"; +import "./style.css"; + +function App() { + return ( + +

    + A UI toolkit for building accessible web apps and design systems with SolidJS. +

    +
    + ); +} +``` + +## Usage + +### Multiple skeletons + +![Nicole Steeves](https://pbs.twimg.com/profile_images/1509139491671445507/pzWYjlYN_400x400.jpg) + +Kobalte + +A UI toolkit for building accessible web apps and design systems with SolidJS. + +index.tsxstyle.css + +``` +Copytsx +import { Skeleton } from "@kobalte/core/skeleton"; +import { Image } from "@kobalte/core/image"; +import "./style.css"; + +function App() { + return ( +
    +
    + + + + + + + Kobalte + +
    + +

    + A UI toolkit for building accessible web apps and design systems with SolidJS. +

    +
    +
    + ); +} +``` + +``` +Copytsx +import { Skeleton } from "@kobalte/core/skeleton"; +import { Image } from "@kobalte/core/image"; +import "./style.css"; + +function App() { + return ( +
    +
    + + + + + + + Kobalte + +
    + +

    + A UI toolkit for building accessible web apps and design systems with SolidJS. +

    +
    +
    + ); +} +``` + +### Toggle example + +Show content + +A UI toolkit for building accessible web apps and design systems with SolidJS. + +index.tsxstyle.css + +``` +Copytsx +import { Skeleton } from "@kobalte/core/skeleton"; +import { ToggleButton } from "@kobalte/core/toggle-button"; +import "./style.css"; + +function App() { + const [visible, setVisible] = createSignal(true); + return ( +
    + + Skeleton {visible() ? "Visible" : "Not Visible"} + + +

    + A UI toolkit for building accessible web apps and design systems with SolidJS. +

    +
    +
    + ); +} +``` + +``` +Copytsx +import { Skeleton } from "@kobalte/core/skeleton"; +import { ToggleButton } from "@kobalte/core/toggle-button"; +import "./style.css"; + +function App() { + const [visible, setVisible] = createSignal(true); + return ( +
    + + Skeleton {visible() ? "Visible" : "Not Visible"} + + +

    + A UI toolkit for building accessible web apps and design systems with SolidJS. +

    +
    +
    + ); +} +``` + +## API Reference + +### Skeleton + +`Skeleton` is equivalent to the `Root` import from `@kobalte/core/skeleton` (and deprecated `Skeleton.Root`). + +| Prop | Description | +| --- | --- | +| visible | `boolean`
    The visible state of the Skeleton. Sets the `data-visible` data attribute. | +| animate | `boolean`
    Whether the skeleton should animate. Sets the `data-animate` data attribute. | +| width | `number`
    The width of the skeleton in px. Defaults to 100%. | +| height | `number`
    The height of the skeleton in px. Defaults to auto. | +| radius | `number`
    Roundness of the skeleton in px. Sets border-radius. | +| circle | `boolean`
    Whether the skeleton should be a circle. Sets border-radius and width to the height. | +| children | `JSX.Element`
    The children of the Skeleton. | + +| Data attribute | Description | +| --- | --- | +| data-visible | Present when the Skeleton is visible. | +| data-animate | Present when the Skeleton can animate. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Skeleton` | `div` | + +Previous[←Separator](https://kobalte.dev/docs/core/components/separator)Next[Slider→](https://kobalte.dev/docs/core/components/slider) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-slider.md b/.firecrawl/kobalte.dev-docs-core-components-slider.md new file mode 100644 index 0000000..d38060e --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-slider.md @@ -0,0 +1,638 @@ +# Slider + +An input where the user selects a value from within a given range. + +## Import + +``` +Copyts +import { Slider } from "@kobalte/core/slider"; +// or +import { Root, Track, ... } from "@kobalte/core/slider"; +// or (deprecated) +import { Slider } from "@kobalte/core"; +``` + +``` +Copyts +import { Slider } from "@kobalte/core/slider"; +// or +import { Root, Track, ... } from "@kobalte/core/slider"; +// or (deprecated) +import { Slider } from "@kobalte/core"; +``` + +## Features + +- Follow the [WAI ARIA Slider](https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/) design pattern. +- Can be controlled or uncontrolled. +- Support for multiple thumbs. +- Support a minimum step between thumbs. +- Support click or touch on track to change value. +- Support right or left direction. +- Support for custom value label. + +## Anatomy + +The slider consists of: + +- **Slider:** The root container for the slider. +- **Slider.Track:** The component that visually represents the slider track. +- **Slider.Fill:** The component that visually represents the slider value. +- **Slider.Thumb:** The thumb that is used to visually indicate a value in the slider. +- **Slider.Input:** The native html input that is visually hidden in the slider thumb. +- **Slider.Label:** The label that gives the user information on the slider. +- **Slider.ValueLabel:** The accessible label text representing the current value in a human-readable format. +- **Slider.Description**: The description that gives the user more information on the slider. +- **Slider.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the slider. + +``` +Copytsx + + + + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + + + + +``` + +## Example + +Label + +0 + +index.tsxstyle.css + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + +
    + Label + +
    + + + + + + +
    + ); +} +``` + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + +
    + Label + +
    + + + + + + +
    + ); +} +``` + +## Usage + +### Multiple Thumbs + +Label + +0, 20 + +index.tsxstyle.css + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + +
    + Label + +
    + + + + + + + + + +
    + ); +} +``` + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + +
    + Label + +
    + + + + + + + + + +
    + ); +} +``` + +### Modify step size + +Step size 8 + +0 + +Step size 10 + +0 + +Step size 20 + +0 + +index.tsxstyle.css + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + <> + +
    + Step size 8 + +
    + + + + + + + + + +
    + +
    + Step size 10 + +
    + + + + + + + + + +
    + +
    + Step size 20 + +
    + + + + + + + + + +
    + + ); +} +``` + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + <> + +
    + Step size 8 + +
    + + + + + + + + + +
    + +
    + Step size 10 + +
    + + + + + + + + + +
    + +
    + Step size 20 + +
    + + + + + + + + + +
    + + ); +} +``` + +### Steps between thumbs + +Label + +10, 20 + +index.tsxstyle.css + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + +
    + Label + +
    + + + + + + + + + +
    + ); +} +``` + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + +
    + Label + +
    + + + + + + + + + +
    + ); +} +``` + +### Vertical Slider + +Label + +0 + +index.tsxstyle.css + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + +
    + Label + +
    + + + + + + +
    + ); +} +``` + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + +
    + Label + +
    + + + + + + +
    + ); +} +``` + +### Custom Value Label + +Money + +$20 - $500 + +index.tsxstyle.css + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + `$${params.values[0]} - $${params.values[1]}`} + > +
    + Money + +
    + + + + + + + + + +
    + ); +} +``` + +``` +Copytsx +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + return ( + `$${params.values[0]} - $${params.values[1]}`} + > +
    + Money + +
    + + + + + + + + + +
    + ); +} +``` + +### Controlled Value + +Label + +40 + +index.tsxstyle.css + +``` +Copytsx +import { createSignal } from 'solid-js' +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + const [values, setValues] = createSignal([40]) + + return ( + +
    + Label + +
    + + + + + + +
    + ); +} +``` + +``` +Copytsx +import { createSignal } from 'solid-js' +import { Slider } from "@kobalte/core/slider"; +import "./style.css"; + +function App() { + const [values, setValues] = createSignal([40]) + + return ( + +
    + Label + +
    + + + + + + +
    + ); +} +``` + +## API Reference + +### Slider + +`Slider` is equivalent to the `Root` import from `@kobalte/core/slider` (and deprecated `Slider.Root`). + +| Prop | Description | +| --- | --- | +| value | `number[]`
    The controlled values of the slider. Must be used in conjunction with `onChange`. | +| defaultValue | `number[]`
    The value of the slider when initially rendered. Use when you do not need to control the state of the slider. | +| onChange | `(value: number[]) => void`
    Event handler called when the value changes. | +| onChangeEnd | `(value: number[]) => void`
    Event handler called when the value changes at the end of an interaction. | +| inverted | `boolean`
    Whether the slider is visually inverted. Defaults to false. | +| minValue | `number`
    The minimum slider value. Defaults to 0 | +| maxValue | `number`
    The maximum slider value. Defaults to 100 | +| step | `number`
    The stepping interval. Defaults to 1 | +| minStepsBetweenThumbs | `number`
    The minimum permitted steps between thumbs. Defaults to 0 | +| getValueLabel | `(params: GetValueLabelParams) => string`
    A function to get the accessible label text representing the current value in a human-readable format. If not provided, the value label will be read as a percentage of the max value. | +| orientation | `'horizontal' | 'vertical'`
    The orientation of the slider. | +| name | `string`
    The name of the slider, used when submitting an HTML form. | +| validationState | `'valid' | 'invalid'`
    Whether the slider should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must check a radio group item before the owning form can be submitted. | +| disabled | `boolean`
    Whether the radio group is disabled. | +| readOnly | `boolean`
    Whether the radio group items can be selected but not changed by the user. | + +| Data attribute | Description | +| --- | --- | +| data-orientation='horizontal' | Present when the slider has horizontal orientation. | +| data-orientation='vertical' | Present when the slider has vertical orientation. | +| data-valid | Present when the slider is valid according to the validation rules. | +| data-invalid | Present when the slider is invalid according to the validation rules. | +| data-required | Present when the user must slider an item before the owning form can be submitted. | +| data-disabled | Present when the slider is disabled. | +| data-readonly | Present when the slider is read only. | + +`Slider.ValueLabel`, `Slider.Fill`, `Slider.Input`, `Slider.Thumb` and `Slider.Track` share the same data-attributes. + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Slider` | `div` | +| `Slider.Track` | `div` | +| `Slider.Fill` | `div` | +| `Slider.Thumb` | `span` | +| `Slider.Input` | `input` | +| `Slider.ValueLabel` | `div` | +| `Slider.Description` | `div` | +| `Slider.ErrorMessage` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `PageUp` | Increases the value of the focused thumb by a larger `step`. | +| `PageDown` | Decreases the value of the focused thumb by a larger `step`. | +| `ArrowDown` | Decreases the value of the focused thumb by the `step` amount. | +| `ArrowUp` | Increases the value of the focused thumb by the `step` amount. | +| `ArrowRight` | Increments/decrements by the `step` value depending on `orientation`. | +| `ArrowLeft` | Increments/decrements by the `step` value depending on `orientation`. | +| `Home` | Sets the value of the first thumb to the minimum value. | +| `End` | Sets the value of the last thumb to the maximum value. | + +Previous[←Skeleton](https://kobalte.dev/docs/core/components/skeleton)Next[Switch→](https://kobalte.dev/docs/core/components/switch) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-switch.md b/.firecrawl/kobalte.dev-docs-core-components-switch.md new file mode 100644 index 0000000..90c8781 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-switch.md @@ -0,0 +1,373 @@ +# Switch + +A control that allows users to choose one of two values: on or off. + +## Import + +``` +Copyts +import { Switch } from "@kobalte/core/switch"; +// or +import { Root, Input, ... } from "@kobalte/core/switch"; +// or (deprecated) +import { Switch } from "@kobalte/core"; +``` + +``` +Copyts +import { Switch } from "@kobalte/core/switch"; +// or +import { Root, Input, ... } from "@kobalte/core/switch"; +// or (deprecated) +import { Switch } from "@kobalte/core"; +``` + +## Features + +- Follow the [WAI ARIA Switch](https://www.w3.org/WAI/ARIA/apg/patterns/switch/) design pattern. +- Built with a native HTML `` element, which is visually hidden to allow custom styling. +- Syncs with form reset events. +- Labeling support for assistive technology. +- Support for description and error message help text linked to the input via ARIA. +- Can be controlled or uncontrolled. + +## Anatomy + +The switch consists of: + +- **Switch:** The root container for a switch. +- **Switch.Input:** The native html input that is visually hidden in the switch. +- **Switch.Control:** The element that visually represents a switch. +- **Switch.Thumb:** The thumb that is used to visually indicate whether the switch is on or off. +- **Switch.Label:** The label that gives the user information on the switch. +- **Switch.Description**: The description that gives the user more information on the switch. +- **Switch.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the switch. + +``` +Copytsx + + + + + + + + + +``` + +``` +Copytsx + + + + + + + + + +``` + +## Example + +Airplane mode + +index.tsxstyle.css + +``` +Copytsx +import { Switch } from "@kobalte/core/switch"; +import "./style.css"; + +function App() { + return ( + + Airplane mode + + + + + + ); +} +``` + +``` +Copytsx +import { Switch } from "@kobalte/core/switch"; +import "./style.css"; + +function App() { + return ( + + Airplane mode + + + + + + ); +} +``` + +## Usage + +### Default checked + +An initial, uncontrolled value can be provided using the `defaultChecked` prop. + +Airplane mode + +``` +Copytsx +... +``` + +``` +Copytsx +... +``` + +### Controlled checked + +The `checked` prop can be used to make the checked state controlled. The `onChange` event is fired when the user toggle the switch, and receives the new value. + +Airplane mode + +Airplane mode is inactive. + +``` +Copytsx +import { createSignal } from "solid-js"; + +export function ControlledExample() { + const [checked, setChecked] = createSignal(false); + + return ( + <> + + ... + +

    Airplane mode is {checked() ? "active" : "inactive"}.

    + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +export function ControlledExample() { + const [checked, setChecked] = createSignal(false); + + return ( + <> + + ... + +

    Airplane mode is {checked() ? "active" : "inactive"}.

    + + ); +} +``` + +### Description + +The `Switch.Description` component can be used to associate additional help text with a switch. + +Airplane mode + +Disable all network connections. + +``` +Copytsx + + Airplane mode + Disable all network connections. + + + + + +``` + +``` +Copytsx + + Airplane mode + Disable all network connections. + + + + + +``` + +### Error message + +The `Switch.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the switch as invalid for assistive technologies. + +By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries). + +Airplane mode + +You must enable airplane mode. + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [checked, setChecked] = createSignal(false); + + return ( + + Airplane mode + You must enable airplane mode. + + + + + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ErrorMessageExample() { + const [checked, setChecked] = createSignal(false); + + return ( + + Airplane mode + You must enable airplane mode. + + + + + + ); +} +``` + +### HTML forms + +The `name` and `value` props can be used for integration with HTML forms. + +Airplane mode + +ResetSubmit + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + return ( +
    + + ... + +
    + + +
    +
    + ); +} +``` + +``` +Copytsx +function HTMLFormExample() { + const onSubmit = (e: SubmitEvent) => { + // handle form submission. + }; + return ( +
    + + ... + +
    + + +
    +
    + ); +} +``` + +## API Reference + +### Switch + +`Switch` is equivalent to the `Root` import from `@kobalte/core/switch` (and deprecated `Switch.Root`). + +| Prop | Description | +| --- | --- | +| checked | `boolean`
    The controlled checked state of the switch. | +| defaultChecked | `boolean`
    The default checked state when initially rendered. Useful when you do not need to control the checked state. | +| onChange | `(checked: boolean) => void`
    Event handler called when the checked state of the switch changes. | +| name | `string`
    The name of the switch, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). | +| value | `string`
    The value of the switch, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefvalue). | +| validationState | `'valid' | 'invalid'`
    Whether the switch should display its "valid" or "invalid" visual styling. | +| required | `boolean`
    Whether the user must check the switch before the owning form can be submitted. | +| disabled | `boolean`
    Whether the switch is disabled. | +| readOnly | `boolean`
    Whether the switch can be checked but not changed by the user. | + +| Render Prop | Description | +| --- | --- | +| checked | `Accessor`
    Whether the switch is checked or not. | + +| Data attribute | Description | +| --- | --- | +| data-valid | Present when the switch is valid according to the validation rules. | +| data-invalid | Present when the switch is invalid according to the validation rules. | +| data-required | Present when the switch is required. | +| data-disabled | Present when the switch is disabled. | +| data-readonly | Present when the switch is read only. | +| data-checked | Present when the switch is checked. | + +`Switch.Input`, `Switch.Control`, `Switch.Thumb`, `Switch.Label`, `Switch.Description` and `Switch.ErrorMessage` shares the same data-attributes. + +### Switch.ErrorMessage + +| Prop | Description | +| --- | --- | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Switch` | `div` | +| `Switch.Input` | `input` | +| `Switch.Control` | `div` | +| `Switch.Indicator` | `div` | +| `Switch.Label` | `label` | +| `Switch.Description` | `div` | +| `Switch.ErrorMessage` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Space` | Toggles the switch on and off. | + +Previous[←Slider](https://kobalte.dev/docs/core/components/slider)Next[Tabs→](https://kobalte.dev/docs/core/components/tabs) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-tabs.md b/.firecrawl/kobalte.dev-docs-core-components-tabs.md new file mode 100644 index 0000000..3b60623 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-tabs.md @@ -0,0 +1,631 @@ +# Tabs + +A set of layered sections of content, known as tab panels, that display one panel of content at a time. + +## Import + +``` +Copyts +import { Tabs } from "@kobalte/core/tabs"; +// or +import { Root, List, ... } from "@kobalte/core/tabs"; +// or (deprecated) +import { Tabs } from "@kobalte/core"; +``` + +``` +Copyts +import { Tabs } from "@kobalte/core/tabs"; +// or +import { Root, List, ... } from "@kobalte/core/tabs"; +// or (deprecated) +import { Tabs } from "@kobalte/core"; +``` + +## Features + +- Follow the [WAI ARIA Tabs](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/) design pattern, semantically linking tabs and their associated tab panels. +- Support for LTR and RTL keyboard navigation. +- Support for disabled tabs. +- Supports horizontal/vertical orientation. +- Supports automatic/manual activation. +- Focus management for tab panels without any focusable children. +- Can be controlled or uncontrolled. + +## Anatomy + +The tabs consist of: + +- **Tabs:** The root container for tabs and tab contents. +- **Tabs.List:** Contains the tabs that are aligned along the edge of the active tab content. +- **Tabs.Trigger:** The button that activates its associated tab content. +- **Tabs.Indicator:** The visual indicator displayed at the bottom of the tab list to indicate the selected tab. +- **Tabs.Content:** Contains the content associated with a tab trigger. + +``` +Copytsx + + + + + + + +``` + +``` +Copytsx + + + + + + + +``` + +## Example + +ProfileDashboardSettingsContact + +Profile details + +index.tsxstyle.css + +``` +Copytsx +import { Tabs } from "@kobalte/core/tabs"; +import "./style.css"; + +function App() { + return ( + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + + ); +} +``` + +``` +Copytsx +import { Tabs } from "@kobalte/core/tabs"; +import "./style.css"; + +function App() { + return ( + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + + ); +} +``` + +## Usage + +### Default value + +A default selected tab can be provided using the `defaultValue` prop, which should correspond to the `value` prop provided to each tab. + +ProfileDashboardSettingsContact + +Dashboard details + +``` +Copytsx + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +``` +Copytsx + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +### Controlled value + +Selected tab can be controlled using the `value` prop, paired with the `onChange` event. The `value` prop from the selected tab will be passed into the callback when the tab is selected, allowing you to update state accordingly. + +ProfileDashboardSettingsContact + +Settings details + +Selected tab: settings + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [selectedTab, setSelectedTab] = createSignal("settings"); + + return ( + <> + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +

    Selected tab: {selectedTab()}

    + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function ControlledExample() { + const [selectedTab, setSelectedTab] = createSignal("settings"); + + return ( + <> + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +

    Selected tab: {selectedTab()}

    + + ); +} +``` + +### Focusable content + +When the tab content doesn't contain any focusable content, the entire content is given a `tabIndex=0` so that the content can be navigated to with the keyboard. + +When the tab content contains focusable content, such as an ``, then the `tabIndex` is omitted because the content itself can receive focus. + +This example uses the same Tabs components from above. Try navigating from the tabs to each content using the keyboard. + +ProfileDashboardSettingsContact + +``` +Copytsx +function FocusableContentExample() { + return ( + + + Profile + Dashboard + Settings + Contact + + + + + + Dashboard details + Settings details + Contact details + + ); +} +``` + +``` +Copytsx +function FocusableContentExample() { + return ( + + + Profile + Dashboard + Settings + Contact + + + + + + Dashboard details + Settings details + Contact details + + ); +} +``` + +### Dynamic tabs + +Tabs can be added/removed dynamically by using a signal and SolidJS `For`. + +Add tabRemove tab + +Tab 1Tab 2Tab 3 + +Tab body 1 + +``` +Copytsx +import { createSignal } from "solid-js"; + +function DynamicContentExample() { + const [tabs, setTabs] = createSignal([\ + { id: "1", title: "Tab 1", content: "Tab body 1" },\ + { id: "2", title: "Tab 2", content: "Tab body 2" },\ + { id: "3", title: "Tab 3", content: "Tab body 3" },\ + ]); + + const addTab = () => { + setTabs(prev => [\ + ...prev,\ + {\ + id: String(prev.length + 1),\ + title: `Tab ${prev.length + 1}`,\ + content: `Tab Body ${prev.length + 1}`,\ + },\ + ]); + }; + + const removeTab = () => { + if (tabs().length > 1) { + setTabs(prev => prev.slice(0, -1)); + } + }; + + return ( + <> + + + + + {tab => {tab.title}} + + + {tab => {tab.content}} + + + ); +} +``` + +``` +Copytsx +import { createSignal } from "solid-js"; + +function DynamicContentExample() { + const [tabs, setTabs] = createSignal([\ + { id: "1", title: "Tab 1", content: "Tab body 1" },\ + { id: "2", title: "Tab 2", content: "Tab body 2" },\ + { id: "3", title: "Tab 3", content: "Tab body 3" },\ + ]); + + const addTab = () => { + setTabs(prev => [\ + ...prev,\ + {\ + id: String(prev.length + 1),\ + title: `Tab ${prev.length + 1}`,\ + content: `Tab Body ${prev.length + 1}`,\ + },\ + ]); + }; + + const removeTab = () => { + if (tabs().length > 1) { + setTabs(prev => prev.slice(0, -1)); + } + }; + + return ( + <> + + + + + {tab => {tab.title}} + + + {tab => {tab.content}} + + + ); +} +``` + +### Activation mode + +By default, pressing the arrow keys while focus is on a Tab will switch selection to the adjacent Tab in that direction, updating the content displayed accordingly. + +If you would like to prevent selection change from happening automatically you can set the `activationMode` prop to `manual`. This will prevent tab selection from changing on arrow key press, requiring a subsequent `Enter` or `Space` key press to confirm tab selection. + +ProfileDashboardSettingsContact + +Profile details + +``` +Copytsx + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +``` +Copytsx + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +### Orientation + +By default, tabs are horizontally oriented. The `orientation` prop can be set to `vertical` to change this. This affects keyboard navigation. You are responsible for styling your tabs accordingly. + +ProfileDashboardSettingsContact + +Profile details + +``` +Copytsx + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +``` +Copytsx + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +### Disabled + +All tabs can be disabled using the `disabled` prop. + +ProfileDashboardSettingsContact + +Profile details + +``` +Copytsx + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +``` +Copytsx + + + Profile + Dashboard + Settings + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +Individual tab can be disabled using the `disabled` prop on the tab itself. + +ProfileDashboardSettingsContact + +Profile details + +``` +Copytsx + + + Profile + Dashboard + + Settings + + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +``` +Copytsx + + + Profile + Dashboard + + Settings + + Contact + + + Profile details + Dashboard details + Settings details + Contact details + +``` + +## API Reference + +### Tabs + +`Tabs` is equivalent to the `Root` import from `@kobalte/core/tabs` (and deprecated `Tabs.Root`). + +| Prop | Description | +| --- | --- | +| value | `string`
    The controlled value of the tab to activate. | +| defaultValue | `string`
    The value of the tab that should be active when initially rendered. Useful when you do not need to control the state. | +| onChange | `(value: string) => void`
    Event handler called when the value changes. | +| orientation | `'horizontal' | 'vertical'`
    The orientation of the tabs. | +| activationMode | `'automatic' | 'manual'`
    Whether tabs are activated automatically on focus or manually. | +| disabled | `boolean`
    Whether the tabs are disabled. | + +| Data attribute | Description | +| --- | --- | +| data-orientation='horizontal' | Present when the separator has horizontal orientation. | +| data-orientation='vertical' | Present when the separator has vertical orientation. | + +`Tabs.List`, `Tabs.Trigger`, `Tabs.Indicator` and `Tabs.Content` share the same data-attributes. + +### Tabs.Trigger + +| Prop | Description | +| --- | --- | +| value | `string`
    The unique key that associates the tab with a tab panel. | +| disabled | `boolean`
    Whether the tab should be disabled. | + +| Data attribute | Description | +| --- | --- | +| data-selected | Present when the trigger is selected. | +| data-disabled | Present when the trigger is disabled. | +| data-highlighted | Present when the trigger is highlighted. | + +### Tabs.Content + +| Prop | Description | +| --- | --- | +| value | `string`
    The unique key that associates the tab panel with a tab. | +| forceMount | `boolean`
    Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | + +| Data attribute | Description | +| --- | --- | +| data-selected | Present when the associated trigger is selected. | + +## Rendered elements + +| Component | Default rendered element | +| --- | --- | +| `Tabs` | `div` | +| `Tabs.List` | `div` | +| `Tabs.Trigger` | `button` | +| `Tabs.Indicator` | `div` | +| `Tabs.Content` | `div` | + +## Accessibility + +### Keyboard Interactions + +| Key | Description | +| --- | --- | +| `Tab` | When focus moves onto the tabs, focuses the active trigger.
    When a trigger is focused, moves focus to the active content. | +| `ArrowDown` | Moves focus to the next trigger in vertical orientation and activates its associated content. | +| `ArrowRight` | Moves focus to the next trigger in horizontal orientation and activates its associated content. | +| `ArrowUp` | Moves focus to the previous trigger in vertical orientation and activates its associated content. | +| `ArrowLeft` | Moves focus to the previous trigger in horizontal orientation and activates its associated content. | +| `Home` | Moves focus to the first trigger and activates its associated content. | +| `End` | Moves focus to the last trigger and activates its associated content. | +| `Enter` | In manual mode, when a trigger is focused, moves focus to its associated content. | +| `Space` | In manual mode, when a trigger is focused, moves focus to its associated content. | + +Previous[←Switch](https://kobalte.dev/docs/core/components/switch)Next[Text Field→](https://kobalte.dev/docs/core/components/text-field) \ No newline at end of file diff --git a/.firecrawl/kobalte.dev-docs-core-components-text-field.md b/.firecrawl/kobalte.dev-docs-core-components-text-field.md new file mode 100644 index 0000000..ddb2bd3 --- /dev/null +++ b/.firecrawl/kobalte.dev-docs-core-components-text-field.md @@ -0,0 +1,394 @@ +# Text Field + +A text input that allow users to input custom text entries with a keyboard. + +## Import + +``` +Copyts +import { TextField } from "@kobalte/core/text-field"; +// or +import { Root, Label, ... } from "@kobalte/core/text-field"; +// or (deprecated) +import { TextField } from "@kobalte/core"; +``` + +``` +Copyts +import { TextField } from "@kobalte/core/text-field"; +// or +import { Root, Label, ... } from "@kobalte/core/text-field"; +// or (deprecated) +import { TextField } from "@kobalte/core"; +``` + +## Features + +- Built with a native `` or `