branding.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. import BasicPage from "../components/BasicPage"
  2. import Head from "next/head"
  3. import Hero from "../components/Hero"
  4. import { withDefaultStaticProps } from "../utils/defaultStaticProps"
  5. import classNames from "classnames"
  6. import Layout from "../components/Layout"
  7. import heroImage from "../public/illustrations/apps_hero_desktop.png"
  8. import Image from "next/legacy/image"
  9. import colors from "../data/colors"
  10. import screenshotComposeLight from "../public/screenshots/iphone-13-pro-max/Compose.light.1.iPhone 13 Pro Max_1_FB1EB7D6-DEF2-462D-9F4F-D622DF75032C.png"
  11. import screenshotHomeLight from "../public/screenshots/iphone-13-pro-max/Home.light.1.iPhone 13 Pro Max_1_E97CFEC9-A24C-4B12-87ED-D2CCD8F17A69.png"
  12. import screenshotProfileLight from "../public/screenshots/iphone-13-pro-max/Profile.light.1.iPhone 13 Pro Max_1_EB8AD280-7875-47A1-A556-D433BE7590E7.png"
  13. import screenshotServerRulesLight from "../public/screenshots/iphone-13-pro-max/ServerRules.light.1.iPhone 13 Pro Max_1_9B7DD752-9F56-4CA5-8A92-4E19B9FEB281.png"
  14. import screenshotThreadLight from "../public/screenshots/iphone-13-pro-max/Thread.light.1.iPhone 13 Pro Max_1_3C6768BF-C8B6-452B-8DD0-4C7919FBBE2F.png"
  15. import CheckIcon from "../public/icons/check.svg?inline"
  16. import LogoPurple from "../public/logos/logo-purple.svg?inline"
  17. import WordmarkWhiteText from "../public/logos/wordmark-white-text.svg?inline"
  18. const BrandSection = ({
  19. title,
  20. copy,
  21. ctas,
  22. preview,
  23. }: {
  24. title: React.ReactNode | string
  25. copy?: React.ReactNode
  26. ctas?: React.ReactNode
  27. preview: React.ReactNode
  28. }) => (
  29. <section className="col-span-12 grid gap-16 text-center md:col-start-3 md:col-end-11">
  30. <div className="full-width-bg">
  31. <div className="full-width-bg__inner flex flex-col items-center justify-center pt-20">
  32. <h2 className="h3 max-w-[17ch]">{title}</h2>
  33. {copy && (
  34. <div className="b1 mt-2 flex max-w-[50ch] flex-col gap-8">{copy}</div>
  35. )}
  36. {ctas && <div className="mt-12 flex justify-center gap-12">{ctas}</div>}
  37. </div>
  38. </div>
  39. {preview}
  40. </section>
  41. )
  42. const Logo = ({
  43. label,
  44. src,
  45. className,
  46. }: {
  47. label: string
  48. src: string
  49. className?: string
  50. }) => (
  51. <div className="flex items-center justify-center rounded-md">
  52. <a
  53. download
  54. title={label}
  55. href={src}
  56. className={classNames(
  57. "flex h-full w-full items-center justify-center rounded-md transition-colors",
  58. className
  59. )}
  60. >
  61. <div className="md:h-18 relative h-16 w-full lg:h-20">
  62. <Image src={src} alt="" layout="fill" />
  63. </div>
  64. </a>
  65. </div>
  66. )
  67. const UsageRule = ({ text }: { text: string }) => {
  68. return (
  69. <div className="flex items-center gap-6 text-left">
  70. <CheckIcon className="shrink-0" />
  71. <p>{text}</p>
  72. </div>
  73. )
  74. }
  75. /** This page does not require translations */
  76. const Branding = () => (
  77. <Layout>
  78. <div dir="ltr" className="[unicode-bidi:plaintext]">
  79. <Hero desktopImage={heroImage} mobileImage={heroImage}>
  80. <h1 className="h1 mb-8 pt-16">Brand Toolkit</h1>
  81. <p className="sh1">
  82. Learn our branding guidelines, download our logos and icons, or use
  83. our brand colors for&nbsp;your&nbsp;projects.
  84. </p>
  85. </Hero>
  86. <div className="grid grid-cols-12 gap-gutter">
  87. <BrandSection
  88. title="Wordmark"
  89. copy={
  90. <p>
  91. We take pride in the Mastodon logo and hope you do too.
  92. Please&nbsp;take a moment to think about how you apply it. If you
  93. want to use our art, please keep it tasteful!
  94. </p>
  95. }
  96. preview={
  97. <>
  98. {[
  99. {
  100. label: "Download the SVG wordmark with white text",
  101. src: "/logos/wordmark-white-text.svg",
  102. styles: "bg-eggplant hocus:bg-black p-16",
  103. },
  104. {
  105. label: "Download the SVG wordmark with black text",
  106. src: "/logos/wordmark-black-text.svg",
  107. styles: "bg-white hocus:bg-gray-5 p-16",
  108. },
  109. ].map((image) => (
  110. <Logo
  111. key={image.src}
  112. src={image.src}
  113. label={image.label}
  114. className={image.styles}
  115. />
  116. ))}
  117. <UsageRule text="Use the main logo (black or white version) on a background that creates enough contrast to retain logo quality" />
  118. {[
  119. {
  120. label:
  121. "Download the SVG wordmark with a white logo and black text",
  122. src: "/logos/logo-full-black.svg",
  123. styles: "bg-blurple-500 hocus:bg-blurple-600 p-16",
  124. },
  125. {
  126. label:
  127. "Download the SVG wordmark with a black logo and white text",
  128. src: "/logos/logo-full-white.svg",
  129. styles: "bg-blurple-500 hocus:bg-blurple-600 p-16",
  130. },
  131. ].map((image) => (
  132. <Logo
  133. key={image.src}
  134. src={image.src}
  135. label={image.label}
  136. className={image.styles}
  137. />
  138. ))}
  139. <UsageRule text="Use a black or white version of the logo when contrast can not be maintained with the main logo — for example above, using the main brand color for a background" />
  140. </>
  141. }
  142. />
  143. <BrandSection
  144. title="Mark only"
  145. copy={
  146. <p>
  147. Use these only when the Mastodon brand has been clearly
  148. established in the design.
  149. </p>
  150. }
  151. preview={
  152. <>
  153. <div className="grid grid-cols-3 gap-gutter md:px-8 lg:gap-24">
  154. {[
  155. {
  156. label: "Download the purple SVG logo",
  157. src: "/logos/logo-purple.svg",
  158. styles: "bg-white hocus:bg-gray-5 p-4 aspect-square",
  159. },
  160. {
  161. label: "Download the black SVG logo",
  162. src: "/logos/logo-black.svg",
  163. styles: "bg-white hocus:bg-gray-5 p-4 aspect-square",
  164. },
  165. {
  166. label: "Download the white SVG logo",
  167. src: "/logos/logo-white.svg",
  168. styles: "bg-black hocus:bg-gray-0 p-4 aspect-square",
  169. },
  170. ].map((image) => (
  171. <Logo
  172. key={image.src}
  173. src={image.src}
  174. label={image.label}
  175. className={image.styles}
  176. />
  177. ))}
  178. </div>
  179. <UsageRule text="Use the small version of the logo when the brand has already been established and / or space is limited to allow appropriate clear space around the main Mastodon logo" />
  180. <UsageRule text="Use the one color black or white version of the logo in applications of print or letterhead when only one print color is available" />
  181. </>
  182. }
  183. />
  184. <BrandSection
  185. title="Clear space"
  186. copy={
  187. <p>
  188. When using our logo, please ensure that you give it room to
  189. breathe! At least 36px on all sides please.
  190. </p>
  191. }
  192. preview={
  193. <div className="flex flex-col items-center justify-center gap-4 overflow-hidden sm:flex-row md:gap-32">
  194. {[LogoPurple, WordmarkWhiteText].map((Svg, i) => (
  195. <div
  196. className="relative rounded bg-eggplant p-[36px] text-blurple-600 shadow-[currentColor_0_0_0_1px_inset]"
  197. key={i}
  198. >
  199. {/* everything except for the image is a guide mark */}
  200. <div className="absolute top-0 left-0 h-[36px] w-[36px] rounded-full border" />
  201. <div className="absolute top-0 right-0 h-[36px] w-[36px] rounded-full border" />
  202. <div className="absolute bottom-0 left-0 h-[36px] w-[36px] rounded-full border" />
  203. <div className="absolute bottom-0 right-0 h-[36px] w-[36px] rounded-full border" />
  204. <div className="absolute top-0 left-0 m-[9px] h-[18px] w-[18px] rounded-full border" />
  205. <div className="absolute top-0 right-0 m-[9px] h-[18px] w-[18px] rounded-full border" />
  206. <div className="absolute bottom-0 left-0 m-[9px] h-[18px] w-[18px] rounded-full border" />
  207. <div className="absolute bottom-0 right-0 m-[9px] h-[18px] w-[18px] rounded-full border" />
  208. <div className="absolute border-x inset-block-0 inset-inline-[35px]" />
  209. <div className="absolute border-y inset-inline-0 inset-block-[35px]" />
  210. <Svg />
  211. </div>
  212. ))}
  213. </div>
  214. }
  215. />
  216. <BrandSection
  217. title="Our colors"
  218. preview={
  219. <div className="grid grid-cols-12 gap-gutter">
  220. <div className="col-span-12 grid grid-cols-2 gap-gutter">
  221. {colors.slice(0, 2).map(({ hex, pantone, cmyk }) => (
  222. <div key={hex} className="flex flex-col gap-2 text-left">
  223. <div
  224. style={{ backgroundColor: hex }}
  225. className="h-28 rounded"
  226. >
  227. <div className="p-4 pt-14 text-white">
  228. <div className="font-black">{hex}</div>
  229. <div className="c2">
  230. Pantone {pantone} &bull; CMYK {cmyk}
  231. </div>
  232. </div>
  233. </div>
  234. </div>
  235. ))}
  236. </div>
  237. <div className="col-span-12 grid grid-cols-3 gap-gutter lg:col-span-10 lg:col-start-2">
  238. {colors.slice(2).map(({ hex, pantone, cmyk }) => (
  239. <div key={hex} className="flex flex-col gap-2 text-left">
  240. <div
  241. style={{ backgroundColor: hex }}
  242. className="h-28 rounded"
  243. >
  244. <div className="p-4 pt-14 text-white">
  245. <div className="font-black">{hex}</div>
  246. <div className="c2">
  247. Pantone {pantone} &bull; CMYK {cmyk}
  248. </div>
  249. </div>
  250. </div>
  251. </div>
  252. ))}
  253. </div>
  254. </div>
  255. }
  256. />
  257. <BrandSection
  258. title="Product screenshots"
  259. copy="Need some screenshots? We've got you covered."
  260. preview={
  261. <div className="mb-16 flex gap-gutter">
  262. {[
  263. {
  264. src: screenshotComposeLight,
  265. download:
  266. "/screenshots/iphone-13-pro-max/Compose.light.1.iPhone 13 Pro Max_1_FB1EB7D6-DEF2-462D-9F4F-D622DF75032C.png",
  267. title: "Compose, light mode, iPhone 13 Pro Max",
  268. },
  269. {
  270. src: screenshotHomeLight,
  271. download:
  272. "/screenshots/iphone-13-pro-max/Home.light.1.iPhone 13 Pro Max_1_E97CFEC9-A24C-4B12-87ED-D2CCD8F17A69.png",
  273. title: "Home, light mode, iPhone 13 Pro Max",
  274. },
  275. {
  276. src: screenshotProfileLight,
  277. download:
  278. "/screenshots/iphone-13-pro-max/Profile.light.1.iPhone 13 Pro Max_1_EB8AD280-7875-47A1-A556-D433BE7590E7.png",
  279. title: "Profile, light mode, iPhone 13 Pro Max",
  280. },
  281. {
  282. src: screenshotServerRulesLight,
  283. download:
  284. "/screenshots/iphone-13-pro-max/ServerRules.light.1.iPhone 13 Pro Max_1_9B7DD752-9F56-4CA5-8A92-4E19B9FEB281.png",
  285. title: "Server rules, light mode, iPhone 13 Pro Max",
  286. },
  287. {
  288. src: screenshotThreadLight,
  289. download:
  290. "/screenshots/iphone-13-pro-max/Thread.light.1.iPhone 13 Pro Max_1_3C6768BF-C8B6-452B-8DD0-4C7919FBBE2F.png",
  291. title: "Thread, light mode, iPhone 13 Pro Max",
  292. },
  293. ].map((screenshot) => (
  294. <a
  295. key={screenshot.title}
  296. href={screenshot.download}
  297. title={screenshot.title}
  298. download
  299. className="block overflow-hidden rounded border border-gray-4 ring-blurple-500 hocus:ring"
  300. >
  301. <Image src={screenshot.src} alt="" />
  302. </a>
  303. ))}
  304. </div>
  305. }
  306. />
  307. </div>
  308. <Head>
  309. <title>Brand Toolkit - Mastodon</title>
  310. <meta property="og:title" content="Brand Toolkit for Mastodon" />
  311. <meta
  312. property="og:description"
  313. content="Learn our branding guidelines, download our logos and icons, or use our brand colors for your projects."
  314. />
  315. <meta
  316. property="description"
  317. content="Learn our branding guidelines, download our logos and icons, or use our brand colors for your projects."
  318. />
  319. </Head>
  320. </div>
  321. </Layout>
  322. )
  323. export const getStaticProps = withDefaultStaticProps()
  324. export default Branding