diff --git a/documentation/ingestion-overview.md b/documentation/ingestion-overview.md index a91fc32ad..6b60cc06f 100644 --- a/documentation/ingestion-overview.md +++ b/documentation/ingestion-overview.md @@ -8,6 +8,8 @@ description: import Screenshot from "@theme/Screenshot" +import { Clients } from "../src/components/Clients" + QuestDB makes top performance "data-in" easy. This guide will prepare you to get the most out of (and into!) QuestDB. @@ -24,13 +26,7 @@ with high volume, [high cardinality](/glossary/high-cardinality/) data streaming To start quickly, select your language: -- [C & C++](/docs/clients/ingest-c-and-cpp) -- [.NET](/docs/clients/ingest-dotnet) -- [Go](/docs/clients/ingest-go) -- [Java](/docs/clients/java_ilp) -- [Node.js](/docs/clients/ingest-node) -- [Python](/docs/clients/ingest-python) -- [Rust](/docs/clients/ingest-rust) + Our clients utitilize the InfluxDB Line Protocol (ILP) which is an insert-only protocol that bypasses SQL `INSERT` statements, thus achieving significantly diff --git a/documentation/introduction.md b/documentation/introduction.md index 819df0c92..79cc80446 100644 --- a/documentation/introduction.md +++ b/documentation/introduction.md @@ -2,16 +2,18 @@ title: Introduction slug: / description: - QuestDB time series database documentation. QuestDB is a fast columnar time - series database that solves ingestion speed bottlenecks + The official QuestDB documentation. Learn how to accelerate your time-series, capital markets, and heavy industry use cases. +custom_edit_url: null --- -import Screenshot from "@theme/Screenshot" +import { Guides } from '../src/components/Guides' +import { Resources } from '../src/components/Resources' +import { HeroPattern } from '../src/components/HeroPattern' +import { DocButton } from '../src/components/DocButton' -import CodeBlock from "@theme/CodeBlock" + -QuestDB is an Apache 2.0 open source columnar database that specializes in time -series. +QuestDB is a top performance database that specializes in time-series. It offers **category-leading ingestion throughput** and **fast SQL queries** with operational simplicity. @@ -19,174 +21,55 @@ with operational simplicity. Given its effiency, QuestDB **reduces operational costs**, all while overcoming ingestion bottlenecks. -As a result, QuestDB offers greatly simplified overall ingress infrastructure. +As a result, QuestDB amplifies intensive **time-series**, **capital market**, and **heavy industry** use cases. -This introduction provides a brief overview on: +
+ + <>Quick start + -- [Top QuestDB features](#features) -- [Benefits of QuestDB](#benefits) -- [QuestDB Enterprise](#questdb-enterprise) -- [Where to next?](#next-up) -- [Support](#support) + + <>Explore clients + -
+ + <>Why QuestDB? + -> **Just want to build? Jump to the [quick start](/docs/quick-start/) guide.** + + <>Try live demo + +
-
+## Ingest your data -## Top QuestDB features {#features} +The first step is to get your data into QuestDB. -QuestDB is applied within cutting edge use cases around the world. +We've got a range of first-party clients, protols and methods for ingestion. -Developers are most enthusiastic about the following key features: +Whether you're using first-party clients or interfacing with a third-party tool or library, we've got you covered. -#### Massive ingestion handling & throughput - -If you are running into throughput bottlenecks using an existing storage engine -or time series database, QuestDB can help. - -#### High performance deduplication & out-of-order indexing - -[High data cardinality](/glossary/high-cardinality/) will not lead to -performance degradation. - -#### Hardware efficiency - -Strong, cost-saving performance on very mninimal hardware, including sensors and -Raspberry Pi. - -#### SQL with time series extensions - -Fast, SIMD-optimized SQL extensions to cruise through querying and analysis. - -No obscure domain-specific languages required. - -Greatest hits include: - -- [`SAMPLE BY`](/docs/reference/sql/sample-by/) summarizes data into chunks - based on a specified time interval, from a year to a microsecond -- [`WHERE IN`](/docs/reference/sql/where/#time-range) to compress time ranges - into concise intervals -- [`LATEST ON`](/docs/reference/sql/latest-on/) for latest values within - multiple series within a table -- [`ASOF JOIN`](/docs/reference/sql/asof-join/) to associate timestamps between - a series based on proximity; no extra indices required - -## Benefits of QuestDB {#benefits} - -To avoid ingestion bottlenecks, high performance data ingestion is essential. - -But performance is only part of the story. - -Efficiency measures how well a database performs relative to its available -resources. - -QuestDB, on maximal hardware, significantly outperforms peers: - - - -However, on less robust hardware the difference is even more pronounced, as seen -in the following benchmark. - -Even on hardware as light as a Raspberry Pi 5, QuestDB outperforms competitors -on stronger hardware: - - - -Beyond performance and efficiency, with a specialized -[time-series database](/glossary/time-series-database/), you don't need to worry -about: - -- out-of-order data -- duplicates -- exactly one semantics -- frequency of ingestion -- many other details you will find in demanding real-world scenarios - -QuestDB provides simplified, hyper-fast data ingestion with tremendous -efficiency and therefore value. - -Write blazing-fast queries and create real-time -[Grafana](/docs/third-party-tools/grafana/) via familiar SQL: - -```questdb-sql title='Navigate time with SQL' demo -SELECT - timestamp, symbol, - first(price) AS open, - last(price) AS close, - min(price), - max(price), - sum(amount) AS volume -FROM trades -WHERE timestamp > dateadd('d', -1, now()) -SAMPLE BY 15m; -``` - -Intrigued? The best way to see whether QuestDB is right for you is to try it -out. - -Click _Demo this query_ in the snippet above to visit our demo instance and -experiment. - -To bring your own data and learn more, keep reading! +
+ + <>Read the ingestion overview + +
## QuestDB Enterprise QuestDB Enterprise offers everything from open source, plus additional features for running QuestDB at greater scale or significance. -For a breakdown of Enterprise features, see the -[QuestDB Enterprise](/enterprise/) page. - -## Where to next? {#next-up} - -You'll be inserting data and generating valuable queries in little time. - -First, the [quick start](/docs/quick-start/) guide will get you running. - -Choose from one of our premium ingest-only language clients: - -- [C & C++](/docs/clients/ingest-c-and-cpp) -- [.NET](/docs/clients/ingest-dotnet) -- [Go](/docs/clients/ingest-go) -- [Java](/docs/clients/java_ilp) -- [Node.js](/docs/clients/ingest-node) -- [Python](/docs/clients/ingest-python) -- [Rust](/docs/clients/ingest-rust) - -From there, you can learn more about what's to offer. - -- [Ingestion overview](/docs/ingestion-overview/) want to see all available - ingestion options? Checkout the overview. -- [Query & SQL Overview](/docs/reference/sql/overview/) learn how to query - QuestDB -- [Web Console](/docs/web-console/) for quick SQL queries, charting and CSV - upload/export functionality -- [Grafana guide](/docs/third-party-tools/grafana/) to visualize your data as - beautiful and functional charts. -- [Capacity planning](/docs/deployment/capacity-planning/) to optimize your - QuestDB deployment for production workloads. - -## Support +
+ + <>Learn more + +
-We are happy to help with any question you may have. +## Guides -The team loves a good performance optimization challenge! + -Feel free to reach out using the following channels: +## Resources -- [Raise an issue on GitHub](https://github.com/questdb/questdb/issues/new/choose) -- [Join our community forums](https://community.questdb.io/) -- [QuestDB on Stack Overflow](https://stackoverflow.com/questions/tagged/questdb) -- or email us at [hello@questdb.io](mailto:hello@questdb.io) + diff --git a/documentation/sidebars.js b/documentation/sidebars.js index 73145fb05..6b70f145b 100644 --- a/documentation/sidebars.js +++ b/documentation/sidebars.js @@ -9,6 +9,11 @@ module.exports = { type: "doc", customProps: { tag: "Popular" }, }, + { + id: "why-questdb", + type: "doc", + customProps: { tag: "Popular" }, + }, { id: "guides/influxdb-migration", type: "doc", diff --git a/documentation/why-questdb.md b/documentation/why-questdb.md new file mode 100644 index 000000000..78cd366f2 --- /dev/null +++ b/documentation/why-questdb.md @@ -0,0 +1,166 @@ +--- +title: Why QuestDB? +slug: why-questdb +description: + We'll explain the main features, advances and benefits of QuestDB. Learn how to accelerate your time-series use cases. +--- + +import { Clients } from '../src/components/Clients' +import Screenshot from "@theme/Screenshot" + +This pages provides a brief overview on: + +- [Top QuestDB features](#features) +- [Benefits of QuestDB](#benefits) +- [QuestDB Enterprise](#questdb-enterprise) +- [Where to next?](#next-up) +- [Support](#support) + +
+ +> **Just want to build? Jump to the [quick start](/docs/quick-start/) guide.** + +
+ +## Top QuestDB features {#features} + +QuestDB is applied within cutting edge use cases around the world. + +Developers are most enthusiastic about the following key features: + +#### Massive ingestion handling & throughput + +If you are running into throughput bottlenecks using an existing storage engine +or time series database, QuestDB can help. + +#### High performance deduplication & out-of-order indexing + +[High data cardinality](/glossary/high-cardinality/) will not lead to +performance degradation. + +#### Hardware efficiency + +Strong, cost-saving performance on very mninimal hardware, including sensors and +Raspberry Pi. + +#### SQL with time series extensions + +Fast, SIMD-optimized SQL extensions to cruise through querying and analysis. + +No obscure domain-specific languages required. + +Greatest hits include: + +- [`SAMPLE BY`](/docs/reference/sql/sample-by/) summarizes data into chunks + based on a specified time interval, from a year to a microsecond +- [`WHERE IN`](/docs/reference/sql/where/#time-range) to compress time ranges + into concise intervals +- [`LATEST ON`](/docs/reference/sql/latest-on/) for latest values within + multiple series within a table +- [`ASOF JOIN`](/docs/reference/sql/asof-join/) to associate timestamps between + a series based on proximity; no extra indices required + +## Benefits of QuestDB {#benefits} + +To avoid ingestion bottlenecks, high performance data ingestion is essential. + +But performance is only part of the story. + +Efficiency measures how well a database performs relative to its available +resources. + +QuestDB, on maximal hardware, significantly outperforms peers: + + + +However, on less robust hardware the difference is even more pronounced, as seen +in the following benchmark. + +Even on hardware as light as a Raspberry Pi 5, QuestDB outperforms competitors +on stronger hardware: + + + +Beyond performance and efficiency, with a specialized +[time-series database](/glossary/time-series-database/), you don't need to worry +about: + +- out-of-order data +- duplicates +- exactly one semantics +- frequency of ingestion +- many other details you will find in demanding real-world scenarios + +QuestDB provides simplified, hyper-fast data ingestion with tremendous +efficiency and therefore value. + +Write blazing-fast queries and create real-time +[Grafana](/docs/third-party-tools/grafana/) via familiar SQL: + +```questdb-sql title='Navigate time with SQL' demo +SELECT + timestamp, symbol, + first(price) AS open, + last(price) AS close, + min(price), + max(price), + sum(amount) AS volume +FROM trades +WHERE timestamp > dateadd('d', -1, now()) +SAMPLE BY 15m; +``` + +Intrigued? The best way to see whether QuestDB is right for you is to try it +out. + +Click _Demo this query_ in the snippet above to visit our demo instance and +experiment. + +To bring your own data and learn more, keep reading! + + +## Where to next? {#next-up} + +You'll be inserting data and generating valuable queries in little time. + +First, the [quick start](/docs/quick-start/) guide will get you running. + +Choose from one of our premium ingest-only language clients: + + + +From there, you can learn more about what's to offer. + +- [Ingestion overview](/docs/ingestion-overview/) want to see all available + ingestion options? Checkout the overview. +- [Query & SQL Overview](/docs/reference/sql/overview/) learn how to query + QuestDB +- [Web Console](/docs/web-console/) for quick SQL queries, charting and CSV + upload/export functionality +- [Grafana guide](/docs/third-party-tools/grafana/) to visualize your data as + beautiful and functional charts. +- [Capacity planning](/docs/deployment/capacity-planning/) to optimize your + QuestDB deployment for production workloads. + +## Support + +We are happy to help with any question you may have. + +The team loves a good performance optimization challenge! + +Feel free to reach out using the following channels: + +- [Raise an issue on GitHub](https://github.com/questdb/questdb/issues/new/choose) +- [Join our community forums](https://community.questdb.io/) +- [QuestDB on Stack Overflow](https://stackoverflow.com/questions/tagged/questdb) +- or email us at [hello@questdb.io](mailto:hello@questdb.io) \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 640f3b366..2ced3fc30 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -17,7 +17,7 @@ const config = { baseUrlIssueBanner: false, favicon: "/images/favicon.webp", organizationName: "QuestDB", - staticDirectories: ['assets', 'images', 'static'], + staticDirectories: ['static'], projectName: "questdb", customFields, onBrokenLinks: "warn", @@ -83,28 +83,6 @@ const config = { ], }, ], - function (context, options) { - return { - name: 'development-redirects', - configureWebpack(config, isServer, utils) { - if (process.env.NODE_ENV === 'development') { - return { - devServer: { - onBeforeSetupMiddleware: function (devServer) { - devServer.app.get('*', function (req, res, next) { - // If path doesn't start with /docs, redirect to Next.js - if (!req.path.startsWith('/docs/')) { - return res.redirect(`http://localhost:3000${req.path}`) - } - next() - }) - } - } - } - } - } - } - } ].filter(Boolean), themeConfig: { diff --git a/netlify.toml b/netlify.toml index 4bfe76b0f..219105c6b 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,7 +1,13 @@ [[plugins]] package = "netlify-plugin-cache" [plugins.inputs] -paths = ["node_modules/.cache"] +paths = [ + "node_modules/.cache", + ".cache", + ".docusaurus", + "build", + "node_modules" +] [[redirects]] from = "/docs/reference/sql/backup/" @@ -637,3 +643,18 @@ X-Frame-Options = "SAMEORIGIN" X-XSS-Protection = "0" X-Content-Type-Options = "nosniff" Content-Security-Policy = "frame-src 'self' app.netlify.com *.demo.questdb.io *.questdb.io www.youtube.com www.slideshare.net forms.hsforms.com;" + +[[headers]] +for = "/static/*" +[headers.values] +Cache-Control = "public, max-age=31536000, immutable" + +[[headers]] +for = "*.js" +[headers.values] +Cache-Control = "public, max-age=31536000, immutable" + +[[headers]] +for = "*.css" +[headers.values] +Cache-Control = "public, max-age=31536000, immutable" diff --git a/package.json b/package.json index c9eb31f56..184dceb55 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "clsx": "2.1.1", "date-fns": "4.1.0", "dotenv": "^16.4.5", + "framer-motion": "^10.18.0", "gray-matter": "4.0.3", "prism-react-renderer": "2.4.0", "react": "18.3.1", @@ -86,7 +87,8 @@ "tailwindcss": "3.4.15", "typescript": "~5.6.3", "webpack": "5.96.1", - "webpack-manifest-plugin": "5.0.0" + "webpack-manifest-plugin": "5.0.0", + "zustand": "4.5.0" }, "browserslist": { "production": [ diff --git a/src/assets/icons/logos/c.svg b/src/assets/icons/logos/c.svg new file mode 100644 index 000000000..f6b3c18c0 --- /dev/null +++ b/src/assets/icons/logos/c.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/logos/cplusplus.svg b/src/assets/icons/logos/cplusplus.svg new file mode 100644 index 000000000..fba7a77a4 --- /dev/null +++ b/src/assets/icons/logos/cplusplus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/logos/dotnet.svg b/src/assets/icons/logos/dotnet.svg new file mode 100644 index 000000000..2184982d9 --- /dev/null +++ b/src/assets/icons/logos/dotnet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/logos/go.svg b/src/assets/icons/logos/go.svg new file mode 100644 index 000000000..7f7b19de5 --- /dev/null +++ b/src/assets/icons/logos/go.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/src/assets/icons/logos/java.svg b/src/assets/icons/logos/java.svg new file mode 100644 index 000000000..13bcfd525 --- /dev/null +++ b/src/assets/icons/logos/java.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/logos/node.svg b/src/assets/icons/logos/node.svg new file mode 100644 index 000000000..1d09de22b --- /dev/null +++ b/src/assets/icons/logos/node.svg @@ -0,0 +1,4 @@ + + + diff --git a/src/assets/icons/logos/php.svg b/src/assets/icons/logos/php.svg new file mode 100644 index 000000000..0a9ac462a --- /dev/null +++ b/src/assets/icons/logos/php.svg @@ -0,0 +1,10 @@ + + + + + diff --git a/src/assets/icons/logos/python.svg b/src/assets/icons/logos/python.svg new file mode 100644 index 000000000..9bceb587a --- /dev/null +++ b/src/assets/icons/logos/python.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/src/assets/icons/logos/ruby.svg b/src/assets/icons/logos/ruby.svg new file mode 100644 index 000000000..b22a5bf10 --- /dev/null +++ b/src/assets/icons/logos/ruby.svg @@ -0,0 +1,4 @@ + + + diff --git a/src/assets/icons/logos/rust.svg b/src/assets/icons/logos/rust.svg new file mode 100644 index 000000000..0a9979ed1 --- /dev/null +++ b/src/assets/icons/logos/rust.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/tailwind/BellIcon.tsx b/src/assets/icons/tailwind/BellIcon.tsx new file mode 100644 index 000000000..1c0c2291c --- /dev/null +++ b/src/assets/icons/tailwind/BellIcon.tsx @@ -0,0 +1,17 @@ +export function BellIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/BoltIcon.tsx b/src/assets/icons/tailwind/BoltIcon.tsx new file mode 100644 index 000000000..308d997cc --- /dev/null +++ b/src/assets/icons/tailwind/BoltIcon.tsx @@ -0,0 +1,11 @@ +export function BoltIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/BookIcon.tsx b/src/assets/icons/tailwind/BookIcon.tsx new file mode 100644 index 000000000..9f7709bc3 --- /dev/null +++ b/src/assets/icons/tailwind/BookIcon.tsx @@ -0,0 +1,17 @@ +export function BookIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/CalendarIcon.tsx b/src/assets/icons/tailwind/CalendarIcon.tsx new file mode 100644 index 000000000..e9d374867 --- /dev/null +++ b/src/assets/icons/tailwind/CalendarIcon.tsx @@ -0,0 +1,23 @@ +export function CalendarIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/CartIcon.tsx b/src/assets/icons/tailwind/CartIcon.tsx new file mode 100644 index 000000000..30c9438f7 --- /dev/null +++ b/src/assets/icons/tailwind/CartIcon.tsx @@ -0,0 +1,15 @@ +export function CartIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/ChatBubbleIcon.tsx b/src/assets/icons/tailwind/ChatBubbleIcon.tsx new file mode 100644 index 000000000..418427b05 --- /dev/null +++ b/src/assets/icons/tailwind/ChatBubbleIcon.tsx @@ -0,0 +1,17 @@ +export function ChatBubbleIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/CheckIcon.tsx b/src/assets/icons/tailwind/CheckIcon.tsx new file mode 100644 index 000000000..b9433644d --- /dev/null +++ b/src/assets/icons/tailwind/CheckIcon.tsx @@ -0,0 +1,17 @@ +export function CheckIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/ChevronRightLeftIcon.tsx b/src/assets/icons/tailwind/ChevronRightLeftIcon.tsx new file mode 100644 index 000000000..281c9de52 --- /dev/null +++ b/src/assets/icons/tailwind/ChevronRightLeftIcon.tsx @@ -0,0 +1,19 @@ +export function ChevronRightLeftIcon( + props: React.ComponentPropsWithoutRef<'svg'>, +) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/ClipboardIcon.tsx b/src/assets/icons/tailwind/ClipboardIcon.tsx new file mode 100644 index 000000000..33d997b5b --- /dev/null +++ b/src/assets/icons/tailwind/ClipboardIcon.tsx @@ -0,0 +1,17 @@ +export function ClipboardIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/CogIcon.tsx b/src/assets/icons/tailwind/CogIcon.tsx new file mode 100644 index 000000000..cedecf542 --- /dev/null +++ b/src/assets/icons/tailwind/CogIcon.tsx @@ -0,0 +1,19 @@ +export function CogIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/CopyIcon.tsx b/src/assets/icons/tailwind/CopyIcon.tsx new file mode 100644 index 000000000..0eedaaa4c --- /dev/null +++ b/src/assets/icons/tailwind/CopyIcon.tsx @@ -0,0 +1,17 @@ +export function CopyIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/DocumentIcon.tsx b/src/assets/icons/tailwind/DocumentIcon.tsx new file mode 100644 index 000000000..8f83d2094 --- /dev/null +++ b/src/assets/icons/tailwind/DocumentIcon.tsx @@ -0,0 +1,17 @@ +export function DocumentIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/EnvelopeIcon.tsx b/src/assets/icons/tailwind/EnvelopeIcon.tsx new file mode 100644 index 000000000..de57e4c47 --- /dev/null +++ b/src/assets/icons/tailwind/EnvelopeIcon.tsx @@ -0,0 +1,17 @@ +export function EnvelopeIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/FaceSmileIcon.tsx b/src/assets/icons/tailwind/FaceSmileIcon.tsx new file mode 100644 index 000000000..7c855a63e --- /dev/null +++ b/src/assets/icons/tailwind/FaceSmileIcon.tsx @@ -0,0 +1,17 @@ +export function FaceSmileIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/FolderIcon.tsx b/src/assets/icons/tailwind/FolderIcon.tsx new file mode 100644 index 000000000..050c77bb7 --- /dev/null +++ b/src/assets/icons/tailwind/FolderIcon.tsx @@ -0,0 +1,22 @@ +export function FolderIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/LinkIcon.tsx b/src/assets/icons/tailwind/LinkIcon.tsx new file mode 100644 index 000000000..f77d6184a --- /dev/null +++ b/src/assets/icons/tailwind/LinkIcon.tsx @@ -0,0 +1,12 @@ +export function LinkIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/ListIcon.tsx b/src/assets/icons/tailwind/ListIcon.tsx new file mode 100644 index 000000000..69354ec06 --- /dev/null +++ b/src/assets/icons/tailwind/ListIcon.tsx @@ -0,0 +1,17 @@ +export function ListIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/MagnifyingGlassIcon.tsx b/src/assets/icons/tailwind/MagnifyingGlassIcon.tsx new file mode 100644 index 000000000..5e219f634 --- /dev/null +++ b/src/assets/icons/tailwind/MagnifyingGlassIcon.tsx @@ -0,0 +1,15 @@ +export function MagnifyingGlassIcon( + props: React.ComponentPropsWithoutRef<'svg'>, +) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/MapPinIcon.tsx b/src/assets/icons/tailwind/MapPinIcon.tsx new file mode 100644 index 000000000..6070adb13 --- /dev/null +++ b/src/assets/icons/tailwind/MapPinIcon.tsx @@ -0,0 +1,19 @@ +export function MapPinIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/PackageIcon.tsx b/src/assets/icons/tailwind/PackageIcon.tsx new file mode 100644 index 000000000..6bd9225f5 --- /dev/null +++ b/src/assets/icons/tailwind/PackageIcon.tsx @@ -0,0 +1,16 @@ +export function PackageIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/PaperAirplaneIcon.tsx b/src/assets/icons/tailwind/PaperAirplaneIcon.tsx new file mode 100644 index 000000000..12c29b915 --- /dev/null +++ b/src/assets/icons/tailwind/PaperAirplaneIcon.tsx @@ -0,0 +1,19 @@ +export function PaperAirplaneIcon( + props: React.ComponentPropsWithoutRef<'svg'>, +) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/PaperClipIcon.tsx b/src/assets/icons/tailwind/PaperClipIcon.tsx new file mode 100644 index 000000000..db51c7f70 --- /dev/null +++ b/src/assets/icons/tailwind/PaperClipIcon.tsx @@ -0,0 +1,12 @@ +export function PaperClipIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/ShapesIcon.tsx b/src/assets/icons/tailwind/ShapesIcon.tsx new file mode 100644 index 000000000..ac57a52ca --- /dev/null +++ b/src/assets/icons/tailwind/ShapesIcon.tsx @@ -0,0 +1,17 @@ +export function ShapesIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/ShirtIcon.tsx b/src/assets/icons/tailwind/ShirtIcon.tsx new file mode 100644 index 000000000..f8cdfd508 --- /dev/null +++ b/src/assets/icons/tailwind/ShirtIcon.tsx @@ -0,0 +1,11 @@ +export function ShirtIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/SquaresPlusIcon.tsx b/src/assets/icons/tailwind/SquaresPlusIcon.tsx new file mode 100644 index 000000000..0005f59d5 --- /dev/null +++ b/src/assets/icons/tailwind/SquaresPlusIcon.tsx @@ -0,0 +1,17 @@ +export function SquaresPlusIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/TagIcon.tsx b/src/assets/icons/tailwind/TagIcon.tsx new file mode 100644 index 000000000..f36024143 --- /dev/null +++ b/src/assets/icons/tailwind/TagIcon.tsx @@ -0,0 +1,19 @@ +export function TagIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/UserIcon.tsx b/src/assets/icons/tailwind/UserIcon.tsx new file mode 100644 index 000000000..78bb8f617 --- /dev/null +++ b/src/assets/icons/tailwind/UserIcon.tsx @@ -0,0 +1,24 @@ +export function UserIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/assets/icons/tailwind/UsersIcon.tsx b/src/assets/icons/tailwind/UsersIcon.tsx new file mode 100644 index 000000000..aa7d13b3d --- /dev/null +++ b/src/assets/icons/tailwind/UsersIcon.tsx @@ -0,0 +1,28 @@ +export function UsersIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} diff --git a/src/components/Clients/index.tsx b/src/components/Clients/index.tsx new file mode 100644 index 000000000..db8abe5b3 --- /dev/null +++ b/src/components/Clients/index.tsx @@ -0,0 +1,91 @@ +import { DocButton } from '../DocButton' +import logoCpp from '../../assets/icons/logos/cplusplus.svg' +import logoDotNet from '../../assets/icons/logos/dotnet.svg' +import logoGo from '../../assets/icons/logos/go.svg' +import logoJava from '../../assets/icons/logos/java.svg' +import logoNode from '../../assets/icons/logos/node.svg' +import logoPython from '../../assets/icons/logos/python.svg' +import logoRust from '../../assets/icons/logos/rust.svg' + +const clients = [ + { + href: '/docs/clients/ingest-c-and-cpp', + name: 'C & C++', + description: + 'High-performance client for systems programming and embedded applications.', + logo: logoCpp, + }, + { + href: '/docs/clients/ingest-dotnet', + name: '.NET', + description: + 'Cross-platform client for building applications with .NET technologies.', + logo: logoDotNet, + }, + { + href: '/docs/clients/ingest-go', + name: 'Go', + description: + 'An open-source programming language supported by Google with built-in concurrency.', + logo: logoGo, + }, + { + href: '/docs/clients/java_ilp', + name: 'Java', + description: + 'Platform-independent client for enterprise applications and Android development.', + logo: logoJava, + }, + { + href: '/docs/clients/ingest-node', + name: 'Node.js', + description: + 'Node.jsĀ® is an open-source, cross-platform JavaScript runtime environment.', + logo: logoNode, + }, + { + href: '/docs/clients/ingest-python', + name: 'Python', + description: + 'Python is a programming language that lets you work quickly and integrate systems more effectively.', + logo: logoPython, + }, + { + href: '/docs/clients/ingest-rust', + name: 'Rust', + description: + 'Systems programming language focused on safety, speed, and concurrency.', + logo: logoRust, + }, +] + +export function Clients() { + return ( +
+
+ {clients.map((client) => ( +
+
+

+ {client.name} +

+

+ {client.description} +

+

+ + Read more + +

+
+ {`${client.name} +
+ ))} +
+
+ ) +} diff --git a/src/components/DocButton/index.tsx b/src/components/DocButton/index.tsx new file mode 100644 index 000000000..c5251eff0 --- /dev/null +++ b/src/components/DocButton/index.tsx @@ -0,0 +1,87 @@ +import Link from '@docusaurus/Link' +import clsx from 'clsx' + +function ArrowIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} + +const variantStyles = { + primary: + 'rounded-full bg-[#a23154] py-1 px-3 text-white hover:bg-[#9c274b] dark:bg-[#d9688b]/10 dark:text-[#d9688b] dark:ring-1 dark:ring-inset dark:ring-[#d9688b]/20 dark:hover:bg-[#d9688b]/10 dark:hover:text-[#e289a4] dark:hover:ring-[#e289a4]', + secondary: + 'rounded-full bg-zinc-100 py-1 px-3 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800/40 dark:text-zinc-400 dark:ring-1 dark:ring-inset dark:ring-zinc-800 dark:hover:bg-zinc-800 dark:hover:text-zinc-300', + filled: + 'rounded-full bg-[#a23154] py-1 px-3 text-white hover:bg-[#9c274b] dark:bg-[#d75c82] dark:text-white dark:hover:bg-[#d9688b]', + outline: + 'rounded-full py-1 px-3 text-zinc-700 ring-1 ring-inset ring-zinc-900/10 hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-400 dark:ring-white/10 dark:hover:bg-white/5 dark:hover:text-white', + text: 'text-[#d75c82] hover:text-[#d9688b] dark:text-[#d9688b] dark:hover:text-[#e289a4]', +} + +type ButtonProps = { + variant?: keyof typeof variantStyles + arrow?: 'left' | 'right' +} & ( + | React.ComponentPropsWithoutRef + | (React.ComponentPropsWithoutRef<'button'> & { href?: undefined }) +) + +export function DocButton({ + variant = 'primary', + className, + children, + arrow, + ...props +}: ButtonProps) { + className = clsx( + 'inline-flex gap-0.5 justify-center overflow-hidden text-sm font-medium transition', + variantStyles[variant], + className, + ) + + let arrowIcon = ( + + ) + + let inner = ( + <> + {arrow === 'left' && arrowIcon} + {children} + {arrow === 'right' && arrowIcon} + + ) + + if (typeof props.href === 'undefined') { + const buttonProps: React.ButtonHTMLAttributes = { + className, + ...props, + type: props.type || 'button', + } + return ( + + ) + } + + return ( + + {inner} + + ) +} diff --git a/src/components/GridPattern/index.tsx b/src/components/GridPattern/index.tsx new file mode 100644 index 000000000..520299114 --- /dev/null +++ b/src/components/GridPattern/index.tsx @@ -0,0 +1,55 @@ +import { useId } from 'react' + +export function GridPattern({ + width, + height, + x, + y, + squares, + ...props +}: React.ComponentPropsWithoutRef<'svg'> & { + width: number + height: number + x: string | number + y: string | number + squares: Array<[x: number, y: number]> +}) { + let patternId = useId() + + return ( + + ) +} diff --git a/src/components/Guides/index.tsx b/src/components/Guides/index.tsx new file mode 100644 index 000000000..13a9cbb76 --- /dev/null +++ b/src/components/Guides/index.tsx @@ -0,0 +1,50 @@ +import { DocButton } from '../DocButton' + +const guides = [ + { + href: '/docs/deployment/capacity-planning/', + name: 'Capacity planning', + description: 'Select a storage medium, plan, size and compress your QuestDB deployment.', + }, + { + href: '/docs/operations/design-for-performance/', + name: 'Design for performance', + description: 'Design and tweak your data model to set yourself up for reliable, optimal performance.', + }, + { + href: '/docs/guides/working-with-timestamps-timezones/', + name: 'Working with time', + description: + `It's about time. Learn how to work with timestamps and timezones in QuestDB.`, + }, + { + href: '/docs/operations/backup/', + name: 'Backup and restore', + description: + 'Safety is key! See the methods to backup and restore your QuestDB deployment.', + }, +] + +export function Guides() { + return ( +
+
+ {guides.map((guide) => ( +
+

+ {guide.name} +

+

+ {guide.description} +

+

+ + Read more + +

+
+ ))} +
+
+ ) +} diff --git a/src/components/HeroPattern/index.tsx b/src/components/HeroPattern/index.tsx new file mode 100644 index 000000000..b3a4278f8 --- /dev/null +++ b/src/components/HeroPattern/index.tsx @@ -0,0 +1,32 @@ +import { GridPattern } from '../GridPattern' + +export function HeroPattern() { + return ( +
+
+
+ +
+ +
+
+ ) +} diff --git a/src/components/Resources/index.tsx b/src/components/Resources/index.tsx new file mode 100644 index 000000000..aa3e47b43 --- /dev/null +++ b/src/components/Resources/index.tsx @@ -0,0 +1,185 @@ +'use client' + +import Link from '@docusaurus/Link' +import { + type MotionValue, + motion, + useMotionTemplate, + useMotionValue, +} from 'framer-motion' + +import { GridPattern } from '../GridPattern' +import { BoltIcon } from '../../assets/icons/tailwind/BoltIcon' +import { CogIcon } from '../../assets/icons/tailwind/CogIcon' +import { MagnifyingGlassIcon } from '../../assets/icons/tailwind/MagnifyingGlassIcon' +import { UsersIcon } from '../../assets/icons/tailwind/UsersIcon' + +interface Resource { + href: string + name: string + description: string + icon: React.ComponentType<{ className?: string }> + pattern: Omit< + React.ComponentPropsWithoutRef, + 'width' | 'height' | 'x' + > +} + +const resources: Array = [ + { + href: '/docs/reference/sql/overview/', + name: 'SQL overview', + description: + 'Learn about our powerful extended SQL and how to use it to query QuestDB.', + icon: MagnifyingGlassIcon, + pattern: { + y: 16, + squares: [ + [0, 1], + [1, 3], + ], + }, + }, + { + href: '/docs/ingestion-overview/#first-party-clients', + name: 'Language clients', + description: + 'Explore our language clients and how to use them to ingest data into QuestDB.', + icon: BoltIcon, + pattern: { + y: -6, + squares: [ + [-1, 2], + [1, 3], + ], + }, + }, + { + href: '/docs/configuration/', + name: 'Configuration', + description: + 'See all of our available configuration options and fine-tune to match your use case.', + icon: CogIcon, + pattern: { + y: 32, + squares: [ + [0, 2], + [1, 4], + ], + }, + }, + { + href: '/docs/third-party-tools/overview/', + name: 'Third-Party Tools', + description: + 'Our recommended third-party tools can aid you in analyzing and visualizing your data.', + icon: UsersIcon, + pattern: { + y: 22, + squares: [[0, 1]], + }, + }, +] + +function ResourceIcon({ icon: Icon }: { icon: Resource['icon'] }) { + return ( +
+ +
+ ) +} + +function ResourcePattern({ + mouseX, + mouseY, + ...gridProps +}: Resource['pattern'] & { + mouseX: MotionValue + mouseY: MotionValue +}) { + let maskImage = useMotionTemplate`radial-gradient(180px at ${mouseX}px ${mouseY}px, white, transparent)` + let style = { maskImage, WebkitMaskImage: maskImage } + + return ( +
+
+ +
+ + + + +
+ ) +} + +function Resource({ resource }: { resource: Resource }) { + let mouseX = useMotionValue(0) + let mouseY = useMotionValue(0) + + function onMouseMove({ + currentTarget, + clientX, + clientY, + }: React.MouseEvent) { + let { left, top } = currentTarget.getBoundingClientRect() + mouseX.set(clientX - left) + mouseY.set(clientY - top) + } + + return ( +
+ +
+
+ +

+ + + {resource.name} + +

+

+ {resource.description} +

+
+
+ ) +} + +export function Resources() { + return ( +
+
+ {resources.map((resource) => ( + + ))} +
+
+ ) +} diff --git a/src/components/Tag/index.tsx b/src/components/Tag/index.tsx new file mode 100644 index 000000000..06b21d644 --- /dev/null +++ b/src/components/Tag/index.tsx @@ -0,0 +1,63 @@ +import clsx from 'clsx' + +const variantStyles = { + small: '', + medium: 'rounded-lg px-1.5 ring-1 ring-inset', +} + +const colorStyles = { + emerald: { + small: 'text-emerald-500 dark:text-emerald-400', + medium: + 'ring-emerald-300 dark:ring-emerald-400/30 bg-emerald-400/10 text-emerald-500 dark:text-emerald-400', + }, + sky: { + small: 'text-sky-500', + medium: + 'ring-sky-300 bg-sky-400/10 text-sky-500 dark:ring-sky-400/30 dark:bg-sky-400/10 dark:text-sky-400', + }, + amber: { + small: 'text-amber-500', + medium: + 'ring-amber-300 bg-amber-400/10 text-amber-500 dark:ring-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400', + }, + rose: { + small: 'text-red-500 dark:text-rose-500', + medium: + 'ring-rose-200 bg-rose-50 text-red-500 dark:ring-rose-500/20 dark:bg-rose-400/10 dark:text-rose-400', + }, + zinc: { + small: 'text-zinc-400 dark:text-zinc-500', + medium: + 'ring-zinc-200 bg-zinc-50 text-zinc-500 dark:ring-zinc-500/20 dark:bg-zinc-400/10 dark:text-zinc-400', + }, +} + +const valueColorMap = { + GET: 'emerald', + POST: 'sky', + PUT: 'amber', + DELETE: 'rose', +} as Record + +export function Tag({ + children, + variant = 'medium', + color = valueColorMap[children] ?? 'emerald', +}: { + children: keyof typeof valueColorMap & (string | {}) + variant?: keyof typeof variantStyles + color?: keyof typeof colorStyles +}) { + return ( + + {children} + + ) +} diff --git a/src/css/_global.css b/src/css/_global.css index 2cb3c3249..14e1f8d55 100644 --- a/src/css/_global.css +++ b/src/css/_global.css @@ -149,99 +149,6 @@ html[data-theme="dark"] { --ifm-color-primary: var(--ifm-color-primary-lighter); } -@media (prefers-color-scheme: light) { - :root.light-mode { - --ifm-color-scheme: light; - } -} - -html[data-theme="light"] { - --palette-pale-blue: #000; - --palette-rock: #262833; - --palette-gray: #4b4e5d; - - --palette-dark-03: rgba(0, 0, 0, 0.03); - --palette-dark-05: rgba(0, 0, 0, 0.05); - --palette-dark-10: rgba(0, 0, 0, 0.1); - --palette-dark-20: rgba(0, 0, 0, 0.2); - --palette-dark-30: rgba(0, 0, 0, 0.3); - --palette-dark-40: rgba(0, 0, 0, 0.4); - --palette-dark-80: rgba(0, 0, 0, 0.8); - - --palette-white-darker: #d9d9d9; - --palette-yellow: #ffd54f; - - --palette-author-color: #000; - --palette-blog-title-color: #000; - --palette-blog-category-color: #000; - - --ifm-background-color: white; - --ifm-font-color-base: #333; - --ifm-navbar-background-color: white; - --ifm-navbar-height: 80px; - --ifm-dropdown-background-color: var(--palette-white); - --ifm-navbar-shadow: 0 1px 0 0 var(--palette-dark-10); - --ifm-toc-border-color: var(--palette-dark-10); - --ifm-link-color: #0000ee; - --ifm-link-hover-color: #5d5de1; - --ifm-link-decoration: none; - --ifm-link-hover-decoration: underline; - --ifm-code-background: #dadada; - --ifm-code-color: var(--palette-charade); - --ifm-footer-link-decoration: none; - - --docsearch-footer-background: var(--ifm-background-color); - --docsearch-key-gradient: linear-gradient( - -26.5deg, - var(--palette-gray) 0%, - var(--palette-rock) 100% - ); - --docsearch-key-shadow: 0 3px 3px var(--palette-dark-30); - - --image-shadow: 0 10px 20px 5px var(--palette-dark-20); - - --theme-text-color: var(--ifm-font-color-base); - --theme-navbar-background-color: rgba(250, 250, 250, 0.8); - - --theme-section-odd-bg-color: #f0f1f5; - --theme-input-bg-color: #f0f1f5; - --theme-input-text-color: #555b88; - - --theme-card-bg-color: #f0f1f5; - --theme-card-bg-color-hover: rgb(225, 227, 235); - --theme-card-border-color: #b7b9c3; - --theme-card-text-color: #21222c; - --theme-card-title-color: #21222c; - - --theme-card-secondary-bg-color: #dde0e9; - --theme-card-secondary-text-color: #21222c; - - --theme-attention-card-bg-color: #f0f1f5; - --theme-card-illustration-bg-color: transparent; - --theme-team-article-title-color: var(--ifm-heading-color); - --theme-section-title-color: var(--palette-dark-80); - --theme-contribute-text-color: var(--palette-dark-80); - - --theme-button-primary-background-color: var(--palette-pink); - --theme-button-primary-text-color: var(--palette-white); - --theme-button-primary-hover-background-color: var(--palette-pink-darker); - - --theme-button-secondary-background-color: var(--palette-dark-10); - --theme-button-secondary-text-color: var(--palette-charade); - --theme-button-secondary-hover-background-color: var(--palette-dark-30); - - --theme-button-tertiary-background-color: var(--palette-dark-30); - --theme-button-tertiary-text-color: var(--palette-dark-80); - --theme-button-tertiary-hover-background-color: var(--palette-dark-40); - - --theme-tutorial-post-card-border: 1px solid transparent; - --theme-tutorial-post-card-hover-border: 1px solid var(--palette-dark-10); - - --theme-screenshot-background-color: white; - --ifm-hr-border-color: var(--palette-black-10); - --ifm-heading-color: #000; -} - html[data-theme="dark"] .DocSearch { --docsearch-text-color: var(--ifm-font-color-base); --docsearch-muted-color: var(--ifm-color-secondary-darkest); @@ -305,148 +212,15 @@ html[data-theme="dark"] .DocSearch { font-weight: 700; } -/* General layout for larger screens */ -.markdown, -.theme-doc-breadcrumbs, -.theme-edit-this-page { - max-width: 100%; - margin-left: auto; - margin-right: auto; - padding-left: 8rem; - padding-right: 4rem; -} - -.sidebar_njMd { - --ifm-navbar-height: 85px; - margin-top: calc(var(--ifm-navbar-height) * -1); -} - .table-of-contents { - border-left-width: 3px; font-size: var(--font-size-small); font-weight: var(--ifm-font-weight-semibold); - position: fixed; - right: 0; top: 100px; - width: 250px; - max-height: calc(100vh - 100px); - overflow-y: auto; - padding-left: 1rem; border-left: 3px solid var(--ifm-color-primary); text-decoration: none; z-index: 1; } -@media (min-width: 2000px) { - .markdown, - .theme-doc-breadcrumbs, - .theme-edit-this-page { - max-width: 100%; - margin-left: auto; - margin-right: auto; - padding-left: 2rem; - padding-right: 2rem; - } - - .table-of-contents { - max-height: none; - overflow-y: visible; - padding-left: 1rem; - border-left: 3px solid var(--ifm-color-primary); - text-decoration: none; - position: static; - } -} - -@media (max-width: 1250px) { - .table-of-contents { - display: none; - } - - .theme-doc-toc-mobile { - display: block; - background-color: var(--ifm-background-color); - border: 1px solid var(--ifm-color-primary); - padding: 0.5rem 1rem; - margin: 1rem 0; - font-size: var(--font-size-small); - max-width: 95%; - margin-left: auto; - margin-right: auto; - border-radius: 8px; - overflow-y: auto; - } - - .theme-doc-toc-mobile .table-of-contents { - display: block; - position: relative; - right: unset; - top: unset; - width: auto; - padding-left: 0; - border: none; - max-height: none; - overflow-y: visible; - } - - .markdown, - .theme-doc-breadcrumbs, - .theme-edit-this-page { - padding-left: 1rem; - padding-right: 1rem; - } - - .markdown { - --ifm-h2-vertical-rhythm-top: 2rem; - --ifm-h3-vertical-rhythm-top: 1.5rem; - --ifm-heading-vertical-rhythm-top: 1.5rem; - --ifm-heading-vertical-rhythm-bottom: 0.75rem; - --ifm-paragraph-margin-bottom: 0.75rem; - } - - .theme-edit-this-page { - margin-top: 0.5rem; - margin-bottom: 0.5rem; - padding-left: 1rem; - padding-right: 1rem; - } - - .theme-doc-breadcrumbs { - padding-left: 1rem; - padding-right: 1rem; - } -} - -@media (max-width: 480px) { - .markdown, - .theme-doc-breadcrumbs, - .theme-edit-this-page, - .theme-doc-toc-mobile { - padding-left: 0.5rem; - padding-right: 0.5rem; - } - - .theme-doc-toc-mobile { - padding: 0.25rem 0.5rem; - font-size: 0.85rem; - max-width: 90%; - border-radius: 5px; - } -} - -html[data-theme="light"] .markdown { - --ifm-table-head-background: #f6f8fa; - --ifm-table-head-color: #24292f; - --ifm-table-border-color: #d0d7de; - --ifm-table-stripe-background: #f6f8fa; -} - -/* syntax railroad charts in documentation */ -html[data-theme="light"] .markdown img[src*="data:image/svg+xml"][alt*="chart"], -html[data-theme="light"] .markdown img[src$=".svg"][alt*="chart"] { - filter: invert(1) hue-rotate(200deg); -} - .markdown table code { display: inline-block; max-width: 25ch; @@ -461,22 +235,6 @@ html[data-theme="light"] .markdown img[src$=".svg"][alt*="chart"] { display: none; } -/** - * - * Globals - * - **/ - -html, -body { - height: 100%; -} - -body { - margin: 0; - transition: var(--ifm-transition-fast) ease color; -} - #__docusaurus { min-height: 100%; display: flex; @@ -494,100 +252,6 @@ body { font-size: var(--font-size-large); } -/** - * - * Blog - * - **/ - -/* Change blog title color */ -.blog-wrapper header h2 a { - --ifm-link-color: var(--palette-white-darker); - --ifm-link-hover-color: var(--palette-white-darker); -} - -html[data-theme="light"] .blog-wrapper header h2 a { - color: var(--ifm-font-color-base); -} - -/** - * - * Careers - * - **/ - -.career { - align-self: center; - box-sizing: content-box; -} - -/** - * - * Glossary - * - **/ - -.glossary { - max-width: 75rem; - margin: 0 auto; - font-size: 1.1rem; -} - -/** - * - * Case study - * - **/ - -.case-study { - max-width: 100%; - margin: 0 auto; - font-size: 1.1rem; -} - -/** - * - * Supplemental docs (Privacy notice, TOS) - * - **/ - -.supplemental { - align-self: center; - box-sizing: content-box; -} - -/** - * - * Pagination - * - **/ - -.pagination-nav__item--next .pagination-nav__link { - background: var(--palette-pink); -} - -.pagination-nav__link { - background: var(--palette-white-05); -} - -html[data-theme="light"] .pagination-nav__item--next .pagination-nav__link { - background: var(--palette-pink); - color: var(--palette-white); -} - -html[data-theme="light"] .pagination-nav__item--next .pagination-nav__sublabel { - color: var(--palette-white); -} - -html[data-theme="light"] .pagination-nav__link { - background: var(--palette-dark-10); - color: var(--palette-dark-80); -} - -html[data-theme="light"] .pagination-nav__sublabel { - color: var(--palette-dark-80); -} - /** * * Hide the "See all ## results" link at the bottom of the search widget. @@ -608,23 +272,6 @@ html[data-theme="light"] .pagination-nav__sublabel { } } -/** - * - * Light theme - * - **/ -html[data-theme="light"] .themedDocusaurus [fill="#FFFF50"] { - fill: greenyellow; -} - -html[data-theme="light"] .svg-mode-visible { - filter: brightness(0.1); -} - -html[data-theme="light"] .react-toggle-track { - background-color: #ebedf0; -} - /* animation style for react-transition-group elements */ .transition-node-enter { opacity: 0; @@ -663,13 +310,6 @@ html[data-theme="light"] .react-toggle-track { --color-even: #446890; } -html[data-theme="light"] .pink-table, -html[data-theme="light"] .blue-table, -html[data-theme="light"] .table-alternate { - --color-odd: #e6a9c9; - --color-even: #80b2ea; -} - .table-alternate th:nth-child(odd), .table-alternate td:nth-child(odd) { background: var(--color-odd); @@ -678,117 +318,4 @@ html[data-theme="light"] .table-alternate { .table-alternate th:nth-child(even), .table-alternate td:nth-child(even) { background: var(--color-even); -} - -/* Hubspot-specific styling */ - -#enterprise-contact-us .hs-form .hs-input { - color: var(--theme-input-text-color); - background: var(--theme-input-bg-color); - font-size: var(--font-size-small); - padding: 0.5rem; - border-radius: calc(var(--ifm-global-border-radius) / 2); - border: 2px solid transparent; -} - -.hs-input:focus { - outline: none; - border-color: var(--palette-white); -} - -.hs-input:placeholder { - color: var(--palette-pale-blue); - font-size: var(--font-size-normal); - font-weight: var(--ifm-font-weight-bold); -} - -.hs-form label { - display: block; - margin-bottom: 0.5rem; - font-size: var(--font-size-large); -} - -.hs-form .hs-error-msgs, -.hs-form-required { - color: #ff5555; -} - -.hs-form .hs-button { - display: inline-flex; - align-items: center; - justify-content: center; - height: 55px; - padding: 0 2rem; - border: none; - border-radius: calc(var(--ifm-global-border-radius) / 2); - font-weight: var(--ifm-font-weight-bold); - font-size: var(--font-size-normal); - transition: background-color var(--transition-fastest) - var(--transition-bezier); -} - -.hs-form .hs-button.primary { - background-color: var(--theme-button-primary-background-color); - color: var(--theme-button-primary-text-color); -} - -#enterprise-contact-us form { - display: grid; - gap: 1rem; - grid-template-columns: 1fr; - width: 100%; -} - -@media screen and (min-width: 600px) { - #enterprise-contact-us form { - grid-template-columns: 1fr 1fr; - grid-template-areas: - "firstname lastname" - "email email" - "company jobtitle" - "message message" - ". ."; - } - - #enterprise-contact-us .hs-firstname { - grid-area: firstname; - } - - #enterprise-contact-us .hs-lastname { - grid-area: lastname; - } - - #enterprise-contact-us .hs-email { - grid-area: email; - } - - #enterprise-contact-us .hs-company { - grid-area: company; - } - - #enterprise-contact-us .hs-jobtitle { - grid-area: jobtitle; - } - - #enterprise-contact-us .hs-message { - grid-area: message; - } - - #enterprise-contact-us .hs-message textarea { - min-height: 150px; - } -} - -#enterprise-contact-us .hs-submit { - grid-column: 1 / -1; -} - -#enterprise-contact-us .hs-submit .actions { - display: flex; - justify-content: center; -} - -.navbar { - min-height: var(--ifm-navbar-height); - height: auto; -} +} \ No newline at end of file diff --git a/src/lib/remToPx.ts b/src/lib/remToPx.ts new file mode 100644 index 000000000..d3c3953a1 --- /dev/null +++ b/src/lib/remToPx.ts @@ -0,0 +1,8 @@ +export function remToPx(remValue: number) { + let rootFontSize = + typeof window === 'undefined' + ? 16 + : parseFloat(window.getComputedStyle(document.documentElement).fontSize) + + return remValue * rootFontSize +} diff --git a/yarn.lock b/yarn.lock index 671357c57..b1c1047a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2098,6 +2098,18 @@ utility-types "^3.10.0" webpack "^5.88.1" +"@emotion/is-prop-valid@^0.8.2": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" + integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== + dependencies: + "@emotion/memoize" "0.7.4" + +"@emotion/memoize@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" @@ -7410,6 +7422,15 @@ fraction.js@^4.3.7: resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== +framer-motion@^10.18.0: + version "10.18.0" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.18.0.tgz#1f4fc51403996ea7170af885bd44a7079d255950" + integrity sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w== + dependencies: + tslib "^2.4.0" + optionalDependencies: + "@emotion/is-prop-valid" "^0.8.2" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -13801,7 +13822,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.6.0, tslib@^2.6.2, tslib@^2.8.0: +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.0, tslib@^2.6.2, tslib@^2.8.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -14245,6 +14266,11 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" +use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -14940,6 +14966,13 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== +zustand@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.0.tgz#141354af56f91de378aa6c4b930032ab338f3ef0" + integrity sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A== + dependencies: + use-sync-external-store "1.2.0" + zwitch@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"