mirror of
https://github.com/netbirdio/docs.git
synced 2026-04-15 23:16:36 +00:00
General Docs Improvements (#542)
This commit is contained in:
@@ -130,6 +130,11 @@ const nextConfig = {
|
||||
destination: '/manage/access-control/endpoint-detection-and-response/sentinelone-edr',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/how-to/huntress-edr',
|
||||
destination: '/manage/access-control/endpoint-detection-and-response/huntress-edr',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/how-to/intune-mdm',
|
||||
destination: '/manage/access-control/endpoint-detection-and-response/intune-mdm',
|
||||
|
||||
@@ -20,8 +20,10 @@ export function ImageZoom() {
|
||||
target.tagName === 'IMG' &&
|
||||
(target.classList.contains('imagewrapper') ||
|
||||
target.classList.contains('imagewrapper-big') ||
|
||||
target.classList.contains('imagewrapper-medium') ||
|
||||
target.closest('.imagewrapper') ||
|
||||
target.closest('.imagewrapper-big'))
|
||||
target.closest('.imagewrapper-big') ||
|
||||
target.closest('.imagewrapper-medium'))
|
||||
) {
|
||||
e.preventDefault()
|
||||
setZoomedImage(target.src)
|
||||
|
||||
@@ -85,6 +85,7 @@ function GitHubIcon(props) {
|
||||
|
||||
function useTableOfContents(tableOfContents) {
|
||||
let [currentSection, setCurrentSection] = useState(tableOfContents[0]?.id)
|
||||
let [showJumpToTop, setShowJumpToTop] = useState(false)
|
||||
|
||||
let getHeadings = useCallback((tableOfContents) => {
|
||||
return tableOfContents
|
||||
@@ -105,7 +106,10 @@ function useTableOfContents(tableOfContents) {
|
||||
if (tableOfContents.length === 0) return
|
||||
let headings = getHeadings(tableOfContents)
|
||||
function onScroll() {
|
||||
let top = window.scrollY + 10;
|
||||
let scrollTop = window.scrollY
|
||||
setShowJumpToTop(scrollTop > 400)
|
||||
|
||||
let top = scrollTop + 10;
|
||||
let current = headings[0]?.id
|
||||
for (let heading of headings) {
|
||||
if (top >= heading?.top) {
|
||||
@@ -123,7 +127,7 @@ function useTableOfContents(tableOfContents) {
|
||||
}
|
||||
}, [getHeadings, tableOfContents])
|
||||
|
||||
return currentSection
|
||||
return { currentSection, showJumpToTop }
|
||||
}
|
||||
|
||||
export function Layout({ children, title, tableOfContents }) {
|
||||
@@ -156,7 +160,12 @@ export function Layout({ children, title, tableOfContents }) {
|
||||
position: toast.POSITION.BOTTOM_RIGHT,
|
||||
});
|
||||
};
|
||||
let currentSection = useTableOfContents(tableOfContents)
|
||||
|
||||
const scrollToTop = () => {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
let { currentSection, showJumpToTop } = useTableOfContents(tableOfContents)
|
||||
|
||||
function isActive(section) {
|
||||
if (section.id === currentSection) {
|
||||
@@ -183,7 +192,7 @@ export function Layout({ children, title, tableOfContents }) {
|
||||
className="contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex"
|
||||
style={{ top: bannerHeight }}
|
||||
>
|
||||
<div className="contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 lg:dark:border-neutral-700/50 lg:px-6 lg:pb-8 lg:pt-4 lg:bg-white/70 lg:dark:bg-[#181A1D]/95 lg:backdrop-blur-lg xl:w-80 lg:overflow-x-visible">
|
||||
<div className="contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 lg:dark:border-neutral-700/50 lg:px-6 lg:pb-8 lg:pt-4 lg:bg-white/70 lg:dark:bg-[#181A1D]/95 lg:backdrop-blur-lg xl:w-80 lg:overflow-x-visible sidebar-scroll">
|
||||
<div className="hidden lg:flex">
|
||||
<Link href="/" aria-label="Home">
|
||||
<Logo className="h-6" />
|
||||
@@ -228,12 +237,26 @@ export function Layout({ children, title, tableOfContents }) {
|
||||
<nav aria-labelledby="on-this-page-title" className="w-80">
|
||||
{tableOfContents.length > 0 && (
|
||||
<>
|
||||
<h2
|
||||
id="on-this-page-title"
|
||||
className="font-display text-sm font-medium text-slate-900 dark:text-white"
|
||||
>
|
||||
On this page
|
||||
</h2>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2
|
||||
id="on-this-page-title"
|
||||
className="font-display text-sm font-medium text-slate-900 dark:text-white"
|
||||
>
|
||||
On this page
|
||||
</h2>
|
||||
{showJumpToTop && (
|
||||
<button
|
||||
onClick={scrollToTop}
|
||||
className="text-xs text-slate-500 hover:text-orange-500 dark:text-slate-400 dark:hover:text-orange-400 transition-colors flex items-center gap-1"
|
||||
aria-label="Jump to top"
|
||||
>
|
||||
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
|
||||
</svg>
|
||||
Top
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<ol role="list" className="mt-4 space-y-3 text-sm">
|
||||
{tableOfContents.map((section) => (
|
||||
<li key={section.id}>
|
||||
|
||||
@@ -6,7 +6,6 @@ import * as mdxComponents from '@/components/mdx'
|
||||
import { useMobileNavigationStore } from '@/components/MobileNavigation'
|
||||
|
||||
import '@/styles/tailwind.css'
|
||||
import '@/styles/global.css';
|
||||
import 'focus-visible'
|
||||
import {Layout} from "@/components/Layout";
|
||||
import {slugifyWithCounter} from "@sindresorhus/slugify";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {Note} from "@/components/mdx";
|
||||
|
||||
export const title = 'FAQ'
|
||||
# FAQ
|
||||
|
||||
## What firewall ports should I open to use NetBird (Network Firewalls)?
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import {Note} from "@/components/mdx";
|
||||
|
||||
export const title = 'How NetBird Works'
|
||||
# How NetBird Works
|
||||
|
||||
## Architecture
|
||||
|
||||
### Overview
|
||||
NetBird is an open source platform consisting of a collection of components, responsible for handling peer-to-peer
|
||||
connections, tunneling, authentication, and network management (IPs, keys, ACLs, etc).
|
||||
|
||||
@@ -35,7 +32,7 @@ In this case, [groups and access controls](/manage/access-control/manage-network
|
||||
|
||||
Let's now take a closer look at each of NetBird's components.
|
||||
|
||||
### Management Service
|
||||
## Management Service
|
||||
|
||||
The Management service is the central coordination component for NetBird with a UI dashboard.
|
||||
It keeps the network state, public WireGuard keys of the peers, authenticates and distributes network changes to peers.
|
||||
@@ -61,7 +58,7 @@ The Management service runs in the cloud NetBird-managed. It can also be self-ho
|
||||
<img src="/docs-static/img/about-netbird/management.png" alt="management-dia" className="imagewrapper-big"/>
|
||||
</p>
|
||||
|
||||
### Client Application
|
||||
## Client Application
|
||||
|
||||
The NetBird Client application (or agent) is a software that is installed on the machines within a NetBird network.
|
||||
It is an entry point to your private network that makes it possible for machines to communicate with each other.
|
||||
@@ -88,7 +85,7 @@ The client also applies other DNS settings that are received from the Management
|
||||
The **private key**, generated by the NetBird client, **never leaves the machine**, ensuring that only the machine that owns the key can decrypt traffic addressed to it.
|
||||
</Note>
|
||||
|
||||
### Signal Service
|
||||
## Signal Service
|
||||
|
||||
The Signal Service, or simply Signal, is a lightweight piece of software that helps peers to negotiate direct connections.
|
||||
It does not store any data and no traffic passes through it.
|
||||
@@ -109,7 +106,7 @@ This is done through Signal. After a connection has been established, Signal ste
|
||||
NetBird Signal is very similar to the signaling servers used in [WebRTC](https://developer.mozilla.org/en-US/Web/API/WebRTC_API/Signaling_and_video_calling#the_signaling_server).
|
||||
It runs in the cloud NetBird-managed and can be self-hosted.
|
||||
|
||||
### Relay Service
|
||||
## Relay Service
|
||||
|
||||
The Relay service is a [TURN server](https://webrtc.org/getting-started/turn-server) in WebRTC terminology.
|
||||
In fact, we use an open-source implementation called [Coturn](https://github.com/coturn/coturn).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {Note} from "@/components/mdx";
|
||||
|
||||
export const title = 'Getting Started'
|
||||
# Getting Started
|
||||
|
||||
## Quickstart Guide
|
||||
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
# Restrict Network Access with Huntress EDR
|
||||
|
||||
[Huntress](https://www.huntress.com/) is a managed detection and response (MDR) platform designed for IT service providers and enterprises to protect endpoints from cyber threats. The Huntress agent continuously monitors endpoints, collecting security telemetry including Windows Defender status, firewall configuration, and policy compliance, which can be used to enforce network access controls based on device security posture.
|
||||
|
||||
The integration of NetBird with Huntress provides network security by ensuring only devices that meet your defined security standards can access the protected network. This approach allows administrators to enforce access restrictions based on critical Windows security settings such as Defender health status, antivirus definitions, firewall state, and policy compliance, ensuring only properly secured endpoints have access to network resources via NetBird.
|
||||
|
||||
In this guide, you'll learn how to integrate NetBird with Huntress and configure access controls to allow only compliant devices onto your network.
|
||||
|
||||
<Note>
|
||||
TLDR: Devices that fail to meet Huntress security requirements (Windows Defender health, firewall status, or policy compliance) will automatically lose network access. Once a device meets all compliance criteria, access is restored.
|
||||
</Note>
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you start creating and configuring a Huntress integration, ensure that you have the following:
|
||||
- A Huntress account with the permissions to create and manage API keys.
|
||||
If you don't have the required permissions, ask your Huntress administrator to grant them to you.
|
||||
|
||||
## Create a Huntress API Key
|
||||
|
||||
- Navigate to your Huntress Management Console
|
||||
- Go to **Settings** » **API Credentials**
|
||||
- Click **Create API Credential**
|
||||
- Fill in the form:
|
||||
- **Name**: `NetBird Integration`
|
||||
- **Description**: `API key for NetBird EDR integration` (optional)
|
||||
- Click **Create**
|
||||
- Copy the generated API key and secret immediately (they will only be displayed once)
|
||||
- Note your Huntress organization key from the console
|
||||
|
||||
<Note>
|
||||
Treat the API credentials securely and store them safely. You will need both the API key and secret for the NetBird integration configuration.
|
||||
</Note>
|
||||
|
||||
## Configure a Huntress Integration in NetBird
|
||||
|
||||
- Navigate to the [Integrations » EDR](https://app.netbird.io/integrations?tab=edr) tab in the NetBird dashboard
|
||||
- Click **Connect Huntress** to start the configuration wizard
|
||||
<p>
|
||||
<img src="/docs-static/img/how-to-guides/endpoint-detection-and-response/huntress/getting-started.png" alt="Huntress integration getting started" className="imagewrapper-big"/>
|
||||
</p>
|
||||
- Click the **Get Started** button to initiate the integration process
|
||||
- Enter your Huntress organization key and click **Continue**
|
||||
|
||||
<p>
|
||||
<img src="/docs-static/img/how-to-guides/endpoint-detection-and-response/huntress/console-config.png" alt="Huntress console configuration" className="imagewrapper-big"/>
|
||||
</p>
|
||||
|
||||
- Enter the API key and secret you created in the previous step and click **Continue** to verify the connection
|
||||
|
||||
<p>
|
||||
<img src="/docs-static/img/how-to-guides/endpoint-detection-and-response/huntress/api-config.png" alt="Huntress API configuration" className="imagewrapper-big"/>
|
||||
</p>
|
||||
|
||||
- Select the **groups** you want to apply the integration to and click **Connect**
|
||||
|
||||
<p>
|
||||
<img src="/docs-static/img/how-to-guides/endpoint-detection-and-response/huntress/group-config.png" alt="Huntress group configuration" className="imagewrapper-big"/>
|
||||
</p>
|
||||
|
||||
|
||||
<Note>
|
||||
The EDR check will apply only to peers in the selected groups and will require a running Huntress agent.
|
||||
You can also use groups [synchronized from your Identity Provider (IdP)](/how-to/idp-sync).
|
||||
</Note>
|
||||
|
||||
- Configure the compliance criteria that devices must meet to access your network. These security requirements ensure only healthy, properly configured devices can connect. Select the criteria that align with your organization's security policies:
|
||||
- **Defender Policy Status**: Requires Windows Defender policy status to be compliant. Default is set to `Compliant`.
|
||||
- **Defender Status**: Requires Windows Defender to be in a healthy state. Default is set to `Healthy`.
|
||||
- **Defender Substatus**: Requires Windows Defender to be up to date with the latest definitions. Default is set to `Up to date`.
|
||||
- **Firewall Status**: Requires the device firewall to be enabled. Can be set to check if firewall is `Enabled` or `Disabled`. Default is to require `Enabled`.
|
||||
|
||||
<p>
|
||||
<img src="/docs-static/img/how-to-guides/endpoint-detection-and-response/huntress/compliance-config.png" alt="edr-integrations" className="imagewrapper-big"/>
|
||||
</p>
|
||||
|
||||
|
||||
- Configure the **Huntress Sync Window** (default is 24 hours). This setting determines which devices NetBird will consider for network access based on their recent activity in Huntress. Only devices that have been active and reporting to Huntress within this time window will be synchronized. These devices must then also meet the configured compliance criteria to gain network access.
|
||||
|
||||
<p>
|
||||
<img src="/docs-static/img/how-to-guides/endpoint-detection-and-response/huntress/sync-config.png" alt="edr-integrations" className="imagewrapper-big"/>
|
||||
</p>
|
||||
|
||||
- Click **Connect** to complete the integration setup
|
||||
|
||||
- Only peers that have the Huntress agent installed and meet all the configured compliance criteria will be granted access to the network.
|
||||
Peers without the Huntress agent or those that don't meet the compliance requirements will appear with an `Approval required` mark in the peers list and won't be able to access
|
||||
the network until they have the agent installed and satisfy all the specified security requirements.
|
||||
|
||||
<p>
|
||||
<img src="/docs-static/img/how-to-guides/endpoint-detection-and-response/huntress/edr-approval-required.png" alt="edr-approval-required" className="imagewrapper-big"/>
|
||||
</p>
|
||||
|
||||
|
||||
<Note>
|
||||
NetBird matches the Huntress agent to the peer using the Serial Number of the device. You must ensure that each of your devices has a unique serial number.
|
||||
</Note>
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
export const title = 'Examples'
|
||||
# Examples
|
||||
|
||||
## NetBird Client on AWS ECS (Terraform)
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.custom-details li {
|
||||
margin-left: 50px !important;
|
||||
}
|
||||
@@ -39,6 +39,28 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.custom-details li {
|
||||
margin-left: 50px !important;
|
||||
}
|
||||
|
||||
/* Hide scrollbar for sidebar navigation */
|
||||
.sidebar-scroll {
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
}
|
||||
|
||||
.sidebar-scroll::-webkit-scrollbar {
|
||||
display: none; /* Chrome, Safari, Opera */
|
||||
}
|
||||
}
|
||||
|
||||
.imagewrapper {
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
border-radius: 4px;
|
||||
@@ -57,6 +79,9 @@
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
border-radius: 4px;
|
||||
overflow:hidden;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.spacer-sm {
|
||||
@@ -69,7 +94,8 @@
|
||||
|
||||
/* Image Zoom / Lightbox Styles */
|
||||
.imagewrapper,
|
||||
.imagewrapper-big {
|
||||
.imagewrapper-big,
|
||||
.imagewrapper-medium {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
|
||||
102
typography.js
102
typography.js
@@ -18,6 +18,8 @@ module.exports = ({ theme }) => ({
|
||||
'--tw-prose-code-ring': theme('colors.zinc.300'),
|
||||
'--tw-prose-th-borders': theme('colors.zinc.300'),
|
||||
'--tw-prose-td-borders': theme('colors.zinc.200'),
|
||||
'--tw-prose-th-bg': theme('colors.zinc.100'),
|
||||
'--tw-prose-td-bg': theme('colors.zinc.50 / 0.5'),
|
||||
|
||||
'--tw-prose-invert-body': theme('colors.zinc.400'),
|
||||
'--tw-prose-invert-headings': theme('colors.white'),
|
||||
@@ -36,6 +38,8 @@ module.exports = ({ theme }) => ({
|
||||
'--tw-prose-invert-code-ring': theme('colors.white / 0.1'),
|
||||
'--tw-prose-invert-th-borders': theme('colors.zinc.600'),
|
||||
'--tw-prose-invert-td-borders': theme('colors.zinc.700'),
|
||||
'--tw-prose-invert-th-bg': theme('colors.zinc.800 / 0.5'),
|
||||
'--tw-prose-invert-td-bg': theme('colors.zinc.800 / 0.2'),
|
||||
|
||||
// Base
|
||||
color: 'var(--tw-prose-body)',
|
||||
@@ -67,8 +71,8 @@ module.exports = ({ theme }) => ({
|
||||
// Lists
|
||||
ol: {
|
||||
listStyleType: 'decimal',
|
||||
marginTop: theme('spacing.5'),
|
||||
marginBottom: theme('spacing.5'),
|
||||
marginTop: theme('spacing.6'),
|
||||
marginBottom: theme('spacing.6'),
|
||||
paddingLeft: '1.625rem',
|
||||
},
|
||||
'ol[type="A"]': {
|
||||
@@ -100,16 +104,17 @@ module.exports = ({ theme }) => ({
|
||||
},
|
||||
ul: {
|
||||
listStyleType: 'disc',
|
||||
marginTop: theme('spacing.5'),
|
||||
marginBottom: theme('spacing.5'),
|
||||
marginTop: theme('spacing.6'),
|
||||
marginBottom: theme('spacing.6'),
|
||||
paddingLeft: '1.625rem',
|
||||
},
|
||||
li: {
|
||||
marginTop: theme('spacing.2'),
|
||||
marginBottom: theme('spacing.2'),
|
||||
marginTop: theme('spacing.3'),
|
||||
marginBottom: theme('spacing.3'),
|
||||
},
|
||||
':is(ol, ul) > li': {
|
||||
paddingLeft: theme('spacing[1.5]'),
|
||||
lineHeight: theme('lineHeight.7'),
|
||||
},
|
||||
'ol > li::marker': {
|
||||
fontWeight: '400',
|
||||
@@ -135,8 +140,8 @@ module.exports = ({ theme }) => ({
|
||||
marginBottom: theme('spacing.5'),
|
||||
},
|
||||
'ul ul, ul ol, ol ul, ol ol': {
|
||||
marginTop: theme('spacing.3'),
|
||||
marginBottom: theme('spacing.3'),
|
||||
marginTop: theme('spacing.4'),
|
||||
marginBottom: theme('spacing.4'),
|
||||
},
|
||||
|
||||
// Horizontal rules
|
||||
@@ -163,12 +168,17 @@ module.exports = ({ theme }) => ({
|
||||
fontWeight: '500',
|
||||
fontStyle: 'italic',
|
||||
color: 'var(--tw-prose-quotes)',
|
||||
borderLeftWidth: '0.25rem',
|
||||
borderLeftColor: 'var(--tw-prose-quote-borders)',
|
||||
borderLeftWidth: '0.375rem',
|
||||
borderLeftColor: theme('colors.orange.500'),
|
||||
backgroundColor: theme('colors.orange.50 / 0.3'),
|
||||
quotes: '"\\201C""\\201D""\\2018""\\2019"',
|
||||
marginTop: theme('spacing.8'),
|
||||
marginBottom: theme('spacing.8'),
|
||||
paddingTop: theme('spacing.4'),
|
||||
paddingRight: theme('spacing.4'),
|
||||
paddingBottom: theme('spacing.4'),
|
||||
paddingLeft: theme('spacing.5'),
|
||||
borderRadius: theme('borderRadius.md'),
|
||||
},
|
||||
'blockquote p:first-of-type::before': {
|
||||
content: 'open-quote',
|
||||
@@ -207,7 +217,23 @@ module.exports = ({ theme }) => ({
|
||||
...theme('fontSize.base')[1],
|
||||
fontWeight: '600',
|
||||
marginTop: theme('spacing.8'),
|
||||
marginBottom: theme('spacing.2'),
|
||||
marginBottom: theme('spacing.3'),
|
||||
},
|
||||
h5: {
|
||||
color: 'var(--tw-prose-headings)',
|
||||
fontSize: theme('fontSize.sm')[0],
|
||||
...theme('fontSize.sm')[1],
|
||||
fontWeight: '600',
|
||||
marginTop: theme('spacing.6'),
|
||||
marginBottom: theme('spacing.3'),
|
||||
},
|
||||
h6: {
|
||||
color: 'var(--tw-prose-headings)',
|
||||
fontSize: theme('fontSize.sm')[0],
|
||||
...theme('fontSize.sm')[1],
|
||||
fontWeight: '600',
|
||||
marginTop: theme('spacing.6'),
|
||||
marginBottom: theme('spacing.3'),
|
||||
},
|
||||
|
||||
// Media
|
||||
@@ -234,53 +260,73 @@ module.exports = ({ theme }) => ({
|
||||
marginTop: theme('spacing.8'),
|
||||
marginBottom: theme('spacing.8'),
|
||||
lineHeight: theme('lineHeight.6'),
|
||||
borderRadius: theme('borderRadius.lg'),
|
||||
overflow: 'hidden',
|
||||
borderWidth: '1px',
|
||||
borderColor: 'var(--tw-prose-th-borders)',
|
||||
boxShadow: theme('boxShadow.sm'),
|
||||
},
|
||||
thead: {
|
||||
borderBottomWidth: '1px',
|
||||
backgroundColor: 'var(--tw-prose-th-bg)',
|
||||
borderBottomWidth: '2px',
|
||||
borderBottomColor: 'var(--tw-prose-th-borders)',
|
||||
},
|
||||
'thead th': {
|
||||
color: 'var(--tw-prose-headings)',
|
||||
fontWeight: '600',
|
||||
verticalAlign: 'bottom',
|
||||
paddingRight: theme('spacing.2'),
|
||||
paddingBottom: theme('spacing.2'),
|
||||
paddingLeft: theme('spacing.2'),
|
||||
paddingTop: theme('spacing.4'),
|
||||
paddingRight: theme('spacing.4'),
|
||||
paddingBottom: theme('spacing.4'),
|
||||
paddingLeft: theme('spacing.4'),
|
||||
fontSize: theme('fontSize.sm')[0],
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: theme('letterSpacing.wide'),
|
||||
},
|
||||
'thead th:first-child': {
|
||||
paddingLeft: '0',
|
||||
paddingLeft: theme('spacing.4'),
|
||||
},
|
||||
'thead th:last-child': {
|
||||
paddingRight: '0',
|
||||
paddingRight: theme('spacing.4'),
|
||||
},
|
||||
'tbody tr': {
|
||||
borderBottomWidth: '1px',
|
||||
borderBottomColor: 'var(--tw-prose-td-borders)',
|
||||
transitionProperty: 'background-color',
|
||||
transitionDuration: theme('transitionDuration.DEFAULT'),
|
||||
transitionTimingFunction: theme('transitionTimingFunction.DEFAULT'),
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--tw-prose-td-bg)',
|
||||
},
|
||||
'&:nth-child(even)': {
|
||||
backgroundColor: 'var(--tw-prose-td-bg)',
|
||||
},
|
||||
},
|
||||
'tbody tr:last-child': {
|
||||
borderBottomWidth: '0',
|
||||
},
|
||||
'tbody td': {
|
||||
verticalAlign: 'baseline',
|
||||
verticalAlign: 'middle',
|
||||
},
|
||||
tfoot: {
|
||||
borderTopWidth: '1px',
|
||||
borderTopWidth: '2px',
|
||||
borderTopColor: 'var(--tw-prose-th-borders)',
|
||||
backgroundColor: 'var(--tw-prose-td-bg)',
|
||||
},
|
||||
'tfoot td': {
|
||||
verticalAlign: 'top',
|
||||
},
|
||||
':is(tbody, tfoot) td': {
|
||||
paddingTop: theme('spacing.2'),
|
||||
paddingRight: theme('spacing.2'),
|
||||
paddingBottom: theme('spacing.2'),
|
||||
paddingLeft: theme('spacing.2'),
|
||||
paddingTop: theme('spacing.4'),
|
||||
paddingRight: theme('spacing.4'),
|
||||
paddingBottom: theme('spacing.4'),
|
||||
paddingLeft: theme('spacing.4'),
|
||||
},
|
||||
':is(tbody, tfoot) td:first-child': {
|
||||
paddingLeft: '0',
|
||||
paddingLeft: theme('spacing.4'),
|
||||
},
|
||||
':is(tbody, tfoot) td:last-child': {
|
||||
paddingRight: '0',
|
||||
paddingRight: theme('spacing.4'),
|
||||
},
|
||||
|
||||
// Inline elements
|
||||
@@ -360,6 +406,12 @@ module.exports = ({ theme }) => ({
|
||||
'--tw-prose-code-ring': 'var(--tw-prose-invert-code-ring)',
|
||||
'--tw-prose-th-borders': 'var(--tw-prose-invert-th-borders)',
|
||||
'--tw-prose-td-borders': 'var(--tw-prose-invert-td-borders)',
|
||||
'--tw-prose-th-bg': 'var(--tw-prose-invert-th-bg)',
|
||||
'--tw-prose-td-bg': 'var(--tw-prose-invert-td-bg)',
|
||||
blockquote: {
|
||||
borderLeftColor: theme('colors.orange.400'),
|
||||
backgroundColor: theme('colors.orange.900 / 0.2'),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user