diff --git a/docs/04-CLI.md b/docs/04-CLI.md new file mode 100644 index 000000000000..f0540ae8c0e3 --- /dev/null +++ b/docs/04-CLI.md @@ -0,0 +1,112 @@ +--- +sidebar_label: CLI +title: CLI +--- + +# CLI + +UI5 Web Components provides command-line tools for scaffolding projects and generating components. + +## Create a New Project + +Scaffold a fully configured UI5 Web Components package with a single command: + +```bash +npm create @ui5/webcomponents-package +``` + +This launches an interactive wizard that sets up a ready-to-run TypeScript project with a sample component, theming, i18n, and a dev server. + +### Options + +| Option | Description | Default | +|--------|-------------|---------| +| `--name` | Package name (npm-compatible, supports scopes) | `my-package` | +| `--tag` | Component tag name (e.g., `my-button`) | Derived from class name | +| `--testSetup` | Test setup: `cypress` or `manual` | `manual` | +| `--skip` | Skip interactive prompts and use defaults | `false` | +| `--skipSubfolder` | Create files in current directory instead of a subfolder | `false` | + +### Examples + +**Non-interactive with a custom name** + +```bash +npm create @ui5/webcomponents-package -- \ + --name "my-components" \ + --skip +``` + +**Scoped package with Cypress testing** + +```bash +npm create @ui5/webcomponents-package -- \ + --name "@scope/my-lib" \ + --testSetup "cypress" \ + --skip +``` + +### What Gets Generated + +The scaffolded project includes: + +- A sample **web component** (`MyFirstComponent`) with a template, styles, and i18n +- **Dev server** with hot reload (`npm start`) +- **Build pipeline** for production (`npm run build`) +- **TypeScript** configuration +- **Cypress** test setup (if selected) +- **ESLint** configuration +- **Theming** infrastructure (SAP Horizon) + +After the project is created: + +```bash +cd my-package +npm install +npm start +``` + +## Generate a Component + +Inside a scaffolded project, generate a new web component: + +```bash +npm run create-ui5-element +``` + +This prompts for a PascalCase component name (e.g., `MyButton`) and generates three files: + +| File | Purpose | +|------|---------| +| `src/.ts` | Component class with `@customElement` decorator | +| `src/Template.tsx` | JSX template | +| `src/themes/.css` | Component styles | + +The tag name is derived automatically — `MyButton` becomes `my-my-button` (using the prefix from `.env`). + +You can also pass the name directly: + +```bash +npm run create-ui5-element "MyButton" +``` + +After generating, import the component in `src/bundle.esm.ts`: + +```typescript +import "./MyButton.js"; +``` + +## Project Commands + +Every scaffolded project comes with these commands: + +| Command | Description | +|---------|-------------| +| `npm start` | Start the dev server with hot reload | +| `npm run build` | Production build | +| `npm run create-ui5-element` | Generate a new web component | +| `npm run lint` | Lint the project | +| `npm run clean` | Clean generated and build artifacts | +| `npm test` | Run tests (if Cypress was selected) | + +[View on npm](https://www.npmjs.com/package/@ui5/create-webcomponents-package) · [GitHub](https://github.com/UI5/webcomponents/tree/main/packages/create-package) diff --git a/docs/05-MCP-Server.md b/docs/05-MCP-Server.md new file mode 100644 index 000000000000..fb8d865b237f --- /dev/null +++ b/docs/05-MCP-Server.md @@ -0,0 +1,72 @@ +--- +sidebar_label: MCP Server +sidebar_class_name: sidebar-sparkle +title: MCP Server +--- + +# MCP Server + +The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server gives your AI assistant direct access to UI5 Web Components documentation, component APIs, and integration guides — no copy-pasting needed. + +## Setup + +Add the following entry to your MCP client configuration (e.g. `mcp.json`): + +```json +{ + "mcpServers": { + "@ui5/webcomponents-mcp-server": { + "type": "stdio", + "command": "npx", + "args": ["-y", "@ui5/webcomponents-mcp-server"] + } + } +} +``` + +### One-Click Setup + +**VS Code (GitHub Copilot)** — paste the JSON config above into your `.vscode/mcp.json`, or run: + +```bash +code --add-mcp '{"name":"@ui5/webcomponents-mcp-server","type":"stdio","command":"npx","args":["-y","@ui5/webcomponents-mcp-server"]}' +``` + +**Claude Code** + +```bash +claude mcp add \ + --transport "stdio" \ + --scope "user" \ + "ui5-webc-mcp-server" \ + -- npx -y "@ui5/webcomponents-mcp-server" +``` + +**Codex** + +```bash +codex mcp add \ + --transport "stdio" \ + "ui5-webc-mcp-server" \ + -- npx -y "@ui5/webcomponents-mcp-server" +``` + +## Available Tools + +| Tool | Description | +|------|-------------| +| `get_component_api` | Fetch API docs for any component — properties, slots, events, methods | +| `get_guidelines` | Get integration guides for React, Angular, or vanilla JavaScript | +| `list_docs` | List all available documentation with summaries | +| `get_doc` | Fetch full content of a specific documentation page | + +## Example Prompts + +Once the MCP server is configured, try asking your AI assistant: + +- *"Show me the API for ui5-button"* +- *"How do I use UI5 Web Components with React?"* +- *"Show me the available documentation"* +- *"Get the theming documentation"* + +[View on npm](https://www.npmjs.com/package/@ui5/webcomponents-mcp-server) · [GitHub](https://github.com/UI5/ui5-web-components-mcp-server) diff --git a/docs/06-Skills.md b/docs/06-Skills.md new file mode 100644 index 000000000000..624d58639021 --- /dev/null +++ b/docs/06-Skills.md @@ -0,0 +1,56 @@ +--- +sidebar_label: Skills +sidebar_class_name: sidebar-sparkle +title: Skills +--- + +# Skills + +UI5 Web Components ships [Agent Skills](https://agentskills.io) — portable, structured knowledge files that teach AI coding assistants how to work with the library. Skills provide domain-specific guidance that goes beyond what a general-purpose LLM knows out of the box. + +## Available Skills + +| Skill | Description | +|-------|-------------| +| **styling** | How to customize and style UI5 Web Components — CSS shadow parts, custom states, CSS variables, and tag-level styling | +| **accessibility** | How to make UI5 Web Components applications accessible — accessibility APIs, label-input relationships, invisible messaging, keyboard handling, and high contrast themes | + +## Installation + +Install all UI5 Web Components skills into your project: + +```bash +npx skills add "UI5/webcomponents" +``` + +This downloads the skill files into your project so that AI assistants (Claude Code, Copilot, Cursor, etc.) can pick them up automatically. + +To install a specific skill: + +```bash +npx skills add "UI5/webcomponents" --skill "styling" +``` + +### In the Repository + +When working inside the UI5 Web Components repository, AI coding assistants automatically discover and use the skills from the [`skills/`](https://github.com/UI5/webcomponents/tree/main/skills) directory — no setup needed. + +### Manual Setup + +You can also copy skills directly from the repository's [`skills/`](https://github.com/UI5/webcomponents/tree/main/skills) directory into your project's `.agents/skills/` folder: + +``` +your-project/ +└── .agents/ + └── skills/ + ├── styling/ + │ └── SKILL.md + └── accessibility/ + └── SKILL.md +``` + +## How Skills Work + +Each skill is a Markdown file (`SKILL.md`) with structured frontmatter (name, description, trigger conditions) and a body containing the actual guidance. When an AI assistant encounters a relevant task — for example, a question about styling a component — it uses the skill's content to provide accurate, project-specific answers instead of generic advice. + +Skills are part of the open [Agent Skills](https://agentskills.io) standard and work across AI tools that support it. diff --git a/docs/4-development/01-package.md b/docs/07-development/01-package.md similarity index 100% rename from docs/4-development/01-package.md rename to docs/07-development/01-package.md diff --git a/docs/4-development/02-component.md b/docs/07-development/02-component.md similarity index 100% rename from docs/4-development/02-component.md rename to docs/07-development/02-component.md diff --git a/docs/4-development/03-properties.md b/docs/07-development/03-properties.md similarity index 100% rename from docs/4-development/03-properties.md rename to docs/07-development/03-properties.md diff --git a/docs/4-development/04-slots.md b/docs/07-development/04-slots.md similarity index 100% rename from docs/4-development/04-slots.md rename to docs/07-development/04-slots.md diff --git a/docs/4-development/05-events.md b/docs/07-development/05-events.md similarity index 100% rename from docs/4-development/05-events.md rename to docs/07-development/05-events.md diff --git a/docs/4-development/06-lifecycle-hooks.md b/docs/07-development/06-lifecycle-hooks.md similarity index 100% rename from docs/4-development/06-lifecycle-hooks.md rename to docs/07-development/06-lifecycle-hooks.md diff --git a/docs/4-development/07-styling.md b/docs/07-development/07-styling.md similarity index 100% rename from docs/4-development/07-styling.md rename to docs/07-development/07-styling.md diff --git a/docs/4-development/08-templates.md b/docs/07-development/08-templates.md similarity index 100% rename from docs/4-development/08-templates.md rename to docs/07-development/08-templates.md diff --git a/docs/4-development/09-internationalization.md b/docs/07-development/09-internationalization.md similarity index 100% rename from docs/4-development/09-internationalization.md rename to docs/07-development/09-internationalization.md diff --git a/docs/4-development/10-testing.md b/docs/07-development/10-testing.md similarity index 100% rename from docs/4-development/10-testing.md rename to docs/07-development/10-testing.md diff --git a/docs/4-development/11-deep-dive-and-best-practices.md b/docs/07-development/11-deep-dive-and-best-practices.md similarity index 100% rename from docs/4-development/11-deep-dive-and-best-practices.md rename to docs/07-development/11-deep-dive-and-best-practices.md diff --git a/docs/4-development/README.md b/docs/07-development/README.md similarity index 100% rename from docs/4-development/README.md rename to docs/07-development/README.md diff --git a/docs/5-contributing/01-development-workflow.md b/docs/08-contributing/01-development-workflow.md similarity index 98% rename from docs/5-contributing/01-development-workflow.md rename to docs/08-contributing/01-development-workflow.md index 5768703d42a1..689f66efcdce 100644 --- a/docs/5-contributing/01-development-workflow.md +++ b/docs/08-contributing/01-development-workflow.md @@ -37,7 +37,7 @@ The server will reload the pages whenever you make changes in the code. **4.1.** Read the dedicated tutorials for component developers: - [Development Conventions and Guidelines](02-conventions-and-guidelines.md); -- [Developing Custom UI5 Web Components](../4-development/01-package.md); +- [Developing Custom UI5 Web Components](../07-development/01-package.md); **4.2.** Create a local branch within your fork and work with it as usual. diff --git a/docs/5-contributing/02-conventions-and-guidelines.md b/docs/08-contributing/02-conventions-and-guidelines.md similarity index 98% rename from docs/5-contributing/02-conventions-and-guidelines.md rename to docs/08-contributing/02-conventions-and-guidelines.md index b7eef50fd70e..8926068273d3 100644 --- a/docs/5-contributing/02-conventions-and-guidelines.md +++ b/docs/08-contributing/02-conventions-and-guidelines.md @@ -6,7 +6,7 @@ You may also find an ESLint integration for your favorite IDE [here](https://esl ## Testing Integration tests are implemented with [Cypress](https://www.cypress.io/). You can run all tests using `npm run test`. -If reasonable, take the time and write a test for the proposed change or fix. Learn more about testing at the [Testing UI5 Web Components page](../4-development/10-testing.md). +If reasonable, take the time and write a test for the proposed change or fix. Learn more about testing at the [Testing UI5 Web Components page](../07-development/10-testing.md). ## Git Guidelines diff --git a/docs/5-contributing/03-DoD.md b/docs/08-contributing/03-DoD.md similarity index 100% rename from docs/5-contributing/03-DoD.md rename to docs/08-contributing/03-DoD.md diff --git a/docs/5-contributing/04-website.md b/docs/08-contributing/04-website.md similarity index 100% rename from docs/5-contributing/04-website.md rename to docs/08-contributing/04-website.md diff --git a/docs/5-contributing/README.md b/docs/08-contributing/README.md similarity index 100% rename from docs/5-contributing/README.md rename to docs/08-contributing/README.md diff --git a/docs/6-migration-guides/01-to-version-2.md b/docs/09-migration-guides/01-to-version-2.md similarity index 100% rename from docs/6-migration-guides/01-to-version-2.md rename to docs/09-migration-guides/01-to-version-2.md diff --git a/docs/6-migration-guides/README.md b/docs/09-migration-guides/README.md similarity index 100% rename from docs/6-migration-guides/README.md rename to docs/09-migration-guides/README.md diff --git a/docs/08-Releases.md b/docs/10-Releases.md similarity index 100% rename from docs/08-Releases.md rename to docs/10-Releases.md diff --git a/docs/09-FAQ.md b/docs/11-FAQ.md similarity index 98% rename from docs/09-FAQ.md rename to docs/11-FAQ.md index 1dcbf08e9e52..c7a1efb38d03 100644 --- a/docs/09-FAQ.md +++ b/docs/11-FAQ.md @@ -27,7 +27,7 @@ sidebar_label: FAQ **Q: Can I create my own UI5 Web Components?** -**A:** Yes, for more information see [Creating a Custom UI5 Web Components Package](4-development/01-package.md) +**A:** Yes, for more information see [Creating a Custom UI5 Web Components Package](07-development/01-package.md) **Q: How can I customize UI5 Web Components' styles?** diff --git a/docs/2-advanced/08-using-i18n-for-apps.md b/docs/2-advanced/08-using-i18n-for-apps.md index 80f3af7e9867..42705daf3ccc 100644 --- a/docs/2-advanced/08-using-i18n-for-apps.md +++ b/docs/2-advanced/08-using-i18n-for-apps.md @@ -10,7 +10,7 @@ None of the code below implies or requires the usage of UI5 Web Components, and The `@ui5/webcomponents-base` package allows the usage of `i18n` functionality not just for UI5 Web Components, but for apps as well. -*Note:* This section is dedicated to apps. For information on how to set up `i18n` for your custom components, please see [Developing Web Components](../4-development/01-package.md). +*Note:* This section is dedicated to apps. For information on how to set up `i18n` for your custom components, please see [Developing Web Components](../07-development/01-package.md). ## Step-by-Step Tutorial diff --git a/docs/README.md b/docs/README.md index 4dc666e155a5..7dadaf9fb7fe 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,17 +6,19 @@ With UI5 Web Components, developers can leverage a powerful, flexible, and futur ## Key Features of UI5 Web Components -- Enterprise-Grade: A comprehensive collection of reusable UI elements that adhere to enterprise standards - accessibility, themeability, i18n and more. +- **Enterprise-Grade:** A comprehensive collection of reusable UI elements that adhere to enterprise standards - accessibility, themeability, i18n and more. -- Framework Agnostic: Fully compatible with any current or future web development frameworks such as React, Angular, and Vue, allowing seamless integration into any tech stack. +- **Framework Agnostic:** Fully compatible with any current or future web development frameworks such as React, Angular, and Vue, allowing seamless integration into any tech stack. -- Elegant: Being custom HTML elements, they hide implementation complexity behind a single HTML tag, making them easily usable with the standard DOM APIs. +- **Elegant:** Being custom HTML elements, they hide implementation complexity behind a single HTML tag, making them easily usable with the standard DOM APIs. -- Consistent User Experience: Implementing the [SAP Fiori design](https://experience.sap.com/fiori-design/) and adhering to the [SAP Fiori Design Guidelines](https://experience.sap.com/fiori-design-web/) ensures a consistent and intuitive user experience across all applications. +- **Consistent User Experience:** Implementing the [SAP Fiori design](https://experience.sap.com/fiori-design/) and adhering to the [SAP Fiori Design Guidelines](https://experience.sap.com/fiori-design-web/) ensures a consistent and intuitive user experience across all applications. -- Open Source: UI5 Web Components is an open-source project available to the general public, inviting developers from all backgrounds to contribute and benefit. +- **Open Source:** UI5 Web Components is an open-source project available to the general public, inviting developers from all backgrounds to contribute and benefit. -- SAP Backing: Developed and maintained by [SAP](https://sap.com) as part of the [UI5](https://openui5.org/) product family, guaranteeing ongoing support and integration with SAP's ecosystem. +- **SAP Backing:** Developed and maintained by [SAP](https://sap.com) as part of the [UI5](https://openui5.org/) product family, guaranteeing ongoing support and integration with SAP's ecosystem. + +- **AI-Ready:** The project is structured for AI-assisted development with an [MCP server](./05-MCP-Server.md) for direct IDE integration, a machine-readable [llms.txt](/llms.txt) file, an [AGENTS.md](https://github.com/UI5/webcomponents/blob/main/AGENTS.md) guide for coding assistants, installable [Agent Skills](./06-Skills.md), and a dedicated set of [AI components](/components/ai/) for building conversational and generative AI interfaces. ## Ecosystem @@ -27,7 +29,11 @@ UI5 Web Components are complemented by a range of related projects that enhance [UI5 Web Components for React](https://github.com/UI5/webcomponents-react) is a wrapper implementation around UI5 Web Components which makes using them in React even more comfortable. The current version of React (`react 18`) has some shortcomings when it comes to handling Custom Elements, namely the binding of `boolean` attributes as well as adding event listeners to custom event names like `selection-change`. With the help of UI5 Web Components for React, you can use the UI5 Web Components in React as if they were native React components. In addition to that, this library is also offering some complex layout components built on top of UI5 Web Components as well as Charting Components. -**Note:** [React 19](https://react.dev/blog/2024/04/25/react-19) promises to fill all gaps in the web coponents support - the binding of `boolean` attributes and subscribing to custom events. +#### Native Web Components Support in React 19 + +[React 19](https://react.dev/blog/2024/04/25/react-19) introduces full native support for Custom Elements, resolving the long-standing gaps in how React handles web components. Specifically, React 19 correctly binds `boolean` attributes, passes properties (not just attributes) to custom elements, and supports subscribing to custom events. This means you can use UI5 Web Components directly in React 19 without a wrapper library — they work just like any other HTML element. + +The UI5 Web Components for React library remains valuable for its additional features — higher-level layout components, charting components, and TypeScript definitions — but it is no longer required for basic usage. ### UI5 Web Components for Angular diff --git a/packages/website/docusaurus.config.ts b/packages/website/docusaurus.config.ts index cf13e8a57e75..43551c69c5b0 100644 --- a/packages/website/docusaurus.config.ts +++ b/packages/website/docusaurus.config.ts @@ -311,6 +311,7 @@ const config: Config = { prism: { theme: prismThemes.github, darkTheme: prismThemes.dracula, + additionalLanguages: ['bash', 'json'], }, } satisfies Preset.ThemeConfig, }; diff --git a/packages/website/src/components/AskAI/index.js b/packages/website/src/components/AskAI/index.js new file mode 100644 index 000000000000..32b82de3f329 --- /dev/null +++ b/packages/website/src/components/AskAI/index.js @@ -0,0 +1,257 @@ +import React, { useState, useRef, useEffect, useCallback } from "react"; +import styles from "./index.module.css"; + +const AI_TOOLS = [ + { + name: "Claude", + url: "https://claude.ai/new", + icon: ( + + + + ), + }, + { + name: "ChatGPT", + url: "https://chatgpt.com", + icon: ( + + + + ), + }, + { + name: "v0", + url: "https://v0.dev/chat", + icon: ( + + + + ), + }, + { + name: "GitHub Copilot", + url: "https://github.com/copilot", + icon: ( + + + + ), + }, +]; + +const SparkleIcon = () => ( + + + +); + +const ExternalLinkIcon = () => ( + + + +); + +const CopyIcon = () => ( + + + + +); + +const CheckIcon = () => ( + + + +); + +const SourceIcon = () => ( + + + + +); + +function buildPrompt(title, tagName, pageUrl) { + if (tagName) { + return `I'm working with UI5 Web Components. Here's the documentation for the <${tagName}> component:\n${pageUrl}\n\nHelp me understand how to use it, give examples, or help debug issues with it.`; + } + return `I'm working with UI5 Web Components. Here's the documentation page "${title}":\n${pageUrl}\n\nHelp me understand the concepts on this page or answer questions about it.`; +} + +function getGitHubSourceUrl(tagName) { + // Map tag prefixes to packages + const tag = tagName.replace(/^ui5-/, ""); + + // Known fiori components (by tag name without prefix) + const fioriTags = [ + "bar", "barcode-scanner-dialog", "dynamic-side-content", + "flexible-column-layout", "illustrated-message", "media-gallery", + "notification-list", "page", "product-switch", + "shell-bar", "side-navigation", "timeline", "upload-collection", + "view-settings-dialog", "wizard", + ]; + + const aiTags = ["button", "prompt-input"]; + + let pkg = "main"; + if (fioriTags.some((t) => tag.startsWith(t))) { + pkg = "fiori"; + } else if (aiTags.some((t) => tag === t)) { + // ai package components might conflict with main, so exact match + // We can't reliably detect ai vs main from tag name alone + // Default to main since most components are there + pkg = "main"; + } + + // Convert tag-name to PascalCase component name + const componentName = tag + .split("-") + .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) + .join(""); + + return `https://github.com/SAP/ui5-webcomponents/tree/main/packages/${pkg}/src/${componentName}.ts`; +} + +export default function AskAI({ title, tagName }) { + const [open, setOpen] = useState(false); + const [copied, setCopied] = useState(false); + const wrapperRef = useRef(null); + + const close = useCallback(() => setOpen(false), []); + + useEffect(() => { + if (!open) return; + + function handleClickOutside(e) { + if (wrapperRef.current && !wrapperRef.current.contains(e.target)) { + close(); + } + } + + function handleEscape(e) { + if (e.key === "Escape") { + close(); + } + } + + document.addEventListener("mousedown", handleClickOutside); + document.addEventListener("keydown", handleEscape); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + document.removeEventListener("keydown", handleEscape); + }; + }, [open, close]); + + const handleCopyMarkdown = async () => { + const el = document.querySelector(".markdown"); + if (!el) return; + + try { + await navigator.clipboard.writeText(el.innerText); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch { + // Fallback for older browsers + const textarea = document.createElement("textarea"); + textarea.value = el.innerText; + document.body.appendChild(textarea); + textarea.select(); + document.execCommand("copy"); + document.body.removeChild(textarea); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } + }; + + const pageUrl = typeof window !== "undefined" ? window.location.href : ""; + const prompt = buildPrompt(title, tagName, pageUrl); + const encodedPrompt = encodeURIComponent(prompt); + + return ( +
+ + + {open && ( +
+
Markdown
+ + {tagName && ( + + + + + View source + + + )} + +
+ +
Open in
+ {AI_TOOLS.map((tool) => ( + + {tool.icon} + {tool.name} + + + ))} +
+ )} +
+ ); +} diff --git a/packages/website/src/components/AskAI/index.module.css b/packages/website/src/components/AskAI/index.module.css new file mode 100644 index 000000000000..5b9edb17251c --- /dev/null +++ b/packages/website/src/components/AskAI/index.module.css @@ -0,0 +1,139 @@ +.wrapper { + position: relative; + display: inline-block; +} + +.trigger { + display: inline-flex; + align-items: center; + gap: 0.375rem; + padding: 0.375rem 0.75rem; + font-size: 0.8125rem; + font-weight: 500; + font-family: inherit; + color: var(--ifm-color-primary); + background: transparent; + border: 1px solid var(--ifm-color-primary); + border-radius: 0.375rem; + cursor: pointer; + transition: background 0.15s, color 0.15s; + white-space: nowrap; + line-height: 1.4; +} + +.trigger:hover { + background: var(--ifm-color-primary); + color: #fff; +} + +.trigger:hover .chevron { + border-color: #fff; +} + +.sparkle { + width: 14px; + height: 14px; + flex-shrink: 0; +} + +.chevron { + display: inline-block; + width: 0.375rem; + height: 0.375rem; + border-right: 1.5px solid var(--ifm-color-primary); + border-bottom: 1.5px solid var(--ifm-color-primary); + transform: rotate(45deg); + margin-top: -2px; + transition: border-color 0.15s; +} + +.dropdown { + position: absolute; + top: calc(100% + 0.375rem); + right: 0; + z-index: 100; + min-width: 220px; + background: #ffffff; + border: 1px solid var(--ifm-color-emphasis-300); + border-radius: 0.5rem; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); + padding: 0.375rem; + opacity: 0; + transform: translateY(-4px); + animation: dropdownIn 0.15s ease forwards; +} + +:global([data-theme='dark']) .dropdown { + background: #1b1b1d; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); +} + +@keyframes dropdownIn { + to { + opacity: 1; + transform: translateY(0); + } +} + +.sectionLabel { + padding: 0.375rem 0.5rem 0.25rem; + font-size: 0.6875rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--ifm-color-emphasis-500); +} + +.item { + display: flex; + align-items: center; + gap: 0.5rem; + width: 100%; + padding: 0.4375rem 0.5rem; + font-size: 0.8125rem; + font-family: inherit; + color: var(--ifm-font-color-base); + background: none; + border: none; + border-radius: 0.3125rem; + cursor: pointer; + text-decoration: none; + transition: background 0.1s; + line-height: 1.4; +} + +.item:hover { + background: var(--ifm-color-emphasis-100); + color: var(--ifm-font-color-base); + text-decoration: none; +} + +.itemIcon { + width: 16px; + height: 16px; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; +} + +.itemLabel { + flex: 1; +} + +.externalIcon { + width: 12px; + height: 12px; + color: var(--ifm-color-emphasis-400); + flex-shrink: 0; +} + +.separator { + height: 1px; + background: var(--ifm-color-emphasis-200); + margin: 0.25rem 0.5rem; +} + +.copied { + color: var(--ifm-color-success); +} diff --git a/packages/website/src/css/custom.css b/packages/website/src/css/custom.css index 26d8ae76b572..27a1f3ba8b28 100644 --- a/packages/website/src/css/custom.css +++ b/packages/website/src/css/custom.css @@ -11,6 +11,7 @@ --ifm-table-background: transparent; --ifm-table-stripe-background: transparent; --playground-toolbar-bg: #334eff; + --ifm-font-family-base: "Segoe UI", Roboto, "Helvetica Neue", sans-serif; } /* For readability concerns, you should choose a lighter palette in dark mode. */ @@ -217,13 +218,16 @@ code { .expComponentBadge:before { color: #fff; position: absolute; - top: 0.25rem; + top: 50%; + transform: translateY(-50%); inset-inline-end: 1rem; - border-radius: 0.5rem; - padding: 0.125rem 0.25rem; + border-radius: 3px; + padding: 1px 5px; box-sizing: border-box; - font-size: 0.75rem; - content: "exp"; + font-size: 0.55rem; + font-weight: 700; + letter-spacing: 0.03em; + content: "EXP"; background: #a100c2; pointer-events: none; } @@ -231,13 +235,16 @@ code { .deprComponentBadge:before { color: #fff; position: absolute; - top: 0.25rem; + top: 50%; + transform: translateY(-50%); inset-inline-end: 1rem; - border-radius: 0.5rem; - padding: 0.125rem 0.25rem; + border-radius: 3px; + padding: 1px 5px; box-sizing: border-box; - font-size: 0.75rem; - content: "depr"; + font-size: 0.55rem; + font-weight: 700; + letter-spacing: 0.03em; + content: "DEPR"; background: #ffb700e0; pointer-events: none; } @@ -255,14 +262,17 @@ code { .newComponentBadge:after { color: #fff; position: absolute; - top: 0.25rem; + top: 50%; + transform: translateY(-50%); inset-inline-end: 1rem; - border-radius: 0.5rem; - padding: 0.125rem 0.25rem; + border-radius: 3px; + padding: 1px 5px; box-sizing: border-box; - font-size: 0.75rem; - content: "new"; - background: #334eff; + font-size: 0.55rem; + font-weight: 700; + letter-spacing: 0.03em; + content: "NEW"; + background: linear-gradient(135deg, #6366f1, #8b5cf6); pointer-events: none; } @@ -270,6 +280,8 @@ code { .theme-doc-sidebar-item-category.expComponentBadge:before, .theme-doc-sidebar-item-category.deprComponentBadge:before { inset-inline-end: 2.25rem; + top: 0.45rem; + transform: none; } .theme-doc-sidebar-item-category.newComponentBadge.expComponentBadge:before, @@ -277,6 +289,20 @@ code { inset-inline-end: 4.5rem; } +/* Sparkle icon for new/trending sidebar items — add sidebar_class_name: sidebar-sparkle to frontmatter */ +.sidebar-sparkle > a::after { + content: "NEW"; + margin-left: 0.5rem; + font-size: 0.55rem; + font-weight: 700; + letter-spacing: 0.03em; + padding: 1px 5px; + border-radius: 3px; + background: linear-gradient(135deg, #6366f1, #8b5cf6); + color: #fff; + vertical-align: middle; +} + .componentAdditionalInfo { margin-top: calc(-1 * calc(var(--ifm-h1-vertical-rhythm-bottom) * var(--ifm-leading))) !important; diff --git a/packages/website/src/pages/index.tsx b/packages/website/src/pages/index.tsx index eb64a6c005bb..4c2ae90e267d 100644 --- a/packages/website/src/pages/index.tsx +++ b/packages/website/src/pages/index.tsx @@ -1,7 +1,6 @@ import clsx from 'clsx'; import Link from '@docusaurus/Link'; import { useColorMode } from '@docusaurus/theme-common'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; import HomepageFeatures from '@site/src/components/HomepageFeatures'; import HomepageDemoApps from '@site/src/components/HomepageDemoApps'; @@ -50,11 +49,10 @@ function HomepageHeader() { } export default function Home(): JSX.Element { - const {siteConfig} = useDocusaurusContext(); return ( + title="Enterprise-Grade Web Components" + description="An open-source UI components library implementing SAP Fiori design for building enterprise-ready web applications.">
diff --git a/packages/website/src/theme/DocItem/Content/index.js b/packages/website/src/theme/DocItem/Content/index.js index 89922fcf0e7b..d6e14983db8c 100644 --- a/packages/website/src/theme/DocItem/Content/index.js +++ b/packages/website/src/theme/DocItem/Content/index.js @@ -4,6 +4,7 @@ import {ThemeClassNames} from '@docusaurus/theme-common'; import {useDoc} from '@docusaurus/theme-common/internal'; import Heading from '@theme/Heading'; import MDXContent from '@theme/MDXContent'; +import AskAI from '@site/src/components/AskAI'; /** Title can be declared inside md content or declared through front matter and added manually. To make both cases consistent, @@ -40,8 +41,12 @@ const renderAdditionalInfo = () => { export default function DocItemContent({children}) { const syntheticTitle = useSyntheticTitle(); + const {metadata, frontMatter} = useDoc(); return (
+
+ +
{syntheticTitle && (
{syntheticTitle} diff --git a/skills/accessibility/SKILL.md b/skills/accessibility/SKILL.md new file mode 100644 index 000000000000..0c9e45c81d73 --- /dev/null +++ b/skills/accessibility/SKILL.md @@ -0,0 +1,233 @@ +--- +name: accessibility +description: How to make UI5 Web Components applications accessible. Covers accessibility APIs (accessibleName, accessibleNameRef, accessibleDescription, accessibleRole, accessibilityAttributes), label-input relationships, invisible messaging, keyboard handling, high contrast themes, and screen reader support. Use when the user asks about ARIA attributes, screen readers, keyboard navigation, accessibility properties, or making their app accessible. +user-invocable: false +--- + +# Accessibility in UI5 Web Components + +UI5 Web Components have built-in accessibility: ARIA roles, keyboard navigation, screen reader support, and high contrast themes are handled automatically in the shadow DOM. Applications should use the accessibility APIs described here to provide additional context that only the app can know (labels, descriptions, relationships). + +## Built-in Accessibility (No App Code Needed) + +Components automatically provide: +- **ARIA roles and attributes** mapped in the shadow DOM (e.g., `ui5-combobox` renders `role="combobox"` internally) +- **Keyboard navigation** within complex components (arrow keys in lists, tables, date pickers, etc.) +- **Focus management** with visible focus indicators +- **State mapping** — `disabled`, `readonly`, `required`, `checked` are automatically mapped to their ARIA equivalents (`aria-disabled`, `aria-readonly`, `aria-required`, `aria-checked`) + +## Accessibility APIs + +Use these properties to enrich the accessibility context for your application. + +### accessibleName + +Maps to `aria-label`. Provides a text alternative when the visual label is insufficient or absent. + +```html + + + + + +``` + +Use `accessibleName` when there is no visible text label, for example icon-only buttons or inputs without a ``. + +### accessibleNameRef + +Alternative to `aria-labelledby` that works across shadow DOM boundaries. Takes one or more IDs of elements whose text content serves as the label. + +```html +Full name + + + +Shipping +Address + +``` + +Prefer `accessibleNameRef` over `accessibleName` when a visible label exists — this keeps the label and the ARIA text in sync automatically. + +### accessibleDescription / accessibleDescriptionRef + +Maps to `aria-description`. Provides additional descriptive text beyond the label. + +```html + + + + +

Must be at least 8 characters

+ + +``` + +### accessibleRole + +Overrides the default ARIA role of a component. + +```html +... +... +Navigate +``` + +Only change the role when the component is used in a non-standard way (e.g., a List used as a menu). + +### accessibilityAttributes + +An object that sets additional ARIA attributes on the component's root element. Use for `aria-expanded`, `aria-haspopup`, `aria-controls`, and similar relationship attributes. + +```html +Open Menu +... + + +``` + +For composite components like `ui5-shellbar`, the object contains nested objects for different internal elements — check the component's API docs. + +## Label-Input Relationships + +Due to shadow DOM, standard HTML `