diff --git a/.vscode/settings.json b/.vscode/settings.json index dba6f75..e0f29f3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -23,6 +23,7 @@ }, "cSpell.words": [ "csspart", - "cssproperty" + "cssproperty", + "Osano" ] } diff --git a/README.md b/README.md index 1476ad4..cf78cc2 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,9 @@ npm install @linuxfoundation/lfx-ui-core - [Design Tokens](docs/design-tokens.md) - [Prettier Configuration](docs/prettier-config.md) - Components + - [Components Overview](docs/components.md) - [Footer Component](docs/footer.md) + - [Tools Component](docs/tools.md) ## Contributing diff --git a/docs/components.md b/docs/components.md new file mode 100644 index 0000000..de375fe --- /dev/null +++ b/docs/components.md @@ -0,0 +1,170 @@ +# LFX UI Core Components + +This document provides an overview of all available components in the LFX UI Core package. + +## Available Components + +### Footer Component (`lfx-footer`) + +A comprehensive footer component that provides consistent copyright and legal information across LFX applications. + +**Key Features:** + +- **Cookie Consent Integration**: Optional Osano cookie consent script loading +- **Extensive Customization**: CSS custom properties for complete theming +- **Accessibility**: Built-in accessibility features and semantic HTML +- **Responsive Design**: Mobile-optimized with responsive breakpoints +- **CSS Parts**: Fine-grained styling control with CSS parts + +**Usage:** + +```html + + + + + + + + +``` + +**Documentation:** [Footer Component](footer.md) + +### Tools Component (`lfx-tools`) + +A tools menu component that provides a grid icon button that opens a dropdown menu with various LFX tools and applications. + +**Key Features:** + +- **Dynamic Menu**: Configurable menu structure with sections and items +- **Font Awesome Integration**: Support for Font Awesome Pro icons +- **Active State Management**: Automatic highlighting of current product +- **Accessibility**: Proper ARIA attributes and keyboard navigation +- **Customizable Styling**: CSS custom properties for theming + +**Usage:** + +```html + + + + + + + + +``` + +**Documentation:** [Tools Component](tools.md) + +## Component Features Overview + +| Feature | Footer | Tools | +| --------------------- | ------ | ----- | +| Cookie Tracking | ✅ | ❌ | +| CSS Custom Properties | ✅ | ✅ | +| CSS Parts | ✅ | ✅ | +| Accessibility | ✅ | ✅ | +| Responsive Design | ✅ | ✅ | +| Framework Agnostic | ✅ | ✅ | +| TypeScript Support | ✅ | ✅ | + +## Installation and Setup + +### Basic Installation + +```bash +npm install @linuxfoundation/lfx-ui-core +``` + +### Import Components + +```typescript +// Import all components +import '@linuxfoundation/lfx-ui-core'; + +// Or import individual components +import '@linuxfoundation/lfx-ui-core/dist/components/footer'; +import '@linuxfoundation/lfx-ui-core/dist/components/tools'; +``` + +### Framework Integration + +#### Angular + +```typescript +// In main.ts or app.module.ts +import '@linuxfoundation/lfx-ui-core'; +``` + +#### Vue + +```typescript +// In main.js +import '@linuxfoundation/lfx-ui-core'; +``` + +#### React + +```typescript +// In your main component or index file +import '@linuxfoundation/lfx-ui-core'; +``` + +## Design System Integration + +All components are built to work seamlessly with the LFX design system: + +- **Design Tokens**: Components use semantic design tokens for consistent theming +- **Theme Support**: Automatic integration with PrimeOne theme system +- **Customization**: Extensive CSS custom properties for framework-specific theming +- **Accessibility**: Built-in accessibility features following WCAG guidelines + +## Development + +### Storybook + +Run Storybook to explore all components and their variations: + +```bash +npm run storybook +``` + +Navigate to [http://localhost:6006](http://localhost:6006) to view the component library. + +### Building + +```bash +npm run build +``` + +### Testing + +```bash +npm test +``` + +## Contributing + +When adding new components: + +1. Follow the established component structure and patterns +2. Include comprehensive JSDoc documentation +3. Create Storybook stories for all variations +4. Add accessibility features and tests +5. Update this documentation +6. Follow the TypeScript and vanilla web component standards + +## Browser Support + +All components support: + +- Chrome 88+ +- Firefox 85+ +- Safari 14+ +- Edge 88+ + +## License + +MIT License - see [LICENSE](../LICENSE) for details. diff --git a/docs/footer.md b/docs/footer.md index 454693f..8d96193 100644 --- a/docs/footer.md +++ b/docs/footer.md @@ -1,6 +1,6 @@ # Footer Component -The footer component provides a consistent bottom section for your application with comprehensive styling options. Here's how to implement and customize it across different frameworks. +The footer component provides a consistent bottom section for your application with comprehensive styling options and optional cookie consent script integration. Here's how to implement and customize it across different frameworks. ## Basic Usage @@ -52,6 +52,107 @@ Then, use the component in your HTML: Example: [https://stackblitz.com/edit/vitejs-vite-vn2ysk?file=index.html](https://stackblitz.com/edit/vitejs-vite-vn2ysk?file=index.html) +## Features + +### Cookie Consent Integration + +The footer component can automatically load the Osano cookie consent script when the `cookie-tracking` attribute is present: + +```html + + + + + + + + + + + +``` + +**Important Notes:** + +- The script will only be loaded once, even if multiple footer components have cookie tracking enabled +- The script is loaded asynchronously for better performance +- The component automatically handles script deduplication +- Works in both browser and server-side rendering environments +- Includes error handling for script loading failures + +### Error Handling + +The component provides error handling for script loading failures: + +```javascript +const footer = document.querySelector('lfx-footer'); + +footer.addEventListener('cookie-script-error', (event) => { + console.error('Cookie script failed to load:', event.detail.error); + // Implement fallback behavior if needed +}); +``` + +**Error Event Details:** + +- `event.detail.scriptSrc`: The script URL that failed to load +- `event.detail.error`: Error description + +### Framework-Specific Cookie Tracking + +#### Angular + +```typescript +// In your component template + + +// In your component class +export class AppComponent { + enableCookieTracking = true; +} +``` + +#### Vue + +```vue + + + +``` + +#### React + +```jsx +function App() { + const [enableCookieTracking, setEnableCookieTracking] = useState(true); + + return ; +} +``` + +## Attributes + +| Attribute | Type | Description | Default | +| ----------------- | ------- | ------------------------------------------ | ------- | +| `cookie-tracking` | boolean | Enable Osano cookie consent script loading | `false` | + +**Boolean Attribute Behavior:** + +- `cookie-tracking` (no value) = enabled +- `cookie-tracking="true"` = enabled +- `cookie-tracking="false"` = disabled +- No attribute = disabled + ## Styling and Customization The footer component is highly customizable using CSS custom properties. Here are the available styling options: diff --git a/package.json b/package.json index d062173..b2dee1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@linuxfoundation/lfx-ui-core", - "version": "0.0.17-alpha.2", + "version": "0.0.0", "description": "LFX UI Core Configurations and Components", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/components/footer/footer.component.ts b/src/components/footer/footer.component.ts index 384504b..b068429 100644 --- a/src/components/footer/footer.component.ts +++ b/src/components/footer/footer.component.ts @@ -7,7 +7,7 @@ import { style } from './footer.style'; /** * @element lfx-footer * @summary A footer component for LFX applications - * @description This component provides a consistent footer across LFX applications + * @description This component provides a consistent footer across LFX applications with optional cookie consent script integration * @csspart footer - The main footer element * @csspart footer-container - The main container of the footer * @csspart footer-content - The content wrapper of the footer @@ -21,10 +21,15 @@ import { style } from './footer.style'; * @cssproperty --lfx-footer-padding - Padding of the footer * @cssproperty --lfx-footer-font-size - Font size of footer text * @cssproperty --lfx-footer-font-family - Font family of footer text + * + * @attr {boolean} cookie-tracking - When true, appends the Osano cookie consent script to the document + * + * @fires cookie-script-error - Fired when the cookie consent script fails to load */ export class LFXFooter extends HTMLElement { private _template!: HTMLTemplateElement; private _rendered = false; + private static readonly OSANO_SCRIPT_SRC = 'https://cmp.osano.com/16A0DbT9yDNIaQkvZ/d6ac078e-c71f-4b96-8c97-818cc1cc6632/osano.js?variant=two'; constructor() { super(); @@ -32,6 +37,16 @@ export class LFXFooter extends HTMLElement { this._createTemplate(); } + static get observedAttributes(): string[] { + return ['cookie-tracking']; + } + + attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void { + if (name === 'cookie-tracking' && this._rendered) { + this._handleCookieTracking(); + } + } + private _createTemplate(): void { this._template = document.createElement('template'); this._template.innerHTML = ` @@ -62,6 +77,56 @@ export class LFXFooter extends HTMLElement { this.shadowRoot!.appendChild(content); this._rendered = true; } + + // Check if cookie tracking should be enabled + this._handleCookieTracking(); + } + + private _handleCookieTracking(): void { + const cookieTrackingAttr = this.getAttribute('cookie-tracking'); + const shouldEnable = cookieTrackingAttr === 'true' || cookieTrackingAttr === ''; + + if (shouldEnable) { + this._appendOsanoScript(); + } + } + + private _appendOsanoScript(): void { + if (typeof document === 'undefined') { + return; + } + + // Check if the script already exists to prevent duplicates + const existingScript = document.querySelector(`script[src="${LFXFooter.OSANO_SCRIPT_SRC}"]`); + if (existingScript) { + return; + } + + // Create and append the script + const script = document.createElement('script'); + script.src = LFXFooter.OSANO_SCRIPT_SRC; + script.async = true; + + // Add error handling + script.onerror = () => { + console.error('LFXFooter: Failed to load Osano cookie consent script'); + // Dispatch custom event for error handling + this.dispatchEvent( + new CustomEvent('cookie-script-error', { + bubbles: true, + detail: { + scriptSrc: LFXFooter.OSANO_SCRIPT_SRC, + error: 'Script failed to load', + }, + }) + ); + }; + + if (document.head) { + document.head.appendChild(script); + } else { + document.body?.appendChild(script); + } } } diff --git a/src/components/footer/footer.stories.ts b/src/components/footer/footer.stories.ts index 7339488..8e5ac37 100644 --- a/src/components/footer/footer.stories.ts +++ b/src/components/footer/footer.stories.ts @@ -5,7 +5,7 @@ import { Meta, StoryObj } from '@storybook/web-components'; import { html } from 'lit'; import './footer.component'; -// Type for CSS custom properties +// Type for CSS custom properties and attributes interface FooterCSSProps { '--lfx-footer-bg'?: string; '--lfx-footer-text'?: string; @@ -14,6 +14,7 @@ interface FooterCSSProps { '--lfx-footer-padding'?: string; '--lfx-footer-font-size'?: string; '--lfx-footer-text-align'?: string; + 'cookie-tracking'?: boolean; [key: string]: any; } @@ -27,6 +28,12 @@ const meta: Meta = { component: ` A footer component that displays consistent copyright and legal information across LFX applications. +## Features +- **Cookie Tracking**: Enable Osano cookie consent script with the \`cookie-tracking\` attribute +- **Customizable Styling**: Extensive CSS custom properties for theming +- **Accessibility**: Semantic HTML with proper ARIA attributes +- **Responsive**: Mobile-optimized design + ## Styling The footer can be styled using CSS custom properties for maximum flexibility: @@ -46,6 +53,11 @@ Plus many more for advanced customization including responsive and accessibility }, }, argTypes: { + 'cookie-tracking': { + control: 'boolean', + description: 'Enable Osano cookie consent script', + table: { category: 'Attributes' }, + }, '--lfx-footer-bg': { control: 'color', description: 'Background color of the footer', @@ -91,7 +103,7 @@ Plus many more for advanced customization including responsive and accessibility return html`
- +
`; }, @@ -105,6 +117,25 @@ export const Default: Story = { args: {}, }; +// Footer with cookie tracking enabled +export const WithCookieTracking: Story = { + args: { + 'cookie-tracking': true, + }, + parameters: { + docs: { + description: { + story: ` +This story demonstrates the footer with cookie tracking enabled. When the \`cookie-tracking\` attribute is set to \`true\`, +the component will automatically append the Osano cookie consent script to the document head. + +**Note**: The script will only be added once, even if multiple footer components have cookie tracking enabled. + `, + }, + }, + }, +}; + // Light theme export const LightTheme: Story = { args: {