diff --git a/website/docs/docs/introduction.md b/website/docs/docs/introduction.md index 5301dae396d..2254738a8e5 100644 --- a/website/docs/docs/introduction.md +++ b/website/docs/docs/introduction.md @@ -17,13 +17,6 @@ Read more about why we want to enable analysts to work more like software engine Use dbt to quickly and collaboratively transform data and deploy analytics code following software engineering best practices like version control, modularity, portability, CI/CD, and documentation. This means anyone on the data team comfortable with SQL can safely contribute to production-grade data pipelines. - - ### dbt Cloud dbt Cloud offers the fastest, most reliable, and scalable way to deploy dbt. Allowing data teams to optimize their data transformation by developing, testing, scheduling, and investigating data models using a single, fully managed service through a web-based user interface (UI). diff --git a/website/src/components/expandable/index.js b/website/src/components/expandable/index.js index 3cf87b3cd34..6abc84cf0fd 100644 --- a/website/src/components/expandable/index.js +++ b/website/src/components/expandable/index.js @@ -10,7 +10,7 @@ function slugify(text) { .replace(/[\u0300-\u036f]/g, '') // remove diacritics .replace(/\s+/g, '-') // replace spaces with - .replace(/[^\w\-]+/g, '') // remove all non-word chars - .replace(/\-\-+/g, '-') // replace multipl - with a single - + .replace(/\-\-+/g, '-') // replace multiple - with a single - .replace(/^-+/, '') // trim - from the start .replace(/-+$/, ''); // trim - from the end } @@ -39,43 +39,46 @@ function Expandable({ children, alt_header = null, lifecycle }) { popup.classList.add('copy-popup'); popup.innerText = 'Link copied!'; - // Add close button ('x') - const closeButton = document.createElement('span'); - closeButton.classList.add('close-button'); - closeButton.innerHTML = ' ×'; // '×' symbol for 'x' - closeButton.addEventListener('click', () => { - if (document.body.contains(popup)) { - document.body.removeChild(popup); - } - }); - popup.appendChild(closeButton); + // Add close button ('x') + const closeButton = document.createElement('span'); + closeButton.classList.add('close-button'); + closeButton.innerHTML = ' ×'; // '×' symbol for 'x' + closeButton.addEventListener('click', () => { + if (document.body.contains(popup)) { + document.body.removeChild(popup); + } + }); + popup.appendChild(closeButton); - document.body.appendChild(popup); + document.body.appendChild(popup); - setTimeout(() => { - if (document.body.contains(popup)) { - document.body.removeChild(popup); - } - }, 3000); -}; + setTimeout(() => { + if (document.body.contains(popup)) { + document.body.removeChild(popup); + } + }, 3000); + }; -useEffect(() => { - if (window.location.hash === `#${anchorId}`) { - setOn(true); - const element = document.getElementById(anchorId); - if (element) { - element.scrollIntoView({ behavior: 'smooth' }); + useEffect(() => { + if (window.location.hash === `#${anchorId}`) { + setOn(true); + const element = document.getElementById(anchorId); + if (element) { + element.scrollIntoView({ behavior: 'smooth' }); + } } - } -}, [anchorId]); + }, [anchorId]); return ( -
+
  - {alt_header} + {alt_header} + e.stopPropagation()}> + +
