diff --git a/samples/inputs/chip/area/README.md b/samples/inputs/chip/area/README.md new file mode 100644 index 0000000000..3b70ff9b66 --- /dev/null +++ b/samples/inputs/chip/area/README.md @@ -0,0 +1,50 @@ +This folder contains implementation of React application with example of Area feature using [Chip](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component. + + + + + + View Docs + + + View Code + + + Run Sample + + + + +## Branches + +> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository. + +## Instructions + +Follow these instructions to run this example: + + +``` +git clone https://github.com/IgniteUI/igniteui-react-examples.git +cd ./igniteui-react-examples +git checkout master +cd ./samples/inputs/chip/area +``` + +open above folder in VS Code or type: +``` +code . +``` + +In terminal window, run: +``` +npm install +npm start +``` + +Then open http://localhost:4200/ in your browser + + +## Learn More + +To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html). diff --git a/samples/inputs/chip/area/index.html b/samples/inputs/chip/area/index.html new file mode 100644 index 0000000000..29df1657b0 --- /dev/null +++ b/samples/inputs/chip/area/index.html @@ -0,0 +1,11 @@ + + + + ChipArea + + + +
+ + + diff --git a/samples/inputs/chip/area/package.json b/samples/inputs/chip/area/package.json new file mode 100644 index 0000000000..557f6323b5 --- /dev/null +++ b/samples/inputs/chip/area/package.json @@ -0,0 +1,42 @@ +{ + "name": "react-chip-area", + "description": "This project provides example of Chip Area using Infragistics React components", + "author": "Infragistics", + "homepage": ".", + "version": "1.4.0", + "private": true, + "scripts": { + "start": "vite --port 4200", + "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "igniteui-dockmanager": "^2.2.1", + "igniteui-react": "19.9.0", + "igniteui-react-core": "19.6.0", + "igniteui-webcomponents": "~7.4.1", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "tslib": "^2.4.0" + }, + "devDependencies": { + "@types/jest": "^30.0.0", + "@types/node": "^24.7.1", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^5.0.2", + "typescript": "^5.9.3", + "vite": "^8.3.1", + "vitest": "^5.0.2", + "vitest-canvas-mock": "^1.2.0", + "worker-loader": "^3.0.8" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/samples/inputs/chip/area/src/index.css b/samples/inputs/chip/area/src/index.css new file mode 100644 index 0000000000..3d1e663af5 --- /dev/null +++ b/samples/inputs/chip/area/src/index.css @@ -0,0 +1,22 @@ +/* shared styles are loaded from: */ +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +.chips-area-sample { + display: flex; + align-items: center; + justify-content: center; +} + +.chips-area { + --ig-size: var(--ig-size-large); + + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + padding: 0.25rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chips-area igc-chip { + display: flex; +} diff --git a/samples/inputs/chip/area/src/index.tsx b/samples/inputs/chip/area/src/index.tsx new file mode 100644 index 0000000000..bfd707f5c9 --- /dev/null +++ b/samples/inputs/chip/area/src/index.tsx @@ -0,0 +1,22 @@ +import ReactDOM from 'react-dom/client'; +import './index.css'; +import { IgrChip } from 'igniteui-react'; +import 'igniteui-webcomponents/themes/light/bootstrap.css'; + +const chips = ['Chip', 'Chip', 'Chip']; + +export default function ChipArea() { + return ( +
+
+ {chips.map((label, index) => ( + {label} + ))} +
+
+ ); +} + +// rendering above component to the React DOM +const root = ReactDOM.createRoot(document.getElementById('root')!); +root.render(); diff --git a/samples/inputs/chip/area/tsconfig.json b/samples/inputs/chip/area/tsconfig.json new file mode 100644 index 0000000000..e27a22be9b --- /dev/null +++ b/samples/inputs/chip/area/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": [ + "es2020", + "dom", + "dom.iterable" + ], + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "types": [ + "vite/client" + ], + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": [ + "src" + ] +} diff --git a/samples/inputs/chip/area/vite.config.js b/samples/inputs/chip/area/vite.config.js new file mode 100644 index 0000000000..342e2b8e11 --- /dev/null +++ b/samples/inputs/chip/area/vite.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + build: { outDir: 'build' }, + server: { open: false }, +}); diff --git a/samples/inputs/chip/interaction-state/README.md b/samples/inputs/chip/interaction-state/README.md new file mode 100644 index 0000000000..a79640140d --- /dev/null +++ b/samples/inputs/chip/interaction-state/README.md @@ -0,0 +1,50 @@ +This folder contains implementation of React application with example of Interaction State feature using [Chip](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component. + + + + + + View Docs + + + View Code + + + Run Sample + + + + +## Branches + +> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository. + +## Instructions + +Follow these instructions to run this example: + + +``` +git clone https://github.com/IgniteUI/igniteui-react-examples.git +cd ./igniteui-react-examples +git checkout master +cd ./samples/inputs/chip/interaction-state +``` + +open above folder in VS Code or type: +``` +code . +``` + +In terminal window, run: +``` +npm install +npm start +``` + +Then open http://localhost:4200/ in your browser + + +## Learn More + +To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html). diff --git a/samples/inputs/chip/interaction-state/index.html b/samples/inputs/chip/interaction-state/index.html new file mode 100644 index 0000000000..aed2f4e8ab --- /dev/null +++ b/samples/inputs/chip/interaction-state/index.html @@ -0,0 +1,11 @@ + + + + ChipInteractionState + + + +
+ + + diff --git a/samples/inputs/chip/interaction-state/package.json b/samples/inputs/chip/interaction-state/package.json new file mode 100644 index 0000000000..2d5a043bd3 --- /dev/null +++ b/samples/inputs/chip/interaction-state/package.json @@ -0,0 +1,42 @@ +{ + "name": "react-chip-interaction-state", + "description": "This project provides example of Chip Interaction State using Infragistics React components", + "author": "Infragistics", + "homepage": ".", + "version": "1.4.0", + "private": true, + "scripts": { + "start": "vite --port 4200", + "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "igniteui-dockmanager": "^2.2.1", + "igniteui-react": "19.9.0", + "igniteui-react-core": "19.6.0", + "igniteui-webcomponents": "~7.4.1", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "tslib": "^2.4.0" + }, + "devDependencies": { + "@types/jest": "^30.0.0", + "@types/node": "^24.7.1", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^5.0.2", + "typescript": "^5.9.3", + "vite": "^8.3.1", + "vitest": "^5.0.2", + "vitest-canvas-mock": "^1.2.0", + "worker-loader": "^3.0.8" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/samples/inputs/chip/interaction-state/src/index.css b/samples/inputs/chip/interaction-state/src/index.css new file mode 100644 index 0000000000..fd04fa0878 --- /dev/null +++ b/samples/inputs/chip/interaction-state/src/index.css @@ -0,0 +1,35 @@ +/* shared styles are loaded from: */ +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +/* Aktiv Grotesk, from the same Adobe Fonts kit the docs use. */ +@import url("https://use.typekit.net/bng2zgw.css"); + +.chip-states { + --ig-size: var(--ig-size-medium); + + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 1.5rem 3.75rem; +} + +.chip-states-item { + display: flex; + align-items: center; + gap: 1.875rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chip-states-item igc-chip { + display: flex; +} + +.chip-states-item span { + color: var(--ig-gray-600); + font-family: aktiv-grotesk, sans-serif; + font-size: 0.8125rem; + font-weight: 400; + line-height: 1.25rem; + letter-spacing: 0.3px; +} diff --git a/samples/inputs/chip/interaction-state/src/index.tsx b/samples/inputs/chip/interaction-state/src/index.tsx new file mode 100644 index 0000000000..6a6eb29414 --- /dev/null +++ b/samples/inputs/chip/interaction-state/src/index.tsx @@ -0,0 +1,33 @@ +import { useEffect, useRef } from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import { IgrChip } from 'igniteui-react'; +import 'igniteui-webcomponents/themes/light/bootstrap.css'; + +export default function ChipInteractionState() { + const sampleRef = useRef(null); + + // The chips only show their look, so inert keeps them out of the tab order and ignores pointer input. + useEffect(() => { + if (sampleRef.current) { + sampleRef.current.inert = true; + } + }, []); + + return ( +
+
+ Enabled + Chip +
+
+ Disabled + Chip +
+
+ ); +} + +// rendering above component to the React DOM +const root = ReactDOM.createRoot(document.getElementById('root')!); +root.render(); diff --git a/samples/inputs/chip/interaction-state/tsconfig.json b/samples/inputs/chip/interaction-state/tsconfig.json new file mode 100644 index 0000000000..e27a22be9b --- /dev/null +++ b/samples/inputs/chip/interaction-state/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": [ + "es2020", + "dom", + "dom.iterable" + ], + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "types": [ + "vite/client" + ], + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": [ + "src" + ] +} diff --git a/samples/inputs/chip/interaction-state/vite.config.js b/samples/inputs/chip/interaction-state/vite.config.js new file mode 100644 index 0000000000..342e2b8e11 --- /dev/null +++ b/samples/inputs/chip/interaction-state/vite.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + build: { outDir: 'build' }, + server: { open: false }, +}); diff --git a/samples/inputs/chip/layout/README.md b/samples/inputs/chip/layout/README.md new file mode 100644 index 0000000000..33d4b82639 --- /dev/null +++ b/samples/inputs/chip/layout/README.md @@ -0,0 +1,50 @@ +This folder contains implementation of React application with example of Layout feature using [Chip](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component. + + + + + + View Docs + + + View Code + + + Run Sample + + + + +## Branches + +> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository. + +## Instructions + +Follow these instructions to run this example: + + +``` +git clone https://github.com/IgniteUI/igniteui-react-examples.git +cd ./igniteui-react-examples +git checkout master +cd ./samples/inputs/chip/layout +``` + +open above folder in VS Code or type: +``` +code . +``` + +In terminal window, run: +``` +npm install +npm start +``` + +Then open http://localhost:4200/ in your browser + + +## Learn More + +To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html). diff --git a/samples/inputs/chip/layout/index.html b/samples/inputs/chip/layout/index.html new file mode 100644 index 0000000000..43f0a6fbdb --- /dev/null +++ b/samples/inputs/chip/layout/index.html @@ -0,0 +1,11 @@ + + + + ChipLayout + + + +
+ + + diff --git a/samples/inputs/chip/layout/package.json b/samples/inputs/chip/layout/package.json new file mode 100644 index 0000000000..5f3fe8a4f5 --- /dev/null +++ b/samples/inputs/chip/layout/package.json @@ -0,0 +1,42 @@ +{ + "name": "react-chip-layout", + "description": "This project provides example of Chip Layout using Infragistics React components", + "author": "Infragistics", + "homepage": ".", + "version": "1.4.0", + "private": true, + "scripts": { + "start": "vite --port 4200", + "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "igniteui-dockmanager": "^2.2.1", + "igniteui-react": "19.9.0", + "igniteui-react-core": "19.6.0", + "igniteui-webcomponents": "~7.4.1", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "tslib": "^2.4.0" + }, + "devDependencies": { + "@types/jest": "^30.0.0", + "@types/node": "^24.7.1", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^5.0.2", + "typescript": "^5.9.3", + "vite": "^8.3.1", + "vitest": "^5.0.2", + "vitest-canvas-mock": "^1.2.0", + "worker-loader": "^3.0.8" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/samples/inputs/chip/layout/src/index.css b/samples/inputs/chip/layout/src/index.css new file mode 100644 index 0000000000..57aa6c947e --- /dev/null +++ b/samples/inputs/chip/layout/src/index.css @@ -0,0 +1,36 @@ +/* shared styles are loaded from: */ +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +/* Aktiv Grotesk, from the same Adobe Fonts kit the docs use. */ +@import url("https://use.typekit.net/bng2zgw.css"); + +.chip-layout { + --ig-size: var(--ig-size-medium); + + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 1.5rem 3.75rem; +} + +.chip-layout-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chip-layout-item igc-chip { + display: flex; +} + +.chip-layout-item span { + color: var(--ig-gray-600); + font-family: aktiv-grotesk, sans-serif; + font-size: 0.8125rem; + font-weight: 400; + line-height: 1.25rem; + letter-spacing: 0.3px; +} diff --git a/samples/inputs/chip/layout/src/index.tsx b/samples/inputs/chip/layout/src/index.tsx new file mode 100644 index 0000000000..e61875fd28 --- /dev/null +++ b/samples/inputs/chip/layout/src/index.tsx @@ -0,0 +1,60 @@ +import { useEffect, useRef } from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import { IgrChip, IgrIcon, registerIconFromText } from 'igniteui-react'; +import 'igniteui-webcomponents/themes/light/bootstrap.css'; + +const icons = [ + { name: 'arrow_upward', text: '' }, + { name: 'account_circle', text: '' }, +]; + +export default function ChipLayout() { + const sampleRef = useRef(null); + + useEffect(() => { + icons.forEach((icon) => registerIconFromText(icon.name, icon.text, 'material')); + }, []); + + // The chips only show their look, so inert keeps them out of the tab order and ignores pointer input. + useEffect(() => { + if (sampleRef.current) { + sampleRef.current.inert = true; + } + }, []); + + return ( +
+
+ Text + Chip +
+
+ Prefix + + + Chip + +
+
+ Prefix+Suffix + + + Chip + + +
+
+ Suffix + + Chip + + +
+
+ ); +} + +// rendering above component to the React DOM +const root = ReactDOM.createRoot(document.getElementById('root')!); +root.render(); diff --git a/samples/inputs/chip/layout/tsconfig.json b/samples/inputs/chip/layout/tsconfig.json new file mode 100644 index 0000000000..e27a22be9b --- /dev/null +++ b/samples/inputs/chip/layout/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": [ + "es2020", + "dom", + "dom.iterable" + ], + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "types": [ + "vite/client" + ], + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": [ + "src" + ] +} diff --git a/samples/inputs/chip/layout/vite.config.js b/samples/inputs/chip/layout/vite.config.js new file mode 100644 index 0000000000..342e2b8e11 --- /dev/null +++ b/samples/inputs/chip/layout/vite.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + build: { outDir: 'build' }, + server: { open: false }, +}); diff --git a/samples/inputs/chip/outlined/src/index.css b/samples/inputs/chip/outlined/src/index.css index 1f53b8aa05..dddbd2c5fb 100644 --- a/samples/inputs/chip/outlined/src/index.css +++ b/samples/inputs/chip/outlined/src/index.css @@ -1,2 +1,36 @@ /* shared styles are loaded from: */ -/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ \ No newline at end of file +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +/* Aktiv Grotesk, from the same Adobe Fonts kit the docs use. */ +@import url("https://use.typekit.net/bng2zgw.css"); + +.chip-outlined { + --ig-size: var(--ig-size-medium); + + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 1.5rem 2.5rem; +} + +.chip-outlined-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chip-outlined-item igc-chip { + display: flex; +} + +.chip-outlined-item span { + color: var(--ig-gray-600); + font-family: aktiv-grotesk, sans-serif; + font-size: 0.8125rem; + font-weight: 400; + line-height: 1.25rem; + letter-spacing: 0.3px; +} diff --git a/samples/inputs/chip/outlined/src/index.tsx b/samples/inputs/chip/outlined/src/index.tsx index 2d9087d122..022aa3d8a1 100644 --- a/samples/inputs/chip/outlined/src/index.tsx +++ b/samples/inputs/chip/outlined/src/index.tsx @@ -3,33 +3,24 @@ import './index.css'; import { IgrChip } from 'igniteui-react'; import 'igniteui-webcomponents/themes/light/bootstrap.css'; -export default function ChipOutlined() { - - function handleChipRemove(event: CustomEvent) { - const chip = event.target as IgrChip; - chip.remove(); - } +const variants = [ + { label: 'Default', variant: undefined }, + { label: 'Primary', variant: 'primary' }, + { label: 'Info', variant: 'info' }, + { label: 'Success', variant: 'success' }, + { label: 'Warning', variant: 'warning' }, + { label: 'Danger', variant: 'danger' }, +] as const; +export default function ChipOutlined() { return ( -
- - Default - - - Primary - - - Info - - - Success - - - Warning - - - Danger - +
+ {variants.map((item) => ( +
+ {item.label} + Chip +
+ ))}
); } diff --git a/samples/inputs/chip/overview/src/index.css b/samples/inputs/chip/overview/src/index.css index 1f53b8aa05..ffdcc0c911 100644 --- a/samples/inputs/chip/overview/src/index.css +++ b/samples/inputs/chip/overview/src/index.css @@ -1,2 +1,62 @@ /* shared styles are loaded from: */ -/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ \ No newline at end of file +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +.sample { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + padding: 1rem; +} + +.profile-card { + --ig-size: var(--ig-size-medium); + + box-sizing: border-box; + display: flex; + flex-direction: column; + gap: 1rem; + width: 21.875rem; + padding: 1rem; + border: 1px solid var(--ig-gray-200); + border-radius: 0.25rem; + background: var(--ig-surface-500); +} + +.section-header { + display: flex; + align-items: center; + height: 2rem; + padding-inline: 1rem; + color: var(--ig-secondary-500); + font-family: var(--ig-overline-font-family, var(--ig-font-family)); + font-size: var(--ig-overline-font-size); + font-weight: var(--ig-overline-font-weight); + line-height: var(--ig-overline-line-height); + letter-spacing: var(--ig-overline-letter-spacing); + text-transform: var(--ig-overline-text-transform); +} + +.name-input { + --ig-size: var(--ig-size-small); +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.skill { + display: flex; +} + +/* The minimum height keeps the card from shrinking when no skill is selected. */ +.chip-group { + box-sizing: border-box; + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + min-height: 2rem; + padding: 0.25rem; +} + +.actions { + display: flex; + justify-content: flex-end; +} diff --git a/samples/inputs/chip/overview/src/index.tsx b/samples/inputs/chip/overview/src/index.tsx index bc1acb994b..fae16fdec4 100644 --- a/samples/inputs/chip/overview/src/index.tsx +++ b/samples/inputs/chip/overview/src/index.tsx @@ -1,20 +1,95 @@ +import { useEffect, useRef, useState } from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; -import { IgrChip } from 'igniteui-react'; +import { IgrButton, IgrChip, IgrInput } from 'igniteui-react'; import 'igniteui-webcomponents/themes/light/bootstrap.css'; +const skills = ['Figma', 'React', 'CSS', 'Prototyping', 'Motion Design']; + export default function ChipOverview() { + const [name, setName] = useState('Jordan Lee'); + const [selectedSkills, setSelectedSkills] = useState(['Prototyping', 'Motion Design']); + const skillsRef = useRef(null); + const selectedRef = useRef(null); + const removed = useRef<{ skill: string; index: number } | null>(null); + + // Both groups list the selected skills in the order of the skills list. + const selected = skills.filter((skill) => selectedSkills.includes(skill)); + + const toggleSkill = (skill: string, isSelected: boolean) => { + setSelectedSkills((current) => + isSelected ? [...current, skill] : current.filter((item) => item !== skill) + ); + }; + + const removeSkill = (skill: string) => { + removed.current = { skill, index: selected.indexOf(skill) }; + toggleSkill(skill, false); + }; + + // The removed chip is gone, so move focus to the next selected skill, or back to the skill itself when none is left. + useEffect(() => { + if (!removed.current) { + return; + } + const { skill, index } = removed.current; + removed.current = null; - function handleChipRemove(event: CustomEvent) { - const chip = event.target as IgrChip; - chip.remove(); - } + const remaining = selectedRef.current?.querySelectorAll('igc-chip'); + const next = remaining?.[index] ?? remaining?.[index - 1]; + // The chip doesn't delegate focus yet, so focus its inner controls directly. + const target = next + ? next.shadowRoot?.querySelector('[part="remove"] igc-icon') + : skillsRef.current?.querySelectorAll('igc-chip')[skills.indexOf(skill)]?.shadowRoot?.querySelector('[part="action"]'); + target?.focus(); + }, [selectedSkills]); return ( -
- - Chip - +
+
+
+ Name + setName(e.detail)} + /> +
+
+ + Skills ยท {selected.length} selected + +
+ {skills.map((skill) => ( + toggleSkill(skill, e.detail)} + > + {skill} + + ))} +
+
+
+ Selected +
+ {selected.map((skill) => ( + removeSkill(skill)}> + {skill} + + ))} +
+
+
+ Save profile +
+
); } diff --git a/samples/inputs/chip/remove/README.md b/samples/inputs/chip/remove/README.md new file mode 100644 index 0000000000..6e327a7a54 --- /dev/null +++ b/samples/inputs/chip/remove/README.md @@ -0,0 +1,50 @@ +This folder contains implementation of React application with example of Remove feature using [Chip](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component. + + + + + + View Docs + + + View Code + + + Run Sample + + + + +## Branches + +> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository. + +## Instructions + +Follow these instructions to run this example: + + +``` +git clone https://github.com/IgniteUI/igniteui-react-examples.git +cd ./igniteui-react-examples +git checkout master +cd ./samples/inputs/chip/remove +``` + +open above folder in VS Code or type: +``` +code . +``` + +In terminal window, run: +``` +npm install +npm start +``` + +Then open http://localhost:4200/ in your browser + + +## Learn More + +To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html). diff --git a/samples/inputs/chip/remove/index.html b/samples/inputs/chip/remove/index.html new file mode 100644 index 0000000000..817bbc4c3c --- /dev/null +++ b/samples/inputs/chip/remove/index.html @@ -0,0 +1,11 @@ + + + + ChipRemove + + + +
+ + + diff --git a/samples/inputs/chip/remove/package.json b/samples/inputs/chip/remove/package.json new file mode 100644 index 0000000000..0a17a1287c --- /dev/null +++ b/samples/inputs/chip/remove/package.json @@ -0,0 +1,42 @@ +{ + "name": "react-chip-remove", + "description": "This project provides example of Chip Remove using Infragistics React components", + "author": "Infragistics", + "homepage": ".", + "version": "1.4.0", + "private": true, + "scripts": { + "start": "vite --port 4200", + "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "igniteui-dockmanager": "^2.2.1", + "igniteui-react": "19.9.0", + "igniteui-react-core": "19.6.0", + "igniteui-webcomponents": "~7.4.1", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "tslib": "^2.4.0" + }, + "devDependencies": { + "@types/jest": "^30.0.0", + "@types/node": "^24.7.1", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^5.0.2", + "typescript": "^5.9.3", + "vite": "^8.3.1", + "vitest": "^5.0.2", + "vitest-canvas-mock": "^1.2.0", + "worker-loader": "^3.0.8" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/samples/inputs/chip/remove/src/index.css b/samples/inputs/chip/remove/src/index.css new file mode 100644 index 0000000000..c3c4f83730 --- /dev/null +++ b/samples/inputs/chip/remove/src/index.css @@ -0,0 +1,28 @@ +/* shared styles are loaded from: */ +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +.chip-remove { + --ig-size: var(--ig-size-medium); + + display: flex; + align-items: center; + justify-content: center; +} + +/* A row as tall as the chip. The restore button can be taller in some themes, so it + overflows the row evenly instead of resizing the sample when it replaces the chip. */ +.chip-remove-slot { + display: flex; + align-items: center; + justify-content: center; + height: 1.5rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chip-remove-slot igc-chip { + display: flex; +} + +.restore-button { + --ig-size: var(--ig-size-small); +} diff --git a/samples/inputs/chip/remove/src/index.tsx b/samples/inputs/chip/remove/src/index.tsx new file mode 100644 index 0000000000..1d0f9e71f9 --- /dev/null +++ b/samples/inputs/chip/remove/src/index.tsx @@ -0,0 +1,51 @@ +import { useEffect, useRef, useState } from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import { IgrButton, IgrChip } from 'igniteui-react'; +import 'igniteui-webcomponents/themes/light/bootstrap.css'; + +export default function ChipRemove() { + const [isVisible, setIsVisible] = useState(true); + const hasToggled = useRef(false); + const chipRef = useRef(null); + const restoreRef = useRef(null); + + // The control the user activated is gone, so move focus to the one that replaced it. + useEffect(() => { + if (!hasToggled.current) { + return; + } + if (isVisible) { + // The chip renders after this effect and doesn't delegate focus yet, so wait and focus its remove control directly. + const chip = chipRef.current; + chip?.updateComplete.then(() => chip.shadowRoot?.querySelector('[part="remove"] igc-icon')?.focus()); + } else { + restoreRef.current?.focus(); + } + }, [isVisible]); + + const toggleChip = (visible: boolean) => { + hasToggled.current = true; + setIsVisible(visible); + }; + + return ( +
+
+ {isVisible ? ( + toggleChip(false)}> + Chip + + ) : ( + toggleChip(true)}> + Restore chip + + )} +
+
+ ); +} + +// rendering above component to the React DOM +const root = ReactDOM.createRoot(document.getElementById('root')!); +root.render(); diff --git a/samples/inputs/chip/remove/tsconfig.json b/samples/inputs/chip/remove/tsconfig.json new file mode 100644 index 0000000000..e27a22be9b --- /dev/null +++ b/samples/inputs/chip/remove/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": [ + "es2020", + "dom", + "dom.iterable" + ], + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "types": [ + "vite/client" + ], + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": [ + "src" + ] +} diff --git a/samples/inputs/chip/remove/vite.config.js b/samples/inputs/chip/remove/vite.config.js new file mode 100644 index 0000000000..342e2b8e11 --- /dev/null +++ b/samples/inputs/chip/remove/vite.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + build: { outDir: 'build' }, + server: { open: false }, +}); diff --git a/samples/inputs/chip/size/src/index.css b/samples/inputs/chip/size/src/index.css index 54124f8f66..e27d0759e5 100644 --- a/samples/inputs/chip/size/src/index.css +++ b/samples/inputs/chip/size/src/index.css @@ -1,6 +1,37 @@ /* shared styles are loaded from: */ /* https://dl.infragistics.com/x/css/samples/shared.v8.css */ +/* Aktiv Grotesk, from the same Adobe Fonts kit the docs use. */ +@import url("https://use.typekit.net/bng2zgw.css"); + +.chip-size { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 1.5rem 3.75rem; +} + +.chip-size-item { + display: flex; + align-items: center; + gap: 1.875rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chip-size-item igc-chip { + display: flex; +} + +.chip-size-item span { + color: var(--ig-gray-600); + font-family: aktiv-grotesk, sans-serif; + font-size: 0.8125rem; + font-weight: 400; + line-height: 1.25rem; + letter-spacing: 0.3px; +} + .size-small { --ig-size: var(--ig-size-small); } @@ -11,4 +42,4 @@ .size-large { --ig-size: var(--ig-size-large); -} \ No newline at end of file +} diff --git a/samples/inputs/chip/size/src/index.tsx b/samples/inputs/chip/size/src/index.tsx index c55433b30f..94b5651389 100644 --- a/samples/inputs/chip/size/src/index.tsx +++ b/samples/inputs/chip/size/src/index.tsx @@ -1,26 +1,37 @@ +import { useEffect } from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; -import { IgrChip } from 'igniteui-react'; +import { IgrChip, IgrIcon, registerIconFromText } from 'igniteui-react'; import 'igniteui-webcomponents/themes/light/bootstrap.css'; -export default function ChipSize() { +const icons = [ + { name: 'arrow_upward', text: '' }, + { name: 'account_circle', text: '' }, +]; + +const sizes = [ + { label: 'Small', className: 'size-small' }, + { label: 'Medium', className: 'size-medium' }, + { label: 'Large', className: 'size-large' }, +]; - function handleChipRemove(event: CustomEvent) { - const chip = event.target as IgrChip; - chip.remove(); - } +export default function ChipSize() { + useEffect(() => { + icons.forEach((icon) => registerIconFromText(icon.name, icon.text, 'material')); + }, []); return ( -
- - Chip - - - Chip - - - Chip - +
+ {sizes.map((size) => ( +
+ {size.label} + + + Chip + + +
+ ))}
); } diff --git a/samples/inputs/chip/state/README.md b/samples/inputs/chip/state/README.md new file mode 100644 index 0000000000..d686abd9ef --- /dev/null +++ b/samples/inputs/chip/state/README.md @@ -0,0 +1,50 @@ +This folder contains implementation of React application with example of State feature using [Chip](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component. + + + + + + View Docs + + + View Code + + + Run Sample + + + + +## Branches + +> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository. + +## Instructions + +Follow these instructions to run this example: + + +``` +git clone https://github.com/IgniteUI/igniteui-react-examples.git +cd ./igniteui-react-examples +git checkout master +cd ./samples/inputs/chip/state +``` + +open above folder in VS Code or type: +``` +code . +``` + +In terminal window, run: +``` +npm install +npm start +``` + +Then open http://localhost:4200/ in your browser + + +## Learn More + +To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html). diff --git a/samples/inputs/chip/state/index.html b/samples/inputs/chip/state/index.html new file mode 100644 index 0000000000..f309053474 --- /dev/null +++ b/samples/inputs/chip/state/index.html @@ -0,0 +1,11 @@ + + + + ChipState + + + +
+ + + diff --git a/samples/inputs/chip/state/package.json b/samples/inputs/chip/state/package.json new file mode 100644 index 0000000000..ec147149e5 --- /dev/null +++ b/samples/inputs/chip/state/package.json @@ -0,0 +1,42 @@ +{ + "name": "react-chip-state", + "description": "This project provides example of Chip State using Infragistics React components", + "author": "Infragistics", + "homepage": ".", + "version": "1.4.0", + "private": true, + "scripts": { + "start": "vite --port 4200", + "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "igniteui-dockmanager": "^2.2.1", + "igniteui-react": "19.9.0", + "igniteui-react-core": "19.6.0", + "igniteui-webcomponents": "~7.4.1", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "tslib": "^2.4.0" + }, + "devDependencies": { + "@types/jest": "^30.0.0", + "@types/node": "^24.7.1", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^5.0.2", + "typescript": "^5.9.3", + "vite": "^8.3.1", + "vitest": "^5.0.2", + "vitest-canvas-mock": "^1.2.0", + "worker-loader": "^3.0.8" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/samples/inputs/chip/state/src/index.css b/samples/inputs/chip/state/src/index.css new file mode 100644 index 0000000000..ec9e0c9615 --- /dev/null +++ b/samples/inputs/chip/state/src/index.css @@ -0,0 +1,49 @@ +/* shared styles are loaded from: */ +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +/* Aktiv Grotesk, from the same Adobe Fonts kit the docs use. */ +@import url("https://use.typekit.net/bng2zgw.css"); + +.chip-state { + --ig-size: var(--ig-size-medium); + + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 1.5rem 2.5rem; +} + +.chip-state-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chip-state-item igc-chip { + display: flex; +} + +.chip-state-item span { + color: var(--ig-gray-600); + font-family: aktiv-grotesk, sans-serif; + font-size: 0.8125rem; + font-weight: 400; + line-height: 1.25rem; + letter-spacing: 0.3px; +} + +/* Hover and focus only happen on interaction, so these chips show the colors the theme uses for them. */ +igc-chip.state-hover::part(base) { + background: var(--hover-background); + color: var(--hover-text-color); +} + +/* The focus ring color is transparent in themes that show focus through the background alone. */ +igc-chip.state-focused::part(base) { + background: var(--focus-background); + color: var(--focus-text-color); + outline: 0.25rem solid var(--focus-shadow-color); +} diff --git a/samples/inputs/chip/state/src/index.tsx b/samples/inputs/chip/state/src/index.tsx new file mode 100644 index 0000000000..900476d71b --- /dev/null +++ b/samples/inputs/chip/state/src/index.tsx @@ -0,0 +1,48 @@ +import { useEffect, useRef } from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import { IgrChip, IgrIcon, registerIconFromText } from 'igniteui-react'; +import 'igniteui-webcomponents/themes/light/bootstrap.css'; + +const arrowUpwardIcon = ''; + +const states = [ + { label: 'Idle', className: '' }, + { label: 'Hover', className: 'state-hover' }, + { label: 'Focused', className: 'state-focused' }, + { label: 'Selected', className: '', selected: true }, +]; + +export default function ChipState() { + const sampleRef = useRef(null); + + useEffect(() => { + registerIconFromText('arrow_upward', arrowUpwardIcon, 'material'); + }, []); + + // The chips only show their look, so inert keeps them out of the tab order and ignores pointer input. + // It also keeps a real hover or focus from changing the hover and focused chips. + useEffect(() => { + if (sampleRef.current) { + sampleRef.current.inert = true; + } + }, []); + + return ( +
+ {states.map((state) => ( +
+ {state.label} + + + Chip + +
+ ))} +
+ ); +} + +// rendering above component to the React DOM +const root = ReactDOM.createRoot(document.getElementById('root')!); +root.render(); diff --git a/samples/inputs/chip/state/tsconfig.json b/samples/inputs/chip/state/tsconfig.json new file mode 100644 index 0000000000..e27a22be9b --- /dev/null +++ b/samples/inputs/chip/state/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": [ + "es2020", + "dom", + "dom.iterable" + ], + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "types": [ + "vite/client" + ], + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": [ + "src" + ] +} diff --git a/samples/inputs/chip/state/vite.config.js b/samples/inputs/chip/state/vite.config.js new file mode 100644 index 0000000000..342e2b8e11 --- /dev/null +++ b/samples/inputs/chip/state/vite.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + build: { outDir: 'build' }, + server: { open: false }, +}); diff --git a/samples/inputs/chip/styling/package.json b/samples/inputs/chip/styling/package.json index 4092645262..12fde85447 100644 --- a/samples/inputs/chip/styling/package.json +++ b/samples/inputs/chip/styling/package.json @@ -1,6 +1,6 @@ { "name": "react-chip-styling", - "description": "This project provides example of Icon Sizing using Infragistics React components", + "description": "This project provides example of Chip Styling using Infragistics React components", "author": "Infragistics", "homepage": ".", "version": "1.4.0", diff --git a/samples/inputs/chip/styling/src/ChipStyle.css b/samples/inputs/chip/styling/src/ChipStyle.css deleted file mode 100644 index 988dd8101e..0000000000 --- a/samples/inputs/chip/styling/src/ChipStyle.css +++ /dev/null @@ -1,8 +0,0 @@ -igc-chip::part(base) { - background: #011627; - color: #ECAA53; -} - -igc-chip::part(suffix) { - color: #B7B6C2; -} \ No newline at end of file diff --git a/samples/inputs/chip/styling/src/index.css b/samples/inputs/chip/styling/src/index.css index 1f53b8aa05..733162b38c 100644 --- a/samples/inputs/chip/styling/src/index.css +++ b/samples/inputs/chip/styling/src/index.css @@ -1,2 +1,71 @@ /* shared styles are loaded from: */ -/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ \ No newline at end of file +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +.chip-styling { + --ig-size: var(--ig-size-medium); + + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 1.5rem 1.875rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chip-styling igc-chip { + display: flex; +} + +/* Default chip */ +.tag-chip { + --ig-chip-background: var(--ig-error-50); + --ig-chip-text-color: var(--ig-error-50-contrast); + --ig-chip-hover-background: var(--ig-error-100); + --ig-chip-hover-text-color: var(--ig-error-100-contrast); + --ig-chip-focus-background: var(--ig-error-200); + --ig-chip-focus-text-color: var(--ig-error-200-contrast); + --ig-chip-remove-icon-color: var(--ig-error-500); + --ig-chip-remove-icon-color-focus: var(--ig-error-500); +} + +/* Selected chip */ +.filter-chip { + --ig-chip-selected-background: var(--ig-primary-50); + --ig-chip-selected-text-color: var(--ig-primary-50-contrast); + --ig-chip-hover-selected-background: var(--ig-primary-100); + --ig-chip-hover-selected-text-color: var(--ig-primary-100-contrast); + --ig-chip-focus-selected-background: var(--ig-primary-200); + --ig-chip-focus-selected-text-color: var(--ig-primary-200-contrast); +} + +/* The prefix part holds the select icon. */ +.filter-chip::part(prefix) { + color: var(--ig-primary-500); +} + +/* Outlined chips */ +.product-chip { + --ig-chip-outlined-background: var(--ig-surface-500); + --ig-chip-outlined-text-color: var(--ig-gray-700); + --ig-chip-border-color: var(--ig-gray-700); + --ig-chip-hover-outlined-text-color: var(--ig-gray-800); + --ig-chip-hover-border-color: var(--ig-gray-800); + --ig-chip-focus-outlined-text-color: var(--ig-gray-900); + --ig-chip-focus-border-color: var(--ig-gray-900); +} + +.contact-chip { + --ig-chip-outlined-background: var(--ig-secondary-100); + --ig-chip-outlined-text-color: var(--ig-secondary-100-contrast); + --ig-chip-border-color: var(--ig-secondary-500); + --ig-chip-hover-outlined-background: var(--ig-secondary-200); + --ig-chip-hover-outlined-text-color: var(--ig-secondary-200-contrast); + --ig-chip-hover-border-color: var(--ig-secondary-500); + --ig-chip-focus-outlined-background: var(--ig-secondary-300); + --ig-chip-focus-outlined-text-color: var(--ig-secondary-300-contrast); + --ig-chip-focus-border-color: var(--ig-secondary-500); +} + +.contact-chip::part(prefix) { + color: var(--ig-secondary-800); +} diff --git a/samples/inputs/chip/styling/src/index.tsx b/samples/inputs/chip/styling/src/index.tsx index 382f35c202..e0bd718826 100644 --- a/samples/inputs/chip/styling/src/index.tsx +++ b/samples/inputs/chip/styling/src/index.tsx @@ -1,21 +1,35 @@ +import { useEffect } from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; -import './ChipStyle.css'; -import { IgrChip } from 'igniteui-react'; +import { IgrChip, IgrIcon, registerIconFromText } from 'igniteui-react'; import 'igniteui-webcomponents/themes/light/bootstrap.css'; -export default function ChipStyling() { +// The outline takes the chip text color, and the filled half keeps the warning color. +const halfStarIcon = ''; +const peopleIcon = ''; - function handleChipRemove(event: CustomEvent) { - const chip = event.target as IgrChip; - chip.remove(); - } +export default function ChipStyling() { + useEffect(() => { + registerIconFromText('star_half', halfStarIcon, 'material'); + registerIconFromText('people', peopleIcon, 'material'); + }, []); return ( -
- - Chip - +
+ + Prototyping + + + Motion Design + + + Sony Headphones + + + + + Simon and Lisa +
); } diff --git a/samples/inputs/chip/tailwind-styling/README.md b/samples/inputs/chip/tailwind-styling/README.md new file mode 100644 index 0000000000..321bbb9305 --- /dev/null +++ b/samples/inputs/chip/tailwind-styling/README.md @@ -0,0 +1,50 @@ +This folder contains implementation of React application with example of Tailwind Styling feature using [Chip](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component. + + + + + + View Docs + + + View Code + + + Run Sample + + + + +## Branches + +> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository. + +## Instructions + +Follow these instructions to run this example: + + +``` +git clone https://github.com/IgniteUI/igniteui-react-examples.git +cd ./igniteui-react-examples +git checkout master +cd ./samples/inputs/chip/tailwind-styling +``` + +open above folder in VS Code or type: +``` +code . +``` + +In terminal window, run: +``` +npm install +npm start +``` + +Then open http://localhost:4200/ in your browser + + +## Learn More + +To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html). diff --git a/samples/inputs/chip/tailwind-styling/index.html b/samples/inputs/chip/tailwind-styling/index.html new file mode 100644 index 0000000000..89f0a5f35a --- /dev/null +++ b/samples/inputs/chip/tailwind-styling/index.html @@ -0,0 +1,11 @@ + + + + ChipTailwindStyling + + + +
+ + + diff --git a/samples/inputs/chip/tailwind-styling/package.json b/samples/inputs/chip/tailwind-styling/package.json new file mode 100644 index 0000000000..6a2f5378eb --- /dev/null +++ b/samples/inputs/chip/tailwind-styling/package.json @@ -0,0 +1,44 @@ +{ + "name": "react-chip-tailwind-styling", + "description": "This project provides example of Chip Tailwind Styling using Infragistics React components", + "author": "Infragistics", + "homepage": ".", + "version": "1.4.0", + "private": true, + "scripts": { + "start": "vite --port 4200", + "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "igniteui-dockmanager": "^2.2.1", + "igniteui-react": "19.9.0", + "igniteui-react-core": "19.6.0", + "igniteui-webcomponents": "~7.4.1", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "tslib": "^2.4.0" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.1.14", + "@types/jest": "^30.0.0", + "@types/node": "^24.7.1", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^5.0.2", + "tailwindcss": "^4.1.14", + "typescript": "^5.9.3", + "vite": "^8.3.1", + "vitest": "^5.0.2", + "vitest-canvas-mock": "^1.2.0", + "worker-loader": "^3.0.8" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/samples/inputs/chip/tailwind-styling/src/icons.ts b/samples/inputs/chip/tailwind-styling/src/icons.ts new file mode 100644 index 0000000000..eb4b879d56 --- /dev/null +++ b/samples/inputs/chip/tailwind-styling/src/icons.ts @@ -0,0 +1,13 @@ +// Material icons used by the sample, registered in the "material" collection. +export const icons: Record = { + self_improvement: '', + pool: '', + hiking: '', + fitness_center: '', + directions_bike: '', + sports_tennis: '', + sports_soccer: '', + sports_baseball: '', + close: '', + add: '', +}; diff --git a/samples/inputs/chip/tailwind-styling/src/index.css b/samples/inputs/chip/tailwind-styling/src/index.css new file mode 100644 index 0000000000..406353cab3 --- /dev/null +++ b/samples/inputs/chip/tailwind-styling/src/index.css @@ -0,0 +1,22 @@ +/* shared styles are loaded from: */ +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +/* Keep this order. An @import after the Tailwind imports is dropped, and in + the samples browser one before the @layer statement drops the Tailwind + imports, so Aktiv Grotesk goes between them. */ +@layer theme, base, components, utilities; +@import url("https://use.typekit.net/bng2zgw.css"); +@import "tailwindcss/theme.css" layer(theme); +@import "tailwindcss/utilities.css" layer(utilities); +@source "./index.tsx"; + +@theme { + /* The design's own palette. It lives here instead of coming from the theme + palette, so the sample keeps its colors in every theme. */ + --color-activity-primary: #006ae6; + --color-activity-primary-strong: #0055b8; + --color-activity-tint: #e6f2ff; + --color-activity-tint-strong: #cce4ff; + --color-activity-surface: #e5ebf3; + --color-activity-ink: #00142b; +} diff --git a/samples/inputs/chip/tailwind-styling/src/index.tsx b/samples/inputs/chip/tailwind-styling/src/index.tsx new file mode 100644 index 0000000000..b5af738262 --- /dev/null +++ b/samples/inputs/chip/tailwind-styling/src/index.tsx @@ -0,0 +1,123 @@ +import { useEffect, useRef, useState } from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import { IgrChip, IgrIcon, registerIconFromText } from 'igniteui-react'; +import 'igniteui-webcomponents/themes/light/bootstrap.css'; +import { icons } from './icons'; + +const activities = [ + { label: 'Yoga', icon: 'self_improvement' }, + { label: 'Swimming', icon: 'pool' }, + { label: 'Hiking', icon: 'hiking' }, + { label: 'Lifting', icon: 'fitness_center' }, + { label: 'Cycling', icon: 'directions_bike' }, + { label: 'Tennis', icon: 'sports_tennis' }, + { label: 'Soccer', icon: 'sports_soccer' }, + { label: 'Baseball', icon: 'sports_baseball' }, +]; + +type Activity = (typeof activities)[number]; + +const chipLabel = 'text-sm font-medium leading-5 tracking-[0.25px]'; + +// `flex` keeps the chip host's line box from adding height around the chip. +const selectedChip = + 'flex [--ig-chip-border-radius:0.5rem] ' + + '[--ig-chip-background:var(--color-activity-primary)] [--ig-chip-text-color:white] ' + + '[--ig-chip-hover-background:var(--color-activity-primary-strong)] [--ig-chip-hover-text-color:white] ' + + '[--ig-chip-focus-background:var(--color-activity-primary-strong)] [--ig-chip-focus-text-color:white] ' + + '[--ig-chip-remove-icon-color:white] [--ig-chip-remove-icon-color-focus:white]'; + +const availableChip = + 'flex [--ig-chip-border-radius:0.5rem] [--ig-chip-border-color:var(--color-activity-primary)] ' + + '[--ig-chip-outlined-background:var(--color-activity-tint)] [--ig-chip-outlined-text-color:var(--color-activity-primary)] ' + + '[--ig-chip-hover-outlined-background:var(--color-activity-tint-strong)] [--ig-chip-hover-outlined-text-color:var(--color-activity-primary)] [--ig-chip-hover-border-color:var(--color-activity-primary)] ' + + '[--ig-chip-focus-outlined-background:var(--color-activity-tint-strong)] [--ig-chip-focus-outlined-text-color:var(--color-activity-primary)] [--ig-chip-focus-border-color:var(--color-activity-primary)]'; + +export default function ChipTailwindStyling() { + const [selected, setSelected] = useState(activities.slice(0, 2)); + const available = activities.filter((activity) => !selected.includes(activity)); + const cardRef = useRef(null); + const focusTarget = useRef<{ list: 'selected' | 'available'; label: string } | null>(null); + + useEffect(() => { + Object.entries(icons).forEach(([name, svg]) => registerIconFromText(name, svg, 'material')); + }, []); + + // The chip that had focus is gone, so focus a chip in the same list, or the moved chip when that list is empty. + useEffect(() => { + const target = focusTarget.current; + focusTarget.current = null; + const chip = target && cardRef.current?.querySelector(`[data-activity="${target.label}"]`); + if (!target || !chip) { + return; + } + // A moved chip renders after this effect, and chips don't delegate focus yet, so wait and focus the control directly. + chip.updateComplete.then(() => { + const control = target.list === 'selected' + ? chip.querySelector('[slot="remove"]') + : chip.shadowRoot?.querySelector('[part="action"]'); + control?.focus(); + }); + }, [selected]); + + const addActivity = (activity: Activity) => { + const rest = available.filter((item) => item !== activity); + const next = rest[Math.min(available.indexOf(activity), rest.length - 1)]; + focusTarget.current = next ? { list: 'available', label: next.label } : { list: 'selected', label: activity.label }; + setSelected([...selected, activity]); + }; + + const removeActivity = (activity: Activity) => { + const rest = selected.filter((item) => item !== activity); + const next = rest[Math.min(selected.indexOf(activity), rest.length - 1)]; + focusTarget.current = next ? { list: 'selected', label: next.label } : { list: 'available', label: activity.label }; + setSelected(rest); + }; + + return ( +
+
+ {/* Not a heading: the theme's heading styles sit outside any CSS layer and would override these utilities. */} + + Preferred Activity + +
+ {selected.map((activity) => ( + removeActivity(activity)}> + + {activity.label} + + + ))} +
+
+ {available.map((activity) => ( + addActivity(activity)}> + + {activity.label} + + ))} +
+
+
+ ); +} + +// rendering above component to the React DOM +const root = ReactDOM.createRoot(document.getElementById('root')!); +root.render(); diff --git a/samples/inputs/chip/tailwind-styling/tsconfig.json b/samples/inputs/chip/tailwind-styling/tsconfig.json new file mode 100644 index 0000000000..e27a22be9b --- /dev/null +++ b/samples/inputs/chip/tailwind-styling/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": [ + "es2020", + "dom", + "dom.iterable" + ], + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "types": [ + "vite/client" + ], + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": [ + "src" + ] +} diff --git a/samples/inputs/chip/tailwind-styling/vite.config.js b/samples/inputs/chip/tailwind-styling/vite.config.js new file mode 100644 index 0000000000..4043727956 --- /dev/null +++ b/samples/inputs/chip/tailwind-styling/vite.config.js @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import tailwindcss from '@tailwindcss/vite'; + +export default defineConfig({ + plugins: [react(), tailwindcss()], + build: { + outDir: 'build', + }, + server: { + open: false, + }, +}); diff --git a/samples/inputs/chip/types/README.md b/samples/inputs/chip/types/README.md new file mode 100644 index 0000000000..44623b28b0 --- /dev/null +++ b/samples/inputs/chip/types/README.md @@ -0,0 +1,50 @@ +This folder contains implementation of React application with example of Types feature using [Chip](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component. + + + + + + View Docs + + + View Code + + + Run Sample + + + + +## Branches + +> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository. + +## Instructions + +Follow these instructions to run this example: + + +``` +git clone https://github.com/IgniteUI/igniteui-react-examples.git +cd ./igniteui-react-examples +git checkout master +cd ./samples/inputs/chip/types +``` + +open above folder in VS Code or type: +``` +code . +``` + +In terminal window, run: +``` +npm install +npm start +``` + +Then open http://localhost:4200/ in your browser + + +## Learn More + +To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html). diff --git a/samples/inputs/chip/types/index.html b/samples/inputs/chip/types/index.html new file mode 100644 index 0000000000..a31d6022f0 --- /dev/null +++ b/samples/inputs/chip/types/index.html @@ -0,0 +1,11 @@ + + + + ChipTypes + + + +
+ + + diff --git a/samples/inputs/chip/types/package.json b/samples/inputs/chip/types/package.json new file mode 100644 index 0000000000..4cc024b7fa --- /dev/null +++ b/samples/inputs/chip/types/package.json @@ -0,0 +1,42 @@ +{ + "name": "react-chip-types", + "description": "This project provides example of Chip Types using Infragistics React components", + "author": "Infragistics", + "homepage": ".", + "version": "1.4.0", + "private": true, + "scripts": { + "start": "vite --port 4200", + "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "igniteui-dockmanager": "^2.2.1", + "igniteui-react": "19.9.0", + "igniteui-react-core": "19.6.0", + "igniteui-webcomponents": "~7.4.1", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "tslib": "^2.4.0" + }, + "devDependencies": { + "@types/jest": "^30.0.0", + "@types/node": "^24.7.1", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.1", + "@vitest/browser": "^5.0.2", + "typescript": "^5.9.3", + "vite": "^8.3.1", + "vitest": "^5.0.2", + "vitest-canvas-mock": "^1.2.0", + "worker-loader": "^3.0.8" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/samples/inputs/chip/types/src/index.css b/samples/inputs/chip/types/src/index.css new file mode 100644 index 0000000000..cbe7b50c7c --- /dev/null +++ b/samples/inputs/chip/types/src/index.css @@ -0,0 +1,35 @@ +/* shared styles are loaded from: */ +/* https://dl.infragistics.com/x/css/samples/shared.v8.css */ + +/* Aktiv Grotesk, from the same Adobe Fonts kit the docs use. */ +@import url("https://use.typekit.net/bng2zgw.css"); + +.chip-types { + --ig-size: var(--ig-size-medium); + + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 1.5rem 3.75rem; +} + +.chip-types-item { + display: flex; + align-items: center; + gap: 1.875rem; +} + +/* The chip host is a block box, so its line box would add height around the chip. */ +.chip-types-item igc-chip { + display: flex; +} + +.chip-types-item span { + color: var(--ig-gray-600); + font-family: aktiv-grotesk, sans-serif; + font-size: 0.8125rem; + font-weight: 400; + line-height: 1.25rem; + letter-spacing: 0.3px; +} diff --git a/samples/inputs/chip/types/src/index.tsx b/samples/inputs/chip/types/src/index.tsx new file mode 100644 index 0000000000..b3fc3a722c --- /dev/null +++ b/samples/inputs/chip/types/src/index.tsx @@ -0,0 +1,33 @@ +import { useEffect, useRef } from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import { IgrChip } from 'igniteui-react'; +import 'igniteui-webcomponents/themes/light/bootstrap.css'; + +export default function ChipTypes() { + const sampleRef = useRef(null); + + // The chips only show their look, so inert keeps them out of the tab order and ignores pointer input. + useEffect(() => { + if (sampleRef.current) { + sampleRef.current.inert = true; + } + }, []); + + return ( +
+
+ Default + Chip +
+
+ Primary + Chip +
+
+ ); +} + +// rendering above component to the React DOM +const root = ReactDOM.createRoot(document.getElementById('root')!); +root.render(); diff --git a/samples/inputs/chip/types/tsconfig.json b/samples/inputs/chip/types/tsconfig.json new file mode 100644 index 0000000000..e27a22be9b --- /dev/null +++ b/samples/inputs/chip/types/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": [ + "es2020", + "dom", + "dom.iterable" + ], + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "types": [ + "vite/client" + ], + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": [ + "src" + ] +} diff --git a/samples/inputs/chip/types/vite.config.js b/samples/inputs/chip/types/vite.config.js new file mode 100644 index 0000000000..342e2b8e11 --- /dev/null +++ b/samples/inputs/chip/types/vite.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + build: { outDir: 'build' }, + server: { open: false }, +});