docs: Add consent banner (#50302)
Adds a consent banner, similar to the one on zed.dev Before you mark this PR as ready for review, make sure that you have: - [x] Added a solid test coverage and/or screenshots from doing manual testing - [x] Done a self-review taking into account security and performance aspects - [x] Aligned any UI changes with the [UI checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) Release Notes: - N/A
This commit is contained in:
1 parent
53b6118f3a
commit
5eeb0bc8ac
10 files changed
+497
-19
No files matched your search
@@ -26,6 +26,7 @@ jobs:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
DOCS_AMPLITUDE_API_KEY: ${{ secrets.DOCS_AMPLITUDE_API_KEY }}
|
||||
DOCS_CONSENT_IO_INSTANCE: ${{ secrets.DOCS_CONSENT_IO_INSTANCE }}
|
||||
|
||||
- name: Deploy Docs
|
||||
uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3
|
||||
|
||||
@@ -578,6 +578,7 @@ fn handle_postprocessing() -> Result<()> {
|
||||
.expect("Default title not a string")
|
||||
.to_string();
|
||||
let amplitude_key = std::env::var("DOCS_AMPLITUDE_API_KEY").unwrap_or_default();
|
||||
let consent_io_instance = std::env::var("DOCS_CONSENT_IO_INSTANCE").unwrap_or_default();
|
||||
|
||||
output.insert("html".to_string(), zed_html);
|
||||
mdbook::Renderer::render(&mdbook::renderer::HtmlHandlebars::new(), &ctx)?;
|
||||
@@ -647,6 +648,7 @@ fn handle_postprocessing() -> Result<()> {
|
||||
zlog::trace!(logger => "Updating {:?}", pretty_path(&file, &root_dir));
|
||||
let contents = contents.replace("#description#", meta_description);
|
||||
let contents = contents.replace("#amplitude_key#", &litude_key);
|
||||
let contents = contents.replace("#consent_io_instance#", &consent_io_instance);
|
||||
let contents = title_regex()
|
||||
.replace(&contents, |_: ®ex::Captures| {
|
||||
format!("<title>{}</title>", meta_title)
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
# Handlebars partials are not supported by Prettier.
|
||||
*.hbs
|
||||
|
||||
# Automatically generated
|
||||
theme/c15t@*.js
|
||||
@@ -64,6 +64,22 @@ This will render a human-readable version of the action name, e.g., "zed: open s
|
||||
Templates are functions that modify the source of the docs pages (usually with a regex match and replace).
|
||||
You can see how the actions and keybindings are templated in `crates/docs_preprocessor/src/main.rs` for reference on how to create new templates.
|
||||
|
||||
## Consent Banner
|
||||
|
||||
We pre-bundle the `c15t` package because the docs pipeline does not include a JS bundler. If you need to update `c15t` and rebuild the bundle, use:
|
||||
|
||||
```
|
||||
mkdir c15t-bundle && cd c15t-bundle
|
||||
npm init -y
|
||||
npm install c15t@<version> esbuild
|
||||
echo "import { getOrCreateConsentRuntime } from 'c15t'; window.c15t = { getOrCreateConsentRuntime };" > entry.js
|
||||
npx esbuild entry.js --bundle --format=iife --minify --outfile=c15t@<version>.js
|
||||
cp c15t@<version>.js ../theme/c15t@<version>.js
|
||||
cd .. && rm -rf c15t-bundle
|
||||
```
|
||||
|
||||
Replace `<version>` with the new version of `c15t` you are installing. Then update `book.toml` to reference the new bundle filename.
|
||||
|
||||
### References
|
||||
|
||||
- Template Trait: `crates/docs_preprocessor/src/templates.rs`
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ default-description = "Learn how to use and customize Zed, the fast, collaborati
|
||||
default-title = "Zed Code Editor Documentation"
|
||||
no-section-label = true
|
||||
preferred-dark-theme = "dark"
|
||||
additional-css = ["theme/page-toc.css", "theme/plugins.css", "theme/highlight.css"]
|
||||
additional-js = ["theme/page-toc.js", "theme/plugins.js"]
|
||||
additional-css = ["theme/page-toc.css", "theme/plugins.css", "theme/highlight.css", "theme/consent-banner.css"]
|
||||
additional-js = ["theme/page-toc.js", "theme/plugins.js", "theme/c15t@2.0.0-rc.3.js", "theme/analytics.js"]
|
||||
|
||||
[output.zed-html.print]
|
||||
enable = false
|
||||
|
||||
Vendored
+93
@@ -0,0 +1,93 @@
|
||||
const amplitudeKey = document.querySelector(
|
||||
'meta[name="amplitude-key"]',
|
||||
)?.content;
|
||||
const consentInstance = document.querySelector(
|
||||
'meta[name="consent-io-instance"]',
|
||||
)?.content;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
if (!consentInstance || consentInstance.length === 0) return;
|
||||
const { getOrCreateConsentRuntime } = window.c15t;
|
||||
|
||||
const { consentStore } = getOrCreateConsentRuntime({
|
||||
mode: "c15t",
|
||||
backendURL: consentInstance,
|
||||
consentCategories: ["necessary", "measurement", "marketing"],
|
||||
storageConfig: {
|
||||
crossSubdomain: true,
|
||||
},
|
||||
scripts: [
|
||||
{
|
||||
id: "amplitude",
|
||||
src: `https://cdn.amplitude.com/script/${amplitudeKey}.js`,
|
||||
category: "measurement",
|
||||
onLoad: () => {
|
||||
window.amplitude.init(amplitudeKey, {
|
||||
fetchRemoteConfig: true,
|
||||
autocapture: true,
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let previousActiveUI = consentStore.getState().activeUI;
|
||||
const banner = document.getElementById("c15t-banner");
|
||||
const configureSection = document.getElementById("c15t-configure-section");
|
||||
const configureBtn = document.getElementById("c15t-configure-btn");
|
||||
const measurementToggle = document.getElementById("c15t-toggle-measurement");
|
||||
const marketingToggle = document.getElementById("c15t-toggle-marketing");
|
||||
|
||||
const toggleConfigureMode = () => {
|
||||
const currentConsents = consentStore.getState().consents;
|
||||
measurementToggle.checked = currentConsents
|
||||
? (currentConsents.measurement ?? false)
|
||||
: false;
|
||||
marketingToggle.checked = currentConsents
|
||||
? (currentConsents.marketing ?? false)
|
||||
: false;
|
||||
configureSection.style.display = "flex";
|
||||
configureBtn.innerHTML = "Save";
|
||||
configureBtn.className = "c15t-button secondary";
|
||||
configureBtn.title = "";
|
||||
};
|
||||
|
||||
consentStore.subscribe((state) => {
|
||||
const hideBanner =
|
||||
state.activeUI === "none" ||
|
||||
(state.activeUI === "banner" && state.mode === "opt-out");
|
||||
banner.style.display = hideBanner ? "none" : "block";
|
||||
|
||||
if (state.activeUI === "dialog" && previousActiveUI !== "dialog") {
|
||||
toggleConfigureMode();
|
||||
}
|
||||
|
||||
previousActiveUI = state.activeUI;
|
||||
});
|
||||
|
||||
configureBtn.addEventListener("click", () => {
|
||||
if (consentStore.getState().activeUI === "dialog") {
|
||||
consentStore
|
||||
.getState()
|
||||
.setConsent("measurement", measurementToggle.checked);
|
||||
consentStore.getState().setConsent("marketing", marketingToggle.checked);
|
||||
consentStore.getState().saveConsents("custom");
|
||||
} else {
|
||||
consentStore.getState().setActiveUI("dialog");
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("c15t-accept").addEventListener("click", () => {
|
||||
consentStore.getState().saveConsents("all");
|
||||
});
|
||||
|
||||
document.getElementById("c15t-decline").addEventListener("click", () => {
|
||||
consentStore.getState().saveConsents("necessary");
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("c15t-manage-consent-btn")
|
||||
.addEventListener("click", () => {
|
||||
consentStore.getState().setActiveUI("dialog");
|
||||
});
|
||||
});
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
(()=>{var ni=Object.defineProperty;var P=(n,e)=>()=>(n&&(e=n(n=0)),e);var Nt=(n,e)=>{for(var t in e)ni(n,t,{get:e[t],enumerable:!0})};var G,$t=P(()=>{G=class extends Error{constructor(e){super(e),this.name="DecodingError"}}});var q,Kt=P(()=>{q=class extends Error{constructor(e){super(e),this.name="EncodingError"}}});var oe,Yt=P(()=>{oe=class extends Error{constructor(e){super(e),this.name="GVLError"}}});var W,Wt=P(()=>{W=class extends Error{constructor(e,t,i=""){super(`invalid value ${t} passed for ${e} ${i}`),this.name="TCModelError"}}});var J=P(()=>{$t();Kt();Yt();Wt()});var pe,rt=P(()=>{J();pe=class{static DICT="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";static REVERSE_DICT=new Map([["A",0],["B",1],["C",2],["D",3],["E",4],["F",5],["G",6],["H",7],["I",8],["J",9],["K",10],["L",11],["M",12],["N",13],["O",14],["P",15],["Q",16],["R",17],["S",18],["T",19],["U",20],["V",21],["W",22],["X",23],["Y",24],["Z",25],["a",26],["b",27],["c",28],["d",29],["e",30],["f",31],["g",32],["h",33],["i",34],["j",35],["k",36],["l",37],["m",38],["n",39],["o",40],["p",41],["q",42],["r",43],["s",44],["t",45],["u",46],["v",47],["w",48],["x",49],["y",50],["z",51],["0",52],["1",53],["2",54],["3",55],["4",56],["5",57],["6",58],["7",59],["8",60],["9",61],["-",62],["_",63]]);static BASIS=6;static LCM=24;static encode(e){if(!/^[0-1]+$/.test(e))throw new q("Invalid bitField");let t=e.length%this.LCM;e+=t?"0".repeat(this.LCM-t):"";let i="";for(let s=0;s<e.length;s+=this.BASIS)i+=this.DICT[parseInt(e.substr(s,this.BASIS),2)];return i}static decode(e){if(!/^[A-Za-z0-9\-_]+$/.test(e))throw new G("Invalidly encoded Base64URL string");let t="";for(let i=0;i<e.length;i++){let s=this.REVERSE_DICT.get(e[i]).toString(2);t+="0".repeat(this.BASIS-s.length)+s}return t}}});var Ee,Jt=P(()=>{Ee=class n{static langSet=new Set(["AR","BG","BS","CA","CS","CY","DA","DE","EL","EN","ES","ET","EU","FI","FR","GL","HE","HI","HR","HU","ID","IS","IT","JA","KA","KO","LT","LV","MK","MS","MT","NL","NO","PL","PT-BR","PT-PT","RO","RU","SK","SL","SQ","SR-LATN","SR-CYRL","SV","SW","TH","TL","TR","UK","VI","ZH","ZH-HANT"]);has(e){return n.langSet.has(e)}parseLanguage(e){e=e.toUpperCase();let t=e.split("-")[0];if(e.length>=2&&t.length==2){if(n.langSet.has(e))return e;if(n.langSet.has(t))return t;let i=t+"-"+t;if(n.langSet.has(i))return i;for(let s of n.langSet)if(s.indexOf(e)!==-1||s.indexOf(t)!==-1)return s}throw new Error(`unsupported language ${e}`)}forEach(e){n.langSet.forEach(e)}get size(){return n.langSet.size}}});var v,ot=P(()=>{v=class{static cmpId="cmpId";static cmpVersion="cmpVersion";static consentLanguage="consentLanguage";static consentScreen="consentScreen";static created="created";static supportOOB="supportOOB";static isServiceSpecific="isServiceSpecific";static lastUpdated="lastUpdated";static numCustomPurposes="numCustomPurposes";static policyVersion="policyVersion";static publisherCountryCode="publisherCountryCode";static publisherCustomConsents="publisherCustomConsents";static publisherCustomLegitimateInterests="publisherCustomLegitimateInterests";static publisherLegitimateInterests="publisherLegitimateInterests";static publisherConsents="publisherConsents";static publisherRestrictions="publisherRestrictions";static purposeConsents="purposeConsents";static purposeLegitimateInterests="purposeLegitimateInterests";static purposeOneTreatment="purposeOneTreatment";static specialFeatureOptins="specialFeatureOptins";static useNonStandardTexts="useNonStandardTexts";static vendorConsents="vendorConsents";static vendorLegitimateInterests="vendorLegitimateInterests";static vendorListVersion="vendorListVersion";static vendorsAllowed="vendorsAllowed";static vendorsDisclosed="vendorsDisclosed";static version="version"}});var Zt=P(()=>{});var Qt=P(()=>{});var te,fe=P(()=>{te=class{clone(){let e=new this.constructor;return Object.keys(this).forEach(i=>{let s=this.deepClone(this[i]);s!==void 0&&(e[i]=s)}),e}deepClone(e){let t=typeof e;if(t==="number"||t==="string"||t==="boolean")return e;if(e!==null&&t==="object"){if(typeof e.clone=="function")return e.clone();if(e instanceof Date)return new Date(e.getTime());if(e[Symbol.iterator]!==void 0){let i=[];for(let s of e)i.push(this.deepClone(s));return e instanceof Array?i:new e.constructor(i)}else{let i={};for(let s in e)e.hasOwnProperty(s)&&(i[s]=this.deepClone(e[s]));return i}}}}});var Z,Ge=P(()=>{(function(n){n[n.NOT_ALLOWED=0]="NOT_ALLOWED",n[n.REQUIRE_CONSENT=1]="REQUIRE_CONSENT",n[n.REQUIRE_LI=2]="REQUIRE_LI"})(Z||(Z={}))});var ae,at=P(()=>{fe();J();Ge();ae=class n extends te{static hashSeparator="-";purposeId_;restrictionType;constructor(e,t){super(),e!==void 0&&(this.purposeId=e),t!==void 0&&(this.restrictionType=t)}static unHash(e){let t=e.split(this.hashSeparator),i=new n;if(t.length!==2)throw new W("hash",e);return i.purposeId=parseInt(t[0],10),i.restrictionType=parseInt(t[1],10),i}get hash(){if(!this.isValid())throw new Error("cannot hash invalid PurposeRestriction");return`${this.purposeId}${n.Line truncated
|
||||
Vendored
+292
@@ -0,0 +1,292 @@
|
||||
#c15t-banner {
|
||||
--color-offgray-50: hsl(218, 12%, 95%);
|
||||
--color-offgray-100: hsl(218, 12%, 88%);
|
||||
--color-offgray-200: hsl(218, 12%, 80%);
|
||||
--color-offgray-300: hsl(218, 12%, 75%);
|
||||
--color-offgray-400: hsl(218, 12%, 64%);
|
||||
--color-offgray-500: hsl(218, 12%, 56%);
|
||||
--color-offgray-600: hsl(218, 12%, 48%);
|
||||
--color-offgray-700: hsl(218, 12%, 40%);
|
||||
--color-offgray-800: hsl(218, 12%, 34%);
|
||||
--color-offgray-900: hsl(218, 12%, 24%);
|
||||
--color-offgray-950: hsl(218, 12%, 15%);
|
||||
--color-offgray-1000: hsl(218, 12%, 5%);
|
||||
|
||||
--color-blue-50: oklch(97% 0.014 254.604);
|
||||
--color-blue-100: oklch(93.2% 0.032 255.585);
|
||||
--color-blue-200: oklch(88.2% 0.059 254.128);
|
||||
--color-blue-300: oklch(80.9% 0.105 251.813);
|
||||
--color-blue-400: oklch(70.7% 0.165 254.624);
|
||||
--color-blue-500: oklch(62.3% 0.214 259.815);
|
||||
--color-blue-600: oklch(54.6% 0.245 262.881);
|
||||
--color-blue-700: oklch(48.8% 0.243 264.376);
|
||||
--color-blue-800: oklch(42.4% 0.199 265.638);
|
||||
--color-blue-900: oklch(37.9% 0.146 265.522);
|
||||
--color-blue-950: oklch(28.2% 0.091 267.935);
|
||||
|
||||
--color-accent-blue: hsla(218, 93%, 42%, 1);
|
||||
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
border-radius: 4px;
|
||||
max-width: 300px;
|
||||
background: white;
|
||||
border: 1px solid
|
||||
color-mix(in oklab, var(--color-offgray-200) 50%, transparent);
|
||||
box-shadow: 6px 6px 0
|
||||
color-mix(in oklab, var(--color-accent-blue) 6%, transparent);
|
||||
}
|
||||
|
||||
.dark #c15t-banner {
|
||||
border-color: color-mix(in oklab, var(--color-offgray-600) 14%, transparent);
|
||||
background: var(--color-offgray-1000);
|
||||
box-shadow: 5px 5px 0
|
||||
color-mix(in oklab, var(--color-accent-blue) 8%, transparent);
|
||||
}
|
||||
|
||||
#c15t-banner > div:first-child {
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#c15t-banner a {
|
||||
color: var(--links);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: var(--link-line-decoration);
|
||||
}
|
||||
|
||||
#c15t-banner a:hover {
|
||||
text-decoration-color: var(--link-line-decoration-hover);
|
||||
}
|
||||
|
||||
#c15t-description {
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
#c15t-configure-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
border-top: 1px solid var(--divider);
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
#c15t-configure-section > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#c15t-configure-section label {
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#c15t-footer {
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-top: 1px solid var(--divider);
|
||||
background-color: color-mix(
|
||||
in oklab,
|
||||
var(--color-offgray-50) 50%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
|
||||
.dark #c15t-footer {
|
||||
background-color: color-mix(
|
||||
in oklab,
|
||||
var(--color-offgray-600) 4%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
|
||||
.c15t-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
max-height: 28px;
|
||||
color: black;
|
||||
padding: 4px 8px;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
transition: 100ms;
|
||||
transition-property: box-shadow, border-color, background-color;
|
||||
}
|
||||
|
||||
.c15t-button:hover {
|
||||
background: color-mix(in oklab, var(--color-offgray-100) 50%, transparent);
|
||||
}
|
||||
|
||||
.dark .c15t-button {
|
||||
color: var(--color-offgray-50);
|
||||
}
|
||||
|
||||
.dark .c15t-button:hover {
|
||||
background: color-mix(in oklab, var(--color-offgray-500) 10%, transparent);
|
||||
}
|
||||
|
||||
.c15t-button.icon {
|
||||
padding: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.c15t-button.primary {
|
||||
color: var(--color-blue-700);
|
||||
background: color-mix(in oklab, var(--color-blue-50) 60%, transparent);
|
||||
border-color: color-mix(in oklab, var(--color-blue-500) 20%, transparent);
|
||||
box-shadow: color-mix(in oklab, var(--color-blue-400) 10%, transparent) 0 -2px
|
||||
0 0 inset;
|
||||
}
|
||||
|
||||
.c15t-button.primary:hover {
|
||||
background: color-mix(in oklab, var(--color-blue-100) 50%, transparent);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.dark .c15t-button.primary {
|
||||
color: var(--color-blue-50);
|
||||
background: color-mix(in oklab, var(--color-blue-500) 10%, transparent);
|
||||
border-color: color-mix(in oklab, var(--color-blue-300) 10%, transparent);
|
||||
box-shadow: color-mix(in oklab, var(--color-blue-300) 8%, transparent) 0 -2px
|
||||
0 0 inset;
|
||||
}
|
||||
|
||||
.dark .c15t-button.primary:hover {
|
||||
background: color-mix(in oklab, var(--color-blue-500) 20%, transparent);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.c15t-button.secondary {
|
||||
background: color-mix(in oklab, var(--color-offgray-50) 60%, transparent);
|
||||
border-color: color-mix(in oklab, var(--color-offgray-200) 50%, transparent);
|
||||
box-shadow: color-mix(in oklab, var(--color-offgray-500) 10%, transparent)
|
||||
0 -2px 0 0 inset;
|
||||
}
|
||||
|
||||
.c15t-button.secondary:hover {
|
||||
background: color-mix(in oklab, var(--color-offgray-100) 50%, transparent);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.dark .c15t-button.secondary {
|
||||
background: color-mix(in oklab, var(--color-offgray-300) 5%, transparent);
|
||||
border-color: color-mix(in oklab, var(--color-offgray-400) 20%, transparent);
|
||||
box-shadow: color-mix(in oklab, var(--color-offgray-300) 8%, transparent)
|
||||
0 -2px 0 0 inset;
|
||||
}
|
||||
|
||||
.dark .c15t-button.secondary:hover {
|
||||
background: color-mix(in oklab, var(--color-offgray-200) 10%, transparent);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.c15t-switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 32px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.c15t-switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.c15t-slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
inset: 0;
|
||||
background-color: color-mix(
|
||||
in oklab,
|
||||
var(--color-offgray-100) 80%,
|
||||
transparent
|
||||
);
|
||||
border-radius: 20px;
|
||||
box-shadow: inset 0 0 0 1px color-mix(in oklab, #000 5%, transparent);
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.c15t-slider:hover {
|
||||
background-color: var(--color-offgray-100);
|
||||
}
|
||||
|
||||
.dark .c15t-slider {
|
||||
background-color: color-mix(in oklab, #fff 5%, transparent);
|
||||
box-shadow: inset 0 0 0 1px color-mix(in oklab, #fff 15%, transparent);
|
||||
}
|
||||
|
||||
.dark .c15t-slider:hover {
|
||||
background-color: color-mix(in oklab, #fff 10%, transparent);
|
||||
}
|
||||
|
||||
.c15t-slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
box-shadow:
|
||||
0 1px 3px 0 rgb(0 0 0 / 0.1),
|
||||
0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.c15t-switch input:checked + .c15t-slider {
|
||||
background-color: var(--color-accent-blue);
|
||||
box-shadow: inset 0 0 0 1px color-mix(in oklab, #000 5%, transparent);
|
||||
}
|
||||
|
||||
.c15t-switch input:checked + .c15t-slider:hover {
|
||||
background-color: var(--color-accent-blue);
|
||||
}
|
||||
|
||||
.dark .c15t-switch input:checked + .c15t-slider {
|
||||
background-color: var(--color-accent-blue);
|
||||
box-shadow: inset 0 0 0 1px color-mix(in oklab, #fff 15%, transparent);
|
||||
}
|
||||
|
||||
.c15t-switch input:checked + .c15t-slider:before {
|
||||
transform: translateX(12px);
|
||||
}
|
||||
|
||||
.c15t-switch input:disabled + .c15t-slider {
|
||||
opacity: 0.5;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.c15t-switch input:disabled + .c15t-slider:hover {
|
||||
background-color: color-mix(
|
||||
in oklab,
|
||||
var(--color-offgray-100) 80%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
|
||||
#c15t-manage-consent-btn {
|
||||
appearance: none;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#c15t-manage-consent-btn:hover {
|
||||
text-decoration-color: var(--link-line-decoration-hover);
|
||||
}
|
||||
Vendored
+85
-17
@@ -70,6 +70,8 @@
|
||||
<!-- MathJax -->
|
||||
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
{{/if}}
|
||||
<meta name="amplitude-key" content="#amplitude_key#" />
|
||||
<meta name="consent-io-instance" content="#consent_io_instance#" />
|
||||
</head>
|
||||
<body class="no-js">
|
||||
<div id="body-container">
|
||||
@@ -343,6 +345,13 @@
|
||||
href="https://zed.dev/blog"
|
||||
>Blog</a
|
||||
>
|
||||
<span class="footer-separator">•</span>
|
||||
<button
|
||||
id="c15t-manage-consent-btn"
|
||||
class="footer-link"
|
||||
>
|
||||
Manage Site Cookies
|
||||
</button>
|
||||
</footer>
|
||||
</main>
|
||||
<div class="toc-container">
|
||||
@@ -444,23 +453,82 @@
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
<!-- Amplitude Analytics -->
|
||||
<script>
|
||||
(function() {
|
||||
var amplitudeKey = '#amplitude_key#';
|
||||
if (amplitudeKey && amplitudeKey.indexOf('#') === -1) {
|
||||
var script = document.createElement('script');
|
||||
script.src = 'https://cdn.amplitude.com/script/' + amplitudeKey + '.js';
|
||||
script.onload = function() {
|
||||
window.amplitude.init(amplitudeKey, {
|
||||
fetchRemoteConfig: true,
|
||||
autocapture: true
|
||||
});
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<!-- c15t Consent Banner -->
|
||||
<div id="c15t-banner" style="display: none;">
|
||||
<div>
|
||||
<p id="c15t-description">
|
||||
Zed uses cookies to improve your experience and for marketing. Read <a href="https://zed.dev/cookie-policy">our cookie policy</a> for more details.
|
||||
</p>
|
||||
</div>
|
||||
<div id="c15t-configure-section" style="display: none">
|
||||
<div>
|
||||
<label for="c15t-toggle-necessary"
|
||||
>Strictly Necessary</label
|
||||
>
|
||||
<label class="c15t-switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="c15t-toggle-necessary"
|
||||
checked
|
||||
disabled
|
||||
/>
|
||||
<span class="c15t-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="c15t-toggle-measurement">Analytics</label>
|
||||
<label class="c15t-switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="c15t-toggle-measurement"
|
||||
/>
|
||||
<span class="c15t-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="c15t-toggle-marketing">Marketing</label>
|
||||
<label class="c15t-switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="c15t-toggle-marketing"
|
||||
/>
|
||||
<span class="c15t-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="c15t-footer">
|
||||
<button
|
||||
id="c15t-configure-btn"
|
||||
class="c15t-button icon"
|
||||
title="Configure"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M20 7h-9" />
|
||||
<path d="M14 17H5" />
|
||||
<circle cx="17" cy="17" r="3" />
|
||||
<circle cx="7" cy="7" r="3" />
|
||||
</svg>
|
||||
</button>
|
||||
<div>
|
||||
<button id="c15t-decline" class="c15t-button">
|
||||
Reject all
|
||||
</button>
|
||||
<button id="c15t-accept" class="c15t-button primary">
|
||||
Accept all
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -42,6 +42,8 @@ extend-exclude = [
|
||||
"crates/gpui_windows/src/window.rs",
|
||||
# Some typos in the base mdBook CSS.
|
||||
"docs/theme/css/",
|
||||
# Automatically generated JS.
|
||||
"docs/theme/c15t@*.js",
|
||||
# Spellcheck triggers on `|Fixe[sd]|` regex part.
|
||||
"script/danger/dangerfile.ts",
|
||||
# Eval examples for prompts and criteria
|
||||
|
||||
Reference in new issue
Block a user