diff --git a/website/src/components/lifeCycle/index.js b/website/src/components/lifeCycle/index.js index 200c948109c..c27906f6c48 100644 --- a/website/src/components/lifeCycle/index.js +++ b/website/src/components/lifeCycle/index.js @@ -1,5 +1,8 @@ -import React from 'react' +/* eslint-disable */ + +import React from 'react'; import styles from './styles.module.css'; +import { STATUS_URLS } from './lifecycle-urls.js'; const statusColors = { enterprise: '#EBEDF0', @@ -12,14 +15,19 @@ const statusColors = { }; const fontColors = { - enterprise: '#262A38', - team: '#262A38', - developer: '#262A38', - // lifecycle statuses use the css determined font color (white) - }; + enterprise: '#262A38', + team: '#262A38', + developer: '#262A38', + preview: '#ffff', + beta: '#ffff', + ga: '#ffff', +}; + +// URL mapping for predefined lifecycle statuses. urls defined in ../lifeCycle/lifecycle-urls.js file so we can update them in one place +const statusUrls = STATUS_URLS; export default function Lifecycle(props) { - const statuses = props.status?.split(',') + const statuses = props.status?.split(','); if (!props.status || !statuses?.length) { return null; } @@ -27,13 +35,43 @@ export default function Lifecycle(props) { return ( <> {statuses.map((status, index) => { + const isKnownStatus = Object.prototype.hasOwnProperty.call(statusColors, status); + const url = isKnownStatus ? statusUrls[status] || props.customUrl || null : null; + const style = { - backgroundColor: props.backgroundColor || statusColors[status] || '#047377', // default to teal if no match - color: fontColors[status] || '#fff' // default font color if no matc + backgroundColor: props.backgroundColor || statusColors[status] || '#d3d3d3', // Default gray for unknown status + color: fontColors[status] || '#000', // Default black for unknown status + cursor: url ? 'pointer' : 'default', // Non-clickable for unknown status + transition: 'background-color 0.2s ease, transform 0.2s ease, text-decoration 0.2s ease', + padding: '5px 10px', + borderRadius: '16px', + textDecoration: url ? 'underline' : 'none', // Underline for clickable pills only }; + // Render a clickable pill for known statuses with a URL + if (url) { + return ( + + {status} + + ); + } + + // Render a static pill for unknown or unlinked statuses return ( - + {status} ); diff --git a/website/src/components/lifeCycle/lifecycle-urls.js b/website/src/components/lifeCycle/lifecycle-urls.js new file mode 100644 index 00000000000..ddc731eef8f --- /dev/null +++ b/website/src/components/lifeCycle/lifecycle-urls.js @@ -0,0 +1,11 @@ +const PRODUCT_LIFECYCLE_URL = 'https://docs.getdbt.com/docs/dbt-versions/product-lifecycles'; +const PLAN_URL = 'https://www.getdbt.com/pricing'; + +export const STATUS_URLS = { + enterprise: PLAN_URL, + team: PLAN_URL, + developer: 'https://www.getdbt.com/signup', + beta: PRODUCT_LIFECYCLE_URL, + preview: PRODUCT_LIFECYCLE_URL, + ga: PRODUCT_LIFECYCLE_URL, +}; diff --git a/website/src/components/lifeCycle/styles.module.css b/website/src/components/lifeCycle/styles.module.css index d7c0661d932..fdd016dff67 100644 --- a/website/src/components/lifeCycle/styles.module.css +++ b/website/src/components/lifeCycle/styles.module.css @@ -5,11 +5,26 @@ font-weight: 600; /* Normal font weight */ padding: 1px 8px; /* Adjust padding for a more pill-like shape */ border-radius: 16px; /* Larger border-radius for rounded edges */ - margin-left: 8px; /* Margin to separate from the header text */ + margin-left: 16px; /* Margin to separate from the header text */ vertical-align: middle; /* Align with the title */ display: inline-block; /* Use inline-block for better control */ text-transform: capitalize; /* Uppercase text */ line-height: 1.6; /* Adjust line height for vertical alignment */ + text-decoration: none; /* No underline by default */ + transition: background-color 0.2s ease, transform 0.2s ease, text-decoration 0.2s ease; + cursor: pointer; } +.lifecycle:hover { + background-color: #EBEDF0; + color: #e3f2fd; + text-decoration: underline; + box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.2); + transform: scale(1.09); /* Slightly enlarge the pill */ +} + +.lifecycle:focus { + outline: 2px solid #EBEDF0; /* Focus outline for accessibility */ + outline-offset: 2px; +}